diff options
Diffstat (limited to 'roles')
52 files changed, 822 insertions, 344 deletions
diff --git a/roles/etcd/meta/main.yml b/roles/etcd/meta/main.yml index 7156a9fff..cfd72dfbc 100644 --- a/roles/etcd/meta/main.yml +++ b/roles/etcd/meta/main.yml @@ -7,7 +7,7 @@ galaxy_info:    description: etcd management    company: Red Hat, Inc.    license: Apache License, Version 2.0 -  min_ansible_version: 1.2 +  min_ansible_version: 2.1    platforms:    - name: EL      versions: @@ -22,4 +22,4 @@ dependencies:      port: "{{etcd_client_port}}/tcp"    - service: etcd peering      port: "{{ etcd_peer_port }}/tcp" -- role: etcd_common +- role: etcd_server_certificates diff --git a/roles/etcd/tasks/main.yml b/roles/etcd/tasks/main.yml index 75d40216d..ba4136327 100644 --- a/roles/etcd/tasks/main.yml +++ b/roles/etcd/tasks/main.yml @@ -58,30 +58,6 @@      group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}"      mode: 0700 -- name: Validate permissions on certificate files -  file: -    path: "{{ item }}" -    mode: 0600 -    owner: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" -    group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" -  when: etcd_url_scheme == 'https' -  with_items: -  - "{{ etcd_ca_file }}" -  - "{{ etcd_cert_file }}" -  - "{{ etcd_key_file }}" - -- name: Validate permissions on peer certificate files -  file: -    path: "{{ item }}" -    mode: 0600 -    owner: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" -    group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" -  when: etcd_peer_url_scheme == 'https' -  with_items: -  - "{{ etcd_peer_ca_file }}" -  - "{{ etcd_peer_cert_file }}" -  - "{{ etcd_peer_key_file }}" -  - name: Write etcd global config file    template:      src: etcd.conf.j2 diff --git a/roles/etcd/templates/etcd.conf.j2 b/roles/etcd/templates/etcd.conf.j2 index cd048ec60..7ccf78212 100644 --- a/roles/etcd/templates/etcd.conf.j2 +++ b/roles/etcd/templates/etcd.conf.j2 @@ -1,5 +1,5 @@  {% macro initial_cluster() -%} -{% for host in etcd_peers -%} +{% for host in etcd_peers | default([]) -%}  {% if loop.last -%}  {{ hostvars[host].etcd_hostname }}={{ etcd_peer_url_scheme }}://{{ hostvars[host].etcd_ip }}:{{ etcd_peer_port }}  {%- else -%} diff --git a/roles/etcd_ca/meta/main.yml b/roles/etcd_ca/meta/main.yml index d02456ca3..e3e2f7781 100644 --- a/roles/etcd_ca/meta/main.yml +++ b/roles/etcd_ca/meta/main.yml @@ -1,10 +1,10 @@  ---  galaxy_info:    author: Jason DeTiberus -  description: +  description: Etcd CA    company: Red Hat, Inc.    license: Apache License, Version 2.0 -  min_ansible_version: 1.9 +  min_ansible_version: 2.1    platforms:    - name: EL      versions: @@ -13,4 +13,4 @@ galaxy_info:    - cloud    - system  dependencies: -- { role: etcd_common } +- role: etcd_common diff --git a/roles/etcd_ca/tasks/main.yml b/roles/etcd_ca/tasks/main.yml index e1bb9baed..865074e41 100644 --- a/roles/etcd_ca/tasks/main.yml +++ b/roles/etcd_ca/tasks/main.yml @@ -2,6 +2,8 @@  - name: Install openssl    action: "{{ ansible_pkg_mgr }} name=openssl state=present"    when: not etcd_is_atomic | bool +  delegate_to: "{{ etcd_ca_host }}" +  run_once: true  - file:      path: "{{ item }}" @@ -13,29 +15,41 @@    - "{{ etcd_ca_new_certs_dir }}"    - "{{ etcd_ca_crl_dir }}"    - "{{ etcd_ca_dir }}/fragments" +  delegate_to: "{{ etcd_ca_host }}" +  run_once: true  - command: cp /etc/pki/tls/openssl.cnf ./    args:      chdir: "{{ etcd_ca_dir }}/fragments"      creates: "{{ etcd_ca_dir }}/fragments/openssl.cnf" +  delegate_to: "{{ etcd_ca_host }}" +  run_once: true  - template:      dest: "{{ etcd_ca_dir }}/fragments/openssl_append.cnf"      src: openssl_append.j2      backup: true +  delegate_to: "{{ etcd_ca_host }}" +  run_once: true  - assemble:      src: "{{ etcd_ca_dir }}/fragments"      dest: "{{ etcd_openssl_conf }}" +  delegate_to: "{{ etcd_ca_host }}" +  run_once: true  - command: touch {{ etcd_ca_db }}    args:      creates: "{{ etcd_ca_db }}" +  delegate_to: "{{ etcd_ca_host }}" +  run_once: true  - copy:      dest: "{{ etcd_ca_serial }}"      content: "01"      force: no +  delegate_to: "{{ etcd_ca_host }}" +  run_once: true  - command: >      openssl req -config {{ etcd_openssl_conf }} -newkey rsa:4096 @@ -48,3 +62,5 @@      creates: "{{ etcd_ca_cert }}"    environment:      SAN: 'etcd-signer' +  delegate_to: "{{ etcd_ca_host }}" +  run_once: true diff --git a/roles/etcd_certificates/tasks/client.yml b/roles/etcd_certificates/tasks/client.yml deleted file mode 100644 index b497a46c0..000000000 --- a/roles/etcd_certificates/tasks/client.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -- name: Ensure generated_certs directory present -  file: -    path: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" -    state: directory -    mode: 0700 -  with_items: "{{ etcd_needing_client_certs | default([]) }}" - -- name: Create the client csr -  command: > -    openssl req -new -keyout {{ item.etcd_cert_prefix }}client.key -    -config {{ etcd_openssl_conf }} -    -out {{ item.etcd_cert_prefix }}client.csr -    -reqexts {{ etcd_req_ext }} -batch -nodes -    -subj /CN={{ item.etcd_hostname }} -  args: -    chdir: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" -    creates: "{{ etcd_generated_certs_dir ~ '/' ~  item.etcd_cert_subdir ~ '/' -                 ~ item.etcd_cert_prefix ~ 'client.csr' }}" -  environment: -    SAN: "IP:{{ item.etcd_ip }}" -  with_items: "{{ etcd_needing_client_certs | default([]) }}" - -- name: Sign and create the client crt -  command: > -    openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }} -    -out {{ item.etcd_cert_prefix }}client.crt -    -in {{ item.etcd_cert_prefix }}client.csr -    -batch -  args: -    chdir: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" -    creates: "{{ etcd_generated_certs_dir ~ '/' ~  item.etcd_cert_subdir ~ '/' -                 ~ item.etcd_cert_prefix ~ 'client.crt' }}" -  environment: -    SAN: "IP:{{ item.etcd_ip }}" -  with_items: "{{ etcd_needing_client_certs | default([]) }}" - -- file: -    src: "{{ etcd_ca_cert }}" -    dest: "{{ etcd_generated_certs_dir}}/{{ item.etcd_cert_subdir }}/{{ item.etcd_cert_prefix }}ca.crt" -    state: hard -  with_items: "{{ etcd_needing_client_certs | default([]) }}" diff --git a/roles/etcd_certificates/tasks/main.yml b/roles/etcd_certificates/tasks/main.yml deleted file mode 100644 index 17092ca58..000000000 --- a/roles/etcd_certificates/tasks/main.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- include: client.yml -  when: etcd_needing_client_certs | default([]) | length > 0 - -- include: server.yml -  when: etcd_needing_server_certs | default([]) | length > 0 diff --git a/roles/etcd_certificates/tasks/server.yml b/roles/etcd_certificates/tasks/server.yml deleted file mode 100644 index 934b8b805..000000000 --- a/roles/etcd_certificates/tasks/server.yml +++ /dev/null @@ -1,71 +0,0 @@ ---- -- name: Ensure generated_certs directory present -  file: -    path: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" -    state: directory -    mode: 0700 -  with_items: "{{ etcd_needing_server_certs | default([]) }}" - -- name: Create the server csr -  command: > -    openssl req -new -keyout {{ item.etcd_cert_prefix }}server.key -    -config {{ etcd_openssl_conf }} -    -out {{ item.etcd_cert_prefix }}server.csr -    -reqexts {{ etcd_req_ext }} -batch -nodes -    -subj /CN={{ item.etcd_hostname }} -  args: -    chdir: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" -    creates: "{{ etcd_generated_certs_dir ~ '/' ~  item.etcd_cert_subdir ~ '/' -                 ~ item.etcd_cert_prefix ~ 'server.csr' }}" -  environment: -    SAN: "IP:{{ item.etcd_ip }}" -  with_items: "{{ etcd_needing_server_certs  | default([]) }}" - -- name: Sign and create the server crt -  command: > -    openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }} -    -out {{ item.etcd_cert_prefix }}server.crt -    -in {{ item.etcd_cert_prefix }}server.csr -    -extensions {{ etcd_ca_exts_server }} -batch -  args: -    chdir: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" -    creates: "{{ etcd_generated_certs_dir ~ '/' ~  item.etcd_cert_subdir ~ '/' -                 ~ item.etcd_cert_prefix ~ 'server.crt' }}" -  environment: -    SAN: "IP:{{ item.etcd_ip }}" -  with_items: "{{ etcd_needing_server_certs  | default([]) }}" - -- name: Create the peer csr -  command: > -    openssl req -new -keyout {{ item.etcd_cert_prefix }}peer.key -    -config {{ etcd_openssl_conf }} -    -out {{ item.etcd_cert_prefix }}peer.csr -    -reqexts {{ etcd_req_ext }} -batch -nodes -    -subj /CN={{ item.etcd_hostname }} -  args: -    chdir: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" -    creates: "{{ etcd_generated_certs_dir ~ '/' ~  item.etcd_cert_subdir ~ '/' -                 ~ item.etcd_cert_prefix ~ 'peer.csr' }}" -  environment: -    SAN: "IP:{{ item.etcd_ip }}" -  with_items: "{{ etcd_needing_server_certs | default([]) }}" - -- name: Sign and create the peer crt -  command: > -    openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }} -    -out {{ item.etcd_cert_prefix }}peer.crt -    -in {{ item.etcd_cert_prefix }}peer.csr -    -extensions {{ etcd_ca_exts_peer }} -batch -  args: -    chdir: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" -    creates: "{{ etcd_generated_certs_dir ~ '/' ~  item.etcd_cert_subdir ~ '/' -                 ~ item.etcd_cert_prefix ~ 'peer.crt' }}" -  environment: -    SAN: "IP:{{ item.etcd_ip }}" -  with_items: "{{ etcd_needing_server_certs | default([]) }}" - -- file: -    src: "{{ etcd_ca_cert }}" -    dest: "{{ etcd_generated_certs_dir}}/{{ item.etcd_cert_subdir }}/{{ item.etcd_cert_prefix }}ca.crt" -    state: hard -  with_items: "{{ etcd_needing_server_certs | default([]) }}" diff --git a/roles/etcd_certificates/README.md b/roles/etcd_client_certificates/README.md index 95f8f8aab..269d5296d 100644 --- a/roles/etcd_certificates/README.md +++ b/roles/etcd_client_certificates/README.md @@ -1,5 +1,5 @@ -OpenShift etcd certificates -======================== +OpenShift Etcd Certificates +===========================  TODO diff --git a/roles/etcd_client_certificates/library b/roles/etcd_client_certificates/library new file mode 120000 index 000000000..494d3c39e --- /dev/null +++ b/roles/etcd_client_certificates/library @@ -0,0 +1 @@ +../../library
\ No newline at end of file diff --git a/roles/etcd_client_certificates/meta/main.yml b/roles/etcd_client_certificates/meta/main.yml new file mode 100644 index 000000000..efebdb599 --- /dev/null +++ b/roles/etcd_client_certificates/meta/main.yml @@ -0,0 +1,16 @@ +--- +galaxy_info: +  author: Jason DeTiberus +  description: Etcd Client Certificates +  company: Red Hat, Inc. +  license: Apache License, Version 2.0 +  min_ansible_version: 2.1 +  platforms: +  - name: EL +    versions: +    - 7 +  categories: +  - cloud +  - system +dependencies: +- role: etcd_common diff --git a/roles/etcd_client_certificates/tasks/main.yml b/roles/etcd_client_certificates/tasks/main.yml new file mode 100644 index 000000000..275aa0a63 --- /dev/null +++ b/roles/etcd_client_certificates/tasks/main.yml @@ -0,0 +1,137 @@ +--- +- name: Ensure CA certificate exists on etcd_ca_host +  stat: +    path: "{{ etcd_ca_cert }}" +  register: g_ca_cert_stat_result +  delegate_to: "{{ etcd_ca_host }}" +  run_once: true + +- fail: +    msg: > +      CA certificate {{ etcd_ca_cert }} doesn't exist on CA host +      {{ etcd_ca_host }}. Apply 'etcd_ca' role to +      {{ etcd_ca_host }}. +  when: not g_ca_cert_stat_result.stat.exists | bool +  run_once: true + +- name: Check status of external etcd certificatees +  stat: +    path: "{{ etcd_cert_config_dir }}/{{ item }}" +  with_items: +  - "{{ etcd_cert_prefix }}client.crt" +  - "{{ etcd_cert_prefix }}client.key" +  - "{{ etcd_cert_prefix }}ca.crt" +  register: g_external_etcd_cert_stat_result +  when: not etcd_certificates_redeploy | default(false) | bool + +- set_fact: +    etcd_client_certs_missing: "{{ true if etcd_certificates_redeploy | default(false) | bool +                                   else (False in (g_external_etcd_cert_stat_result.results +                                                   | default({}) +                                                   | oo_collect(attribute='stat.exists') +                                                   | list)) }}" + +- name: Ensure generated_certs directory present +  file: +    path: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" +    state: directory +    mode: 0700 +  when: etcd_client_certs_missing | bool +  delegate_to: "{{ etcd_ca_host }}" + +- name: Create the client csr +  command: > +    openssl req -new -keyout {{ etcd_cert_prefix }}client.key +    -config {{ etcd_openssl_conf }} +    -out {{ etcd_cert_prefix }}client.csr +    -reqexts {{ etcd_req_ext }} -batch -nodes +    -subj /CN={{ etcd_hostname }} +  args: +    chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" +    creates: "{{ etcd_generated_certs_dir ~ '/' ~  etcd_cert_subdir ~ '/' +                 ~ etcd_cert_prefix ~ 'client.csr' }}" +  environment: +    SAN: "IP:{{ etcd_ip }}" +  when: etcd_client_certs_missing | bool +  delegate_to: "{{ etcd_ca_host }}" + +# Certificates must be signed serially in order to avoid competing +# for the serial file. +- name: Sign and create the client crt +  delegated_serial_command: +    command: > +      openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }} +      -out {{ etcd_cert_prefix }}client.crt +      -in {{ etcd_cert_prefix }}client.csr +      -batch +    chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" +    creates: "{{ etcd_generated_certs_dir ~ '/' ~  etcd_cert_subdir ~ '/' +                 ~ etcd_cert_prefix ~ 'client.crt' }}" +  environment: +    SAN: "IP:{{ etcd_ip }}" +  when: etcd_client_certs_missing | bool +  delegate_to: "{{ etcd_ca_host }}" + +- file: +    src: "{{ etcd_ca_cert }}" +    dest: "{{ etcd_generated_certs_dir}}/{{ etcd_cert_subdir }}/{{ etcd_cert_prefix }}ca.crt" +    state: hard +  when: etcd_client_certs_missing | bool +  delegate_to: "{{ etcd_ca_host }}" + +- name: Create local temp directory for syncing certs +  local_action: command mktemp -d /tmp/etcd_certificates-XXXXXXX +  register: g_etcd_client_mktemp +  changed_when: False +  when: etcd_client_certs_missing | bool +  delegate_to: localhost +  become: no + +- name: Create a tarball of the etcd certs +  command: > +    tar -czvf {{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz +      -C {{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }} . +  args: +    creates: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz" +  when: etcd_client_certs_missing | bool +  delegate_to: "{{ etcd_ca_host }}" + +- name: Retrieve the etcd cert tarballs +  fetch: +    src: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz" +    dest: "{{ g_etcd_client_mktemp.stdout }}/" +    flat: yes +    fail_on_missing: yes +    validate_checksum: yes +  when: etcd_client_certs_missing | bool +  delegate_to: "{{ etcd_ca_host }}" + +- name: Ensure certificate directory exists +  file: +    path: "{{ etcd_cert_config_dir }}" +    state: directory +  when: etcd_client_certs_missing | bool + +- name: Unarchive etcd cert tarballs +  unarchive: +    src: "{{ g_etcd_client_mktemp.stdout }}/{{ etcd_cert_subdir }}.tgz" +    dest: "{{ etcd_cert_config_dir }}" +  when: etcd_client_certs_missing | bool + +- file: +    path: "{{ etcd_cert_config_dir }}/{{ item }}" +    owner: root +    group: root +    mode: 0600 +  with_items: +  - "{{ etcd_cert_prefix }}client.crt" +  - "{{ etcd_cert_prefix }}client.key" +  - "{{ etcd_cert_prefix }}ca.crt" +  when: etcd_client_certs_missing | bool + +- name: Delete temporary directory +  file: name={{ g_etcd_client_mktemp.stdout }} state=absent +  changed_when: False +  when: etcd_client_certs_missing | bool +  delegate_to: localhost +  become: no diff --git a/roles/etcd_server_certificates/README.md b/roles/etcd_server_certificates/README.md new file mode 100644 index 000000000..269d5296d --- /dev/null +++ b/roles/etcd_server_certificates/README.md @@ -0,0 +1,34 @@ +OpenShift Etcd Certificates +=========================== + +TODO + +Requirements +------------ + +TODO + +Role Variables +-------------- + +TODO + +Dependencies +------------ + +TODO + +Example Playbook +---------------- + +TODO + +License +------- + +Apache License Version 2.0 + +Author Information +------------------ + +Scott Dodson (sdodson@redhat.com) diff --git a/roles/etcd_server_certificates/library b/roles/etcd_server_certificates/library new file mode 120000 index 000000000..494d3c39e --- /dev/null +++ b/roles/etcd_server_certificates/library @@ -0,0 +1 @@ +../../library
\ No newline at end of file diff --git a/roles/etcd_certificates/meta/main.yml b/roles/etcd_server_certificates/meta/main.yml index 41370fab4..b453f2bd8 100644 --- a/roles/etcd_certificates/meta/main.yml +++ b/roles/etcd_server_certificates/meta/main.yml @@ -1,10 +1,10 @@  ---  galaxy_info:    author: Jason DeTiberus -  description: +  description: Etcd Server Certificates    company: Red Hat, Inc.    license: Apache License, Version 2.0 -  min_ansible_version: 1.8 +  min_ansible_version: 2.1    platforms:    - name: EL      versions: @@ -13,4 +13,4 @@ galaxy_info:    - cloud    - system  dependencies: -- { role: etcd_ca } +- role: etcd_ca diff --git a/roles/etcd_server_certificates/tasks/main.yml b/roles/etcd_server_certificates/tasks/main.yml new file mode 100644 index 000000000..718515023 --- /dev/null +++ b/roles/etcd_server_certificates/tasks/main.yml @@ -0,0 +1,179 @@ +--- +- name: Install etcd +  action: "{{ ansible_pkg_mgr }} name=etcd state=present" +  when: not etcd_is_containerized | bool + +- name: Check status of etcd certificates +  stat: +    path: "{{ etcd_cert_config_dir }}/{{ item }}" +  with_items: +  - "{{ etcd_cert_prefix }}server.crt" +  - "{{ etcd_cert_prefix }}peer.crt" +  - "{{ etcd_cert_prefix }}ca.crt" +  register: g_etcd_server_cert_stat_result +  when: not etcd_certificates_redeploy | default(false) | bool + +- set_fact: +    etcd_server_certs_missing: "{{ true if etcd_certificates_redeploy | default(false) | bool +                                   else (False in (g_etcd_server_cert_stat_result.results +                                                   | default({}) +                                                   | oo_collect(attribute='stat.exists') +                                                   | list)) }}" + +- name: Ensure generated_certs directory present +  file: +    path: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" +    state: directory +    mode: 0700 +  when: etcd_server_certs_missing | bool +  delegate_to: "{{ etcd_ca_host }}" + +- name: Create the server csr +  command: > +    openssl req -new -keyout {{ etcd_cert_prefix }}server.key +    -config {{ etcd_openssl_conf }} +    -out {{ etcd_cert_prefix }}server.csr +    -reqexts {{ etcd_req_ext }} -batch -nodes +    -subj /CN={{ etcd_hostname }} +  args: +    chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" +    creates: "{{ etcd_generated_certs_dir ~ '/' ~  etcd_cert_subdir ~ '/' +                 ~ etcd_cert_prefix ~ 'server.csr' }}" +  environment: +    SAN: "IP:{{ etcd_ip }}" +  when: etcd_server_certs_missing | bool +  delegate_to: "{{ etcd_ca_host }}" + +# Certificates must be signed serially in order to avoid competing +# for the serial file. +- name: Sign and create the server crt +  delegated_serial_command: +    command: > +      openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }} +      -out {{ etcd_cert_prefix }}server.crt +      -in {{ etcd_cert_prefix }}server.csr +      -extensions {{ etcd_ca_exts_server }} -batch +    chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" +    creates: "{{ etcd_generated_certs_dir ~ '/' ~  etcd_cert_subdir ~ '/' +                 ~ etcd_cert_prefix ~ 'server.crt' }}" +  environment: +    SAN: "IP:{{ etcd_ip }}" +  delegate_to: "{{ etcd_ca_host }}" + +- name: Create the peer csr +  command: > +    openssl req -new -keyout {{ etcd_cert_prefix }}peer.key +    -config {{ etcd_openssl_conf }} +    -out {{ etcd_cert_prefix }}peer.csr +    -reqexts {{ etcd_req_ext }} -batch -nodes +    -subj /CN={{ etcd_hostname }} +  args: +    chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" +    creates: "{{ etcd_generated_certs_dir ~ '/' ~  etcd_cert_subdir ~ '/' +                 ~ etcd_cert_prefix ~ 'peer.csr' }}" +  environment: +    SAN: "IP:{{ etcd_ip }}" +  when: etcd_server_certs_missing | bool +  delegate_to: "{{ etcd_ca_host }}" + +# Certificates must be signed serially in order to avoid competing +# for the serial file. +- name: Sign and create the peer crt +  delegated_serial_command: +    command: > +      openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }} +      -out {{ etcd_cert_prefix }}peer.crt +      -in {{ etcd_cert_prefix }}peer.csr +      -extensions {{ etcd_ca_exts_peer }} -batch +    chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" +    creates: "{{ etcd_generated_certs_dir ~ '/' ~  etcd_cert_subdir ~ '/' +                 ~ etcd_cert_prefix ~ 'peer.crt' }}" +  environment: +    SAN: "IP:{{ etcd_ip }}" +  when: etcd_server_certs_missing | bool +  delegate_to: "{{ etcd_ca_host }}" + +- file: +    src: "{{ etcd_ca_cert }}" +    dest: "{{ etcd_generated_certs_dir}}/{{ etcd_cert_subdir }}/{{ etcd_cert_prefix }}ca.crt" +    state: hard +  when: etcd_server_certs_missing | bool +  delegate_to: "{{ etcd_ca_host }}" + +- name: Create local temp directory for syncing certs +  local_action: command mktemp -d /tmp/etcd_certificates-XXXXXXX +  become: no +  register: g_etcd_server_mktemp +  changed_when: False +  when: etcd_server_certs_missing | bool +  delegate_to: localhost + +- name: Create a tarball of the etcd certs +  command: > +    tar -czvf {{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz +      -C {{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }} . +  args: +    creates: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz" +  when: etcd_server_certs_missing | bool +  delegate_to: "{{ etcd_ca_host }}" + +- name: Retrieve etcd cert tarball +  fetch: +    src: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz" +    dest: "{{ g_etcd_server_mktemp.stdout }}/" +    flat: yes +    fail_on_missing: yes +    validate_checksum: yes +  when: etcd_server_certs_missing | bool +  delegate_to: "{{ etcd_ca_host }}" + +- name: Ensure certificate directory exists +  file: +    path: "{{ etcd_cert_config_dir }}" +    state: directory +  when: etcd_server_certs_missing | bool + +- name: Unarchive cert tarball +  unarchive: +    src: "{{ g_etcd_server_mktemp.stdout }}/{{ etcd_cert_subdir }}.tgz" +    dest: "{{ etcd_cert_config_dir }}" +  when: etcd_server_certs_missing | bool + +- name: Delete temporary directory +  file: name={{ g_etcd_server_mktemp.stdout }} state=absent +  become: no +  changed_when: False +  when: etcd_server_certs_missing | bool +  delegate_to: localhost + +- name: Validate permissions on certificate files +  file: +    path: "{{ item }}" +    mode: 0600 +    owner: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" +    group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" +  when: etcd_url_scheme == 'https' +  with_items: +  - "{{ etcd_ca_file }}" +  - "{{ etcd_cert_file }}" +  - "{{ etcd_key_file }}" + +- name: Validate permissions on peer certificate files +  file: +    path: "{{ item }}" +    mode: 0600 +    owner: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" +    group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" +  when: etcd_peer_url_scheme == 'https' +  with_items: +  - "{{ etcd_peer_ca_file }}" +  - "{{ etcd_peer_cert_file }}" +  - "{{ etcd_peer_key_file }}" + +- name: Validate permissions on the config dir +  file: +    path: "{{ etcd_conf_dir }}" +    state: directory +    owner: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" +    group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" +    mode: 0700 diff --git a/roles/flannel/meta/main.yml b/roles/flannel/meta/main.yml index 909bdbfa4..616ae61d2 100644 --- a/roles/flannel/meta/main.yml +++ b/roles/flannel/meta/main.yml @@ -4,7 +4,7 @@ galaxy_info:    description: flannel management    company: Red Hat, Inc.    license: Apache License, Version 2.0 -  min_ansible_version: 1.2 +  min_ansible_version: 2.1    platforms:    - name: EL      versions: @@ -13,4 +13,6 @@ galaxy_info:    - cloud    - system  dependencies: -- { role: openshift_facts } +- role: openshift_facts +- role: openshift_etcd_client_certificates +  etcd_cert_prefix: flannel.etcd- diff --git a/roles/openshift_ca/meta/main.yml b/roles/openshift_ca/meta/main.yml index a08aa1686..444c5b77e 100644 --- a/roles/openshift_ca/meta/main.yml +++ b/roles/openshift_ca/meta/main.yml @@ -15,3 +15,4 @@ galaxy_info:  dependencies:  - role: openshift_repos  - role: openshift_cli +- role: openshift_named_certificates diff --git a/roles/openshift_ca/tasks/main.yml b/roles/openshift_ca/tasks/main.yml index 4d9768ce7..bb89b65a6 100644 --- a/roles/openshift_ca/tasks/main.yml +++ b/roles/openshift_ca/tasks/main.yml @@ -3,6 +3,10 @@      msg: "openshift_ca_host variable must be defined for this role"    when: openshift_ca_host is not defined +- fail: +    msg: "Both 'certfile' and 'keyfile' keys must be supplied when configuring openshift_master_ca_certificate" +  when: openshift_master_ca_certificate is defined and ('certfile' not in openshift_master_ca_certificate or 'keyfile' not in openshift_master_ca_certificate) +  - name: Install the base package for admin tooling    action: "{{ ansible_pkg_mgr }} name={{ openshift.common.service_type }}{{ openshift_pkg_version | default('') | oo_image_tag_to_rpm_version(include_dash=True) }} state=present"    when: not openshift.common.is_containerized | bool @@ -28,26 +32,82 @@      path: "{{ openshift_ca_config_dir }}/{{ item }}"    register: g_master_ca_stat_result    with_items: +  - ca-bundle.crt    - ca.crt    - ca.key    delegate_to: "{{ openshift_ca_host }}"    run_once: true  - set_fact: -    master_ca_missing: "{{ False in (g_master_ca_stat_result.results -                           | oo_collect(attribute='stat.exists') -                           | list) }}" +    master_ca_missing: "{{ true if openshift_certificates_redeploy | default(false) | bool +                           else False in (g_master_ca_stat_result.results +                                         | oo_collect(attribute='stat.exists') +                                         | list) }}" +  run_once: true + +- name: Retain original serviceaccount keys +  copy: +    src: "{{ item }}" +    dest: "{{ item }}.keep" +    remote_src: true +  with_items: +  - "{{ openshift_ca_config_dir }}/serviceaccounts.private.key" +  - "{{ openshift_ca_config_dir }}/serviceaccounts.public.key" +  when: openshift_certificates_redeploy | default(false) | bool + +- name: Deploy master ca certificate +  copy: +    src: "{{ item.src }}" +    dest: "{{ openshift_ca_config_dir }}/{{ item.dest }}" +    force: "{{ true if openshift_certificates_redeploy_ca | default(false) | bool else false }}" +  with_items: +  - src: "{{ (openshift_master_ca_certificate | default({'certfile':none})).certfile }}" +    dest: ca.crt +  - src: "{{ (openshift_master_ca_certificate | default({'keyfile':none})).keyfile }}" +    dest: ca.key +  when: openshift_master_ca_certificate is defined +  delegate_to: "{{ openshift_ca_host }}" +  run_once: true + +- name: Create ca serial +  copy: +    content: "1" +    dest: "{{ openshift_ca_config_dir }}/ca.serial.txt" +    force: "{{ true if openshift_certificates_redeploy | default(false) | bool else false }}" +  when: openshift_master_ca_certificate is defined    delegate_to: "{{ openshift_ca_host }}"    run_once: true  - name: Create the master certificates if they do not already exist    command: >      {{ openshift.common.admin_binary }} create-master-certs -      --hostnames={{ openshift_master_hostnames | join(',') }} -      --master={{ openshift.master.api_url }} -      --public-master={{ openshift.master.public_api_url }} -      --cert-dir={{ openshift_ca_config_dir }} -      --overwrite=false -  when: hostvars[openshift_ca_host].master_ca_missing | bool +    {% for named_ca_certificate in openshift.master.named_certificates | default([]) | oo_collect('cafile') %} +    --certificate-authority {{ named_ca_certificate }} +    {% endfor %} +    --hostnames={{ openshift_master_hostnames | join(',') }} +    --master={{ openshift.master.api_url }} +    --public-master={{ openshift.master.public_api_url }} +    --cert-dir={{ openshift_ca_config_dir }} +    --overwrite=false +  when: master_ca_missing | bool    delegate_to: "{{ openshift_ca_host }}"    run_once: true + +- name: Restore original serviceaccount keys +  copy: +    src: "{{ item }}.keep" +    dest: "{{ item }}" +    remote_src: true +  with_items: +  - "{{ openshift_ca_config_dir }}/serviceaccounts.private.key" +  - "{{ openshift_ca_config_dir }}/serviceaccounts.public.key" +  when: openshift_certificates_redeploy | default(false) | bool + +- name: Remove backup serviceaccount keys +  file: +    path: "{{ item }}.keep" +    state: absent +  with_items: +  - "{{ openshift_ca_config_dir }}/serviceaccounts.private.key" +  - "{{ openshift_ca_config_dir }}/serviceaccounts.public.key" +  when: openshift_certificates_redeploy | default(false) | bool diff --git a/roles/openshift_etcd_client_certificates/meta/main.yml b/roles/openshift_etcd_client_certificates/meta/main.yml new file mode 100644 index 000000000..3268c390f --- /dev/null +++ b/roles/openshift_etcd_client_certificates/meta/main.yml @@ -0,0 +1,16 @@ +--- +galaxy_info: +  author: Jason DeTiberus +  description: OpenShift Etcd Client Certificates +  company: Red Hat, Inc. +  license: Apache License, Version 2.0 +  min_ansible_version: 2.1 +  platforms: +  - name: EL +    versions: +    - 7 +  categories: +  - cloud +dependencies: +- role: openshift_etcd_facts +- role: etcd_client_certificates diff --git a/roles/openshift_etcd_facts/tasks/main.yml b/roles/openshift_etcd_facts/tasks/main.yml new file mode 100644 index 000000000..22fb39006 --- /dev/null +++ b/roles/openshift_etcd_facts/tasks/main.yml @@ -0,0 +1,5 @@ +--- +- openshift_facts: +    role: etcd +    local_facts: +      etcd_image: "{{ osm_etcd_image | default(None) }}" diff --git a/roles/openshift_etcd_facts/vars/main.yml b/roles/openshift_etcd_facts/vars/main.yml index 6f3894565..cae15d61a 100644 --- a/roles/openshift_etcd_facts/vars/main.yml +++ b/roles/openshift_etcd_facts/vars/main.yml @@ -3,3 +3,8 @@ etcd_is_containerized: "{{ openshift.common.is_containerized }}"  etcd_is_atomic: "{{ openshift.common.is_atomic }}"  etcd_hostname: "{{ openshift.common.hostname }}"  etcd_ip: "{{ openshift.common.ip }}" +etcd_cert_subdir: "etcd-{{ openshift.common.hostname }}" +etcd_cert_prefix: +etcd_cert_config_dir: /etc/etcd +etcd_peer_url_scheme: https +etcd_url_scheme: https diff --git a/roles/openshift_etcd_server_certificates/meta/main.yml b/roles/openshift_etcd_server_certificates/meta/main.yml new file mode 100644 index 000000000..7750f14af --- /dev/null +++ b/roles/openshift_etcd_server_certificates/meta/main.yml @@ -0,0 +1,16 @@ +--- +galaxy_info: +  author: Jason DeTiberus +  description: OpenShift Etcd Server Certificates +  company: Red Hat, Inc. +  license: Apache License, Version 2.0 +  min_ansible_version: 2.1 +  platforms: +  - name: EL +    versions: +    - 7 +  categories: +  - cloud +dependencies: +- role: openshift_etcd_facts +- role: etcd_server_certificates diff --git a/roles/openshift_facts/library/openshift_facts.py b/roles/openshift_facts/library/openshift_facts.py index 659f4eba6..30cec82ce 100755 --- a/roles/openshift_facts/library/openshift_facts.py +++ b/roles/openshift_facts/library/openshift_facts.py @@ -944,7 +944,12 @@ def format_url(use_ssl, hostname, port, path=''):      netloc = hostname      if (use_ssl and port != '443') or (not use_ssl and port != '80'):          netloc += ":%s" % port -    return urlparse.urlunparse((scheme, netloc, path, '', '', '')) +    try: +        url = urlparse.urlunparse((scheme, netloc, path, '', '', '')) +    except AttributeError: +        # pylint: disable=undefined-variable +        url = urlunparse((scheme, netloc, path, '', '', '')) +    return url  def get_current_config(facts):      """ Get current openshift config @@ -1599,11 +1604,13 @@ class OpenShiftFacts(object):          try:              # ansible-2.1 -            # pylint: disable=too-many-function-args +            # pylint: disable=too-many-function-args,invalid-name              self.system_facts = ansible_facts(module, ['hardware', 'network', 'virtual', 'facter']) -        except TypeError: -            # ansible-1.9.x,ansible-2.0.x -            self.system_facts = ansible_facts(module) +            for (k, v) in self.system_facts.items(): +                self.system_facts["ansible_%s" % k.replace('-', '_')] = v +        except UnboundLocalError: +            # ansible-2.2 +            self.system_facts = get_all_facts(module)['ansible_facts']          self.facts = self.generate_facts(local_facts,                                           additive_facts_to_overwrite, @@ -1684,11 +1691,11 @@ class OpenShiftFacts(object):                  dict: The generated default facts          """          defaults = {} -        ip_addr = self.system_facts['default_ipv4']['address'] +        ip_addr = self.system_facts['ansible_default_ipv4']['address']          exit_code, output, _ = module.run_command(['hostname', '-f'])          hostname_f = output.strip() if exit_code == 0 else '' -        hostname_values = [hostname_f, self.system_facts['nodename'], -                           self.system_facts['fqdn']] +        hostname_values = [hostname_f, self.system_facts['ansible_nodename'], +                           self.system_facts['ansible_fqdn']]          hostname = choose_hostname(hostname_values, ip_addr)          defaults['common'] = dict(use_openshift_sdn=True, ip=ip_addr, @@ -1708,6 +1715,7 @@ class OpenShiftFacts(object):                  {"name": "PodFitsResources"},                  {"name": "PodFitsPorts"},                  {"name": "NoDiskConflict"}, +                {"name": "NoVolumeZoneConflict"},                  {"name": "Region", "argument": {"serviceAffinity" : {"labels" : ["region"]}}}              ]              scheduler_priorities = [ @@ -1821,10 +1829,10 @@ class OpenShiftFacts(object):                  dict: The generated default facts for the detected provider          """          # TODO: cloud provider facts should probably be submitted upstream -        product_name = self.system_facts['product_name'] -        product_version = self.system_facts['product_version'] -        virt_type = self.system_facts['virtualization_type'] -        virt_role = self.system_facts['virtualization_role'] +        product_name = self.system_facts['ansible_product_name'] +        product_version = self.system_facts['ansible_product_version'] +        virt_type = self.system_facts['ansible_virtualization_type'] +        virt_role = self.system_facts['ansible_virtualization_role']          provider = None          metadata = None @@ -2107,12 +2115,16 @@ def main():              additive_facts_to_overwrite=dict(default=[], type='list', required=False),              openshift_env=dict(default={}, type='dict', required=False),              openshift_env_structures=dict(default=[], type='list', required=False), -            protected_facts_to_overwrite=dict(default=[], type='list', required=False), +            protected_facts_to_overwrite=dict(default=[], type='list', required=False)          ),          supports_check_mode=True,          add_file_common_args=True,      ) +    module.params['gather_subset'] = ['hardware', 'network', 'virtual', 'facter'] +    module.params['gather_timeout'] = 10 +    module.params['filter'] = '*' +      role = module.params['role']      local_facts = module.params['local_facts']      additive_facts_to_overwrite = module.params['additive_facts_to_overwrite'] diff --git a/roles/openshift_hosted/meta/main.yml b/roles/openshift_hosted/meta/main.yml index c7d20f88b..74c50ae1d 100644 --- a/roles/openshift_hosted/meta/main.yml +++ b/roles/openshift_hosted/meta/main.yml @@ -11,27 +11,4 @@ galaxy_info:      - 7    categories:    - cloud -dependencies: -- role: openshift_cli -- role: openshift_hosted_facts -- role: openshift_projects -  # TODO: Move standard project definitions to openshift_hosted/vars/main.yml -  # Vars are not accessible in meta/main.yml in ansible-1.9.x -  openshift_projects: "{{ openshift_additional_projects | default({}) | oo_merge_dicts({'default':{'default_node_selector':''},'openshift-infra':{'default_node_selector':''},'logging':{'default_node_selector':''}}) }}" -- role: openshift_serviceaccounts -  openshift_serviceaccounts_names: -  - router -  openshift_serviceaccounts_namespace: default -  openshift_serviceaccounts_sccs: -  - hostnetwork -  when: openshift.common.version_gte_3_2_or_1_2 -- role: openshift_serviceaccounts -  openshift_serviceaccounts_names: -  - router -  - registry -  openshift_serviceaccounts_namespace: default -  openshift_serviceaccounts_sccs: -  - privileged -  when: not openshift.common.version_gte_3_2_or_1_2 -- role: openshift_metrics -  when: openshift.hosted.metrics.deploy | bool +dependencies: [] diff --git a/roles/openshift_hosted/tasks/main.yml b/roles/openshift_hosted/tasks/main.yml index c801a0e67..67c6bbfd7 100644 --- a/roles/openshift_hosted/tasks/main.yml +++ b/roles/openshift_hosted/tasks/main.yml @@ -13,7 +13,10 @@    changed_when: False  - include: router/router.yml +  when: openshift_hosted_manage_router | default(true) | bool +  - include: registry/registry.yml +  when: openshift_hosted_manage_registry | default(true) | bool  - name: Delete temp directory    file: diff --git a/roles/openshift_hosted/tasks/registry/registry.yml b/roles/openshift_hosted/tasks/registry/registry.yml index 08c7e944e..b28974236 100644 --- a/roles/openshift_hosted/tasks/registry/registry.yml +++ b/roles/openshift_hosted/tasks/registry/registry.yml @@ -4,12 +4,12 @@      {{ openshift.common.client_binary }} --api-version='v1' -o json      get nodes -n default --config={{ openshift_hosted_kubeconfig }}      --selector={{ openshift.hosted.registry.selector | default('') }} -  register: openshift_hosted_registry_nodes_json +  register: registry_nodes_json    changed_when: false    when: openshift.hosted.registry.replicas | default(none) is none  - set_fact: -    l_node_count: "{{ (openshift_hosted_registry_nodes_json.stdout | default('{\"items\":[]}') | from_json)['items'] | length }}" +    l_node_count: "{{ (registry_nodes_json.stdout | default('{\"items\":[]}') | from_json)['items'] | length }}"  # Determine the default number of registry/router replicas to use if no count  # has been specified. @@ -50,7 +50,9 @@    when: replicas | int > 0  - include: storage/object_storage.yml +  static: no    when: replicas | int > 0 and openshift.hosted.registry.storage.kind | default(none) == 'object'  - include: storage/persistent_volume.yml +  static: no    when: replicas | int > 0 and openshift.hosted.registry.storage.kind | default(none) in ['nfs', 'openstack'] diff --git a/roles/openshift_hosted/tasks/router/router.yml b/roles/openshift_hosted/tasks/router/router.yml index d0a129c95..e18b9781c 100644 --- a/roles/openshift_hosted/tasks/router/router.yml +++ b/roles/openshift_hosted/tasks/router/router.yml @@ -39,12 +39,12 @@      {{ openshift.common.client_binary }} --api-version='v1' -o json      get nodes -n default --config={{ openshift_hosted_kubeconfig }}      --selector={{ openshift.hosted.router.selector | default('') }} -  register: openshift_hosted_router_nodes_json +  register: router_nodes_json    changed_when: false    when: openshift.hosted.router.replicas | default(none) is none  - set_fact: -    replicas: "{{ openshift.hosted.router.replicas | default((openshift_hosted_router_nodes_json.stdout | default('{\"items\":[]}') | from_json)['items'] | length) }}" +    replicas: "{{ openshift.hosted.router.replicas | default((router_nodes_json.stdout | default('{\"items\":[]}') | from_json)['items'] | length) }}"  - name: Create OpenShift router    command: > diff --git a/roles/openshift_hosted/templates/registry_config.j2 b/roles/openshift_hosted/templates/registry_config.j2 index ea5626642..71539775d 100644 --- a/roles/openshift_hosted/templates/registry_config.j2 +++ b/roles/openshift_hosted/templates/registry_config.j2 @@ -58,6 +58,10 @@ auth:    openshift:      realm: openshift  middleware: +{% if openshift.common.version_gte_3_3_or_1_3 | bool %} +  registry: +  - name: openshift +{% endif -%}    repository:    - name: openshift      options: @@ -69,4 +73,7 @@ middleware:        baseurl: {{ openshift.hosted.registry.storage.s3.cloudfront.baseurl }}        privatekey: {{ openshift.hosted.registry.storage.s3.cloudfront.privatekeyfile }}        keypairid: {{ openshift.hosted.registry.storage.s3.cloudfront.keypairid }} +{% elif openshift.common.version_gte_3_3_or_1_3 | bool %} +  storage: +  - name: openshift  {% endif -%} diff --git a/roles/openshift_master/handlers/main.yml b/roles/openshift_master/handlers/main.yml index f7dfb11f7..edb7369de 100644 --- a/roles/openshift_master/handlers/main.yml +++ b/roles/openshift_master/handlers/main.yml @@ -17,7 +17,12 @@    # Using curl here since the uri module requires python-httplib2 and    # wait_for port doesn't provide health information.    command: > -    curl --silent --cacert {{ openshift.common.config_base }}/master/ca.crt +    curl --silent +    {% if openshift.common.version_gte_3_2_or_1_2 | bool %} +    --cacert {{ openshift.common.config_base }}/master/ca-bundle.crt +    {% else %} +    --cacert {{ openshift.common.config_base }}/master/ca.crt +    {% endif %}      {{ openshift.master.api_url }}/healthz/ready    register: api_available_output    until: api_available_output.stdout == 'ok' diff --git a/roles/openshift_master/meta/main.yml b/roles/openshift_master/meta/main.yml index be70d9102..a2f665702 100644 --- a/roles/openshift_master/meta/main.yml +++ b/roles/openshift_master/meta/main.yml @@ -11,32 +11,4 @@ galaxy_info:      - 7    categories:    - cloud -dependencies: -- role: openshift_clock -- role: openshift_master_certificates -- role: openshift_cloud_provider -- role: openshift_builddefaults -- role: openshift_master_facts -- role: openshift_hosted_facts -- role: os_firewall -  os_firewall_allow: -  - service: etcd embedded -    port: 4001/tcp -  - service: api server https -    port: "{{ openshift.master.api_port }}/tcp" -  - service: api controllers https -    port: "{{ openshift.master.controllers_port }}/tcp" -  - service: skydns tcp -    port: "{{ openshift.master.dns_port }}/tcp" -  - service: skydns udp -    port: "{{ openshift.master.dns_port }}/udp" -  - service: Fluentd td-agent tcp -    port: 24224/tcp -  - service: Fluentd td-agent udp -    port: 24224/udp -  - service: pcsd -    port: 2224/tcp -  - service: Corosync UDP -    port: 5404/udp -  - service: Corosync UDP -    port: 5405/udp +dependencies: [] diff --git a/roles/openshift_master/tasks/main.yml b/roles/openshift_master/tasks/main.yml index 115a64aeb..6259fd996 100644 --- a/roles/openshift_master/tasks/main.yml +++ b/roles/openshift_master/tasks/main.yml @@ -224,7 +224,12 @@    # Using curl here since the uri module requires python-httplib2 and    # wait_for port doesn't provide health information.    command: > -    curl --silent --cacert {{ openshift.common.config_base }}/master/ca.crt +    curl --silent +    {% if openshift.common.version_gte_3_2_or_1_2 | bool %} +    --cacert {{ openshift.common.config_base }}/master/ca-bundle.crt +    {% else %} +    --cacert {{ openshift.common.config_base }}/master/ca.crt +    {% endif %}      {{ openshift.master.api_url }}/healthz/ready    register: api_available_output    until: api_available_output.stdout == 'ok' @@ -272,37 +277,3 @@  - name: Set the cluster user password    shell: echo {{ openshift_master_cluster_password | quote }} | passwd --stdin hacluster    when: install_result | changed - -- name: Lookup default group for ansible_ssh_user -  command: "/usr/bin/id -g {{ ansible_ssh_user }}" -  changed_when: false -  register: _ansible_ssh_user_gid - -- set_fact: -    client_users: "{{ [ansible_ssh_user, 'root'] | unique }}" - -- name: Create the client config dir(s) -  file: -    path: "~{{ item }}/.kube" -    state: directory -    mode: 0700 -    owner: "{{ item }}" -    group: "{{ 'root' if item == 'root' else _ansible_ssh_user_gid.stdout  }}" -  with_items: "{{ client_users }}" - -# TODO: Update this file if the contents of the source file are not present in -# the dest file, will need to make sure to ignore things that could be added -- name: Copy the admin client config(s) -  command: cp {{ openshift_master_config_dir }}/admin.kubeconfig ~{{ item }}/.kube/config -  args: -    creates: ~{{ item }}/.kube/config -  with_items: "{{ client_users }}" - -- name: Update the permissions on the admin client config(s) -  file: -    path: "~{{ item }}/.kube/config" -    state: file -    mode: 0700 -    owner: "{{ item }}" -    group: "{{ 'root' if item == 'root' else _ansible_ssh_user_gid.stdout  }}" -  with_items: "{{ client_users }}" diff --git a/roles/openshift_master/tasks/systemd_units.yml b/roles/openshift_master/tasks/systemd_units.yml index 458b56fd1..0c0c7e61e 100644 --- a/roles/openshift_master/tasks/systemd_units.yml +++ b/roles/openshift_master/tasks/systemd_units.yml @@ -16,7 +16,7 @@  # workaround for missing systemd unit files  - name: Create the systemd unit files    template: -    src: "docker/master.docker.service.j2" +    src: "master_docker/master.docker.service.j2"      dest: "{{ containerized_svc_dir }}/{{ openshift.common.service_type }}-master.service"    when: openshift.common.is_containerized | bool and (openshift.master.ha is not defined or not openshift.master.ha | bool)    register: create_master_unit_file @@ -84,12 +84,12 @@      line: "{{ item }}"    with_items: "{{ master_controllers_proxy.stdout_lines | default([]) }}"    when: openshift.master.ha is defined and openshift.master.ha | bool and openshift_master_cluster_method == "native" -        and master_controllers_proxy.rc == 0 and 'http_proxy' not in openshift.common and 'https_proxy' not in openshift.common  +        and master_controllers_proxy.rc == 0 and 'http_proxy' not in openshift.common and 'https_proxy' not in openshift.common  - name: Install Master docker service file    template:      dest: "/etc/systemd/system/{{ openshift.common.service_type }}-master.service" -    src: docker/master.docker.service.j2 +    src: master_docker/master.docker.service.j2    register: install_result    when: openshift.common.is_containerized | bool and openshift.master.ha is defined and not openshift.master.ha | bool @@ -112,4 +112,4 @@      dest: /etc/sysconfig/{{ openshift.common.service_type }}-master      line: "{{ item }}"    with_items: "{{ master_proxy.stdout_lines | default([]) }}" -  when: master_proxy.rc == 0 and 'http_proxy' not in openshift.common and 'https_proxy' not in openshift.common
\ No newline at end of file +  when: master_proxy.rc == 0 and 'http_proxy' not in openshift.common and 'https_proxy' not in openshift.common diff --git a/roles/openshift_master/templates/master.yaml.v1.j2 b/roles/openshift_master/templates/master.yaml.v1.j2 index b18a42e32..31e86f5bd 100644 --- a/roles/openshift_master/templates/master.yaml.v1.j2 +++ b/roles/openshift_master/templates/master.yaml.v1.j2 @@ -131,7 +131,21 @@ kubernetesMasterConfig:  {% endif %}  masterClients:  {# TODO: allow user to set externalKubernetesKubeConfig #} +{% if openshift.common.version_gte_3_3_or_1_3 | bool %} +  externalKubernetesClientConnectionOverrides: +    acceptContentTypes: application/vnd.kubernetes.protobuf,application/json +    contentType: application/vnd.kubernetes.protobuf +    burst: 400 +    qps: 200 +{% endif %}    externalKubernetesKubeConfig: "" +{% if openshift.common.version_gte_3_3_or_1_3 | bool %} +  openshiftLoopbackClientConnectionOverrides: +    acceptContentTypes: application/vnd.kubernetes.protobuf,application/json +    contentType: application/vnd.kubernetes.protobuf +    burst: 600 +    qps: 300 +{% endif %}    openshiftLoopbackKubeConfig: openshift-master.kubeconfig  masterPublicURL: {{ openshift.master.public_api_url }}  networkConfig: @@ -156,7 +170,11 @@ oauthConfig:  {% for line in translated_identity_providers.splitlines() %}    {{ line }}  {% endfor %} -  masterCA: ca.crt +{% if openshift.common.version_gte_3_2_or_1_2 | bool %} +  masterCA: ca-bundle.crt +{% else %} +  masterCA: ca.rt +{% endif %}    masterPublicURL: {{ openshift.master.public_api_url }}    masterURL: {{ openshift.master.api_url }}    sessionConfig: @@ -189,7 +207,11 @@ serviceAccountConfig:    - default    - builder    - deployer -  masterCA: ca.crt +{% if openshift.common.version_gte_3_2_or_1_2 | bool %} +  masterCA: ca-bundle.crt +{% else %} +  masterCA: ca.rt +{% endif %}    privateKeyFile: serviceaccounts.private.key    publicKeyFiles:    - serviceaccounts.public.key @@ -201,7 +223,7 @@ servingInfo:    keyFile: master.server.key    maxRequestsInFlight: {{ openshift.master.max_requests_inflight }}    requestTimeoutSeconds: 3600 -{% if openshift.master.named_certificates %} +{% if openshift.master.named_certificates | default([]) | length > 0 %}    namedCertificates:  {% for named_certificate in openshift.master.named_certificates %}    - certFile: {{ named_certificate['certfile'] }} diff --git a/roles/openshift_master/templates/docker/master.docker.service.j2 b/roles/openshift_master/templates/master_docker/master.docker.service.j2 index 97f698b68..97f698b68 100644 --- a/roles/openshift_master/templates/docker/master.docker.service.j2 +++ b/roles/openshift_master/templates/master_docker/master.docker.service.j2 diff --git a/roles/openshift_master_certificates/meta/main.yml b/roles/openshift_master_certificates/meta/main.yml index dd19c8ded..018186e86 100644 --- a/roles/openshift_master_certificates/meta/main.yml +++ b/roles/openshift_master_certificates/meta/main.yml @@ -13,4 +13,5 @@ galaxy_info:    - cloud    - system  dependencies: +- role: openshift_master_facts  - role: openshift_ca diff --git a/roles/openshift_master_certificates/tasks/main.yml b/roles/openshift_master_certificates/tasks/main.yml index 6fb5830cf..aafb06f93 100644 --- a/roles/openshift_master_certificates/tasks/main.yml +++ b/roles/openshift_master_certificates/tasks/main.yml @@ -21,18 +21,22 @@    with_items:    - "{{ openshift_master_certs }}"    register: g_master_cert_stat_result +  when: not openshift_certificates_redeploy | default(false) | bool  - set_fact: -    master_certs_missing: "{{ False in (g_master_cert_stat_result.results -                              | oo_collect(attribute='stat.exists') -                              | list) }}" +    master_certs_missing: "{{ true if openshift_certificates_redeploy | default(false) | bool +                              else (False in (g_master_cert_stat_result.results +                                              | default({}) +                                              | oo_collect(attribute='stat.exists') +                                              | list)) }}" +  - name: Ensure the generated_configs directory present    file:      path: "{{ openshift_master_generated_config_dir }}"      state: directory      mode: 0700 -  when: master_certs_missing | bool +  when: master_certs_missing | bool and inventory_hostname != openshift_ca_host    delegate_to: "{{ openshift_ca_host }}"  - file: @@ -43,18 +47,21 @@    - ca.crt    - ca.key    - ca.serial.txt -  when: master_certs_missing | bool +  when: master_certs_missing | bool and inventory_hostname != openshift_ca_host    delegate_to: "{{ openshift_ca_host }}"  - name: Create the master certificates if they do not already exist    command: >      {{ openshift.common.admin_binary }} create-master-certs -      --hostnames={{ openshift.common.all_hostnames | join(',') }} -      --master={{ openshift.master.api_url }} -      --public-master={{ openshift.master.public_api_url }} -      --cert-dir={{ openshift_master_generated_config_dir }} -      --overwrite=false -  when: master_certs_missing | bool +    {% for named_ca_certificate in openshift.master.named_certificates | default([]) | oo_collect('cafile') %} +    --certificate-authority {{ named_ca_certificate }} +    {% endfor %} +    --hostnames={{ openshift.common.all_hostnames | join(',') }} +    --master={{ openshift.master.api_url }} +    --public-master={{ openshift.master.public_api_url }} +    --cert-dir={{ openshift_master_generated_config_dir }} +    --overwrite=false +  when: master_certs_missing | bool and inventory_hostname != openshift_ca_host    delegate_to: "{{ openshift_ca_host }}"  - file: @@ -64,7 +71,7 @@      force: true    with_items:    - "{{ hostvars[inventory_hostname] | certificates_to_synchronize }}" -  when: master_certs_missing | bool +  when: master_certs_missing | bool and inventory_hostname != openshift_ca_host    delegate_to: "{{ openshift_ca_host }}"  - name: Remove generated etcd client certs when using external etcd @@ -121,3 +128,39 @@    when: master_certs_missing | bool    delegate_to: localhost    become: no + +- name: Lookup default group for ansible_ssh_user +  command: "/usr/bin/id -g {{ ansible_ssh_user }}" +  changed_when: false +  register: _ansible_ssh_user_gid + +- set_fact: +    client_users: "{{ [ansible_ssh_user, 'root'] | unique }}" + +- name: Create the client config dir(s) +  file: +    path: "~{{ item }}/.kube" +    state: directory +    mode: 0700 +    owner: "{{ item }}" +    group: "{{ 'root' if item == 'root' else _ansible_ssh_user_gid.stdout  }}" +  with_items: "{{ client_users }}" + +# TODO: Update this file if the contents of the source file are not present in +# the dest file, will need to make sure to ignore things that could be added +- name: Copy the admin client config(s) +  copy: +    src: "{{ openshift_master_config_dir }}/admin.kubeconfig" +    dest: "~{{ item }}/.kube/config" +    remote_src: yes +    force: "{{ openshift_certificates_redeploy | default(false) }}" +  with_items: "{{ client_users }}" + +- name: Update the permissions on the admin client config(s) +  file: +    path: "~{{ item }}/.kube/config" +    state: file +    mode: 0700 +    owner: "{{ item }}" +    group: "{{ 'root' if item == 'root' else _ansible_ssh_user_gid.stdout  }}" +  with_items: "{{ client_users }}" diff --git a/roles/openshift_named_certificates/README.md b/roles/openshift_named_certificates/README.md new file mode 100644 index 000000000..41f895813 --- /dev/null +++ b/roles/openshift_named_certificates/README.md @@ -0,0 +1,32 @@ +OpenShift Named Certificates +============================ + +TODO + +Requirements +------------ + +Role Variables +-------------- + +TODO + +Dependencies +------------ + +TODO + +Example Playbook +---------------- + +TODO + +License +------- + +Apache License Version 2.0 + +Author Information +------------------ + +Andrew Butcher <abutcher@redhat.com> diff --git a/roles/openshift_etcd_certificates/meta/main.yml b/roles/openshift_named_certificates/meta/main.yml index 2725fdb51..2c6e12494 100644 --- a/roles/openshift_etcd_certificates/meta/main.yml +++ b/roles/openshift_named_certificates/meta/main.yml @@ -1,16 +1,16 @@  ---  galaxy_info:    author: Andrew Butcher -  description: OpenShift etcd Certificates +  description: OpenShift Named Certificates    company: Red Hat, Inc.    license: Apache License, Version 2.0 -  min_ansible_version: 1.9 +  min_ansible_version: 2.1    platforms:    - name: EL      versions:      - 7    categories:    - cloud +  - system  dependencies: -- role: openshift_etcd_facts -- role: etcd_certificates +- role: openshift_facts diff --git a/roles/openshift_named_certificates/tasks/main.yml b/roles/openshift_named_certificates/tasks/main.yml new file mode 100644 index 000000000..7f20cf401 --- /dev/null +++ b/roles/openshift_named_certificates/tasks/main.yml @@ -0,0 +1,46 @@ +--- +- set_fact: +    parsed_named_certificates: "{{ named_certificates | oo_parse_named_certificates(named_certs_dir, internal_hostnames) }}" +  when: named_certificates | length > 0 +  delegate_to: localhost +  become: no +  run_once: true + +- openshift_facts: +    role: master +    local_facts: +      named_certificates: "{{ parsed_named_certificates | default([]) }}" +    additive_facts_to_overwrite: +    - "{{ 'master.named_certificates' if overwrite_named_certs | bool else omit }}" + +- name: Clear named certificates +  file: +    path: "{{ named_certs_dir }}" +    state: absent +  when: overwrite_named_certs | bool + +- name: Ensure named certificate directory exists +  file: +    path: "{{ named_certs_dir }}" +    state: directory +    mode: 0700 + +- name: Land named certificates +  copy: +    src: "{{ item.certfile }}" +    dest: "{{ named_certs_dir }}" +  with_items: "{{ named_certificates }}" + +- name: Land named certificate keys +  copy: +    src: "{{ item.keyfile }}" +    dest: "{{ named_certs_dir }}" +    mode: 0600 +  with_items: "{{ named_certificates }}" + +- name: Land named CA certificates +  copy: +    src: "{{ item }}" +    dest: "{{ named_certs_dir }}" +    mode: 0600 +  with_items: "{{ named_certificates | oo_collect('cafile') }}" diff --git a/roles/openshift_named_certificates/tasks/named_certificates.yml b/roles/openshift_named_certificates/tasks/named_certificates.yml new file mode 100644 index 000000000..7b097b443 --- /dev/null +++ b/roles/openshift_named_certificates/tasks/named_certificates.yml @@ -0,0 +1,32 @@ +--- +- name: Clear named certificates +  file: +    path: "{{ named_certs_dir }}" +    state: absent +  when: overwrite_named_certs | bool + +- name: Ensure named certificate directory exists +  file: +    path: "{{ named_certs_dir }}" +    state: directory +    mode: 0700 + +- name: Land named certificates +  copy: +    src: "{{ item.certfile }}" +    dest: "{{ named_certs_dir }}" +  with_items: "{{ openshift_master_named_certificates | default([]) }}" + +- name: Land named certificate keys +  copy: +    src: "{{ item.keyfile }}" +    dest: "{{ named_certs_dir }}" +    mode: 0600 +  with_items: "{{ openshift_master_named_certificates | default([]) }}" + +- name: Land named CA certificates +  copy: +    src: "{{ item }}" +    dest: "{{ named_certs_dir }}" +    mode: 0600 +  with_items: "{{ openshift_master_named_certificates | default([]) | oo_collect('cafile') }}" diff --git a/roles/openshift_named_certificates/vars/main.yml b/roles/openshift_named_certificates/vars/main.yml new file mode 100644 index 000000000..368e9bdac --- /dev/null +++ b/roles/openshift_named_certificates/vars/main.yml @@ -0,0 +1,11 @@ +--- +openshift_ca_config_dir: "{{ openshift.common.config_base }}/master" +openshift_ca_cert: "{{ openshift_ca_config_dir }}/ca.crt" +openshift_ca_key: "{{ openshift_ca_config_dir }}/ca.key" +openshift_ca_serial: "{{ openshift_ca_config_dir }}/ca.serial.txt" +openshift_version: "{{ openshift_pkg_version | default('') }}" + +overwrite_named_certs: "{{ openshift_master_overwrite_named_certificates | default(false) }}" +named_certs_dir: "{{ openshift.common.config_base }}/master/named_certificates/" +internal_hostnames: "{{ openshift.common.internal_hostnames }}" +named_certificates: "{{ openshift_master_named_certificates | default([]) }}" diff --git a/roles/openshift_node/meta/main.yml b/roles/openshift_node/meta/main.yml index fd493340b..c39269f33 100644 --- a/roles/openshift_node/meta/main.yml +++ b/roles/openshift_node/meta/main.yml @@ -11,26 +11,4 @@ galaxy_info:      - 7    categories:    - cloud -dependencies: -- role: openshift_clock -- role: openshift_docker -- role: openshift_node_certificates -- role: openshift_cloud_provider -- role: openshift_common -- role: openshift_node_dnsmasq -  when: openshift.common.use_dnsmasq -- role: os_firewall -  os_firewall_allow: -  - service: Kubernetes kubelet -    port: 10250/tcp -  - service: http -    port: 80/tcp -  - service: https -    port: 443/tcp -  - service: Openshift kubelet ReadOnlyPort -    port: 10255/tcp -  - service: Openshift kubelet ReadOnlyPort udp -    port: 10255/udp -  - service: OpenShift OVS sdn -    port: 4789/udp -    when: openshift.node.use_openshift_sdn | bool +dependencies: [] diff --git a/roles/openshift_node/tasks/main.yml b/roles/openshift_node/tasks/main.yml index 889541e25..9c71af6d9 100644 --- a/roles/openshift_node/tasks/main.yml +++ b/roles/openshift_node/tasks/main.yml @@ -106,8 +106,20 @@    notify:    - restart node -- name: Additional storage plugin configuration -  include: storage_plugins/main.yml +- name: NFS storage plugin configuration +  include: storage_plugins/nfs.yml + +- name: GlusterFS storage plugin configuration +  include: storage_plugins/glusterfs.yml +  when: "'glusterfs' in openshift.node.storage_plugin_deps" + +- name: Ceph storage plugin configuration +  include: storage_plugins/ceph.yml +  when: "'ceph' in openshift.node.storage_plugin_deps" + +- name: iSCSI storage plugin configuration +  include: storage_plugins/iscsi.yml +  when: "'iscsi' in openshift.node.storage_plugin_deps"  # Necessary because when you're on a node that's also a master the master will be  # restarted after the node restarts docker and it will take up to 60 seconds for diff --git a/roles/openshift_node/tasks/storage_plugins/main.yml b/roles/openshift_node/tasks/storage_plugins/main.yml deleted file mode 100644 index fe638718d..000000000 --- a/roles/openshift_node/tasks/storage_plugins/main.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -# The NFS storage plugin is always enabled since it doesn't require any -# additional package dependencies -- name: NFS storage plugin configuration -  include: nfs.yml - -- name: GlusterFS storage plugin configuration -  include: glusterfs.yml -  when: "'glusterfs' in openshift.node.storage_plugin_deps" - -- name: Ceph storage plugin configuration -  include: ceph.yml -  when: "'ceph' in openshift.node.storage_plugin_deps" - -- name: iSCSI storage plugin configuration -  include: iscsi.yml -  when: "'iscsi' in openshift.node.storage_plugin_deps" diff --git a/roles/openshift_node/templates/node.yaml.v1.j2 b/roles/openshift_node/templates/node.yaml.v1.j2 index a37770c4a..414f0d5e3 100644 --- a/roles/openshift_node/templates/node.yaml.v1.j2 +++ b/roles/openshift_node/templates/node.yaml.v1.j2 @@ -12,15 +12,22 @@ imageConfig:    latest: false  kind: NodeConfig  kubeletArguments: {{ openshift.node.kubelet_args | default(None) | to_padded_yaml(level=1) }} +{% if openshift.common.version_gte_3_3_or_1_3 | bool %} +masterClientConnectionOverrides: +  acceptContentTypes: application/vnd.kubernetes.protobuf,application/json +  contentType: application/vnd.kubernetes.protobuf +  burst: 200 +  qps: 100 +{% endif %}  masterKubeConfig: system:node:{{ openshift.common.hostname }}.kubeconfig -{% if openshift.common.use_openshift_sdn %} +{% if openshift.common.use_openshift_sdn | bool and not openshift.common.version_gte_3_3_or_1_3 | bool %}  networkPluginName: {{ openshift.common.sdn_network_plugin_name }}  {% endif %}  # networkConfig struct introduced in origin 1.0.6 and OSE 3.0.2 which  # deprecates networkPluginName above. The two should match.  networkConfig:     mtu: {{ openshift.node.sdn_mtu }} -{% if openshift.common.use_openshift_sdn or openshift.common.use_nuage %} +{% if ( openshift.common.use_openshift_sdn | bool or openshift.common.use_nuage | bool ) and not openshift.common.version_gte_3_3_or_1_3 | bool%}     networkPluginName: {{ openshift.common.sdn_network_plugin_name }}  {% endif %}  {% if openshift.node.set_node_ip | bool %} diff --git a/roles/openshift_node_certificates/tasks/main.yml b/roles/openshift_node_certificates/tasks/main.yml index 0e69dc6f0..fef7caab8 100644 --- a/roles/openshift_node_certificates/tasks/main.yml +++ b/roles/openshift_node_certificates/tasks/main.yml @@ -25,11 +25,14 @@    - server.key    - server.crt    register: g_node_cert_stat_result +  when: not openshift_certificates_redeploy | default(false) | bool  - set_fact: -    node_certs_missing: "{{ False in (g_node_cert_stat_result.results -                            | oo_collect(attribute='stat.exists') -                            | list) }}" +    node_certs_missing: "{{ true if openshift_certificates_redeploy | default(false) | bool +                            else (False in (g_node_cert_stat_result.results +                                            | default({}) +                                            | oo_collect(attribute='stat.exists') +                                            | list)) }}"  - name: Create openshift_generated_configs_dir if it does not exist    file: @@ -42,6 +45,9 @@  - name: Generate the node client config    command: >      {{ openshift.common.admin_binary }} create-api-client-config +      {% for named_ca_certificate in hostvars[openshift_ca_host].openshift.master.named_certificates | default([]) | oo_collect('cafile') %} +      --certificate-authority {{ named_ca_certificate }} +      {% endfor %}        --certificate-authority={{ openshift_ca_cert }}        --client-dir={{ openshift_node_generated_config_dir }}        --groups=system:nodes diff --git a/roles/openshift_repos/files/fedora-openshift-enterprise/gpg_keys/.gitkeep b/roles/openshift_repos/files/fedora-openshift-enterprise/gpg_keys/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/roles/openshift_repos/files/fedora-openshift-enterprise/gpg_keys/.gitkeep diff --git a/roles/openshift_repos/files/fedora-openshift-enterprise/repos/.gitkeep b/roles/openshift_repos/files/fedora-openshift-enterprise/repos/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/roles/openshift_repos/files/fedora-openshift-enterprise/repos/.gitkeep diff --git a/roles/openshift_repos/files/openshift-enterprise/gpg_keys/.gitkeep b/roles/openshift_repos/files/openshift-enterprise/gpg_keys/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/roles/openshift_repos/files/openshift-enterprise/gpg_keys/.gitkeep diff --git a/roles/openshift_repos/files/openshift-enterprise/repos/.gitkeep b/roles/openshift_repos/files/openshift-enterprise/repos/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/roles/openshift_repos/files/openshift-enterprise/repos/.gitkeep diff --git a/roles/openshift_repos/tasks/main.yaml b/roles/openshift_repos/tasks/main.yaml index d8e43438a..07a8d28fd 100644 --- a/roles/openshift_repos/tasks/main.yaml +++ b/roles/openshift_repos/tasks/main.yaml @@ -34,7 +34,12 @@      path: "/etc/yum.repos.d/{{ item | basename }}"      state: absent    with_fileglob: -  - '*/repos/*' +  - "fedora-openshift-enterprise/repos/*" +  - "fedora-origin/repos/*" +  - "online/repos/*" +  - "openshift-enterprise/repos/*" +  - "origin/repos/*" +  - "removed/repos/*"    when: not openshift.common.is_containerized | bool          and not (item | search("/files/" ~ openshift_deployment_type ~ "/repos"))          and (ansible_os_family == "RedHat" and ansible_distribution != "Fedora") @@ -42,10 +47,15 @@  - name: Remove any yum repo files for other deployment types Fedora    file: -    path: "/etc/yum.repos.d/{{ item | basename }}" +    path: "{{ item | basename }}"      state: absent    with_fileglob: -  - '*/repos/*' +  - "fedora-openshift-enterprise/repos/*" +  - "fedora-origin/repos/*" +  - "online/repos/*" +  - "openshift-enterprise/repos/*" +  - "origin/repos/*" +  - "removed/repos/*"    when: not openshift.common.is_containerized | bool          and not (item | search("/files/fedora-" ~ openshift_deployment_type ~ "/repos"))          and (ansible_distribution == "Fedora")  | 
