diff options
27 files changed, 500 insertions, 337 deletions
diff --git a/playbooks/common/openshift-cluster/upgrades/v3_1_to_v3_2/pre.yml b/playbooks/common/openshift-cluster/upgrades/v3_1_to_v3_2/pre.yml index a27b62971..a32123952 100644 --- a/playbooks/common/openshift-cluster/upgrades/v3_1_to_v3_2/pre.yml +++ b/playbooks/common/openshift-cluster/upgrades/v3_1_to_v3_2/pre.yml @@ -163,6 +163,8 @@ - name: Verify containers are available for upgrade command: > docker pull {{ openshift.common.cli_image }}:{{ openshift_image_tag }} + register: pull_result + changed_when: "'Downloaded newer image' in pull_result.stdout" when: openshift.common.is_containerized | bool - name: Check latest available OpenShift RPM version diff --git a/playbooks/common/openshift-master/config.yml b/playbooks/common/openshift-master/config.yml index bb8fb77b6..911c23d70 100644 --- a/playbooks/common/openshift-master/config.yml +++ b/playbooks/common/openshift-master/config.yml @@ -156,79 +156,6 @@ - master.etcd-ca.crt when: etcd_client_certs_missing is defined and etcd_client_certs_missing -- name: Determine if master certificates need to be generated - hosts: oo_first_master:oo_masters_to_config - tasks: - - set_fact: - openshift_master_certs_no_etcd: - - admin.crt - - master.kubelet-client.crt - - "{{ 'master.proxy-client.crt' if openshift.common.version_gte_3_1_or_1_1 else omit }}" - - master.server.crt - - openshift-master.crt - - openshift-registry.crt - - openshift-router.crt - - etcd.server.crt - openshift_master_certs_etcd: - - master.etcd-client.crt - - - set_fact: - openshift_master_certs: "{{ (openshift_master_certs_no_etcd | union(openshift_master_certs_etcd)) if (groups.oo_etcd_to_config is defined and groups.oo_etcd_to_config) else openshift_master_certs_no_etcd }}" - - - name: Check status of master certificates - stat: - path: "{{ openshift.common.config_base }}/master/{{ item }}" - with_items: "{{ openshift_master_certs }}" - register: g_master_cert_stat_result - - set_fact: - master_certs_missing: "{{ False in (g_master_cert_stat_result.results - | oo_collect(attribute='stat.exists') - | list ) }}" - master_cert_subdir: master-{{ openshift.common.hostname }} - master_cert_config_dir: "{{ openshift.common.config_base }}/master" - -- name: Configure master certificates - hosts: oo_first_master - vars: - master_generated_certs_dir: "{{ openshift.common.config_base }}/generated-configs" - masters_needing_certs: "{{ hostvars - | oo_select_keys(groups['oo_masters_to_config'] | difference(groups['oo_first_master'])) - | oo_filter_list(filter_attr='master_certs_missing') }}" - master_hostnames: "{{ hostvars - | oo_select_keys(groups['oo_masters_to_config']) - | oo_collect('openshift.common.all_hostnames') - | oo_flatten | unique }}" - sync_tmpdir: "{{ hostvars.localhost.g_master_mktemp.stdout }}" - roles: - - openshift_master_certificates - post_tasks: - - name: Remove generated etcd client certs when using external etcd - file: - path: "{{ master_generated_certs_dir }}/{{ item.0.master_cert_subdir }}/{{ item.1 }}" - state: absent - when: groups.oo_etcd_to_config is defined and groups.oo_etcd_to_config - with_nested: - - "{{ masters_needing_certs | default([]) }}" - - - master.etcd-client.crt - - master.etcd-client.key - - - name: Create a tarball of the master certs - command: > - tar -czvf {{ master_generated_certs_dir }}/{{ item.master_cert_subdir }}.tgz - -C {{ master_generated_certs_dir }}/{{ item.master_cert_subdir }} . - args: - creates: "{{ master_generated_certs_dir }}/{{ item.master_cert_subdir }}.tgz" - with_items: "{{ masters_needing_certs | default([]) }}" - - - name: Retrieve the master cert tarball from the master - fetch: - src: "{{ master_generated_certs_dir }}/{{ item.master_cert_subdir }}.tgz" - dest: "{{ sync_tmpdir }}/" - flat: yes - fail_on_missing: yes - validate_checksum: yes - with_items: "{{ masters_needing_certs | default([]) }}" - - name: Check for cached session secrets hosts: oo_first_master roles: @@ -243,7 +170,7 @@ - name: Generate master session secrets hosts: oo_first_master vars: - g_session_secrets_present: "{{ (openshift.master.session_auth_secrets | default([]) and openshift.master.session_encryption_secrets | default([])) | length > 0 }}" + g_session_secrets_present: "{{ (openshift.master.session_auth_secrets | default([])) | length > 0 and (openshift.master.session_encryption_secrets | default([])) | length > 0 }}" g_session_auth_secrets: "{{ [ 24 | oo_generate_secret ] }}" g_session_encryption_secrets: "{{ [ 24 | oo_generate_secret ] }}" roles: @@ -263,7 +190,7 @@ vars: internal_hostnames: "{{ hostvars[groups.oo_first_master.0].openshift.common.internal_hostnames }}" named_certificates: "{{ hostvars[groups.oo_first_master.0].openshift_master_named_certificates | default([]) }}" - named_certificates_dir: "{{ hostvars[groups.oo_first_master.0].master_cert_config_dir }}/named_certificates/" + named_certificates_dir: "{{ hostvars[groups.oo_first_master.0].openshift.common.config_base }}/master/named_certificates/" tasks: - set_fact: parsed_named_certificates: "{{ named_certificates | oo_parse_named_certificates(named_certificates_dir, internal_hostnames) }}" @@ -307,7 +234,6 @@ - name: Configure masters hosts: oo_masters_to_config any_errors_fatal: true - serial: 1 vars: sync_tmpdir: "{{ hostvars.localhost.g_master_mktemp.stdout }}" openshift_master_ha: "{{ openshift.master.ha }}" @@ -321,19 +247,17 @@ }}" when: "{{ (openshift_http_proxy is defined or openshift_https_proxy is defined) and openshift_generate_no_proxy_hosts | default(True) | bool }}" - pre_tasks: - - name: Ensure certificate directory exists - file: - path: "{{ openshift.common.config_base }}/master" - state: directory - when: master_certs_missing | bool and 'oo_first_master' not in group_names - - name: Unarchive the tarball on the master - unarchive: - src: "{{ sync_tmpdir }}/{{ master_cert_subdir }}.tgz" - dest: "{{ master_cert_config_dir }}" - when: master_certs_missing | bool and 'oo_first_master' not in group_names roles: - - openshift_master + - role: openshift_master + openshift_ca_host: "{{ groups.oo_first_master.0 }}" + openshift_master_etcd_hosts: "{{ hostvars + | oo_select_keys(groups['oo_etcd_to_config'] | default([])) + | oo_collect('openshift.common.hostname') + | default(none, true) }}" + openshift_master_hostnames: "{{ hostvars + | oo_select_keys(groups['oo_masters_to_config'] | default([])) + | oo_collect('openshift.common.all_hostnames') + | oo_flatten | unique }}" - role: nickhammond.logrotate - role: nuage_master when: openshift.common.use_nuage | bool diff --git a/playbooks/common/openshift-node/config.yml b/playbooks/common/openshift-node/config.yml index 80659dc52..a8c49d37b 100644 --- a/playbooks/common/openshift-node/config.yml +++ b/playbooks/common/openshift-node/config.yml @@ -19,23 +19,6 @@ labels: "{{ openshift_node_labels | default(None) }}" annotations: "{{ openshift_node_annotations | default(None) }}" schedulable: "{{ openshift_schedulable | default(openshift_scheduleable) | default(None) }}" - - name: Check status of node certificates - stat: - path: "{{ openshift.common.config_base }}/node/{{ item }}" - with_items: - - "system:node:{{ openshift.common.hostname }}.crt" - - "system:node:{{ openshift.common.hostname }}.key" - - "system:node:{{ openshift.common.hostname }}.kubeconfig" - - ca.crt - - server.key - - server.crt - register: stat_result - - set_fact: - certs_missing: "{{ stat_result.results | oo_collect(attribute='stat.exists') - | list | intersect([false])}}" - node_subdir: node-{{ openshift.common.hostname }} - config_dir: "{{ openshift.common.config_base }}/generated-configs/node-{{ openshift.common.hostname }}" - node_cert_dir: "{{ openshift.common.config_base }}/node" - name: Create temp directory for syncing certs hosts: localhost @@ -48,53 +31,6 @@ register: mktemp changed_when: False -- name: Create node certificates - hosts: oo_first_master - vars: - nodes_needing_certs: "{{ hostvars - | oo_select_keys(groups['oo_nodes_to_config'] - | default([])) - | oo_filter_list(filter_attr='certs_missing') }}" - sync_tmpdir: "{{ hostvars.localhost.mktemp.stdout }}" - roles: - - openshift_node_certificates - post_tasks: - - name: Create a tarball of the node config directories - command: > - tar -czvf {{ item.config_dir }}.tgz - --transform 's|system:{{ item.node_subdir }}|node|' - -C {{ item.config_dir }} . - args: - creates: "{{ item.config_dir }}.tgz" - with_items: "{{ nodes_needing_certs | default([]) }}" - - - name: Retrieve the node config tarballs from the master - fetch: - src: "{{ item.config_dir }}.tgz" - dest: "{{ sync_tmpdir }}/" - flat: yes - fail_on_missing: yes - validate_checksum: yes - with_items: "{{ nodes_needing_certs | default([]) }}" - -- name: Deploy node certificates - hosts: oo_nodes_to_config - vars: - sync_tmpdir: "{{ hostvars.localhost.mktemp.stdout }}" - tasks: - - name: Ensure certificate directory exists - file: - path: "{{ node_cert_dir }}" - state: directory - # TODO: notify restart node - # possibly test service started time against certificate/config file - # timestamps in node to trigger notify - - name: Unarchive the tarball on the node - unarchive: - src: "{{ sync_tmpdir }}/{{ node_subdir }}.tgz" - dest: "{{ node_cert_dir }}" - when: certs_missing - - name: Evaluate node groups hosts: localhost become: no @@ -124,7 +60,8 @@ when: "{{ (openshift_http_proxy is defined or openshift_https_proxy is defined) and openshift_generate_no_proxy_hosts | default(True) | bool }}" roles: - - openshift_node + - role: openshift_node + openshift_ca_host: "{{ groups.oo_first_master.0 }}" - name: Configure node instances hosts: oo_nodes_to_config:!oo_containerized_master_nodes @@ -140,7 +77,8 @@ when: "{{ (openshift_http_proxy is defined or openshift_https_proxy is defined) and openshift_generate_no_proxy_hosts | default(True) | bool }}" roles: - - openshift_node + - role: openshift_node + openshift_ca_host: "{{ groups.oo_first_master.0 }}" - name: Gather and set facts for flannel certificatess hosts: oo_nodes_to_config diff --git a/roles/etcd/tasks/main.yml b/roles/etcd/tasks/main.yml index 71735dc25..75d40216d 100644 --- a/roles/etcd/tasks/main.yml +++ b/roles/etcd/tasks/main.yml @@ -12,6 +12,8 @@ - name: Pull etcd container command: docker pull {{ openshift.etcd.etcd_image }} + register: pull_result + changed_when: "'Downloaded newer image' in pull_result.stdout" when: etcd_is_containerized | bool - name: Install etcd container service file diff --git a/roles/openshift_ca/README.md b/roles/openshift_ca/README.md new file mode 100644 index 000000000..96c9cd5f2 --- /dev/null +++ b/roles/openshift_ca/README.md @@ -0,0 +1,48 @@ +OpenShift CA +============ + +This role delegates all tasks to the `openshift_ca_host` such that this role can be depended on by other OpenShift certificate roles. + +Requirements +------------ + +Role Variables +-------------- + +From this role: + +| Name | Default value | Description | +|-------------------------|-----------------------------------------------|-----------------------------------------------------------------------------| +| openshift_ca_host | None (Required) | The hostname of the system where the OpenShift CA will be created. | +| openshift_ca_config_dir | `{{ openshift.common.config_base }}/master` | CA certificate directory. | +| openshift_ca_cert | `{{ openshift_ca_config_dir }}/ca.crt` | CA certificate path including CA certificate filename. | +| openshift_ca_key | `{{ openshift_ca_config_dir }}/ca.key` | CA key path including CA key filename. | +| openshift_ca_serial | `{{ openshift_ca_config_dir }}/ca.serial.txt` | CA serial path including CA serial filename. | +| openshift_version | `{{ openshift_pkg_version }}` | OpenShift package version. | + +Dependencies +------------ + +* openshift_repos +* openshift_cli + +Example Playbook +---------------- + +``` +- name: Create OpenShift CA + hosts: localhost + roles: + - role: openshift_ca + openshift_ca_host: master1.example.com +``` + +License +------- + +Apache License Version 2.0 + +Author Information +------------------ + +Jason DeTiberus (jdetiber@redhat.com) diff --git a/roles/openshift_master_ca/meta/main.yml b/roles/openshift_ca/meta/main.yml index b5dd466c9..a08aa1686 100644 --- a/roles/openshift_master_ca/meta/main.yml +++ b/roles/openshift_ca/meta/main.yml @@ -1,10 +1,10 @@ --- galaxy_info: author: Jason DeTiberus - description: + description: OpenShift CA 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,5 +13,5 @@ galaxy_info: - cloud - system dependencies: -- { role: openshift_repos } -- { role: openshift_cli } +- role: openshift_repos +- role: openshift_cli diff --git a/roles/openshift_ca/vars/main.yml b/roles/openshift_ca/vars/main.yml new file mode 100644 index 000000000..a32e385ec --- /dev/null +++ b/roles/openshift_ca/vars/main.yml @@ -0,0 +1,6 @@ +--- +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('') }}" diff --git a/roles/openshift_cli/library/openshift_container_binary_sync.py b/roles/openshift_cli/library/openshift_container_binary_sync.py new file mode 100644 index 000000000..fd290c6fc --- /dev/null +++ b/roles/openshift_cli/library/openshift_container_binary_sync.py @@ -0,0 +1,131 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# vim: expandtab:tabstop=4:shiftwidth=4 +# pylint: disable=missing-docstring,invalid-name +# + +import random +import tempfile +import shutil +import os.path + +# pylint: disable=redefined-builtin,wildcard-import,unused-wildcard-import +from ansible.module_utils.basic import * + + +DOCUMENTATION = ''' +--- +module: openshift_container_binary_sync +short_description: Copies OpenShift binaries out of the given image tag to host system. +''' + + +class BinarySyncError(Exception): + def __init__(self, msg): + super(BinarySyncError, self).__init__(msg) + self.msg = msg + + +# pylint: disable=too-few-public-methods +class BinarySyncer(object): + """ + Syncs the openshift, oc, oadm, and kubectl binaries/symlinks out of + a container onto the host system. + """ + + def __init__(self, module, image, tag): + self.module = module + self.changed = False + self.output = [] + self.bin_dir = '/usr/local/bin' + self.image = image + self.tag = tag + self.temp_dir = None # TBD + + def sync(self): + container_name = "openshift-cli-%s" % random.randint(1, 100000) + rc, stdout, stderr = self.module.run_command(['docker', 'create', '--name', + container_name, '%s:%s' % (self.image, self.tag)]) + if rc: + raise BinarySyncError("Error creating temporary docker container. stdout=%s, stderr=%s" % + (stdout, stderr)) + self.output.append(stdout) + try: + self.temp_dir = tempfile.mkdtemp() + self.output.append("Using temp dir: %s" % self.temp_dir) + + rc, stdout, stderr = self.module.run_command(['docker', 'cp', "%s:/usr/bin/openshift" % container_name, + self.temp_dir]) + if rc: + raise BinarySyncError("Error copying file from docker container: stdout=%s, stderr=%s" % + (stdout, stderr)) + + rc, stdout, stderr = self.module.run_command(['docker', 'cp', "%s:/usr/bin/oc" % container_name, + self.temp_dir]) + if rc: + raise BinarySyncError("Error copying file from docker container: stdout=%s, stderr=%s" % + (stdout, stderr)) + + self._sync_binary('openshift') + + # In older versions, oc was a symlink to openshift: + if os.path.islink(os.path.join(self.temp_dir, 'oc')): + self._sync_symlink('oc', 'openshift') + else: + self._sync_binary('oc') + + # Ensure correct symlinks created: + self._sync_symlink('kubectl', 'openshift') + self._sync_symlink('oadm', 'openshift') + finally: + shutil.rmtree(self.temp_dir) + self.module.run_command(['docker', 'rm', container_name]) + + def _sync_symlink(self, binary_name, link_to): + """ Ensure the given binary name exists and links to the expected binary. """ + link_path = os.path.join(self.bin_dir, binary_name) + link_dest = os.path.join(self.bin_dir, binary_name) + if not os.path.exists(link_path) or \ + not os.path.islink(link_path) or \ + os.path.realpath(link_path) != os.path.realpath(link_dest): + if os.path.exists(link_path): + os.remove(link_path) + os.symlink(link_to, os.path.join(self.bin_dir, binary_name)) + self.output.append("Symlinked %s to %s." % (link_path, link_dest)) + self.changed = True + + def _sync_binary(self, binary_name): + src_path = os.path.join(self.temp_dir, binary_name) + dest_path = os.path.join(self.bin_dir, binary_name) + incoming_checksum = self.module.run_command(['sha256sum', src_path])[1] + if not os.path.exists(dest_path) or self.module.run_command(['sha256sum', dest_path])[1] != incoming_checksum: + shutil.move(src_path, dest_path) + self.output.append("Moved %s to %s." % (src_path, dest_path)) + self.changed = True + + +def main(): + module = AnsibleModule( + argument_spec=dict( + image=dict(required=True), + tag=dict(required=True), + ), + supports_check_mode=True + ) + + image = module.params['image'] + tag = module.params['tag'] + + binary_syncer = BinarySyncer(module, image, tag) + + try: + binary_syncer.sync() + except BinarySyncError as ex: + module.fail_json(msg=ex.msg) + + return module.exit_json(changed=binary_syncer.changed, + output=binary_syncer.output) + + +if __name__ == '__main__': + main() diff --git a/roles/openshift_cli/tasks/main.yml b/roles/openshift_cli/tasks/main.yml index 4d6219b94..11c73b25c 100644 --- a/roles/openshift_cli/tasks/main.yml +++ b/roles/openshift_cli/tasks/main.yml @@ -6,24 +6,14 @@ - name: Pull CLI Image command: > docker pull {{ openshift.common.cli_image }}:{{ openshift_image_tag }} + register: pull_result + changed_when: "'Downloaded newer image' in pull_result.stdout" when: openshift.common.is_containerized | bool -- name: Create /usr/local/bin/openshift cli wrapper - template: - src: openshift.j2 - dest: /usr/local/bin/openshift - mode: 0755 - when: openshift.common.is_containerized | bool - -- name: Create client symlinks - file: - path: "{{ item }}" - state: link - src: /usr/local/bin/openshift - with_items: - - /usr/local/bin/oadm - - /usr/local/bin/oc - - /usr/local/bin/kubectl +- name: Copy client binaries/symlinks out of CLI image for use on the host + openshift_container_binary_sync: + image: "{{ openshift.common.cli_image }}" + tag: "{{ openshift_image_tag }}" when: openshift.common.is_containerized | bool - name: Reload facts to pick up installed OpenShift version diff --git a/roles/openshift_cli/templates/openshift.j2 b/roles/openshift_cli/templates/openshift.j2 deleted file mode 100644 index 7786acead..000000000 --- a/roles/openshift_cli/templates/openshift.j2 +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -if [ ! -d ~/.kube ]; then - mkdir -m 0700 ~/.kube -fi -cmd=`basename $0` -user=`id -u` -group=`id -g` -image_tag="{{ openshift_image_tag }}" - ->&2 echo """ -================================================================================ -ATTENTION: You are running ${cmd} via a wrapper around 'docker run {{ openshift.common.cli_image }}:${image_tag}'. -This wrapper is intended only to be used to bootstrap an environment. Please -install client tools on another host once you have granted cluster-admin -privileges to a user. -{% if openshift.common.deployment_type in ['openshift-enterprise','atomic-enterprise'] %} -See https://docs.openshift.com/enterprise/latest/cli_reference/get_started_cli.html -{% else %} -See https://docs.openshift.org/latest/cli_reference/get_started_cli.html -{% endif %} -================================================================================= -""" - -if [ -n "$image_tag" ]; then - image_tag=":$image_tag" -fi - -docker run -i --privileged --net=host --user=${user}:${group} -v ~/.kube:/root/.kube -v /tmp:/tmp -v {{ openshift.common.config_base}}:{{ openshift.common.config_base }} -e KUBECONFIG=/root/.kube/config --entrypoint ${cmd} --rm {{ openshift.common.cli_image }}${image_tag} "${@}" diff --git a/roles/openshift_hosted/tasks/registry/registry.yml b/roles/openshift_hosted/tasks/registry/registry.yml index a242ce30f..a1edef132 100644 --- a/roles/openshift_hosted/tasks/registry/registry.yml +++ b/roles/openshift_hosted/tasks/registry/registry.yml @@ -9,7 +9,7 @@ when: openshift.hosted.registry.replicas | default(none) is none - set_fact: - replicas: "{{ openshift.hosted.registry.replicas | default(((openshift_hosted_registry_nodes_json.stdout | from_json)['items'] | length) if openshift.hosted.registry.storage.kind | default(none) is not none else 1) }}" + replicas: "{{ openshift.hosted.registry.replicas | default(((openshift_hosted_registry_nodes_json.stdout | default('{\"items\":[]}') | from_json)['items'] | length) if openshift.hosted.registry.storage.kind | default(none) is not none else 1) }}" - name: Create OpenShift registry command: > diff --git a/roles/openshift_hosted/tasks/router/router.yml b/roles/openshift_hosted/tasks/router/router.yml index dfea8ca4b..7f3731c7d 100644 --- a/roles/openshift_hosted/tasks/router/router.yml +++ b/roles/openshift_hosted/tasks/router/router.yml @@ -44,7 +44,7 @@ when: openshift.hosted.router.replicas | default(none) is none - set_fact: - replicas: "{{ openshift.hosted.router.replicas | default((openshift_hosted_router_nodes_json.stdout | from_json)['items'] | length) }}" + replicas: "{{ openshift.hosted.router.replicas | default((openshift_hosted_router_nodes_json.stdout | default('{\"items\":[]}') | from_json)['items'] | length) }}" - name: Create OpenShift router command: > diff --git a/roles/openshift_master/meta/main.yml b/roles/openshift_master/meta/main.yml index 0a69b3eef..be70d9102 100644 --- a/roles/openshift_master/meta/main.yml +++ b/roles/openshift_master/meta/main.yml @@ -4,7 +4,7 @@ galaxy_info: description: Master company: Red Hat, Inc. license: Apache License, Version 2.0 - min_ansible_version: 1.7 + min_ansible_version: 2.1 platforms: - name: EL versions: @@ -13,8 +13,7 @@ galaxy_info: - cloud dependencies: - role: openshift_clock -- role: openshift_docker -- role: openshift_cli +- role: openshift_master_certificates - role: openshift_cloud_provider - role: openshift_builddefaults - role: openshift_master_facts diff --git a/roles/openshift_master/tasks/main.yml b/roles/openshift_master/tasks/main.yml index 7a80ed8e3..0b87ae48c 100644 --- a/roles/openshift_master/tasks/main.yml +++ b/roles/openshift_master/tasks/main.yml @@ -30,6 +30,8 @@ - name: Pull master image command: > docker pull {{ openshift.master.master_image }}:{{ openshift_image_tag }} + register: pull_result + changed_when: "'Downloaded newer image' in pull_result.stdout" when: openshift.common.is_containerized | bool - name: Create openshift.common.data_dir @@ -210,6 +212,7 @@ until: api_available_output.stdout == 'ok' retries: 120 delay: 1 + run_once: true changed_when: false when: openshift_master_ha | bool and openshift.master.cluster_method == 'native' and master_api_service_status_changed | bool diff --git a/roles/openshift_master_ca/README.md b/roles/openshift_master_ca/README.md deleted file mode 100644 index 5b2d3601b..000000000 --- a/roles/openshift_master_ca/README.md +++ /dev/null @@ -1,34 +0,0 @@ -OpenShift Master CA -======================== - -TODO - -Requirements ------------- - -TODO - -Role Variables --------------- - -TODO - -Dependencies ------------- - -TODO - -Example Playbook ----------------- - -TODO - -License -------- - -Apache License Version 2.0 - -Author Information ------------------- - -Jason DeTiberus (jdetiber@redhat.com) diff --git a/roles/openshift_master_ca/tasks/main.yml b/roles/openshift_master_ca/tasks/main.yml deleted file mode 100644 index ae99467f0..000000000 --- a/roles/openshift_master_ca/tasks/main.yml +++ /dev/null @@ -1,24 +0,0 @@ ---- - -- 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 - register: install_result - -- name: Reload generated facts - openshift_facts: - when: install_result | changed - -- name: Create openshift_master_config_dir if it doesn't exist - file: - path: "{{ openshift_master_config_dir }}" - state: directory - -- name: Create the master certificates if they do not already exist - command: > - {{ openshift.common.admin_binary }} create-master-certs - --hostnames={{ master_hostnames | join(',') }} - --master={{ openshift.master.api_url }} - --public-master={{ openshift.master.public_api_url }} - --cert-dir={{ openshift_master_config_dir }} --overwrite=false - when: master_certs_missing | bool diff --git a/roles/openshift_master_ca/vars/main.yml b/roles/openshift_master_ca/vars/main.yml deleted file mode 100644 index 1f6af808c..000000000 --- a/roles/openshift_master_ca/vars/main.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -openshift_master_config_dir: "{{ openshift.common.config_base }}/master" -openshift_master_ca_cert: "{{ openshift_master_config_dir }}/ca.crt" -openshift_master_ca_key: "{{ openshift_master_config_dir }}/ca.key" -openshift_master_ca_serial: "{{ openshift_master_config_dir }}/ca.serial.txt" diff --git a/roles/openshift_master_certificates/README.md b/roles/openshift_master_certificates/README.md index ba3d5f28c..a80d47040 100644 --- a/roles/openshift_master_certificates/README.md +++ b/roles/openshift_master_certificates/README.md @@ -1,27 +1,44 @@ OpenShift Master Certificates ======================== -TODO +This role determines if OpenShift master certificates must be created, delegates certificate creation to the `openshift_ca_host` and then deploys those certificates to master hosts which this role is being applied to. If this role is applied to the `openshift_ca_host`, certificate deployment will be skipped. Requirements ------------ -TODO - Role Variables -------------- -TODO +From `openshift_ca`: + +| Name | Default value | Description | +|---------------------------------------|---------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------| +| openshift_ca_host | None (Required) | The hostname of the system where the OpenShift CA will be (or has been) created. | + +From this role: + +| Name | Default value | Description | +|---------------------------------------|---------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------| +| openshift_generated_configs_dir | `{{ openshift.common.config_base }}/generated-configs` | Directory in which per-master generated config directories will be created on the `openshift_ca_host`. | +| openshift_master_cert_subdir | `master-{{ openshift.common.hostname }}` | Directory within `openshift_generated_configs_dir` where per-master configurations will be placed on the `openshift_ca_host`. | +| openshift_master_config_dir | `{{ openshift.common.config_base }}/master` | Master configuration directory in which certificates will be deployed on masters. | +| openshift_master_generated_config_dir | `{{ openshift_generated_configs_dir }}/{{ openshift_master_cert_subdir }` | Full path to the per-master generated config directory. | Dependencies ------------ -TODO +* openshift_ca Example Playbook ---------------- -TODO +``` +- name: Create OpenShift Master Certificates + hosts: masters + roles: + - role: openshift_master_certificates + openshift_ca_host: master1.example.com +``` License ------- diff --git a/roles/openshift_master_certificates/meta/main.yml b/roles/openshift_master_certificates/meta/main.yml index fd7b73b0f..dd19c8ded 100644 --- a/roles/openshift_master_certificates/meta/main.yml +++ b/roles/openshift_master_certificates/meta/main.yml @@ -1,10 +1,10 @@ --- galaxy_info: author: Jason DeTiberus - description: + description: OpenShift Master 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: openshift_master_ca } +- role: openshift_ca diff --git a/roles/openshift_master_certificates/tasks/main.yml b/roles/openshift_master_certificates/tasks/main.yml index 394f9d381..6fb5830cf 100644 --- a/roles/openshift_master_certificates/tasks/main.yml +++ b/roles/openshift_master_certificates/tasks/main.yml @@ -1,38 +1,123 @@ --- +- set_fact: + openshift_master_certs_no_etcd: + - admin.crt + - master.kubelet-client.crt + - "{{ 'master.proxy-client.crt' if openshift.common.version_gte_3_1_or_1_1 else omit }}" + - master.server.crt + - openshift-master.crt + - openshift-registry.crt + - openshift-router.crt + - etcd.server.crt + openshift_master_certs_etcd: + - master.etcd-client.crt + +- set_fact: + openshift_master_certs: "{{ (openshift_master_certs_no_etcd | union(openshift_master_certs_etcd )) if openshift_master_etcd_hosts | length > 0 else openshift_master_certs_no_etcd }}" + +- name: Check status of master certificates + stat: + path: "{{ openshift_master_config_dir }}/{{ item }}" + with_items: + - "{{ openshift_master_certs }}" + register: g_master_cert_stat_result + +- set_fact: + master_certs_missing: "{{ False in (g_master_cert_stat_result.results + | oo_collect(attribute='stat.exists') + | list) }}" + - name: Ensure the generated_configs directory present file: - path: "{{ openshift_generated_configs_dir }}/{{ item.master_cert_subdir }}" + path: "{{ openshift_master_generated_config_dir }}" state: directory mode: 0700 - with_items: "{{ masters_needing_certs | default([]) }}" + when: master_certs_missing | bool + delegate_to: "{{ openshift_ca_host }}" - file: - src: "{{ openshift_master_config_dir }}/{{ item.1 }}" - dest: "{{ openshift_generated_configs_dir }}/{{ item.0.master_cert_subdir }}/{{ item.1 }}" + src: "{{ openshift_master_config_dir }}/{{ item }}" + dest: "{{ openshift_master_generated_config_dir }}/{{ item }}" state: hard - with_nested: - - "{{ masters_needing_certs | default([]) }}" - - - - ca.crt - - ca.key - - ca.serial.txt + with_items: + - ca.crt + - ca.key + - ca.serial.txt + when: master_certs_missing | bool + 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={{ item.openshift.common.all_hostnames | join(',') }} - --master={{ item.openshift.master.api_url }} - --public-master={{ item.openshift.master.public_api_url }} - --cert-dir={{ openshift_generated_configs_dir }}/{{ item.master_cert_subdir }} + --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: item.master_certs_missing | bool - with_items: "{{ masters_needing_certs | default([]) }}" + when: master_certs_missing | bool + delegate_to: "{{ openshift_ca_host }}" - file: - src: "{{ openshift_master_config_dir }}/{{ item.1 }}" - dest: "{{ openshift_generated_configs_dir }}/{{ item.0.master_cert_subdir }}/{{ item.1 }}" + src: "{{ openshift_master_config_dir }}/{{ item }}" + dest: "{{ openshift_master_generated_config_dir }}/{{ item }}" state: hard force: true - with_nested: - - "{{ masters_needing_certs | default([]) }}" + with_items: - "{{ hostvars[inventory_hostname] | certificates_to_synchronize }}" + when: master_certs_missing | bool + delegate_to: "{{ openshift_ca_host }}" + +- name: Remove generated etcd client certs when using external etcd + file: + path: "{{ openshift_master_generated_config_dir }}/{{ item }}" + state: absent + when: openshift_master_etcd_hosts | length > 0 + with_items: + - master.etcd-client.crt + - master.etcd-client.key + delegate_to: "{{ openshift_ca_host }}" + +- name: Create local temp directory for syncing certs + local_action: command mktemp -d /tmp/openshift-ansible-XXXXXXX + register: g_master_mktemp + changed_when: False + when: master_certs_missing | bool + delegate_to: localhost + become: no + +- name: Create a tarball of the master certs + command: > + tar -czvf {{ openshift_master_generated_config_dir }}.tgz + -C {{ openshift_master_generated_config_dir }} . + args: + creates: "{{ openshift_master_generated_config_dir }}.tgz" + when: master_certs_missing | bool and inventory_hostname != openshift_ca_host + delegate_to: "{{ openshift_ca_host }}" + +- name: Retrieve the master cert tarball from the master + fetch: + src: "{{ openshift_master_generated_config_dir }}.tgz" + dest: "{{ g_master_mktemp.stdout }}/" + flat: yes + fail_on_missing: yes + validate_checksum: yes + when: master_certs_missing | bool and inventory_hostname != openshift_ca_host + delegate_to: "{{ openshift_ca_host }}" + +- name: Ensure certificate directory exists + file: + path: "{{ openshift_master_config_dir }}" + state: directory + when: master_certs_missing | bool and inventory_hostname != openshift_ca_host + +- name: Unarchive the tarball on the master + unarchive: + src: "{{ g_master_mktemp.stdout }}/{{ openshift_master_cert_subdir }}.tgz" + dest: "{{ openshift_master_config_dir }}" + when: master_certs_missing | bool and inventory_hostname != openshift_ca_host + +- file: name={{ g_master_mktemp.stdout }} state=absent + changed_when: False + when: master_certs_missing | bool + delegate_to: localhost + become: no diff --git a/roles/openshift_master_certificates/vars/main.yml b/roles/openshift_master_certificates/vars/main.yml index 3f18ddc79..66f2e5162 100644 --- a/roles/openshift_master_certificates/vars/main.yml +++ b/roles/openshift_master_certificates/vars/main.yml @@ -1,3 +1,5 @@ --- openshift_generated_configs_dir: "{{ openshift.common.config_base }}/generated-configs" +openshift_master_cert_subdir: "master-{{ openshift.common.hostname }}" openshift_master_config_dir: "{{ openshift.common.config_base }}/master" +openshift_master_generated_config_dir: "{{ openshift_generated_configs_dir }}/{{ openshift_master_cert_subdir }}" diff --git a/roles/openshift_node/meta/main.yml b/roles/openshift_node/meta/main.yml index 97ab8241b..fd493340b 100644 --- a/roles/openshift_node/meta/main.yml +++ b/roles/openshift_node/meta/main.yml @@ -4,7 +4,7 @@ galaxy_info: description: OpenShift Node company: Red Hat, Inc. license: Apache License, Version 2.0 - min_ansible_version: 1.7 + min_ansible_version: 2.1 platforms: - name: EL versions: @@ -14,6 +14,7 @@ galaxy_info: dependencies: - role: openshift_clock - role: openshift_docker +- role: openshift_node_certificates - role: openshift_cloud_provider - role: openshift_common - role: openshift_node_dnsmasq diff --git a/roles/openshift_node/tasks/main.yml b/roles/openshift_node/tasks/main.yml index 97a21544d..889541e25 100644 --- a/roles/openshift_node/tasks/main.yml +++ b/roles/openshift_node/tasks/main.yml @@ -41,11 +41,15 @@ - name: Pull node image command: > docker pull {{ openshift.node.node_image }}:{{ openshift_image_tag }} + register: pull_result + changed_when: "'Downloaded newer image' in pull_result.stdout" when: openshift.common.is_containerized | bool - name: Pull OpenVSwitch image command: > docker pull {{ openshift.node.ovs_image }}:{{ openshift_image_tag }} + register: pull_result + changed_when: "'Downloaded newer image' in pull_result.stdout" when: openshift.common.is_containerized | bool and openshift.common.use_openshift_sdn | bool - name: Install the systemd units @@ -129,12 +133,12 @@ service: name={{ openshift.common.service_type }}-node enabled=yes state=started register: node_start_result ignore_errors: yes - + - name: Wait 30 seconds for docker initialization whenever node has failed pause: seconds: 30 when: node_start_result | failed - + - name: Start and enable node again service: name={{ openshift.common.service_type }}-node enabled=yes state=started register: node_start_result diff --git a/roles/openshift_node_certificates/README.md b/roles/openshift_node_certificates/README.md index 6264d253a..f56066b29 100644 --- a/roles/openshift_node_certificates/README.md +++ b/roles/openshift_node_certificates/README.md @@ -1,27 +1,44 @@ -OpenShift/Atomic Enterprise Node Certificates -============================================= +OpenShift Node Certificates +=========================== -TODO +This role determines if OpenShift node certificates must be created, delegates certificate creation to the `openshift_ca_host` and then deploys those certificates to node hosts which this role is being applied to. Requirements ------------ -TODO - Role Variables -------------- -TODO +From `openshift_ca`: + +| Name | Default value | Description | +|-------------------------------------|-------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------| +| openshift_ca_host | None (Required) | The hostname of the system where the OpenShift CA will be (or has been) created. | + +From this role: + +| Name | Default value | Description | +|-------------------------------------|-------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------| +| openshift_generated_configs_dir | `{{ openshift.common.config_base }}/generated-configs` | Directory in which per-node generated config directories will be created on the `openshift_ca_host`. | +| openshift_node_cert_subdir | `node-{{ openshift.common.hostname }}` | Directory within `openshift_generated_configs_dir` where per-node certificates will be placed on the `openshift_ca_host`. | +| openshift_node_config_dir | `{{ openshift.common.config_base }}/node` | Node configuration directory in which certificates will be deployed on nodes. | +| openshift_node_generated_config_dir | `{{ openshift_generated_configs_dir }}/{{ openshift_node_cert_subdir }` | Full path to the per-node generated config directory. | Dependencies ------------ -TODO +* openshift_ca Example Playbook ---------------- -TODO +``` +- name: Create OpenShift Node Certificates + hosts: nodes + roles: + - role: openshift_node_certificates + openshift_ca_host: master1.example.com +``` License ------- diff --git a/roles/openshift_node_certificates/meta/main.yml b/roles/openshift_node_certificates/meta/main.yml index f3236e850..50a862ee9 100644 --- a/roles/openshift_node_certificates/meta/main.yml +++ b/roles/openshift_node_certificates/meta/main.yml @@ -1,10 +1,10 @@ --- galaxy_info: author: Jason DeTiberus - description: + description: OpenShift Node 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: openshift_facts } +- role: openshift_facts diff --git a/roles/openshift_node_certificates/tasks/main.yml b/roles/openshift_node_certificates/tasks/main.yml index 216c11093..0e69dc6f0 100644 --- a/roles/openshift_node_certificates/tasks/main.yml +++ b/roles/openshift_node_certificates/tasks/main.yml @@ -1,36 +1,117 @@ --- -- name: Create openshift_generated_configs_dir if it doesn\'t exist +- name: Ensure CA certificate exists on openshift_ca_host + stat: + path: "{{ openshift_ca_cert }}" + register: g_ca_cert_stat_result + delegate_to: "{{ openshift_ca_host }}" + run_once: true + +- fail: + msg: > + CA certificate {{ openshift_ca_cert }} doesn't exist on CA host + {{ openshift_ca_host }}. Apply 'openshift_ca' role to + {{ openshift_ca_host }}. + when: not g_ca_cert_stat_result.stat.exists | bool + run_once: true + +- name: Check status of node certificates + stat: + path: "{{ openshift.common.config_base }}/node/{{ item }}" + with_items: + - "system:node:{{ openshift.common.hostname }}.crt" + - "system:node:{{ openshift.common.hostname }}.key" + - "system:node:{{ openshift.common.hostname }}.kubeconfig" + - ca.crt + - server.key + - server.crt + register: g_node_cert_stat_result + +- set_fact: + node_certs_missing: "{{ False in (g_node_cert_stat_result.results + | oo_collect(attribute='stat.exists') + | list) }}" + +- name: Create openshift_generated_configs_dir if it does not exist file: path: "{{ openshift_generated_configs_dir }}" state: directory mode: 0700 - when: nodes_needing_certs | length > 0 + when: node_certs_missing | bool + delegate_to: "{{ openshift_ca_host }}" - name: Generate the node client config command: > {{ openshift.common.admin_binary }} create-api-client-config - --certificate-authority={{ openshift_master_ca_cert }} - --client-dir={{ openshift_generated_configs_dir }}/node-{{ item.openshift.common.hostname }} + --certificate-authority={{ openshift_ca_cert }} + --client-dir={{ openshift_node_generated_config_dir }} --groups=system:nodes - --master={{ openshift.master.api_url }} - --signer-cert={{ openshift_master_ca_cert }} - --signer-key={{ openshift_master_ca_key }} - --signer-serial={{ openshift_master_ca_serial }} - --user=system:node:{{ item.openshift.common.hostname }} + --master={{ hostvars[openshift_ca_host].openshift.master.api_url }} + --signer-cert={{ openshift_ca_cert }} + --signer-key={{ openshift_ca_key }} + --signer-serial={{ openshift_ca_serial }} + --user=system:node:{{ openshift.common.hostname }} args: - creates: "{{ openshift_generated_configs_dir }}/node-{{ item.openshift.common.hostname }}" - with_items: "{{ nodes_needing_certs | default([]) }}" + creates: "{{ openshift_node_generated_config_dir }}" + when: node_certs_missing | bool + delegate_to: "{{ openshift_ca_host }}" - name: Generate the node server certificate command: > {{ openshift.common.admin_binary }} ca create-server-cert - --cert={{ openshift_generated_configs_dir }}/node-{{ item.openshift.common.hostname }}/server.crt - --key={{ openshift_generated_configs_dir }}/node-{{ item.openshift.common.hostname }}/server.key + --cert={{ openshift_node_generated_config_dir }}/server.crt + --key={{ openshift_generated_configs_dir }}/node-{{ openshift.common.hostname }}/server.key --overwrite=true - --hostnames={{ item.openshift.common.all_hostnames |join(",") }} - --signer-cert={{ openshift_master_ca_cert }} - --signer-key={{ openshift_master_ca_key }} - --signer-serial={{ openshift_master_ca_serial }} + --hostnames={{ openshift.common.all_hostnames |join(",") }} + --signer-cert={{ openshift_ca_cert }} + --signer-key={{ openshift_ca_key }} + --signer-serial={{ openshift_ca_serial }} + args: + creates: "{{ openshift_node_generated_config_dir }}/server.crt" + when: node_certs_missing | bool + delegate_to: "{{ openshift_ca_host}}" + +- name: Create local temp directory for syncing certs + local_action: command mktemp -d /tmp/openshift-ansible-XXXXXXX + register: node_cert_mktemp + changed_when: False + when: node_certs_missing | bool + delegate_to: localhost + become: no + +- name: Create a tarball of the node config directories + command: > + tar -czvf {{ openshift_node_generated_config_dir }}.tgz + --transform 's|system:{{ openshift_node_cert_subdir }}|node|' + -C {{ openshift_node_generated_config_dir }} . args: - creates: "{{ openshift_generated_configs_dir }}/node-{{ item.openshift.common.hostname }}/server.crt" - with_items: "{{ nodes_needing_certs | default([]) }}" + creates: "{{ openshift_node_generated_config_dir }}.tgz" + when: node_certs_missing | bool + delegate_to: "{{ openshift_ca_host }}" + +- name: Retrieve the node config tarballs from the master + fetch: + src: "{{ openshift_node_generated_config_dir }}.tgz" + dest: "{{ node_cert_mktemp.stdout }}/" + flat: yes + fail_on_missing: yes + validate_checksum: yes + when: node_certs_missing | bool + delegate_to: "{{ openshift_ca_host }}" + +- name: Ensure certificate directory exists + file: + path: "{{ openshift_node_cert_dir }}" + state: directory + when: node_certs_missing | bool + +- name: Unarchive the tarball on the node + unarchive: + src: "{{ node_cert_mktemp.stdout }}/{{ openshift_node_cert_subdir }}.tgz" + dest: "{{ openshift_node_cert_dir }}" + when: node_certs_missing | bool + +- file: name={{ node_cert_mktemp.stdout }} state=absent + changed_when: False + when: node_certs_missing | bool + delegate_to: localhost + become: no diff --git a/roles/openshift_node_certificates/vars/main.yml b/roles/openshift_node_certificates/vars/main.yml index 61fbb1e51..17ad8106d 100644 --- a/roles/openshift_node_certificates/vars/main.yml +++ b/roles/openshift_node_certificates/vars/main.yml @@ -1,7 +1,11 @@ --- -openshift_node_config_dir: "{{ openshift.common.config_base }}/node" -openshift_master_config_dir: "{{ openshift.common.config_base }}/master" openshift_generated_configs_dir: "{{ openshift.common.config_base }}/generated-configs" -openshift_master_ca_cert: "{{ openshift_master_config_dir }}/ca.crt" -openshift_master_ca_key: "{{ openshift_master_config_dir }}/ca.key" -openshift_master_ca_serial: "{{ openshift_master_config_dir }}/ca.serial.txt" +openshift_node_cert_dir: "{{ openshift.common.config_base }}/node" +openshift_node_cert_subdir: "node-{{ openshift.common.hostname }}" +openshift_node_config_dir: "{{ openshift.common.config_base }}/node" +openshift_node_generated_config_dir: "{{ openshift_generated_configs_dir }}/{{ openshift_node_cert_subdir }}" + +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" |