diff options
Diffstat (limited to 'roles')
65 files changed, 1225 insertions, 894 deletions
diff --git a/roles/calico_master/defaults/main.yaml b/roles/calico_master/defaults/main.yaml index 5b324bce5..b2df0105f 100644 --- a/roles/calico_master/defaults/main.yaml +++ b/roles/calico_master/defaults/main.yaml @@ -4,3 +4,4 @@ kubeconfig: "{{ openshift.common.config_base }}/master/openshift-master.kubeconf calicoctl_bin_dir: "/usr/local/bin/" calico_url_calicoctl: "https://github.com/projectcalico/calicoctl/releases/download/v1.1.3/calicoctl" +calico_url_policy_controller: "quay.io/calico/kube-policy-controller:v0.5.4" diff --git a/roles/calico_master/templates/calico-policy-controller.yml.j2 b/roles/calico_master/templates/calico-policy-controller.yml.j2 index 1b87758ce..811884473 100644 --- a/roles/calico_master/templates/calico-policy-controller.yml.j2 +++ b/roles/calico_master/templates/calico-policy-controller.yml.j2 @@ -74,7 +74,7 @@ spec: serviceAccountName: calico containers: - name: calico-policy-controller - image: quay.io/calico/kube-policy-controller:v0.5.4 + image: {{ calico_url_policy_controller }} env: # The location of the Calico etcd cluster. - name: ETCD_ENDPOINTS diff --git a/roles/etcd/tasks/system_container.yml b/roles/etcd/tasks/system_container.yml index 72ffadbd2..f1d948d16 100644 --- a/roles/etcd/tasks/system_container.yml +++ b/roles/etcd/tasks/system_container.yml @@ -15,6 +15,56 @@ {%- endif -%} {% endfor -%} +- name: Check etcd system container package + command: > + atomic containers list --no-trunc -a -f container=etcd -f backend=ostree + register: etcd_result + +- name: Unmask etcd service + systemd: + name: etcd + state: stopped + enabled: yes + masked: no + daemon_reload: yes + register: task_result + failed_when: task_result|failed and 'could not' not in task_result.msg|lower + when: "'etcd' in etcd_result.stdout" + +- name: Disable etcd_container + systemd: + name: etcd_container + state: stopped + enabled: no + masked: yes + daemon_reload: yes + register: task_result + failed_when: task_result|failed and 'could not' not in task_result.msg|lower + +- name: Check for previous etcd data store + stat: + path: "{{ etcd_data_dir }}/member/" + register: src_datastore + +- name: Check for etcd system container data store + stat: + path: "{{ r_etcd_common_system_container_host_dir }}/etcd.etcd/member" + register: dest_datastore + +- name: Ensure that etcd system container data dirs exist + file: path="{{ item }}" state=directory + with_items: + - "{{ r_etcd_common_system_container_host_dir }}/etc" + - "{{ r_etcd_common_system_container_host_dir }}/etcd.etcd" + +- name: Copy etcd data store + command: > + cp -a {{ etcd_data_dir }}/member + {{ r_etcd_common_system_container_host_dir }}/etcd.etcd/member + when: + - src_datastore.stat.exists + - not dest_datastore.stat.exists + - name: Install or Update Etcd system container package oc_atomic_container: name: etcd @@ -35,3 +85,5 @@ - ETCD_PEER_CA_FILE={{ etcd_system_container_conf_dir }}/ca.crt - ETCD_PEER_CERT_FILE={{ etcd_system_container_conf_dir }}/peer.crt - ETCD_PEER_KEY_FILE={{ etcd_system_container_conf_dir }}/peer.key + - ETCD_TRUSTED_CA_FILE={{ etcd_system_container_conf_dir }}/ca.crt + - ETCD_PEER_TRUSTED_CA_FILE={{ etcd_system_container_conf_dir }}/ca.crt diff --git a/roles/etcd_common/defaults/main.yml b/roles/etcd_common/defaults/main.yml index e1a080b34..14e712fcf 100644 --- a/roles/etcd_common/defaults/main.yml +++ b/roles/etcd_common/defaults/main.yml @@ -1,9 +1,11 @@ --- # runc, docker, host r_etcd_common_etcd_runtime: "docker" +r_etcd_common_embedded_etcd: false # etcd server vars -etcd_conf_dir: "{{ '/etc/etcd' if r_etcd_common_etcd_runtime != 'runc' else '/var/lib/etcd/etcd.etcd/etc' }}" +etcd_conf_dir: '/etc/etcd' +r_etcd_common_system_container_host_dir: /var/lib/etcd/etcd.etcd etcd_system_container_conf_dir: /var/lib/etcd/etc etcd_conf_file: "{{ etcd_conf_dir }}/etcd.conf" etcd_ca_file: "{{ etcd_conf_dir }}/ca.crt" @@ -40,7 +42,7 @@ etcd_is_containerized: False etcd_is_thirdparty: False # etcd dir vars -etcd_data_dir: /var/lib/etcd/ +etcd_data_dir: "{{ '/var/lib/origin/openshift.local.etcd' if r_etcd_common_embedded_etcd | bool else '/var/lib/etcd/' }}" # etcd ports and protocols etcd_client_port: 2379 diff --git a/roles/etcd_server_certificates/tasks/main.yml b/roles/etcd_server_certificates/tasks/main.yml index 3ac7f3401..4795188a6 100644 --- a/roles/etcd_server_certificates/tasks/main.yml +++ b/roles/etcd_server_certificates/tasks/main.yml @@ -5,11 +5,14 @@ - name: Check status of etcd certificates stat: - path: "{{ etcd_cert_config_dir }}/{{ item }}" + path: "{{ item }}" with_items: - - "{{ etcd_cert_prefix }}server.crt" - - "{{ etcd_cert_prefix }}peer.crt" - - "{{ etcd_cert_prefix }}ca.crt" + - "{{ etcd_cert_config_dir }}/{{ etcd_cert_prefix }}server.crt" + - "{{ etcd_cert_config_dir }}/{{ etcd_cert_prefix }}peer.crt" + - "{{ etcd_cert_config_dir }}/{{ etcd_cert_prefix }}ca.crt" + - "{{ etcd_system_container_cert_config_dir }}/{{ etcd_cert_prefix }}server.crt" + - "{{ etcd_system_container_cert_config_dir }}/{{ etcd_cert_prefix }}peer.crt" + - "{{ etcd_system_container_cert_config_dir }}/{{ etcd_cert_prefix }}ca.crt" register: g_etcd_server_cert_stat_result when: not etcd_certificates_redeploy | default(false) | bool @@ -132,8 +135,11 @@ - name: Ensure certificate directory exists file: - path: "{{ etcd_cert_config_dir }}" + path: "{{ item }}" state: directory + with_items: + - "{{ etcd_cert_config_dir }}" + - "{{ etcd_system_container_cert_config_dir }}" when: etcd_server_certs_missing | bool - name: Unarchive cert tarball @@ -164,15 +170,28 @@ - name: Ensure ca directory exists file: - path: "{{ etcd_ca_dir }}" + path: "{{ item }}" state: directory + with_items: + - "{{ etcd_ca_dir }}" + - "{{ etcd_system_container_cert_config_dir }}/ca" when: etcd_server_certs_missing | bool -- name: Unarchive etcd ca cert tarballs +- name: Unarchive cert tarball for the system container + unarchive: + src: "{{ g_etcd_server_mktemp.stdout }}/{{ etcd_cert_subdir }}.tgz" + dest: "{{ etcd_system_container_cert_config_dir }}" + when: + - etcd_server_certs_missing | bool + - r_etcd_common_etcd_runtime == 'runc' + +- name: Unarchive etcd ca cert tarballs for the system container unarchive: src: "{{ g_etcd_server_mktemp.stdout }}/{{ etcd_ca_name }}.tgz" - dest: "{{ etcd_ca_dir }}" - when: etcd_server_certs_missing | bool + dest: "{{ etcd_system_container_cert_config_dir }}/ca" + when: + - etcd_server_certs_missing | bool + - r_etcd_common_etcd_runtime == 'runc' - name: Delete temporary directory local_action: file path="{{ g_etcd_server_mktemp.stdout }}" state=absent diff --git a/roles/etcd_upgrade/defaults/main.yml b/roles/etcd_upgrade/defaults/main.yml index 01ad8a268..b61bf526c 100644 --- a/roles/etcd_upgrade/defaults/main.yml +++ b/roles/etcd_upgrade/defaults/main.yml @@ -1,8 +1,8 @@ --- r_etcd_upgrade_action: upgrade r_etcd_upgrade_mechanism: rpm -r_etcd_upgrade_embedded_etcd: False - +r_etcd_upgrade_embedded_etcd: false +r_etcd_common_embedded_etcd: "{{ r_etcd_upgrade_embedded_etcd }}" # etcd run on a host => use etcdctl command directly # etcd run as a docker container => use docker exec # etcd run as a runc container => use runc exec diff --git a/roles/etcd_upgrade/meta/main.yml b/roles/etcd_upgrade/meta/main.yml index 018bdc8d7..afdb0267f 100644 --- a/roles/etcd_upgrade/meta/main.yml +++ b/roles/etcd_upgrade/meta/main.yml @@ -14,3 +14,4 @@ galaxy_info: - system dependencies: - role: etcd_common + r_etcd_common_embedded_etcd: "{{ r_etcd_upgrade_embedded_etcd }}" diff --git a/roles/lib_openshift/library/oc_adm_ca_server_cert.py b/roles/lib_openshift/library/oc_adm_ca_server_cert.py index 3974cc4dd..1b73bfd0e 100644 --- a/roles/lib_openshift/library/oc_adm_ca_server_cert.py +++ b/roles/lib_openshift/library/oc_adm_ca_server_cert.py @@ -1097,10 +1097,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1110,34 +1106,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_adm_manage_node.py b/roles/lib_openshift/library/oc_adm_manage_node.py index 320eac17e..b09321a5b 100644 --- a/roles/lib_openshift/library/oc_adm_manage_node.py +++ b/roles/lib_openshift/library/oc_adm_manage_node.py @@ -1083,10 +1083,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1096,34 +1092,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_adm_policy_group.py b/roles/lib_openshift/library/oc_adm_policy_group.py index f9658d6e1..221ef5094 100644 --- a/roles/lib_openshift/library/oc_adm_policy_group.py +++ b/roles/lib_openshift/library/oc_adm_policy_group.py @@ -1069,10 +1069,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1082,34 +1078,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_adm_policy_user.py b/roles/lib_openshift/library/oc_adm_policy_user.py index 0bdfd0bad..071562875 100644 --- a/roles/lib_openshift/library/oc_adm_policy_user.py +++ b/roles/lib_openshift/library/oc_adm_policy_user.py @@ -1069,10 +1069,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1082,34 +1078,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_adm_registry.py b/roles/lib_openshift/library/oc_adm_registry.py index df0e40d20..bf2650460 100644 --- a/roles/lib_openshift/library/oc_adm_registry.py +++ b/roles/lib_openshift/library/oc_adm_registry.py @@ -1187,10 +1187,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1200,34 +1196,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_adm_router.py b/roles/lib_openshift/library/oc_adm_router.py index 8af8cb196..a2b7d12c0 100644 --- a/roles/lib_openshift/library/oc_adm_router.py +++ b/roles/lib_openshift/library/oc_adm_router.py @@ -1212,10 +1212,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1225,34 +1221,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_clusterrole.py b/roles/lib_openshift/library/oc_clusterrole.py index 3ed0d65dc..289f08b83 100644 --- a/roles/lib_openshift/library/oc_clusterrole.py +++ b/roles/lib_openshift/library/oc_clusterrole.py @@ -1061,10 +1061,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1074,34 +1070,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_configmap.py b/roles/lib_openshift/library/oc_configmap.py index 5c8ed48d2..7cd29215f 100644 --- a/roles/lib_openshift/library/oc_configmap.py +++ b/roles/lib_openshift/library/oc_configmap.py @@ -1067,10 +1067,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1080,34 +1076,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_edit.py b/roles/lib_openshift/library/oc_edit.py index f3b6d552d..5b11f45ba 100644 --- a/roles/lib_openshift/library/oc_edit.py +++ b/roles/lib_openshift/library/oc_edit.py @@ -1111,10 +1111,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1124,34 +1120,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_env.py b/roles/lib_openshift/library/oc_env.py index c6421128a..d3834ce0c 100644 --- a/roles/lib_openshift/library/oc_env.py +++ b/roles/lib_openshift/library/oc_env.py @@ -1078,10 +1078,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1091,34 +1087,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_group.py b/roles/lib_openshift/library/oc_group.py index a791c29af..0d751fe28 100644 --- a/roles/lib_openshift/library/oc_group.py +++ b/roles/lib_openshift/library/oc_group.py @@ -1051,10 +1051,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1064,34 +1060,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_image.py b/roles/lib_openshift/library/oc_image.py index bbc123ce0..3a6ba3e56 100644 --- a/roles/lib_openshift/library/oc_image.py +++ b/roles/lib_openshift/library/oc_image.py @@ -1070,10 +1070,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1083,34 +1079,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_label.py b/roles/lib_openshift/library/oc_label.py index cd1afd0d2..5db036b23 100644 --- a/roles/lib_openshift/library/oc_label.py +++ b/roles/lib_openshift/library/oc_label.py @@ -1087,10 +1087,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1100,34 +1096,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_obj.py b/roles/lib_openshift/library/oc_obj.py index 215723cc8..56af303cc 100644 --- a/roles/lib_openshift/library/oc_obj.py +++ b/roles/lib_openshift/library/oc_obj.py @@ -1090,10 +1090,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1103,34 +1099,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval @@ -1473,7 +1461,12 @@ class OCObject(OpenShiftCLI): def delete(self): '''delete the object''' - return self._delete(self.kind, name=self.name, selector=self.selector) + results = self._delete(self.kind, name=self.name, selector=self.selector) + if (results['returncode'] != 0 and 'stderr' in results and + '\"{}\" not found'.format(self.name) in results['stderr']): + results['returncode'] = 0 + + return results def create(self, files=None, content=None): ''' @@ -1557,7 +1550,8 @@ class OCObject(OpenShiftCLI): if state == 'absent': # verify its not in our results if (params['name'] is not None or params['selector'] is not None) and \ - (len(api_rval['results']) == 0 or len(api_rval['results'][0].get('items', [])) == 0): + (len(api_rval['results']) == 0 or \ + ('items' in api_rval['results'][0] and len(api_rval['results'][0]['items']) == 0)): return {'changed': False, 'state': state} if check_mode: diff --git a/roles/lib_openshift/library/oc_objectvalidator.py b/roles/lib_openshift/library/oc_objectvalidator.py index 358ef5130..130521761 100644 --- a/roles/lib_openshift/library/oc_objectvalidator.py +++ b/roles/lib_openshift/library/oc_objectvalidator.py @@ -1022,10 +1022,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1035,34 +1031,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_process.py b/roles/lib_openshift/library/oc_process.py index 025b846c6..c6568d520 100644 --- a/roles/lib_openshift/library/oc_process.py +++ b/roles/lib_openshift/library/oc_process.py @@ -1079,10 +1079,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1092,34 +1088,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_project.py b/roles/lib_openshift/library/oc_project.py index 05dfddab8..a78bc06d2 100644 --- a/roles/lib_openshift/library/oc_project.py +++ b/roles/lib_openshift/library/oc_project.py @@ -1076,10 +1076,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1089,34 +1085,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_pvc.py b/roles/lib_openshift/library/oc_pvc.py index d7de4964c..a88639bfc 100644 --- a/roles/lib_openshift/library/oc_pvc.py +++ b/roles/lib_openshift/library/oc_pvc.py @@ -1071,10 +1071,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1084,34 +1080,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_route.py b/roles/lib_openshift/library/oc_route.py index 3090b4cad..0c0bc9386 100644 --- a/roles/lib_openshift/library/oc_route.py +++ b/roles/lib_openshift/library/oc_route.py @@ -1121,10 +1121,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1134,34 +1130,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_scale.py b/roles/lib_openshift/library/oc_scale.py index 6a505fb6b..f112b6dd0 100644 --- a/roles/lib_openshift/library/oc_scale.py +++ b/roles/lib_openshift/library/oc_scale.py @@ -1065,10 +1065,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1078,34 +1074,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_secret.py b/roles/lib_openshift/library/oc_secret.py index 02257500f..d762e0c38 100644 --- a/roles/lib_openshift/library/oc_secret.py +++ b/roles/lib_openshift/library/oc_secret.py @@ -1117,10 +1117,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1130,34 +1126,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval @@ -1613,7 +1601,7 @@ class OCSecret(OpenShiftCLI): '''delete a secret by name''' return self._delete('secrets', self.name) - def create(self, files=None, contents=None): + def create(self, files=None, contents=None, force=False): '''Create a secret ''' if not files: files = Utils.create_tmp_files_from_contents(contents) @@ -1622,6 +1610,8 @@ class OCSecret(OpenShiftCLI): cmd = ['secrets', 'new', self.name] if self.type is not None: cmd.append("--type=%s" % (self.type)) + if force: + cmd.append('--confirm') cmd.extend(secrets) results = self.openshift_cmd(cmd) @@ -1634,7 +1624,7 @@ class OCSecret(OpenShiftCLI): This receives a list of file names and converts it into a secret. The secret is then written to disk and passed into the `oc replace` command. ''' - secret = self.prep_secret(files) + secret = self.prep_secret(files, force) if secret['returncode'] != 0: return secret @@ -1646,7 +1636,7 @@ class OCSecret(OpenShiftCLI): return self._replace(sfile_path, force=force) - def prep_secret(self, files=None, contents=None): + def prep_secret(self, files=None, contents=None, force=False): ''' return what the secret would look like if created This is accomplished by passing -ojson. This will most likely change in the future ''' @@ -1657,6 +1647,8 @@ class OCSecret(OpenShiftCLI): cmd = ['-ojson', 'secrets', 'new', self.name] if self.type is not None: cmd.extend(["--type=%s" % (self.type)]) + if force: + cmd.append('--confirm') cmd.extend(secrets) return self.openshift_cmd(cmd, output=True) @@ -1719,7 +1711,7 @@ class OCSecret(OpenShiftCLI): return {'changed': True, 'msg': 'Would have performed a create.'} - api_rval = ocsecret.create(files, params['contents']) + api_rval = ocsecret.create(files, params['contents'], force=params['force']) # Remove files if files and params['delete_after']: @@ -1736,7 +1728,7 @@ class OCSecret(OpenShiftCLI): ######## # Update ######## - secret = ocsecret.prep_secret(params['files'], params['contents']) + secret = ocsecret.prep_secret(params['files'], params['contents'], force=params['force']) if secret['returncode'] != 0: return {'failed': True, 'msg': secret} diff --git a/roles/lib_openshift/library/oc_service.py b/roles/lib_openshift/library/oc_service.py index 308f45488..769b75e15 100644 --- a/roles/lib_openshift/library/oc_service.py +++ b/roles/lib_openshift/library/oc_service.py @@ -1124,10 +1124,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1137,34 +1133,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_serviceaccount.py b/roles/lib_openshift/library/oc_serviceaccount.py index 68c1fc51c..446987eff 100644 --- a/roles/lib_openshift/library/oc_serviceaccount.py +++ b/roles/lib_openshift/library/oc_serviceaccount.py @@ -1063,10 +1063,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1076,34 +1072,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_serviceaccount_secret.py b/roles/lib_openshift/library/oc_serviceaccount_secret.py index ebc5bf8a2..c7eb1986a 100644 --- a/roles/lib_openshift/library/oc_serviceaccount_secret.py +++ b/roles/lib_openshift/library/oc_serviceaccount_secret.py @@ -1063,10 +1063,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1076,34 +1072,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_user.py b/roles/lib_openshift/library/oc_user.py index d1a20fddc..3a98693b7 100644 --- a/roles/lib_openshift/library/oc_user.py +++ b/roles/lib_openshift/library/oc_user.py @@ -1123,10 +1123,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1136,34 +1132,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_version.py b/roles/lib_openshift/library/oc_version.py index 548c9d8e0..939261526 100644 --- a/roles/lib_openshift/library/oc_version.py +++ b/roles/lib_openshift/library/oc_version.py @@ -1035,10 +1035,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1048,34 +1044,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/library/oc_volume.py b/roles/lib_openshift/library/oc_volume.py index 3826cd8e5..41e7d0ab8 100644 --- a/roles/lib_openshift/library/oc_volume.py +++ b/roles/lib_openshift/library/oc_volume.py @@ -1112,10 +1112,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -1125,34 +1121,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/src/class/oc_obj.py b/roles/lib_openshift/src/class/oc_obj.py index 6f0da3d5c..5e423bea9 100644 --- a/roles/lib_openshift/src/class/oc_obj.py +++ b/roles/lib_openshift/src/class/oc_obj.py @@ -33,7 +33,12 @@ class OCObject(OpenShiftCLI): def delete(self): '''delete the object''' - return self._delete(self.kind, name=self.name, selector=self.selector) + results = self._delete(self.kind, name=self.name, selector=self.selector) + if (results['returncode'] != 0 and 'stderr' in results and + '\"{}\" not found'.format(self.name) in results['stderr']): + results['returncode'] = 0 + + return results def create(self, files=None, content=None): ''' @@ -117,7 +122,8 @@ class OCObject(OpenShiftCLI): if state == 'absent': # verify its not in our results if (params['name'] is not None or params['selector'] is not None) and \ - (len(api_rval['results']) == 0 or len(api_rval['results'][0].get('items', [])) == 0): + (len(api_rval['results']) == 0 or \ + ('items' in api_rval['results'][0] and len(api_rval['results'][0]['items']) == 0)): return {'changed': False, 'state': state} if check_mode: diff --git a/roles/lib_openshift/src/class/oc_secret.py b/roles/lib_openshift/src/class/oc_secret.py index ee83580df..4ee6443e9 100644 --- a/roles/lib_openshift/src/class/oc_secret.py +++ b/roles/lib_openshift/src/class/oc_secret.py @@ -44,7 +44,7 @@ class OCSecret(OpenShiftCLI): '''delete a secret by name''' return self._delete('secrets', self.name) - def create(self, files=None, contents=None): + def create(self, files=None, contents=None, force=False): '''Create a secret ''' if not files: files = Utils.create_tmp_files_from_contents(contents) @@ -53,6 +53,8 @@ class OCSecret(OpenShiftCLI): cmd = ['secrets', 'new', self.name] if self.type is not None: cmd.append("--type=%s" % (self.type)) + if force: + cmd.append('--confirm') cmd.extend(secrets) results = self.openshift_cmd(cmd) @@ -65,7 +67,7 @@ class OCSecret(OpenShiftCLI): This receives a list of file names and converts it into a secret. The secret is then written to disk and passed into the `oc replace` command. ''' - secret = self.prep_secret(files) + secret = self.prep_secret(files, force) if secret['returncode'] != 0: return secret @@ -77,7 +79,7 @@ class OCSecret(OpenShiftCLI): return self._replace(sfile_path, force=force) - def prep_secret(self, files=None, contents=None): + def prep_secret(self, files=None, contents=None, force=False): ''' return what the secret would look like if created This is accomplished by passing -ojson. This will most likely change in the future ''' @@ -88,6 +90,8 @@ class OCSecret(OpenShiftCLI): cmd = ['-ojson', 'secrets', 'new', self.name] if self.type is not None: cmd.extend(["--type=%s" % (self.type)]) + if force: + cmd.append('--confirm') cmd.extend(secrets) return self.openshift_cmd(cmd, output=True) @@ -150,7 +154,7 @@ class OCSecret(OpenShiftCLI): return {'changed': True, 'msg': 'Would have performed a create.'} - api_rval = ocsecret.create(files, params['contents']) + api_rval = ocsecret.create(files, params['contents'], force=params['force']) # Remove files if files and params['delete_after']: @@ -167,7 +171,7 @@ class OCSecret(OpenShiftCLI): ######## # Update ######## - secret = ocsecret.prep_secret(params['files'], params['contents']) + secret = ocsecret.prep_secret(params['files'], params['contents'], force=params['force']) if secret['returncode'] != 0: return {'failed': True, 'msg': secret} diff --git a/roles/lib_openshift/src/lib/base.py b/roles/lib_openshift/src/lib/base.py index b3f01008b..16770b22d 100644 --- a/roles/lib_openshift/src/lib/base.py +++ b/roles/lib_openshift/src/lib/base.py @@ -273,10 +273,6 @@ class OpenShiftCLI(object): elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 cmds.extend(['-n', self.namespace]) - rval = {} - results = '' - err = None - if self.verbose: print(' '.join(cmds)) @@ -286,34 +282,26 @@ class OpenShiftCLI(object): returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex) rval = {"returncode": returncode, - "results": results, "cmd": ' '.join(cmds)} - if returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as verr: - if "No JSON object could be decoded" in verr.args: - err = verr.args - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print("STDOUT: {0}".format(stdout)) - print("STDERR: {0}".format(stderr)) - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds}) + if output_type == 'json': + rval['results'] = {} + if output and stdout: + try: + rval['results'] = json.loads(stdout) + except ValueError as verr: + if "No JSON object could be decoded" in verr.args: + rval['err'] = verr.args + elif output_type == 'raw': + rval['results'] = stdout if output else '' - else: + if self.verbose: + print("STDOUT: {0}".format(stdout)) + print("STDERR: {0}".format(stderr)) + + if 'err' in rval or returncode != 0: rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}}) + "stdout": stdout}) return rval diff --git a/roles/lib_openshift/src/test/unit/test_oc_secret.py b/roles/lib_openshift/src/test/unit/test_oc_secret.py index 09cc4a374..323b3423c 100755 --- a/roles/lib_openshift/src/test/unit/test_oc_secret.py +++ b/roles/lib_openshift/src/test/unit/test_oc_secret.py @@ -48,6 +48,7 @@ class OCSecretTest(unittest.TestCase): 'debug': False, 'files': None, 'delete_after': True, + 'force': False, } # Return values of our mocked function call. These get returned once per call. diff --git a/roles/openshift_default_storage_class/README.md b/roles/openshift_default_storage_class/README.md new file mode 100644 index 000000000..198163127 --- /dev/null +++ b/roles/openshift_default_storage_class/README.md @@ -0,0 +1,39 @@ +openshift_master_storage_class +========= + +A role that deploys configuratons for Openshift StorageClass + +Requirements +------------ + +None + +Role Variables +-------------- + +openshift_storageclass_name: Name of the storage class to create +openshift_storageclass_provisioner: The kubernetes provisioner to use +openshift_storageclass_type: type of storage to use. This is different among clouds/providers + +Dependencies +------------ + + +Example Playbook +---------------- + +- role: openshift_default_storage_class + openshift_storageclass_name: awsEBS + openshift_storageclass_provisioner: kubernetes.io/aws-ebs + openshift_storageclass_type: gp2 + + +License +------- + +Apache + +Author Information +------------------ + +Openshift Operations diff --git a/roles/openshift_default_storage_class/defaults/main.yml b/roles/openshift_default_storage_class/defaults/main.yml new file mode 100644 index 000000000..66ffd2a73 --- /dev/null +++ b/roles/openshift_default_storage_class/defaults/main.yml @@ -0,0 +1,14 @@ +--- +openshift_storageclass_defaults: + aws: + name: gp2 + provisioner: kubernetes.io/aws-ebs + type: gp2 + gce: + name: standard + provisioner: kubernetes.io/gce-pd + type: pd-standard + +openshift_storageclass_name: "{{ openshift_storageclass_defaults[openshift_cloudprovider_kind]['name'] }}" +openshift_storageclass_provisioner: "{{ openshift_storageclass_defaults[openshift_cloudprovider_kind]['provisioner'] }}" +openshift_storageclass_type: "{{ openshift_storageclass_defaults[openshift_cloudprovider_kind]['type'] }}" diff --git a/roles/openshift_default_storage_class/meta/main.yml b/roles/openshift_default_storage_class/meta/main.yml new file mode 100644 index 000000000..d7d57fe39 --- /dev/null +++ b/roles/openshift_default_storage_class/meta/main.yml @@ -0,0 +1,15 @@ +--- +galaxy_info: + author: Openshift Operations + description: This role configures the StorageClass in Openshift + company: Red Hat + license: Apache + min_ansible_version: 2.2 + platforms: + - name: EL + verisons: + - 7 + categories: + - cloud +dependencies: +- role: lib_openshift diff --git a/roles/openshift_default_storage_class/tasks/main.yml b/roles/openshift_default_storage_class/tasks/main.yml new file mode 100644 index 000000000..408fc17c7 --- /dev/null +++ b/roles/openshift_default_storage_class/tasks/main.yml @@ -0,0 +1,19 @@ +--- +# Install default storage classes in GCE & AWS +- name: Ensure storageclass object + oc_obj: + kind: storageclass + name: "{{ openshift_storageclass_name }}" + content: + path: /tmp/openshift_storageclass + data: + kind: StorageClass + apiVersion: storage.k8s.io/v1beta1 + metadata: + name: "{{ openshift_storageclass_name }}" + annotations: + storageclass.beta.kubernetes.io/is-default-class: "true" + provisioner: "{{ openshift_storageclass_provisioner }}" + parameters: + type: "{{ openshift_storageclass_type }}" + run_once: true diff --git a/roles/openshift_default_storage_class/vars/main.yml b/roles/openshift_default_storage_class/vars/main.yml new file mode 100644 index 000000000..ed97d539c --- /dev/null +++ b/roles/openshift_default_storage_class/vars/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/openshift_etcd_facts/vars/main.yml b/roles/openshift_etcd_facts/vars/main.yml index 82db36eba..b3ecd57a6 100644 --- a/roles/openshift_etcd_facts/vars/main.yml +++ b/roles/openshift_etcd_facts/vars/main.yml @@ -5,6 +5,7 @@ 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' if not openshift.common.is_etcd_system_container | bool else '/var/lib/etcd/etcd.etcd/etc' }}" +etcd_cert_config_dir: "/etc/etcd" +etcd_system_container_cert_config_dir: /var/lib/etcd/etcd.etcd/etc etcd_peer_url_scheme: https etcd_url_scheme: https diff --git a/roles/openshift_health_checker/openshift_checks/docker_image_availability.py b/roles/openshift_health_checker/openshift_checks/docker_image_availability.py index 4588ed634..27e6fe383 100644 --- a/roles/openshift_health_checker/openshift_checks/docker_image_availability.py +++ b/roles/openshift_health_checker/openshift_checks/docker_image_availability.py @@ -1,8 +1,9 @@ # pylint: disable=missing-docstring from openshift_checks import OpenShiftCheck, get_var +from openshift_checks.mixins import DockerHostMixin -class DockerImageAvailability(OpenShiftCheck): +class DockerImageAvailability(DockerHostMixin, OpenShiftCheck): """Check that required Docker images are available. This check attempts to ensure that required docker images are @@ -36,19 +37,11 @@ class DockerImageAvailability(OpenShiftCheck): def run(self, tmp, task_vars): msg, failed, changed = self.ensure_dependencies(task_vars) - - # exit early if Skopeo update fails if failed: - if "No package matching" in msg: - msg = "Ensure that all required dependencies can be installed via `yum`.\n" return { "failed": True, "changed": changed, - "msg": ( - "Unable to update or install required dependency packages on this host;\n" - "These are required in order to check Docker image availability:" - "\n {deps}\n{msg}" - ).format(deps=',\n '.join(self.dependencies), msg=msg), + "msg": "Some dependencies are required in order to check Docker image availability.\n" + msg } required_images = self.required_images(task_vars) @@ -168,12 +161,3 @@ class DockerImageAvailability(OpenShiftCheck): args = {"_raw_params": cmd_str} result = self.module_executor("command", args, task_vars) return not result.get("failed", False) and result.get("rc", 0) == 0 - - # ensures that the skopeo and python-docker-py packages exist - # check is skipped on atomic installations - def ensure_dependencies(self, task_vars): - if get_var(task_vars, "openshift", "common", "is_atomic"): - return "", False, False - - result = self.module_executor("yum", {"name": self.dependencies, "state": "latest"}, task_vars) - return result.get("msg", ""), result.get("failed", False) or result.get("rc", 0) != 0, result.get("changed") diff --git a/roles/openshift_health_checker/openshift_checks/docker_storage.py b/roles/openshift_health_checker/openshift_checks/docker_storage.py new file mode 100644 index 000000000..7f1751b36 --- /dev/null +++ b/roles/openshift_health_checker/openshift_checks/docker_storage.py @@ -0,0 +1,185 @@ +"""Check Docker storage driver and usage.""" +import json +import re +from openshift_checks import OpenShiftCheck, OpenShiftCheckException, get_var +from openshift_checks.mixins import DockerHostMixin + + +class DockerStorage(DockerHostMixin, OpenShiftCheck): + """Check Docker storage driver compatibility. + + This check ensures that Docker is using a supported storage driver, + and that loopback is not being used (if using devicemapper). + Also that storage usage is not above threshold. + """ + + name = "docker_storage" + tags = ["pre-install", "health", "preflight"] + + dependencies = ["python-docker-py"] + storage_drivers = ["devicemapper", "overlay2"] + max_thinpool_data_usage_percent = 90.0 + max_thinpool_meta_usage_percent = 90.0 + + # pylint: disable=too-many-return-statements + # Reason: permanent stylistic exception; + # it is clearer to return on failures and there are just many ways to fail here. + def run(self, tmp, task_vars): + msg, failed, changed = self.ensure_dependencies(task_vars) + if failed: + return { + "failed": True, + "changed": changed, + "msg": "Some dependencies are required in order to query docker storage on host:\n" + msg + } + + # attempt to get the docker info hash from the API + info = self.execute_module("docker_info", {}, task_vars) + if info.get("failed"): + return {"failed": True, "changed": changed, + "msg": "Failed to query Docker API. Is docker running on this host?"} + if not info.get("info"): # this would be very strange + return {"failed": True, "changed": changed, + "msg": "Docker API query missing info:\n{}".format(json.dumps(info))} + info = info["info"] + + # check if the storage driver we saw is valid + driver = info.get("Driver", "[NONE]") + if driver not in self.storage_drivers: + msg = ( + "Detected unsupported Docker storage driver '{driver}'.\n" + "Supported storage drivers are: {drivers}" + ).format(driver=driver, drivers=', '.join(self.storage_drivers)) + return {"failed": True, "changed": changed, "msg": msg} + + # driver status info is a list of tuples; convert to dict and validate based on driver + driver_status = {item[0]: item[1] for item in info.get("DriverStatus", [])} + if driver == "devicemapper": + if driver_status.get("Data loop file"): + msg = ( + "Use of loopback devices with the Docker devicemapper storage driver\n" + "(the default storage configuration) is unsupported in production.\n" + "Please use docker-storage-setup to configure a backing storage volume.\n" + "See http://red.ht/2rNperO for further information." + ) + return {"failed": True, "changed": changed, "msg": msg} + result = self._check_dm_usage(driver_status, task_vars) + result['changed'] = result.get('changed', False) or changed + return result + + # TODO(lmeyer): determine how to check usage for overlay2 + + return {"changed": changed} + + def _check_dm_usage(self, driver_status, task_vars): + """ + Backing assumptions: We expect devicemapper to be backed by an auto-expanding thin pool + implemented as an LV in an LVM2 VG. This is how docker-storage-setup currently configures + devicemapper storage. The LV is "thin" because it does not use all available storage + from its VG, instead expanding as needed; so to determine available space, we gather + current usage as the Docker API reports for the driver as well as space available for + expansion in the pool's VG. + Usage within the LV is divided into pools allocated to data and metadata, either of which + could run out of space first; so we check both. + """ + vals = dict( + vg_free=self._get_vg_free(driver_status.get("Pool Name"), task_vars), + data_used=driver_status.get("Data Space Used"), + data_total=driver_status.get("Data Space Total"), + metadata_used=driver_status.get("Metadata Space Used"), + metadata_total=driver_status.get("Metadata Space Total"), + ) + + # convert all human-readable strings to bytes + for key, value in vals.copy().items(): + try: + vals[key + "_bytes"] = self._convert_to_bytes(value) + except ValueError as err: # unlikely to hit this from API info, but just to be safe + return { + "failed": True, + "values": vals, + "msg": "Could not interpret {} value '{}' as bytes: {}".format(key, value, str(err)) + } + + # determine the threshold percentages which usage should not exceed + for name, default in [("data", self.max_thinpool_data_usage_percent), + ("metadata", self.max_thinpool_meta_usage_percent)]: + percent = get_var(task_vars, "max_thinpool_" + name + "_usage_percent", default=default) + try: + vals[name + "_threshold"] = float(percent) + except ValueError: + return { + "failed": True, + "msg": "Specified thinpool {} usage limit '{}' is not a percentage".format(name, percent) + } + + # test whether the thresholds are exceeded + messages = [] + for name in ["data", "metadata"]: + vals[name + "_pct_used"] = 100 * vals[name + "_used_bytes"] / ( + vals[name + "_total_bytes"] + vals["vg_free_bytes"]) + if vals[name + "_pct_used"] > vals[name + "_threshold"]: + messages.append( + "Docker thinpool {name} usage percentage {pct:.1f} " + "is higher than threshold {thresh:.1f}.".format( + name=name, + pct=vals[name + "_pct_used"], + thresh=vals[name + "_threshold"], + )) + vals["failed"] = True + + vals["msg"] = "\n".join(messages or ["Thinpool usage is within thresholds."]) + return vals + + def _get_vg_free(self, pool, task_vars): + # Determine which VG to examine according to the pool name, the only indicator currently + # available from the Docker API driver info. We assume a name that looks like + # "vg--name-docker--pool"; vg and lv names with inner hyphens doubled, joined by a hyphen. + match = re.match(r'((?:[^-]|--)+)-(?!-)', pool) # matches up to the first single hyphen + if not match: # unlikely, but... be clear if we assumed wrong + raise OpenShiftCheckException( + "This host's Docker reports it is using a storage pool named '{}'.\n" + "However this name does not have the expected format of 'vgname-lvname'\n" + "so the available storage in the VG cannot be determined.".format(pool) + ) + vg_name = match.groups()[0].replace("--", "-") + vgs_cmd = "/sbin/vgs --noheadings -o vg_free --select vg_name=" + vg_name + # should return free space like " 12.00g" if the VG exists; empty if it does not + + ret = self.execute_module("command", {"_raw_params": vgs_cmd}, task_vars) + if ret.get("failed") or ret.get("rc", 0) != 0: + raise OpenShiftCheckException( + "Is LVM installed? Failed to run /sbin/vgs " + "to determine docker storage usage:\n" + ret.get("msg", "") + ) + size = ret.get("stdout", "").strip() + if not size: + raise OpenShiftCheckException( + "This host's Docker reports it is using a storage pool named '{pool}'.\n" + "which we expect to come from local VG '{vg}'.\n" + "However, /sbin/vgs did not find this VG. Is Docker for this host" + "running and using the storage on the host?".format(pool=pool, vg=vg_name) + ) + return size + + @staticmethod + def _convert_to_bytes(string): + units = dict( + b=1, + k=1024, + m=1024**2, + g=1024**3, + t=1024**4, + p=1024**5, + ) + string = string or "" + match = re.match(r'(\d+(?:\.\d+)?)\s*(\w)?', string) # float followed by optional unit + if not match: + raise ValueError("Cannot convert to a byte size: " + string) + + number, unit = match.groups() + multiplier = 1 if not unit else units.get(unit.lower()) + if not multiplier: + raise ValueError("Cannot convert to a byte size: " + string) + + return float(number) * multiplier diff --git a/roles/openshift_health_checker/openshift_checks/mixins.py b/roles/openshift_health_checker/openshift_checks/mixins.py index 20d160eaf..7f3d78cc4 100644 --- a/roles/openshift_health_checker/openshift_checks/mixins.py +++ b/roles/openshift_health_checker/openshift_checks/mixins.py @@ -1,4 +1,3 @@ -# pylint: disable=missing-docstring,too-few-public-methods """ Mixin classes meant to be used with subclasses of OpenShiftCheck. """ @@ -8,8 +7,49 @@ from openshift_checks import get_var class NotContainerizedMixin(object): """Mixin for checks that are only active when not in containerized mode.""" + # permanent # pylint: disable=too-few-public-methods + # Reason: The mixin is not intended to stand on its own as a class. @classmethod def is_active(cls, task_vars): + """Only run on non-containerized hosts.""" is_containerized = get_var(task_vars, "openshift", "common", "is_containerized") return super(NotContainerizedMixin, cls).is_active(task_vars) and not is_containerized + + +class DockerHostMixin(object): + """Mixin for checks that are only active on hosts that require Docker.""" + + dependencies = [] + + @classmethod + def is_active(cls, task_vars): + """Only run on hosts that depend on Docker.""" + is_containerized = get_var(task_vars, "openshift", "common", "is_containerized") + is_node = "nodes" in get_var(task_vars, "group_names", default=[]) + return super(DockerHostMixin, cls).is_active(task_vars) and (is_containerized or is_node) + + def ensure_dependencies(self, task_vars): + """ + Ensure that docker-related packages exist, but not on atomic hosts + (which would not be able to install but should already have them). + Returns: msg, failed, changed + """ + if get_var(task_vars, "openshift", "common", "is_atomic"): + return "", False, False + + # NOTE: we would use the "package" module but it's actually an action plugin + # and it's not clear how to invoke one of those. This is about the same anyway: + pkg_manager = get_var(task_vars, "ansible_pkg_mgr", default="yum") + result = self.module_executor(pkg_manager, {"name": self.dependencies, "state": "present"}, task_vars) + msg = result.get("msg", "") + if result.get("failed"): + if "No package matching" in msg: + msg = "Ensure that all required dependencies can be installed via `yum`.\n" + msg = ( + "Unable to install required packages on this host:\n" + " {deps}\n{msg}" + ).format(deps=',\n '.join(self.dependencies), msg=msg) + failed = result.get("failed", False) or result.get("rc", 0) != 0 + changed = result.get("changed", False) + return msg, failed, changed diff --git a/roles/openshift_health_checker/test/docker_image_availability_test.py b/roles/openshift_health_checker/test/docker_image_availability_test.py index 0379cafb5..197c65f51 100644 --- a/roles/openshift_health_checker/test/docker_image_availability_test.py +++ b/roles/openshift_health_checker/test/docker_image_availability_test.py @@ -3,19 +3,25 @@ import pytest from openshift_checks.docker_image_availability import DockerImageAvailability -@pytest.mark.parametrize('deployment_type,is_active', [ - ("origin", True), - ("openshift-enterprise", True), - ("enterprise", False), - ("online", False), - ("invalid", False), - ("", False), +@pytest.mark.parametrize('deployment_type, is_containerized, group_names, expect_active', [ + ("origin", True, [], True), + ("openshift-enterprise", True, [], True), + ("enterprise", True, [], False), + ("online", True, [], False), + ("invalid", True, [], False), + ("", True, [], False), + ("origin", False, [], False), + ("openshift-enterprise", False, [], False), + ("origin", False, ["nodes", "masters"], True), + ("openshift-enterprise", False, ["etcd"], False), ]) -def test_is_active(deployment_type, is_active): +def test_is_active(deployment_type, is_containerized, group_names, expect_active): task_vars = dict( + openshift=dict(common=dict(is_containerized=is_containerized)), openshift_deployment_type=deployment_type, + group_names=group_names, ) - assert DockerImageAvailability.is_active(task_vars=task_vars) == is_active + assert DockerImageAvailability.is_active(task_vars=task_vars) == expect_active @pytest.mark.parametrize("is_containerized,is_atomic", [ diff --git a/roles/openshift_health_checker/test/docker_storage_test.py b/roles/openshift_health_checker/test/docker_storage_test.py new file mode 100644 index 000000000..292a323db --- /dev/null +++ b/roles/openshift_health_checker/test/docker_storage_test.py @@ -0,0 +1,224 @@ +import pytest + +from openshift_checks import OpenShiftCheckException +from openshift_checks.docker_storage import DockerStorage + + +def dummy_check(execute_module=None): + def dummy_exec(self, status, task_vars): + raise Exception("dummy executor called") + return DockerStorage(execute_module=execute_module or dummy_exec) + + +@pytest.mark.parametrize('is_containerized, group_names, is_active', [ + (False, ["masters", "etcd"], False), + (False, ["masters", "nodes"], True), + (True, ["etcd"], True), +]) +def test_is_active(is_containerized, group_names, is_active): + task_vars = dict( + openshift=dict(common=dict(is_containerized=is_containerized)), + group_names=group_names, + ) + assert DockerStorage.is_active(task_vars=task_vars) == is_active + + +non_atomic_task_vars = {"openshift": {"common": {"is_atomic": False}}} + + +@pytest.mark.parametrize('docker_info, failed, expect_msg', [ + ( + dict(failed=True, msg="Error connecting: Error while fetching server API version"), + True, + ["Is docker running on this host?"], + ), + ( + dict(msg="I have no info"), + True, + ["missing info"], + ), + ( + dict(info={ + "Driver": "devicemapper", + "DriverStatus": [("Pool Name", "docker-docker--pool")], + }), + False, + [], + ), + ( + dict(info={ + "Driver": "devicemapper", + "DriverStatus": [("Data loop file", "true")], + }), + True, + ["loopback devices with the Docker devicemapper storage driver"], + ), + ( + dict(info={ + "Driver": "overlay2", + "DriverStatus": [] + }), + False, + [], + ), + ( + dict(info={ + "Driver": "overlay", + }), + True, + ["unsupported Docker storage driver"], + ), + ( + dict(info={ + "Driver": "unsupported", + }), + True, + ["unsupported Docker storage driver"], + ), +]) +def test_check_storage_driver(docker_info, failed, expect_msg): + def execute_module(module_name, args, tmp=None, task_vars=None): + if module_name == "yum": + return {} + if module_name != "docker_info": + raise ValueError("not expecting module " + module_name) + return docker_info + + check = dummy_check(execute_module=execute_module) + check._check_dm_usage = lambda status, task_vars: dict() # stub out for this test + result = check.run(tmp=None, task_vars=non_atomic_task_vars) + + if failed: + assert result["failed"] + else: + assert not result.get("failed", False) + + for word in expect_msg: + assert word in result["msg"] + + +enough_space = { + "Pool Name": "docker--vg-docker--pool", + "Data Space Used": "19.92 MB", + "Data Space Total": "8.535 GB", + "Metadata Space Used": "40.96 kB", + "Metadata Space Total": "25.17 MB", +} + +not_enough_space = { + "Pool Name": "docker--vg-docker--pool", + "Data Space Used": "10 GB", + "Data Space Total": "10 GB", + "Metadata Space Used": "42 kB", + "Metadata Space Total": "43 kB", +} + + +@pytest.mark.parametrize('task_vars, driver_status, vg_free, success, expect_msg', [ + ( + {"max_thinpool_data_usage_percent": "not a float"}, + enough_space, + "12g", + False, + ["is not a percentage"], + ), + ( + {}, + {}, # empty values from driver status + "bogus", # also does not parse as bytes + False, + ["Could not interpret", "as bytes"], + ), + ( + {}, + enough_space, + "12.00g", + True, + [], + ), + ( + {}, + not_enough_space, + "0.00", + False, + ["data usage", "metadata usage", "higher than threshold"], + ), +]) +def test_dm_usage(task_vars, driver_status, vg_free, success, expect_msg): + check = dummy_check() + check._get_vg_free = lambda pool, task_vars: vg_free + result = check._check_dm_usage(driver_status, task_vars) + result_success = not result.get("failed") + + assert result_success is success + for msg in expect_msg: + assert msg in result["msg"] + + +@pytest.mark.parametrize('pool, command_returns, raises, returns', [ + ( + "foo-bar", + { # vgs missing + "msg": "[Errno 2] No such file or directory", + "failed": True, + "cmd": "/sbin/vgs", + "rc": 2, + }, + "Failed to run /sbin/vgs", + None, + ), + ( + "foo", # no hyphen in name - should not happen + {}, + "name does not have the expected format", + None, + ), + ( + "foo-bar", + dict(stdout=" 4.00g\n"), + None, + "4.00g", + ), + ( + "foo-bar", + dict(stdout="\n"), # no matching VG + "vgs did not find this VG", + None, + ) +]) +def test_vg_free(pool, command_returns, raises, returns): + def execute_module(module_name, args, tmp=None, task_vars=None): + if module_name != "command": + raise ValueError("not expecting module " + module_name) + return command_returns + + check = dummy_check(execute_module=execute_module) + if raises: + with pytest.raises(OpenShiftCheckException) as err: + check._get_vg_free(pool, {}) + assert raises in str(err.value) + else: + ret = check._get_vg_free(pool, {}) + assert ret == returns + + +@pytest.mark.parametrize('string, expect_bytes', [ + ("12", 12.0), + ("12 k", 12.0 * 1024), + ("42.42 MB", 42.42 * 1024**2), + ("12g", 12.0 * 1024**3), +]) +def test_convert_to_bytes(string, expect_bytes): + got = DockerStorage._convert_to_bytes(string) + assert got == expect_bytes + + +@pytest.mark.parametrize('string', [ + "bork", + "42 Qs", +]) +def test_convert_to_bytes_error(string): + with pytest.raises(ValueError) as err: + DockerStorage._convert_to_bytes(string) + assert "Cannot convert" in str(err.value) + assert string in str(err.value) diff --git a/roles/openshift_hosted/tasks/registry/storage/object_storage.yml b/roles/openshift_hosted/tasks/registry/storage/object_storage.yml index 3dde83bee..8aaba0f3c 100644 --- a/roles/openshift_hosted/tasks/registry/storage/object_storage.yml +++ b/roles/openshift_hosted/tasks/registry/storage/object_storage.yml @@ -1,20 +1,4 @@ --- -- name: Assert supported openshift.hosted.registry.storage.provider - assert: - that: - - openshift.hosted.registry.storage.provider in ['azure_blob', 's3', 'swift'] - msg: > - Object Storage Provider: "{{ openshift.hosted.registry.storage.provider }}" - is not currently supported - -- name: Assert implemented openshift.hosted.registry.storage.provider - assert: - that: - - openshift.hosted.registry.storage.provider not in ['azure_blob', 'swift'] - msg: > - Support for provider: "{{ openshift.hosted.registry.storage.provider }}" - not implemented yet - - include: s3.yml when: openshift.hosted.registry.storage.provider == 's3' diff --git a/roles/openshift_logging/defaults/main.yml b/roles/openshift_logging/defaults/main.yml index 573cbdd09..3c343c9dc 100644 --- a/roles/openshift_logging/defaults/main.yml +++ b/roles/openshift_logging/defaults/main.yml @@ -87,7 +87,7 @@ openshift_logging_es_cpu_limit: null # the logging appenders for the root loggers to write ES logs. Valid values: 'file', 'console' openshift_logging_es_log_appenders: ['file'] openshift_logging_es_memory_limit: "{{ openshift_hosted_logging_elasticsearch_instance_ram | default('8Gi') }}" -openshift_logging_es_pv_selector: null +openshift_logging_es_pv_selector: "{{ openshift_hosted_logging_storage_labels | default(null) }}" openshift_logging_es_pvc_dynamic: "{{ openshift_hosted_logging_elasticsearch_pvc_dynamic | default(False) }}" openshift_logging_es_pvc_size: "{{ openshift_hosted_logging_elasticsearch_pvc_size | default('') }}" openshift_logging_es_pvc_prefix: "{{ openshift_hosted_logging_elasticsearch_pvc_prefix | default('logging-es') }}" @@ -126,7 +126,7 @@ openshift_logging_es_ops_client_key: /etc/fluent/keys/key openshift_logging_es_ops_cluster_size: "{{ openshift_hosted_logging_elasticsearch_ops_cluster_size | default(1) }}" openshift_logging_es_ops_cpu_limit: null openshift_logging_es_ops_memory_limit: "{{ openshift_hosted_logging_elasticsearch_ops_instance_ram | default('8Gi') }}" -openshift_logging_es_ops_pv_selector: None +openshift_logging_es_ops_pv_selector: "{{ openshift_hosted_loggingops_storage_labels | default(null) }}" openshift_logging_es_ops_pvc_dynamic: "{{ openshift_hosted_logging_elasticsearch_ops_pvc_dynamic | default(False) }}" openshift_logging_es_ops_pvc_size: "{{ openshift_hosted_logging_elasticsearch_ops_pvc_size | default('') }}" openshift_logging_es_ops_pvc_prefix: "{{ openshift_hosted_logging_elasticsearch_ops_pvc_prefix | default('logging-es-ops') }}" diff --git a/roles/openshift_logging/tasks/generate_certs.yaml b/roles/openshift_logging/tasks/generate_certs.yaml index 040356e3d..9c8f0986a 100644 --- a/roles/openshift_logging/tasks/generate_certs.yaml +++ b/roles/openshift_logging/tasks/generate_certs.yaml @@ -17,7 +17,7 @@ - name: Generate certificates command: > - {{ openshift.common.admin_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig ca create-signer-cert + {{ openshift.common.client_binary }} adm --config={{ mktemp.stdout }}/admin.kubeconfig ca create-signer-cert --key={{generated_certs_dir}}/ca.key --cert={{generated_certs_dir}}/ca.crt --serial={{generated_certs_dir}}/ca.serial.txt --name=logging-signer-test check_mode: no diff --git a/roles/openshift_logging/tasks/procure_server_certs.yaml b/roles/openshift_logging/tasks/procure_server_certs.yaml index 7ab140357..00de0ca06 100644 --- a/roles/openshift_logging/tasks/procure_server_certs.yaml +++ b/roles/openshift_logging/tasks/procure_server_certs.yaml @@ -27,7 +27,7 @@ - name: Creating signed server cert and key for {{ cert_info.procure_component }} command: > - {{ openshift.common.admin_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig ca create-server-cert + {{ openshift.common.client_binary }} adm --config={{ mktemp.stdout }}/admin.kubeconfig ca create-server-cert --key={{generated_certs_dir}}/{{cert_info.procure_component}}.key --cert={{generated_certs_dir}}/{{cert_info.procure_component}}.crt --hostnames={{cert_info.hostnames|quote}} --signer-cert={{generated_certs_dir}}/ca.crt --signer-key={{generated_certs_dir}}/ca.key --signer-serial={{generated_certs_dir}}/ca.serial.txt diff --git a/roles/openshift_logging_elasticsearch/tasks/main.yaml b/roles/openshift_logging_elasticsearch/tasks/main.yaml index 7e88a7498..f1d15b76d 100644 --- a/roles/openshift_logging_elasticsearch/tasks/main.yaml +++ b/roles/openshift_logging_elasticsearch/tasks/main.yaml @@ -217,7 +217,7 @@ access_modes: "{{ openshift_logging_elasticsearch_pvc_access_modes | list }}" pv_selector: "{{ openshift_logging_elasticsearch_pvc_pv_selector }}" annotations: - volume.alpha.kubernetes.io/storage-class: "dynamic" + volume.beta.kubernetes.io/storage-class: "dynamic" when: - openshift_logging_elasticsearch_storage_type == "pvc" - openshift_logging_elasticsearch_pvc_dynamic diff --git a/roles/openshift_logging_elasticsearch/templates/es.j2 b/roles/openshift_logging_elasticsearch/templates/es.j2 index e129205ca..bd2289f0d 100644 --- a/roles/openshift_logging_elasticsearch/templates/es.j2 +++ b/roles/openshift_logging_elasticsearch/templates/es.j2 @@ -84,6 +84,9 @@ spec: name: "RECOVER_AFTER_TIME" value: "{{openshift_logging_elasticsearch_recover_after_time}}" - + name: "READINESS_PROBE_TIMEOUT" + value: "30" + - name: "IS_MASTER" value: "{% if deploy_type in ['data-master', 'master'] %}true{% else %}false{% endif %}" @@ -104,8 +107,8 @@ spec: exec: command: - "/usr/share/elasticsearch/probe/readiness.sh" - initialDelaySeconds: 5 - timeoutSeconds: 4 + initialDelaySeconds: 10 + timeoutSeconds: 30 periodSeconds: 5 volumes: - name: elasticsearch diff --git a/roles/openshift_logging_kibana/tasks/main.yaml b/roles/openshift_logging_kibana/tasks/main.yaml index d13255386..bae55ffaa 100644 --- a/roles/openshift_logging_kibana/tasks/main.yaml +++ b/roles/openshift_logging_kibana/tasks/main.yaml @@ -43,6 +43,31 @@ kibana_name: "{{ 'logging-kibana' ~ ( (openshift_logging_kibana_ops_deployment | default(false) | bool) | ternary('-ops', '')) }}" kibana_component: "{{ 'kibana' ~ ( (openshift_logging_kibana_ops_deployment | default(false) | bool) | ternary('-ops', '')) }}" +# Check {{ generated_certs_dir }} for session_secret and oauth_secret +- name: Checking for session_secret + stat: path="{{generated_certs_dir}}/session_secret" + register: session_secret_file + +- name: Checking for oauth_secret + stat: path="{{generated_certs_dir}}/oauth_secret" + register: oauth_secret_file + +# gen session_secret if necessary +- name: Generate session secret + copy: + content: "{{ 200 | oo_random_word }}" + dest: "{{ generated_certs_dir }}/session_secret" + when: + - not session_secret_file.stat.exists + +# gen oauth_secret if necessary +- name: Generate oauth secret + copy: + content: "{{ 64 | oo_random_word }}" + dest: "{{ generated_certs_dir }}/oauth_secret" + when: + - not oauth_secret_file.stat.exists + - name: Retrieving the cert to use when generating secrets for the logging components slurp: src: "{{ generated_certs_dir }}/{{ item.file }}" @@ -52,6 +77,8 @@ - { name: "kibana_internal_key", file: "kibana-internal.key"} - { name: "kibana_internal_cert", file: "kibana-internal.crt"} - { name: "server_tls", file: "server-tls.json"} + - { name: "session_secret", file: "session_secret" } + - { name: "oauth_secret", file: "oauth_secret" } # services - name: Set {{ kibana_name }} service @@ -120,19 +147,16 @@ files: - "{{ tempdir }}/templates/kibana-route.yaml" -# gen session_secret -- if necessary -# TODO: make idempotent -- name: Generate proxy session - set_fact: - session_secret: "{{ 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' | random_word(200) }}" - check_mode: no +# preserve list of current hostnames +- name: Get current oauthclient hostnames + oc_obj: + state: list + name: kibana-proxy + namespace: "{{ openshift_logging_namespace }}" + kind: oauthclient + register: oauth_client_list -# gen oauth_secret -- if necessary -# TODO: make idempotent -- name: Generate oauth client secret - set_fact: - oauth_secret: "{{ 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' | random_word(64) }}" - check_mode: no +- set_fact: proxy_hostnames={{ oauth_client_list.results.results[0].redirectURIs | default ([]) + ['https://' ~ openshift_logging_kibana_hostname] }} # create oauth client - name: Create oauth-client template @@ -140,8 +164,8 @@ src: oauth-client.j2 dest: "{{ tempdir }}/templates/oauth-client.yml" vars: - kibana_hostname: "{{ openshift_logging_kibana_hostname }}" - secret: "{{ oauth_secret }}" + kibana_hostnames: "{{ proxy_hostnames | unique }}" + secret: "{{ key_pairs | entry_from_named_pair('oauth_secret') | b64decode }}" - name: Set kibana-proxy oauth-client oc_obj: @@ -183,9 +207,9 @@ # path: "{{ generated_certs_dir }}/server-tls.json" contents: - path: oauth-secret - data: "{{ oauth_secret }}" + data: "{{ key_pairs | entry_from_named_pair('oauth_secret') | b64decode }}" - path: session-secret - data: "{{ session_secret }}" + data: "{{ key_pairs | entry_from_named_pair('session_secret') | b64decode }}" - path: server-key data: "{{ key_pairs | entry_from_named_pair('kibana_internal_key') | b64decode }}" - path: server-cert diff --git a/roles/openshift_logging_kibana/templates/oauth-client.j2 b/roles/openshift_logging_kibana/templates/oauth-client.j2 index 6767f6d89..c80ff3d30 100644 --- a/roles/openshift_logging_kibana/templates/oauth-client.j2 +++ b/roles/openshift_logging_kibana/templates/oauth-client.j2 @@ -4,9 +4,11 @@ metadata: name: kibana-proxy labels: logging-infra: support -secret: {{secret}} +secret: {{ secret }} redirectURIs: -- https://{{kibana_hostname}} +{% for host in kibana_hostnames %} +- {{ host }} +{% endfor %} scopeRestrictions: - literals: - user:info diff --git a/roles/openshift_metrics/defaults/main.yaml b/roles/openshift_metrics/defaults/main.yaml index 1d3db8a1a..467db34c8 100644 --- a/roles/openshift_metrics/defaults/main.yaml +++ b/roles/openshift_metrics/defaults/main.yaml @@ -16,6 +16,7 @@ openshift_metrics_hawkular_nodeselector: "" openshift_metrics_cassandra_replicas: 1 openshift_metrics_cassandra_storage_type: "{{ openshift_hosted_metrics_storage_kind | default('emptydir') }}" openshift_metrics_cassandra_pvc_size: "{{ openshift_hosted_metrics_storage_volume_size | default('10Gi') }}" +openshift_metrics_cassandra_pv_selector: "{{ openshift_hosted_metrics_storage_labels | default(null) }}" openshift_metrics_cassandra_limits_memory: 2G openshift_metrics_cassandra_limits_cpu: null openshift_metrics_cassandra_requests_memory: 1G diff --git a/roles/openshift_metrics/tasks/generate_certificates.yaml b/roles/openshift_metrics/tasks/generate_certificates.yaml index 7af3f9467..3dc15d58b 100644 --- a/roles/openshift_metrics/tasks/generate_certificates.yaml +++ b/roles/openshift_metrics/tasks/generate_certificates.yaml @@ -1,7 +1,7 @@ --- - name: generate ca certificate chain command: > - {{ openshift.common.admin_binary }} ca create-signer-cert + {{ openshift.common.client_binary }} adm ca create-signer-cert --config={{ mktemp.stdout }}/admin.kubeconfig --key='{{ mktemp.stdout }}/ca.key' --cert='{{ mktemp.stdout }}/ca.crt' diff --git a/roles/openshift_metrics/tasks/install_cassandra.yaml b/roles/openshift_metrics/tasks/install_cassandra.yaml index 3b4e8560f..62b7f52cb 100644 --- a/roles/openshift_metrics/tasks/install_cassandra.yaml +++ b/roles/openshift_metrics/tasks/install_cassandra.yaml @@ -23,7 +23,7 @@ changed_when: false - set_fact: openshift_metrics_cassandra_pvc_prefix="hawkular-metrics" - when: not openshift_metrics_cassandra_pvc_prefix or openshift_metrics_cassandra_pvc_prefix == '' + when: "not openshift_metrics_cassandra_pvc_prefix or openshift_metrics_cassandra_pvc_prefix == ''" - name: generate hawkular-cassandra persistent volume claims template: @@ -35,6 +35,7 @@ metrics-infra: hawkular-cassandra access_modes: "{{ openshift_metrics_cassandra_pvc_access | list }}" size: "{{ openshift_metrics_cassandra_pvc_size }}" + pv_selector: "{{ openshift_metrics_cassandra_pv_selector }}" with_sequence: count={{ openshift_metrics_cassandra_replicas }} when: - openshift_metrics_cassandra_storage_type != 'emptydir' @@ -50,9 +51,10 @@ labels: metrics-infra: hawkular-cassandra annotations: - volume.alpha.kubernetes.io/storage-class: dynamic + volume.beta.kubernetes.io/storage-class: dynamic access_modes: "{{ openshift_metrics_cassandra_pvc_access | list }}" size: "{{ openshift_metrics_cassandra_pvc_size }}" + pv_selector: "{{ openshift_metrics_cassandra_pv_selector }}" with_sequence: count={{ openshift_metrics_cassandra_replicas }} when: openshift_metrics_cassandra_storage_type == 'dynamic' changed_when: false diff --git a/roles/openshift_metrics/tasks/setup_certificate.yaml b/roles/openshift_metrics/tasks/setup_certificate.yaml index 199968579..2d880f4d6 100644 --- a/roles/openshift_metrics/tasks/setup_certificate.yaml +++ b/roles/openshift_metrics/tasks/setup_certificate.yaml @@ -1,7 +1,7 @@ --- - name: generate {{ component }} keys command: > - {{ openshift.common.admin_binary }} ca create-server-cert + {{ openshift.common.client_binary }} adm ca create-server-cert --config={{ mktemp.stdout }}/admin.kubeconfig --key='{{ mktemp.stdout }}/{{ component }}.key' --cert='{{ mktemp.stdout }}/{{ component }}.crt' diff --git a/roles/openshift_metrics/templates/pvc.j2 b/roles/openshift_metrics/templates/pvc.j2 index c2e56ba21..0b801b33f 100644 --- a/roles/openshift_metrics/templates/pvc.j2 +++ b/roles/openshift_metrics/templates/pvc.j2 @@ -18,6 +18,13 @@ metadata: {% endfor %} {% endif %} spec: +{% if pv_selector is defined and pv_selector is mapping %} + selector: + matchLabels: +{% for key,value in pv_selector.iteritems() %} + {{key}}: {{value}} +{% endfor %} +{% endif %} accessModes: {% for mode in access_modes %} - {{ mode }} diff --git a/roles/openshift_node/handlers/main.yml b/roles/openshift_node/handlers/main.yml index 4dcf1eef8..a6bd12d4e 100644 --- a/roles/openshift_node/handlers/main.yml +++ b/roles/openshift_node/handlers/main.yml @@ -1,6 +1,8 @@ --- - name: restart openvswitch - systemd: name=openvswitch state=restarted + systemd: + name: openvswitch + state: restarted when: (not skip_node_svc_handlers | default(False) | bool) and not (ovs_service_status_changed | default(false) | bool) and openshift.common.use_openshift_sdn | bool notify: - restart openvswitch pause @@ -10,8 +12,13 @@ when: (not skip_node_svc_handlers | default(False) | bool) and openshift.common.is_containerized | bool - name: restart node - systemd: name={{ openshift.common.service_type }}-node state=restarted + systemd: + name: "{{ openshift.common.service_type }}-node" + state: restarted when: (not skip_node_svc_handlers | default(False) | bool) and not (node_service_status_changed | default(false) | bool) - name: reload sysctl.conf command: /sbin/sysctl -p + +- name: reload systemd units + command: systemctl daemon-reload diff --git a/roles/openshift_node/tasks/systemd_units.yml b/roles/openshift_node/tasks/systemd_units.yml index f58c803c4..e3ce5df3d 100644 --- a/roles/openshift_node/tasks/systemd_units.yml +++ b/roles/openshift_node/tasks/systemd_units.yml @@ -8,6 +8,9 @@ src: openshift.docker.node.dep.service register: install_node_dep_result when: openshift.common.is_containerized | bool + notify: + - reload systemd units + - restart node - block: - name: Pre-pull node image @@ -21,6 +24,9 @@ dest: "/etc/systemd/system/{{ openshift.common.service_type }}-node.service" src: openshift.docker.node.service register: install_node_result + notify: + - reload systemd units + - restart node when: - openshift.common.is_containerized | bool - not openshift.common.is_node_system_container | bool @@ -31,6 +37,9 @@ src: "{{ openshift.common.service_type }}-node.service.j2" register: install_node_result when: not openshift.common.is_containerized | bool + notify: + - reload systemd units + - restart node - name: Create the openvswitch service env file template: @@ -39,6 +48,7 @@ when: openshift.common.is_containerized | bool register: install_ovs_sysconfig notify: + - reload systemd units - restart openvswitch - name: Install Node system container @@ -67,6 +77,7 @@ when: openshift.common.use_openshift_sdn | default(true) | bool register: install_oom_fix_result notify: + - reload systemd units - restart openvswitch - block: @@ -81,6 +92,7 @@ dest: "/etc/systemd/system/openvswitch.service" src: openvswitch.docker.service notify: + - reload systemd units - restart openvswitch when: - openshift.common.is_containerized | bool @@ -119,8 +131,3 @@ when: ('http_proxy' in openshift.common and openshift.common.http_proxy != '') notify: - restart node - -- name: Reload systemd units - command: systemctl daemon-reload - notify: - - restart node diff --git a/roles/openshift_persistent_volumes/templates/persistent-volume.yml.j2 b/roles/openshift_persistent_volumes/templates/persistent-volume.yml.j2 index 877e88002..9c5103597 100644 --- a/roles/openshift_persistent_volumes/templates/persistent-volume.yml.j2 +++ b/roles/openshift_persistent_volumes/templates/persistent-volume.yml.j2 @@ -7,6 +7,12 @@ items: kind: PersistentVolume metadata: name: "{{ volume.name }}" +{% if volume.labels is defined and volume.labels is mapping %} + labels: +{% for key,value in volume.labels.iteritems() %} + {{ key }}: {{ value }} +{% endfor %} +{% endif %} spec: capacity: storage: "{{ volume.capacity }}" |