diff options
Diffstat (limited to 'roles')
51 files changed, 492 insertions, 269 deletions
diff --git a/roles/ansible_service_broker/vars/openshift-enterprise.yml b/roles/ansible_service_broker/vars/openshift-enterprise.yml index 0b3a2a69d..ce2ae8365 100644 --- a/roles/ansible_service_broker/vars/openshift-enterprise.yml +++ b/roles/ansible_service_broker/vars/openshift-enterprise.yml @@ -1,7 +1,7 @@ --- __ansible_service_broker_image_prefix: registry.access.redhat.com/openshift3/ose- -__ansible_service_broker_image_tag: latest +__ansible_service_broker_image_tag: v3.6 __ansible_service_broker_etcd_image_prefix: rhel7/ __ansible_service_broker_etcd_image_tag: latest diff --git a/roles/cockpit/defaults/main.yml b/roles/cockpit/defaults/main.yml index cbe5bb92b..15c40e3b5 100644 --- a/roles/cockpit/defaults/main.yml +++ b/roles/cockpit/defaults/main.yml @@ -1,6 +1,6 @@ --- -r_cockpit_firewall_enabled: True -r_cockpit_use_firewalld: False +r_cockpit_firewall_enabled: "{{ os_firewall_enabled | default(True) }}" +r_cockpit_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}" r_cockpit_os_firewall_deny: [] r_cockpit_os_firewall_allow: diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml index 1f9ac5059..78c6671d8 100644 --- a/roles/docker/tasks/main.yml +++ b/roles/docker/tasks/main.yml @@ -7,8 +7,8 @@ - set_fact: l_use_system_container: "{{ openshift.docker.use_system_container | default(False) }}" - l_use_crio: "{{ openshift.docker.use_crio | default(False) }}" - l_use_crio_only: "{{ openshift.docker.use_crio_only | default(False) }}" + l_use_crio: "{{ openshift_use_crio | default(False) }}" + l_use_crio_only: "{{ openshift_use_crio_only | default(False) }}" - name: Use Package Docker if Requested include: package_docker.yml diff --git a/roles/docker/templates/crio.conf.j2 b/roles/docker/templates/crio.conf.j2 index eae1759ab..5b31932b1 100644 --- a/roles/docker/templates/crio.conf.j2 +++ b/roles/docker/templates/crio.conf.j2 @@ -43,7 +43,7 @@ stream_port = "10010" # This is a mandatory setting as this runtime will be the default one # and will also be used for untrusted container workloads if # runtime_untrusted_workload is not set. -runtime = "/usr/libexec/crio/runc" +runtime = "/usr/bin/runc" # runtime_untrusted_workload is the OCI compatible runtime used for untrusted # container workloads. This is an optional setting, except if diff --git a/roles/lib_openshift/library/oc_route.py b/roles/lib_openshift/library/oc_route.py index d6db75e1e..8f8e46e1e 100644 --- a/roles/lib_openshift/library/oc_route.py +++ b/roles/lib_openshift/library/oc_route.py @@ -1665,9 +1665,6 @@ class OCRoute(OpenShiftCLI): @staticmethod def get_cert_data(path, content): '''get the data for a particular value''' - if not path and not content: - return None - rval = None if path and os.path.exists(path) and os.access(path, os.R_OK): rval = open(path).read() @@ -1706,14 +1703,14 @@ class OCRoute(OpenShiftCLI): if params['tls_termination'] and params['tls_termination'].lower() != 'passthrough': # E501 for key, option in files.items(): - if key == 'destcacert' and params['tls_termination'] != 'reencrypt': + if not option['path'] and not option['content']: continue option['value'] = OCRoute.get_cert_data(option['path'], option['content']) # E501 if not option['value']: return {'failed': True, - 'msg': 'Verify that you pass a value for %s' % key} + 'msg': 'Verify that you pass a correct value for %s' % key} rconfig = RouteConfig(params['name'], params['namespace'], diff --git a/roles/lib_openshift/src/class/oc_route.py b/roles/lib_openshift/src/class/oc_route.py index 3935525f1..3a1bd732f 100644 --- a/roles/lib_openshift/src/class/oc_route.py +++ b/roles/lib_openshift/src/class/oc_route.py @@ -68,9 +68,6 @@ class OCRoute(OpenShiftCLI): @staticmethod def get_cert_data(path, content): '''get the data for a particular value''' - if not path and not content: - return None - rval = None if path and os.path.exists(path) and os.access(path, os.R_OK): rval = open(path).read() @@ -109,14 +106,14 @@ class OCRoute(OpenShiftCLI): if params['tls_termination'] and params['tls_termination'].lower() != 'passthrough': # E501 for key, option in files.items(): - if key == 'destcacert' and params['tls_termination'] != 'reencrypt': + if not option['path'] and not option['content']: continue option['value'] = OCRoute.get_cert_data(option['path'], option['content']) # E501 if not option['value']: return {'failed': True, - 'msg': 'Verify that you pass a value for %s' % key} + 'msg': 'Verify that you pass a correct value for %s' % key} rconfig = RouteConfig(params['name'], params['namespace'], diff --git a/roles/nuage_master/defaults/main.yml b/roles/nuage_master/defaults/main.yml index ffab25775..5f1d8686a 100644 --- a/roles/nuage_master/defaults/main.yml +++ b/roles/nuage_master/defaults/main.yml @@ -1,6 +1,6 @@ --- -r_nuage_master_firewall_enabled: True -r_nuage_master_use_firewalld: False +r_nuage_master_firewall_enabled: "{{ os_firewall_enabled | default(True) }}" +r_nuage_master_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}" nuage_mon_rest_server_port: '9443' diff --git a/roles/nuage_node/defaults/main.yml b/roles/nuage_node/defaults/main.yml index b3d2e3cec..9a2e34387 100644 --- a/roles/nuage_node/defaults/main.yml +++ b/roles/nuage_node/defaults/main.yml @@ -1,6 +1,6 @@ --- -r_nuage_node_firewall_enabled: True -r_nuage_node_use_firewalld: False +r_nuage_node_firewall_enabled: "{{ os_firewall_enabled | default(True) }}" +r_nuage_node_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}" nuage_mon_rest_server_port: '9443' diff --git a/roles/nuage_node/handlers/main.yaml b/roles/nuage_node/handlers/main.yaml index 60247c33e..e68ae74bd 100644 --- a/roles/nuage_node/handlers/main.yaml +++ b/roles/nuage_node/handlers/main.yaml @@ -1,7 +1,7 @@ --- - name: restart node become: yes - systemd: name={{ openshift.common.service_type }}-node state=restarted + systemd: name={{ openshift.common.service_type }}-node daemon-reload=yes state=restarted - name: save iptable rules become: yes diff --git a/roles/nuage_node/tasks/main.yaml b/roles/nuage_node/tasks/main.yaml index 3764681ff..9db9dbb6a 100644 --- a/roles/nuage_node/tasks/main.yaml +++ b/roles/nuage_node/tasks/main.yaml @@ -33,6 +33,11 @@ - include: certificates.yml +- name: Add additional Docker mounts for Nuage for atomic hosts + become: yes + lineinfile: dest="{{ openshift_atomic_node_config_file }}" line="{{ nuage_atomic_docker_additional_mounts }}" + when: openshift.common.is_atomic | bool + - name: Restart node services command: /bin/true notify: diff --git a/roles/nuage_node/vars/main.yaml b/roles/nuage_node/vars/main.yaml index 4cf68411f..d8bfca62a 100644 --- a/roles/nuage_node/vars/main.yaml +++ b/roles/nuage_node/vars/main.yaml @@ -23,3 +23,5 @@ cni_conf_dir: "/etc/cni/net.d/" cni_bin_dir: "/opt/cni/bin/" nuage_plugin_crt_dir: /usr/share/vsp-openshift +openshift_atomic_node_config_file: /etc/sysconfig/{{ openshift.common.service_type }}-node +nuage_atomic_docker_additional_mounts: "DOCKER_ADDTL_BIND_MOUNTS=-v /var/usr/share/vsp-openshift:/var/usr/share/vsp-openshift -v /etc/default:/etc/default -v /var/run:/var/run -v /opt/cni/bin:/opt/cni/bin -v /etc/cni/net.d:/etc/cni/net.d" diff --git a/roles/openshift_aws_ami_copy/tasks/main.yml b/roles/openshift_aws_ami_copy/tasks/main.yml index 15444c8d0..bcccd4042 100644 --- a/roles/openshift_aws_ami_copy/tasks/main.yml +++ b/roles/openshift_aws_ami_copy/tasks/main.yml @@ -1,7 +1,7 @@ --- - fail: msg: "{{ item }} needs to be defined" - when: "{{ item }} is not defined" + when: item is not defined with_items: - r_openshift_aws_ami_copy_src_ami - r_openshift_aws_ami_copy_name diff --git a/roles/openshift_aws_iam_kms/tasks/main.yml b/roles/openshift_aws_iam_kms/tasks/main.yml index b541b466c..32aac2666 100644 --- a/roles/openshift_aws_iam_kms/tasks/main.yml +++ b/roles/openshift_aws_iam_kms/tasks/main.yml @@ -1,7 +1,7 @@ --- - fail: msg: "{{ item.name }} needs to be defined." - when: "{{ item.cond }}" + when: item.cond | bool with_items: - name: "{{ r_openshift_aws_iam_kms_alias }}" cond: "{{ r_openshift_aws_iam_kms_alias is undefined }}" diff --git a/roles/openshift_cli/meta/main.yml b/roles/openshift_cli/meta/main.yml index c1de367d9..04a1ce873 100644 --- a/roles/openshift_cli/meta/main.yml +++ b/roles/openshift_cli/meta/main.yml @@ -15,4 +15,4 @@ dependencies: - role: openshift_docker when: not skip_docker_role | default(False) | bool - role: openshift_common -- role: openshift_cli_facts +- role: openshift_facts diff --git a/roles/openshift_cli/tasks/main.yml b/roles/openshift_cli/tasks/main.yml index c716a0860..9e61805f9 100644 --- a/roles/openshift_cli/tasks/main.yml +++ b/roles/openshift_cli/tasks/main.yml @@ -1,6 +1,6 @@ --- - set_fact: - l_use_crio: "{{ openshift_docker_use_crio | default(false) }}" + l_use_crio: "{{ openshift_use_crio | default(false) }}" - name: Install clients package: name={{ openshift.common.service_type }}-clients state=present diff --git a/roles/openshift_cli_facts/meta/main.yml b/roles/openshift_cli_facts/meta/main.yml deleted file mode 100644 index 59acde215..000000000 --- a/roles/openshift_cli_facts/meta/main.yml +++ /dev/null @@ -1,15 +0,0 @@ ---- -galaxy_info: - author: Jason DeTiberus - description: OpenShift CLI Facts - company: Red Hat, Inc. - license: Apache License, Version 2.0 - min_ansible_version: 1.9 - platforms: - - name: EL - versions: - - 7 - categories: - - cloud -dependencies: -- role: openshift_facts diff --git a/roles/openshift_cli_facts/tasks/main.yml b/roles/openshift_cli_facts/tasks/main.yml deleted file mode 100644 index dd1ed8965..000000000 --- a/roles/openshift_cli_facts/tasks/main.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -# TODO: move this to a new 'cli' role -- openshift_facts: - role: common - local_facts: - cli_image: "{{ osm_image | default(None) }}" diff --git a/roles/openshift_docker_facts/tasks/main.yml b/roles/openshift_docker_facts/tasks/main.yml index 516d7dc29..334150f63 100644 --- a/roles/openshift_docker_facts/tasks/main.yml +++ b/roles/openshift_docker_facts/tasks/main.yml @@ -17,7 +17,7 @@ hosted_registry_insecure: "{{ openshift_docker_hosted_registry_insecure | default(openshift.docker.hosted_registry_insecure | default(False)) }}" hosted_registry_network: "{{ openshift_docker_hosted_registry_network | default(None) }}" use_system_container: "{{ openshift_docker_use_system_container | default(False) }}" - use_crio: "{{ openshift_docker_use_crio | default(False) }}" + use_crio: "{{ openshift_use_crio | default(False) }}" - role: node local_facts: sdn_mtu: "{{ openshift_node_sdn_mtu | default(None) }}" diff --git a/roles/openshift_health_checker/action_plugins/openshift_health_check.py b/roles/openshift_health_checker/action_plugins/openshift_health_check.py index 05e53333d..8d35db6b5 100644 --- a/roles/openshift_health_checker/action_plugins/openshift_health_check.py +++ b/roles/openshift_health_checker/action_plugins/openshift_health_check.py @@ -1,76 +1,74 @@ """ Ansible action plugin to execute health checks in OpenShift clusters. """ -# pylint: disable=wrong-import-position,missing-docstring,invalid-name import sys import os +import traceback from collections import defaultdict +from ansible.plugins.action import ActionBase +from ansible.module_utils.six import string_types + try: from __main__ import display except ImportError: + # pylint: disable=ungrouped-imports; this is the standard way how to import + # the default display object in Ansible action plugins. from ansible.utils.display import Display display = Display() -from ansible.plugins.action import ActionBase -from ansible.module_utils.six import string_types - # Augment sys.path so that we can import checks from a directory relative to # this callback plugin. sys.path.insert(1, os.path.dirname(os.path.dirname(__file__))) +# pylint: disable=wrong-import-position; the import statement must come after +# the manipulation of sys.path. from openshift_checks import OpenShiftCheck, OpenShiftCheckException, load_checks # noqa: E402 class ActionModule(ActionBase): + """Action plugin to execute health checks.""" def run(self, tmp=None, task_vars=None): result = super(ActionModule, self).run(tmp, task_vars) task_vars = task_vars or {} - # vars are not supportably available in the callback plugin, - # so record any it will need in the result. + # callback plugins cannot read Ansible vars, but we would like + # zz_failure_summary to have access to certain values. We do so by + # storing the information we need in the result. result['playbook_context'] = task_vars.get('r_openshift_health_checker_playbook_context') - if "openshift" not in task_vars: - result["failed"] = True - result["msg"] = "'openshift' is undefined, did 'openshift_facts' run?" - return result - try: known_checks = self.load_known_checks(tmp, task_vars) args = self._task.args requested_checks = normalize(args.get('checks', [])) + + if not requested_checks: + result['failed'] = True + result['msg'] = list_known_checks(known_checks) + return result + resolved_checks = resolve_checks(requested_checks, known_checks.values()) - except OpenShiftCheckException as e: + except OpenShiftCheckException as exc: result["failed"] = True - result["msg"] = str(e) + result["msg"] = str(exc) + return result + + if "openshift" not in task_vars: + result["failed"] = True + result["msg"] = "'openshift' is undefined, did 'openshift_facts' run?" return result result["checks"] = check_results = {} user_disabled_checks = normalize(task_vars.get('openshift_disable_check', [])) - for check_name in resolved_checks: - display.banner("CHECK [{} : {}]".format(check_name, task_vars["ansible_host"])) - check = known_checks[check_name] - - if not check.is_active(): - r = dict(skipped=True, skipped_reason="Not active for this host") - elif check_name in user_disabled_checks: - r = dict(skipped=True, skipped_reason="Disabled by user request") - else: - try: - r = check.run() - except OpenShiftCheckException as e: - r = dict( - failed=True, - msg=str(e), - ) - + for name in resolved_checks: + display.banner("CHECK [{} : {}]".format(name, task_vars["ansible_host"])) + check = known_checks[name] + check_results[name] = run_check(name, check, user_disabled_checks) if check.changed: - r["changed"] = True - check_results[check_name] = r + check_results[name]["changed"] = True result["changed"] = any(r.get("changed") for r in check_results.values()) if any(r.get("failed") for r in check_results.values()): @@ -80,22 +78,55 @@ class ActionModule(ActionBase): return result def load_known_checks(self, tmp, task_vars): + """Find all existing checks and return a mapping of names to instances.""" load_checks() known_checks = {} for cls in OpenShiftCheck.subclasses(): - check_name = cls.name - if check_name in known_checks: - other_cls = known_checks[check_name].__class__ + name = cls.name + if name in known_checks: + other_cls = known_checks[name].__class__ raise OpenShiftCheckException( - "non-unique check name '{}' in: '{}.{}' and '{}.{}'".format( - check_name, - cls.__module__, cls.__name__, - other_cls.__module__, other_cls.__name__)) - known_checks[check_name] = cls(execute_module=self._execute_module, tmp=tmp, task_vars=task_vars) + "duplicate check name '{}' in: '{}' and '{}'" + "".format(name, full_class_name(cls), full_class_name(other_cls)) + ) + known_checks[name] = cls(execute_module=self._execute_module, tmp=tmp, task_vars=task_vars) return known_checks +def list_known_checks(known_checks): + """Return text listing the existing checks and tags.""" + # TODO: we could include a description of each check by taking it from a + # check class attribute (e.g., __doc__) when building the message below. + msg = ( + 'This playbook is meant to run health checks, but no checks were ' + 'requested. Set the `openshift_checks` variable to a comma-separated ' + 'list of check names or a YAML list. Available checks:\n {}' + ).format('\n '.join(sorted(known_checks))) + + tags = describe_tags(known_checks.values()) + + msg += ( + '\n\nTags can be used as a shortcut to select multiple ' + 'checks. Available tags and the checks they select:\n {}' + ).format('\n '.join(tags)) + + return msg + + +def describe_tags(check_classes): + """Return a sorted list of strings describing tags and the checks they include.""" + tag_checks = defaultdict(list) + for cls in check_classes: + for tag in cls.tags: + tag_checks[tag].append(cls.name) + tags = [ + '@{} = {}'.format(tag, ','.join(sorted(checks))) + for tag, checks in tag_checks.items() + ] + return sorted(tags) + + def resolve_checks(names, all_checks): """Returns a set of resolved check names. @@ -123,6 +154,12 @@ def resolve_checks(names, all_checks): if unknown_tag_names: msg.append('Unknown tag names: {}.'.format(', '.join(sorted(unknown_tag_names)))) msg.append('Make sure there is no typo in the playbook and no files are missing.') + # TODO: implement a "Did you mean ...?" when the input is similar to a + # valid check or tag. + msg.append('Known checks:') + msg.append(' {}'.format('\n '.join(sorted(known_check_names)))) + msg.append('Known tags:') + msg.append(' {}'.format('\n '.join(describe_tags(all_checks)))) raise OpenShiftCheckException('\n'.join(msg)) tag_to_checks = defaultdict(set) @@ -146,3 +183,32 @@ def normalize(checks): if isinstance(checks, string_types): checks = checks.split(',') return [name.strip() for name in checks if name.strip()] + + +def run_check(name, check, user_disabled_checks): + """Run a single check if enabled and return a result dict.""" + if name in user_disabled_checks: + return dict(skipped=True, skipped_reason="Disabled by user request") + + # pylint: disable=broad-except; capturing exceptions broadly is intentional, + # to isolate arbitrary failures in one check from others. + try: + is_active = check.is_active() + except Exception as exc: + reason = "Could not determine if check should be run, exception: {}".format(exc) + return dict(skipped=True, skipped_reason=reason, exception=traceback.format_exc()) + + if not is_active: + return dict(skipped=True, skipped_reason="Not active for this host") + + try: + return check.run() + except OpenShiftCheckException as exc: + return dict(failed=True, msg=str(exc)) + except Exception as exc: + return dict(failed=True, msg=str(exc), exception=traceback.format_exc()) + + +def full_class_name(cls): + """Return the name of a class prefixed with its module name.""" + return '{}.{}'.format(cls.__module__, cls.__name__) diff --git a/roles/openshift_health_checker/callback_plugins/zz_failure_summary.py b/roles/openshift_health_checker/callback_plugins/zz_failure_summary.py index d10200719..349655966 100644 --- a/roles/openshift_health_checker/callback_plugins/zz_failure_summary.py +++ b/roles/openshift_health_checker/callback_plugins/zz_failure_summary.py @@ -1,161 +1,223 @@ -""" -Ansible callback plugin to give a nicely formatted summary of failures. -""" +"""Ansible callback plugin to print a nicely formatted summary of failures. -# Reason: In several locations below we disable pylint protected-access -# for Ansible objects that do not give us any public way -# to access the full details we need to report check failures. -# Status: disabled permanently or until Ansible object has a public API. -# This does leave the code more likely to be broken by future Ansible changes. +The file / module name is prefixed with `zz_` to make this plugin be loaded last +by Ansible, thus making its output the last thing that users see. +""" -from pprint import pformat +from collections import defaultdict +import traceback from ansible.plugins.callback import CallbackBase from ansible import constants as C from ansible.utils.color import stringc +FAILED_NO_MSG = u'Failed without returning a message.' + + class CallbackModule(CallbackBase): - """ - This callback plugin stores task results and summarizes failures. - The file name is prefixed with `zz_` to make this plugin be loaded last by - Ansible, thus making its output the last thing that users see. - """ + """This callback plugin stores task results and summarizes failures.""" CALLBACK_VERSION = 2.0 CALLBACK_TYPE = 'aggregate' CALLBACK_NAME = 'failure_summary' CALLBACK_NEEDS_WHITELIST = False - _playbook_file = None def __init__(self): super(CallbackModule, self).__init__() self.__failures = [] + self.__playbook_file = '' def v2_playbook_on_start(self, playbook): super(CallbackModule, self).v2_playbook_on_start(playbook) - # re: playbook attrs see top comment # pylint: disable=protected-access - self._playbook_file = playbook._file_name + # pylint: disable=protected-access; Ansible gives us no public API to + # get the file name of the current playbook from a callback plugin. + self.__playbook_file = playbook._file_name def v2_runner_on_failed(self, result, ignore_errors=False): super(CallbackModule, self).v2_runner_on_failed(result, ignore_errors) if not ignore_errors: - self.__failures.append(dict(result=result, ignore_errors=ignore_errors)) + self.__failures.append(result) def v2_playbook_on_stats(self, stats): super(CallbackModule, self).v2_playbook_on_stats(stats) - if self.__failures: - self._print_failure_details(self.__failures) - - def _print_failure_details(self, failures): - """Print a summary of failed tasks or checks.""" - self._display.display(u'\nFailure summary:\n') - - width = len(str(len(failures))) - initial_indent_format = u' {{:>{width}}}. '.format(width=width) - initial_indent_len = len(initial_indent_format.format(0)) - subsequent_indent = u' ' * initial_indent_len - subsequent_extra_indent = u' ' * (initial_indent_len + 10) - - for i, failure in enumerate(failures, 1): - entries = _format_failure(failure) - self._display.display(u'\n{}{}'.format(initial_indent_format.format(i), entries[0])) - for entry in entries[1:]: - entry = entry.replace(u'\n', u'\n' + subsequent_extra_indent) - indented = u'{}{}'.format(subsequent_indent, entry) - self._display.display(indented) - - failed_checks = set() - playbook_context = None - # re: result attrs see top comment # pylint: disable=protected-access - for failure in failures: - # Get context from check task result since callback plugins cannot access task vars. - # NOTE: thus context is not known unless checks run. Failures prior to checks running - # don't have playbook_context in the results. But we only use it now when checks fail. - playbook_context = playbook_context or failure['result']._result.get('playbook_context') - failed_checks.update( - name - for name, result in failure['result']._result.get('checks', {}).items() - if result.get('failed') - ) - if failed_checks: - self._print_check_failure_summary(failed_checks, playbook_context) - - def _print_check_failure_summary(self, failed_checks, context): - checks = ','.join(sorted(failed_checks)) - # The purpose of specifying context is to vary the output depending on what the user was - # expecting to happen (based on which playbook they ran). The only use currently is to - # vary the message depending on whether the user was deliberately running checks or was - # trying to install/upgrade and checks are just included. Other use cases may arise. - summary = ( # default to explaining what checks are in the first place - '\n' - 'The execution of "{playbook}"\n' - 'includes checks designed to fail early if the requirements\n' - 'of the playbook are not met. One or more of these checks\n' - 'failed. To disregard these results, you may choose to\n' - 'disable failing checks by setting an Ansible variable:\n\n' - ' openshift_disable_check={checks}\n\n' - 'Failing check names are shown in the failure details above.\n' - 'Some checks may be configurable by variables if your requirements\n' - 'are different from the defaults; consult check documentation.\n' - 'Variables can be set in the inventory or passed on the\n' - 'command line using the -e flag to ansible-playbook.\n\n' - ).format(playbook=self._playbook_file, checks=checks) - if context in ['pre-install', 'health']: - summary = ( # user was expecting to run checks, less explanation needed - '\n' - 'You may choose to configure or disable failing checks by\n' - 'setting Ansible variables. To disable those above:\n\n' - ' openshift_disable_check={checks}\n\n' - 'Consult check documentation for configurable variables.\n' - 'Variables can be set in the inventory or passed on the\n' - 'command line using the -e flag to ansible-playbook.\n\n' - ).format(checks=checks) - self._display.display(summary) - - -# re: result attrs see top comment # pylint: disable=protected-access -def _format_failure(failure): + # pylint: disable=broad-except; capturing exceptions broadly is + # intentional, to isolate arbitrary failures in this callback plugin. + try: + if self.__failures: + self._display.display(failure_summary(self.__failures, self.__playbook_file)) + except Exception: + msg = stringc( + u'An error happened while generating a summary of failures:\n' + u'{}'.format(traceback.format_exc()), C.COLOR_WARN) + self._display.v(msg) + + +def failure_summary(failures, playbook): + """Return a summary of failed tasks, including details on health checks.""" + if not failures: + return u'' + + # NOTE: because we don't have access to task_vars from callback plugins, we + # store the playbook context in the task result when the + # openshift_health_check action plugin is used, and we use this context to + # customize the error message. + # pylint: disable=protected-access; Ansible gives us no sufficient public + # API on TaskResult objects. + context = next(( + context for context in + (failure._result.get('playbook_context') for failure in failures) + if context + ), None) + + failures = [failure_to_dict(failure) for failure in failures] + failures = deduplicate_failures(failures) + + summary = [u'', u'', u'Failure summary:', u''] + + width = len(str(len(failures))) + initial_indent_format = u' {{:>{width}}}. '.format(width=width) + initial_indent_len = len(initial_indent_format.format(0)) + subsequent_indent = u' ' * initial_indent_len + subsequent_extra_indent = u' ' * (initial_indent_len + 10) + + for i, failure in enumerate(failures, 1): + entries = format_failure(failure) + summary.append(u'\n{}{}'.format(initial_indent_format.format(i), entries[0])) + for entry in entries[1:]: + entry = entry.replace(u'\n', u'\n' + subsequent_extra_indent) + indented = u'{}{}'.format(subsequent_indent, entry) + summary.append(indented) + + failed_checks = set() + for failure in failures: + failed_checks.update(name for name, message in failure['checks']) + if failed_checks: + summary.append(check_failure_footer(failed_checks, context, playbook)) + + return u'\n'.join(summary) + + +def failure_to_dict(failed_task_result): + """Extract information out of a failed TaskResult into a dict. + + The intent is to transform a TaskResult object into something easier to + manipulate. TaskResult is ansible.executor.task_result.TaskResult. + """ + # pylint: disable=protected-access; Ansible gives us no sufficient public + # API on TaskResult objects. + _result = failed_task_result._result + return { + 'host': failed_task_result._host.get_name(), + 'play': play_name(failed_task_result._task), + 'task': failed_task_result.task_name, + 'msg': _result.get('msg', FAILED_NO_MSG), + 'checks': tuple( + (name, result.get('msg', FAILED_NO_MSG)) + for name, result in sorted(_result.get('checks', {}).items()) + if result.get('failed') + ), + } + + +def play_name(obj): + """Given a task or block, return the name of its parent play. + + This is loosely inspired by ansible.playbook.base.Base.dump_me. + """ + # pylint: disable=protected-access; Ansible gives us no sufficient public + # API to implement this. + if not obj: + return '' + if hasattr(obj, '_play'): + return obj._play.get_name() + return play_name(getattr(obj, '_parent')) + + +def deduplicate_failures(failures): + """Group together similar failures from different hosts. + + Returns a new list of failures such that identical failures from different + hosts are grouped together in a single entry. The relative order of failures + is preserved. + """ + groups = defaultdict(list) + for failure in failures: + group_key = tuple(sorted((key, value) for key, value in failure.items() if key != 'host')) + groups[group_key].append(failure) + result = [] + for failure in failures: + group_key = tuple(sorted((key, value) for key, value in failure.items() if key != 'host')) + if group_key not in groups: + continue + failure['host'] = tuple(sorted(g_failure['host'] for g_failure in groups.pop(group_key))) + result.append(failure) + return result + + +def format_failure(failure): """Return a list of pretty-formatted text entries describing a failure, including relevant information about it. Expect that the list of text entries will be joined by a newline separator when output to the user.""" - result = failure['result'] - host = result._host.get_name() - play = _get_play(result._task) - if play: - play = play.get_name() - task = result._task.get_name() - msg = result._result.get('msg', u'???') + host = u', '.join(failure['host']) + play = failure['play'] + task = failure['task'] + msg = failure['msg'] + checks = failure['checks'] fields = ( - (u'Host', host), + (u'Hosts', host), (u'Play', play), (u'Task', task), (u'Message', stringc(msg, C.COLOR_ERROR)), ) - if 'checks' in result._result: - fields += ((u'Details', _format_failed_checks(result._result['checks'])),) + if checks: + fields += ((u'Details', format_failed_checks(checks)),) row_format = '{:10}{}' return [row_format.format(header + u':', body) for header, body in fields] -def _format_failed_checks(checks): +def format_failed_checks(checks): """Return pretty-formatted text describing checks that failed.""" - failed_check_msgs = [] - for check, body in checks.items(): - if body.get('failed', False): # only show the failed checks - msg = body.get('msg', u"Failed without returning a message") - failed_check_msgs.append('check "%s":\n%s' % (check, msg)) - if failed_check_msgs: - return stringc("\n\n".join(failed_check_msgs), C.COLOR_ERROR) - else: # something failed but no checks will admit to it, so dump everything - return stringc(pformat(checks), C.COLOR_ERROR) - - -# This is inspired by ansible.playbook.base.Base.dump_me. -# re: play/task/block attrs see top comment # pylint: disable=protected-access -def _get_play(obj): - """Given a task or block, recursively try to find its parent play.""" - if hasattr(obj, '_play'): - return obj._play - if getattr(obj, '_parent'): - return _get_play(obj._parent) + messages = [] + for name, message in checks: + messages.append(u'check "{}":\n{}'.format(name, message)) + return stringc(u'\n\n'.join(messages), C.COLOR_ERROR) + + +def check_failure_footer(failed_checks, context, playbook): + """Return a textual explanation about checks depending on context. + + The purpose of specifying context is to vary the output depending on what + the user was expecting to happen (based on which playbook they ran). The + only use currently is to vary the message depending on whether the user was + deliberately running checks or was trying to install/upgrade and checks are + just included. Other use cases may arise. + """ + checks = ','.join(sorted(failed_checks)) + summary = [u''] + if context in ['pre-install', 'health', 'adhoc']: + # User was expecting to run checks, less explanation needed. + summary.extend([ + u'You may configure or disable checks by setting Ansible ' + u'variables. To disable those above, set:', + u' openshift_disable_check={checks}'.format(checks=checks), + u'Consult check documentation for configurable variables.', + ]) + else: + # User may not be familiar with the checks, explain what checks are in + # the first place. + summary.extend([ + u'The execution of "{playbook}" includes checks designed to fail ' + u'early if the requirements of the playbook are not met. One or ' + u'more of these checks failed. To disregard these results,' + u'explicitly disable checks by setting an Ansible variable:'.format(playbook=playbook), + u' openshift_disable_check={checks}'.format(checks=checks), + u'Failing check names are shown in the failure details above. ' + u'Some checks may be configurable by variables if your requirements ' + u'are different from the defaults; consult check documentation.', + ]) + summary.append( + u'Variables can be set in the inventory or passed on the command line ' + u'using the -e flag to ansible-playbook.' + ) + return u'\n'.join(summary) diff --git a/roles/openshift_health_checker/test/action_plugin_test.py b/roles/openshift_health_checker/test/action_plugin_test.py index f5161d6f5..c109ebd24 100644 --- a/roles/openshift_health_checker/test/action_plugin_test.py +++ b/roles/openshift_health_checker/test/action_plugin_test.py @@ -80,7 +80,8 @@ def skipped(result): None, {}, ]) -def test_action_plugin_missing_openshift_facts(plugin, task_vars): +def test_action_plugin_missing_openshift_facts(plugin, task_vars, monkeypatch): + monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check']) result = plugin.run(tmp=None, task_vars=task_vars) assert failed(result, msg_has=['openshift_facts']) @@ -94,7 +95,7 @@ def test_action_plugin_cannot_load_checks_with_the_same_name(plugin, task_vars, result = plugin.run(tmp=None, task_vars=task_vars) - assert failed(result, msg_has=['unique', 'duplicate_name', 'FakeCheck']) + assert failed(result, msg_has=['duplicate', 'duplicate_name', 'FakeCheck']) def test_action_plugin_skip_non_active_checks(plugin, task_vars, monkeypatch): @@ -217,24 +218,21 @@ def test_resolve_checks_ok(names, all_checks, expected): assert resolve_checks(names, all_checks) == expected -@pytest.mark.parametrize('names,all_checks,words_in_exception,words_not_in_exception', [ +@pytest.mark.parametrize('names,all_checks,words_in_exception', [ ( ['testA', 'testB'], [], ['check', 'name', 'testA', 'testB'], - ['tag', 'group', '@'], ), ( ['@group'], [], ['tag', 'name', 'group'], - ['check', '@'], ), ( ['testA', 'testB', '@group'], [], ['check', 'name', 'testA', 'testB', 'tag', 'group'], - ['@'], ), ( ['testA', 'testB', '@group'], @@ -244,13 +242,10 @@ def test_resolve_checks_ok(names, all_checks, expected): fake_check('from_group_2', ['preflight', 'group']), ], ['check', 'name', 'testA', 'testB'], - ['tag', 'group', '@'], ), ]) -def test_resolve_checks_failure(names, all_checks, words_in_exception, words_not_in_exception): +def test_resolve_checks_failure(names, all_checks, words_in_exception): with pytest.raises(Exception) as excinfo: resolve_checks(names, all_checks) for word in words_in_exception: assert word in str(excinfo.value) - for word in words_not_in_exception: - assert word not in str(excinfo.value) diff --git a/roles/openshift_health_checker/test/conftest.py b/roles/openshift_health_checker/test/conftest.py index 3cbd65507..244a1f0fa 100644 --- a/roles/openshift_health_checker/test/conftest.py +++ b/roles/openshift_health_checker/test/conftest.py @@ -7,5 +7,6 @@ openshift_health_checker_path = os.path.dirname(os.path.dirname(__file__)) sys.path[1:1] = [ openshift_health_checker_path, os.path.join(openshift_health_checker_path, 'action_plugins'), + os.path.join(openshift_health_checker_path, 'callback_plugins'), os.path.join(openshift_health_checker_path, 'library'), ] diff --git a/roles/openshift_health_checker/test/zz_failure_summary_test.py b/roles/openshift_health_checker/test/zz_failure_summary_test.py new file mode 100644 index 000000000..0fc258133 --- /dev/null +++ b/roles/openshift_health_checker/test/zz_failure_summary_test.py @@ -0,0 +1,70 @@ +from zz_failure_summary import deduplicate_failures + +import pytest + + +@pytest.mark.parametrize('failures,deduplicated', [ + ( + [ + { + 'host': 'master1', + 'msg': 'One or more checks failed', + }, + ], + [ + { + 'host': ('master1',), + 'msg': 'One or more checks failed', + }, + ], + ), + ( + [ + { + 'host': 'master1', + 'msg': 'One or more checks failed', + }, + { + 'host': 'node1', + 'msg': 'One or more checks failed', + }, + ], + [ + { + 'host': ('master1', 'node1'), + 'msg': 'One or more checks failed', + }, + ], + ), + ( + [ + { + 'host': 'node1', + 'msg': 'One or more checks failed', + 'checks': (('test_check', 'error message'),), + }, + { + 'host': 'master2', + 'msg': 'Some error happened', + }, + { + 'host': 'master1', + 'msg': 'One or more checks failed', + 'checks': (('test_check', 'error message'),), + }, + ], + [ + { + 'host': ('master1', 'node1'), + 'msg': 'One or more checks failed', + 'checks': (('test_check', 'error message'),), + }, + { + 'host': ('master2',), + 'msg': 'Some error happened', + }, + ], + ), +]) +def test_deduplicate_failures(failures, deduplicated): + assert deduplicate_failures(failures) == deduplicated diff --git a/roles/openshift_hosted/defaults/main.yml b/roles/openshift_hosted/defaults/main.yml index f0e303e43..f3747eead 100644 --- a/roles/openshift_hosted/defaults/main.yml +++ b/roles/openshift_hosted/defaults/main.yml @@ -1,9 +1,9 @@ --- -r_openshift_hosted_router_firewall_enabled: True -r_openshift_hosted_router_use_firewalld: False +r_openshift_hosted_router_firewall_enabled: "{{ os_firewall_enabled | default(True) }}" +r_openshift_hosted_router_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}" -r_openshift_hosted_registry_firewall_enabled: True -r_openshift_hosted_registry_use_firewalld: False +r_openshift_hosted_registry_firewall_enabled: "{{ os_firewall_enabled | default(True) }}" +r_openshift_hosted_registry_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}" openshift_hosted_router_wait: True openshift_hosted_registry_wait: True diff --git a/roles/openshift_hosted/tasks/registry/secure.yml b/roles/openshift_hosted/tasks/registry/secure.yml index a18e6eea9..a8a6f6fc8 100644 --- a/roles/openshift_hosted/tasks/registry/secure.yml +++ b/roles/openshift_hosted/tasks/registry/secure.yml @@ -37,6 +37,9 @@ hostnames: - "{{ docker_registry_service.results.clusterip }}" - "{{ docker_registry_route.results[0].spec.host }}" + - "{{ openshift_hosted_registry_name }}.default.svc" + - "{{ openshift_hosted_registry_name }}.default.svc.{{ openshift.common.dns_domain }}" + - "{{ openshift_hosted_registry_routehost }}" cert: "{{ docker_registry_cert_path }}" key: "{{ docker_registry_key_path }}" expire_days: "{{ openshift_hosted_registry_cert_expire_days if openshift_version | oo_version_gte_3_5_or_1_5(openshift.common.deployment_type) | bool else omit }}" diff --git a/roles/openshift_loadbalancer/defaults/main.yml b/roles/openshift_loadbalancer/defaults/main.yml index 3f6409233..41a2b12a2 100644 --- a/roles/openshift_loadbalancer/defaults/main.yml +++ b/roles/openshift_loadbalancer/defaults/main.yml @@ -1,6 +1,6 @@ --- -r_openshift_loadbalancer_firewall_enabled: True -r_openshift_loadbalancer_use_firewalld: False +r_openshift_loadbalancer_firewall_enabled: "{{ os_firewall_enabled | default(True) }}" +r_openshift_loadbalancer_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}" haproxy_frontends: - name: main diff --git a/roles/openshift_logging/README.md b/roles/openshift_logging/README.md index 84ead3548..70aef02cd 100644 --- a/roles/openshift_logging/README.md +++ b/roles/openshift_logging/README.md @@ -22,7 +22,19 @@ When both `openshift_logging_install_logging` and `openshift_logging_upgrade_log ###Optional vars: - `openshift_logging_image_prefix`: The prefix for the logging images to use. Defaults to 'docker.io/openshift/origin-'. +- `openshift_logging_curator_image_prefix`: Setting the image prefix for Curator image. Defaults to `openshift_logging_image_prefix`. +- `openshift_logging_elasticsearch_image_prefix`: Setting the image prefix for Elasticsearch image. Defaults to `openshift_logging_image_prefix`. +- `openshift_logging_fluentd_image_prefix`: Setting the image prefix for Fluentd image. Defaults to `openshift_logging_image_prefix`. +- `openshift_logging_kibana_image_prefix`: Setting the image prefix for Kibana image. Defaults to `openshift_logging_image_prefix`. +- `openshift_logging_kibana_proxy_image_prefix`: Setting the image prefix for Kibana proxy image. Defaults to `openshift_logging_image_prefix`. +- `openshift_logging_mux_image_prefix`: Setting the image prefix for Mux image. Defaults to `openshift_logging_image_prefix`. - `openshift_logging_image_version`: The image version for the logging images to use. Defaults to 'latest'. +- `openshift_logging_curator_image_version`: Setting the image version for Curator image. Defaults to `openshift_logging_image_version`. +- `openshift_logging_elasticsearch_image_version`: Setting the image version for Elasticsearch image. Defaults to `openshift_logging_image_version`. +- `openshift_logging_fluentd_image_version`: Setting the image version for Fluentd image. Defaults to `openshift_logging_image_version`. +- `openshift_logging_kibana_image_version`: Setting the image version for Kibana image. Defaults to `openshift_logging_image_version`. +- `openshift_logging_kibana_proxy_image_version`: Setting the image version for Kibana proxy image. Defaults to `openshift_logging_image_version`. +- `openshift_logging_mux_image_version`: Setting the image version for Mux image. Defaults to `openshift_logging_image_version`. - `openshift_logging_use_ops`: If 'True', set up a second ES and Kibana cluster for infrastructure logs. Defaults to 'False'. - `openshift_logging_master_url`: The URL for the Kubernetes master, this does not need to be public facing but should be accessible from within the cluster. Defaults to 'https://kubernetes.default.svc.{{openshift.common.dns_domain}}'. - `openshift_logging_master_public_url`: The public facing URL for the Kubernetes master, this is used for Authentication redirection. Defaults to 'https://{{openshift.common.public_hostname}}:{{openshift.master.api_port}}'. diff --git a/roles/openshift_logging/tasks/install_logging.yaml b/roles/openshift_logging/tasks/install_logging.yaml index 654a7ce3e..a77df9986 100644 --- a/roles/openshift_logging/tasks/install_logging.yaml +++ b/roles/openshift_logging/tasks/install_logging.yaml @@ -185,8 +185,6 @@ openshift_logging_kibana_namespace: "{{ openshift_logging_namespace }}" openshift_logging_kibana_master_url: "{{ openshift_logging_master_url }}" openshift_logging_kibana_master_public_url: "{{ openshift_logging_master_public_url }}" - openshift_logging_kibana_image_prefix: "{{ openshift_logging_image_prefix }}" - openshift_logging_kibana_image_version: "{{ openshift_logging_image_version }}" openshift_logging_kibana_replicas: "{{ openshift_logging_kibana_replica_count }}" openshift_logging_kibana_es_host: "{{ openshift_logging_es_host }}" openshift_logging_kibana_es_port: "{{ openshift_logging_es_port }}" @@ -201,8 +199,6 @@ openshift_logging_kibana_namespace: "{{ openshift_logging_namespace }}" openshift_logging_kibana_master_url: "{{ openshift_logging_master_url }}" openshift_logging_kibana_master_public_url: "{{ openshift_logging_master_public_url }}" - openshift_logging_kibana_image_prefix: "{{ openshift_logging_image_prefix }}" - openshift_logging_kibana_image_version: "{{ openshift_logging_image_version }}" openshift_logging_kibana_image_pull_secret: "{{ openshift_logging_image_pull_secret }}" openshift_logging_kibana_es_host: "{{ openshift_logging_es_ops_host }}" openshift_logging_kibana_es_port: "{{ openshift_logging_es_ops_port }}" @@ -231,8 +227,6 @@ openshift_logging_curator_es_host: "{{ openshift_logging_es_host }}" openshift_logging_curator_es_port: "{{ openshift_logging_es_port }}" openshift_logging_curator_master_url: "{{ openshift_logging_master_url }}" - openshift_logging_curator_image_prefix: "{{ openshift_logging_image_prefix }}" - openshift_logging_curator_image_version: "{{ openshift_logging_image_version }}" openshift_logging_curator_image_pull_secret: "{{ openshift_logging_image_pull_secret }}" - include_role: @@ -244,8 +238,6 @@ openshift_logging_curator_es_port: "{{ openshift_logging_es_ops_port }}" openshift_logging_curator_namespace: "{{ openshift_logging_namespace }}" openshift_logging_curator_master_url: "{{ openshift_logging_master_url }}" - openshift_logging_curator_image_prefix: "{{ openshift_logging_image_prefix }}" - openshift_logging_curator_image_version: "{{ openshift_logging_image_version }}" openshift_logging_curator_image_pull_secret: "{{ openshift_logging_image_pull_secret }}" openshift_logging_curator_cpu_limit: "{{ openshift_logging_curator_ops_cpu_limit }}" openshift_logging_curator_memory_limit: "{{ openshift_logging_curator_ops_memory_limit }}" @@ -261,8 +253,6 @@ openshift_logging_mux_ops_host: "{{ ( openshift_logging_use_ops | bool ) | ternary('logging-es-ops', 'logging-es') }}" openshift_logging_mux_namespace: "{{ openshift_logging_namespace }}" openshift_logging_mux_master_url: "{{ openshift_logging_master_url }}" - openshift_logging_mux_image_prefix: "{{ openshift_logging_image_prefix }}" - openshift_logging_mux_image_version: "{{ openshift_logging_image_version }}" openshift_logging_mux_image_pull_secret: "{{ openshift_logging_image_pull_secret }}" when: - openshift_logging_use_mux | bool @@ -274,8 +264,6 @@ vars: generated_certs_dir: "{{openshift.common.config_base}}/logging" openshift_logging_fluentd_ops_host: "{{ ( openshift_logging_use_ops | bool ) | ternary('logging-es-ops', 'logging-es') }}" - openshift_logging_fluentd_image_prefix: "{{ openshift_logging_image_prefix }}" - openshift_logging_fluentd_image_version: "{{ openshift_logging_image_version }}" openshift_logging_fluentd_image_pull_secret: "{{ openshift_logging_image_pull_secret }}" openshift_logging_fluentd_master_url: "{{ openshift_logging_master_url }}" openshift_logging_fluentd_namespace: "{{ openshift_logging_namespace }}" diff --git a/roles/openshift_logging_curator/defaults/main.yml b/roles/openshift_logging_curator/defaults/main.yml index 82ffb2f93..17807b644 100644 --- a/roles/openshift_logging_curator/defaults/main.yml +++ b/roles/openshift_logging_curator/defaults/main.yml @@ -1,7 +1,7 @@ --- ### General logging settings -openshift_logging_curator_image_prefix: "{{ openshift_hosted_logging_deployer_prefix | default('docker.io/openshift/origin-') }}" -openshift_logging_curator_image_version: "{{ openshift_hosted_logging_deployer_version | default('latest') }}" +openshift_logging_curator_image_prefix: "{{ openshift_logging_image_prefix | default(__openshift_logging_image_prefix) }}" +openshift_logging_curator_image_version: "{{ openshift_logging_image_version | default('latest') }}" openshift_logging_curator_image_pull_secret: "{{ openshift_hosted_logging_image_pull_secret | default('') }}" openshift_logging_curator_master_url: "https://kubernetes.default.svc.cluster.local" diff --git a/roles/openshift_logging_curator/tasks/main.yaml b/roles/openshift_logging_curator/tasks/main.yaml index 3113fb3c9..6e8fab2b5 100644 --- a/roles/openshift_logging_curator/tasks/main.yaml +++ b/roles/openshift_logging_curator/tasks/main.yaml @@ -86,7 +86,7 @@ component: "{{ curator_component }}" logging_component: curator deploy_name: "{{ curator_name }}" - image: "{{openshift_logging_image_prefix}}logging-curator:{{openshift_logging_image_version}}" + image: "{{openshift_logging_curator_image_prefix}}logging-curator:{{openshift_logging_curator_image_version}}" es_host: "{{ openshift_logging_curator_es_host }}" es_port: "{{ openshift_logging_curator_es_port }}" curator_cpu_limit: "{{ openshift_logging_curator_cpu_limit }}" diff --git a/roles/openshift_logging_elasticsearch/defaults/main.yml b/roles/openshift_logging_elasticsearch/defaults/main.yml index 0690bf114..75bd479be 100644 --- a/roles/openshift_logging_elasticsearch/defaults/main.yml +++ b/roles/openshift_logging_elasticsearch/defaults/main.yml @@ -1,7 +1,7 @@ --- ### Common settings -openshift_logging_elasticsearch_image_prefix: "{{ openshift_hosted_logging_deployer_prefix | default('docker.io/openshift/origin-') }}" -openshift_logging_elasticsearch_image_version: "{{ openshift_hosted_logging_deployer_version | default('latest') }}" +openshift_logging_elasticsearch_image_prefix: "{{ openshift_logging_image_prefix | default(__openshift_logging_image_prefix) }}" +openshift_logging_elasticsearch_image_version: "{{ openshift_logging_image_version | default('latest') }}" openshift_logging_elasticsearch_image_pull_secret: "{{ openshift_hosted_logging_image_pull_secret | default('') }}" openshift_logging_elasticsearch_namespace: logging diff --git a/roles/openshift_logging_elasticsearch/tasks/main.yaml b/roles/openshift_logging_elasticsearch/tasks/main.yaml index 28c3ffd96..931846fdb 100644 --- a/roles/openshift_logging_elasticsearch/tasks/main.yaml +++ b/roles/openshift_logging_elasticsearch/tasks/main.yaml @@ -277,7 +277,7 @@ component: "{{ es_component }}" logging_component: elasticsearch deploy_name: "{{ es_deploy_name }}" - image: "{{ openshift_logging_image_prefix }}logging-elasticsearch:{{ openshift_logging_image_version }}" + image: "{{ openshift_logging_elasticsearch_image_prefix }}logging-elasticsearch:{{ openshift_logging_elasticsearch_image_version }}" es_cpu_limit: "{{ openshift_logging_elasticsearch_cpu_limit }}" es_memory_limit: "{{ openshift_logging_elasticsearch_memory_limit }}" es_node_selector: "{{ openshift_logging_elasticsearch_nodeselector | default({}) }}" diff --git a/roles/openshift_logging_fluentd/defaults/main.yml b/roles/openshift_logging_fluentd/defaults/main.yml index a53bbd2df..30d3d854a 100644 --- a/roles/openshift_logging_fluentd/defaults/main.yml +++ b/roles/openshift_logging_fluentd/defaults/main.yml @@ -1,7 +1,7 @@ --- ### General logging settings -openshift_logging_fluentd_image_prefix: "{{ openshift_hosted_logging_deployer_prefix | default('docker.io/openshift/origin-') }}" -openshift_logging_fluentd_image_version: "{{ openshift_hosted_logging_deployer_version | default('latest') }}" +openshift_logging_fluentd_image_prefix: "{{ openshift_logging_image_prefix | default(__openshift_logging_image_prefix) }}" +openshift_logging_fluentd_image_version: "{{ openshift_logging_image_version | default('latest') }}" openshift_logging_fluentd_image_pull_secret: "{{ openshift_hosted_logging_image_pull_secret | default('') }}" openshift_logging_fluentd_master_url: "https://kubernetes.default.svc.{{ openshift.common.dns_domain }}" openshift_logging_fluentd_namespace: logging diff --git a/roles/openshift_logging_fluentd/templates/fluentd.j2 b/roles/openshift_logging_fluentd/templates/fluentd.j2 index 39dffba19..88e039e3f 100644 --- a/roles/openshift_logging_fluentd/templates/fluentd.j2 +++ b/roles/openshift_logging_fluentd/templates/fluentd.j2 @@ -28,7 +28,7 @@ spec: {{ fluentd_nodeselector_key }}: "{{ fluentd_nodeselector_value }}" containers: - name: "{{ daemonset_container_name }}" - image: "{{ openshift_logging_image_prefix }}{{ daemonset_name }}:{{ openshift_logging_image_version }}" + image: "{{ openshift_logging_fluentd_image_prefix }}{{ daemonset_name }}:{{ openshift_logging_fluentd_image_version }}" imagePullPolicy: Always securityContext: privileged: true diff --git a/roles/openshift_logging_kibana/defaults/main.yml b/roles/openshift_logging_kibana/defaults/main.yml index 14787a62b..ee265bb14 100644 --- a/roles/openshift_logging_kibana/defaults/main.yml +++ b/roles/openshift_logging_kibana/defaults/main.yml @@ -2,8 +2,8 @@ ### Common settings openshift_logging_kibana_master_url: "https://kubernetes.default.svc.cluster.local" openshift_logging_kibana_master_public_url: "https://kubernetes.default.svc.cluster.local" -openshift_logging_kibana_image_prefix: "{{ openshift_hosted_logging_deployer_prefix | default('docker.io/openshift/origin-') }}" -openshift_logging_kibana_image_version: "{{ openshift_hosted_logging_deployer_version | default('latest') }}" +openshift_logging_kibana_image_prefix: "{{ openshift_logging_image_prefix | default(__openshift_logging_image_prefix) }}" +openshift_logging_kibana_image_version: "{{ openshift_logging_image_version | default('latest') }}" openshift_logging_kibana_image_pull_secret: "{{ openshift_hosted_logging_image_pull_secret | default('') }}" openshift_logging_kibana_namespace: logging @@ -24,6 +24,8 @@ openshift_logging_kibana_edge_term_policy: Redirect openshift_logging_kibana_ops_deployment: false # Proxy settings +openshift_logging_kibana_proxy_image_prefix: "{{ openshift_logging_image_prefix | default(__openshift_logging_image_prefix) }}" +openshift_logging_kibana_proxy_image_version: "{{ openshift_logging_image_version | default('latest') }}" openshift_logging_kibana_proxy_debug: false openshift_logging_kibana_proxy_cpu_limit: null openshift_logging_kibana_proxy_memory_limit: 256Mi diff --git a/roles/openshift_logging_kibana/tasks/main.yaml b/roles/openshift_logging_kibana/tasks/main.yaml index 166f102f7..e17e8c1f2 100644 --- a/roles/openshift_logging_kibana/tasks/main.yaml +++ b/roles/openshift_logging_kibana/tasks/main.yaml @@ -225,8 +225,8 @@ component: "{{ kibana_component }}" logging_component: kibana deploy_name: "{{ kibana_name }}" - image: "{{ openshift_logging_image_prefix }}logging-kibana:{{ openshift_logging_image_version }}" - proxy_image: "{{ openshift_logging_image_prefix }}logging-auth-proxy:{{ openshift_logging_image_version }}" + image: "{{ openshift_logging_kibana_image_prefix }}logging-kibana:{{ openshift_logging_kibana_image_version }}" + proxy_image: "{{ openshift_logging_kibana_proxy_image_prefix }}logging-auth-proxy:{{ openshift_logging_kibana_proxy_image_version }}" es_host: "{{ openshift_logging_kibana_es_host }}" es_port: "{{ openshift_logging_kibana_es_port }}" kibana_cpu_limit: "{{ openshift_logging_kibana_cpu_limit }}" diff --git a/roles/openshift_logging_mux/defaults/main.yml b/roles/openshift_logging_mux/defaults/main.yml index 7a3da9b4c..68412aec8 100644 --- a/roles/openshift_logging_mux/defaults/main.yml +++ b/roles/openshift_logging_mux/defaults/main.yml @@ -1,7 +1,7 @@ --- ### General logging settings -openshift_logging_mux_image_prefix: "{{ openshift_hosted_logging_deployer_prefix | default('docker.io/openshift/origin-') }}" -openshift_logging_mux_image_version: "{{ openshift_hosted_logging_deployer_version | default('latest') }}" +openshift_logging_mux_image_prefix: "{{ openshift_logging_image_prefix | default(__openshift_logging_image_prefix) }}" +openshift_logging_mux_image_version: "{{ openshift_logging_image_version | default('latest') }}" openshift_logging_mux_image_pull_secret: "{{ openshift_hosted_logging_image_pull_secret | default('') }}" openshift_logging_mux_master_url: "https://kubernetes.default.svc.{{ openshift.common.dns_domain }}" openshift_logging_mux_master_public_url: "{{ openshift_hosted_logging_master_public_url | default('https://' + openshift.common.public_hostname + ':' ~ (openshift_master_api_port | default('8443', true))) }}" diff --git a/roles/openshift_logging_mux/tasks/main.yaml b/roles/openshift_logging_mux/tasks/main.yaml index 8ec93de7d..2ec863afa 100644 --- a/roles/openshift_logging_mux/tasks/main.yaml +++ b/roles/openshift_logging_mux/tasks/main.yaml @@ -165,7 +165,7 @@ component: mux logging_component: mux deploy_name: "logging-{{ component }}" - image: "{{ openshift_logging_image_prefix }}logging-fluentd:{{ openshift_logging_image_version }}" + image: "{{ openshift_logging_mux_image_prefix }}logging-fluentd:{{ openshift_logging_mux_image_version }}" es_host: "{{ openshift_logging_mux_app_host }}" es_port: "{{ openshift_logging_mux_app_port }}" ops_host: "{{ openshift_logging_mux_ops_host }}" diff --git a/roles/openshift_master/defaults/main.yml b/roles/openshift_master/defaults/main.yml index a4c178908..d70106276 100644 --- a/roles/openshift_master/defaults/main.yml +++ b/roles/openshift_master/defaults/main.yml @@ -1,6 +1,6 @@ --- -r_openshift_master_firewall_enabled: True -r_openshift_master_use_firewalld: False +r_openshift_master_firewall_enabled: "{{ os_firewall_enabled | default(True) }}" +r_openshift_master_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}" openshift_node_ips: [] r_openshift_master_clean_install: false @@ -19,3 +19,8 @@ r_openshift_master_os_firewall_allow: - service: etcd embedded port: 4001/tcp cond: "{{ groups.oo_etcd_to_config | default([]) | length == 0 }}" + +oreg_url: '' +oreg_host: "{{ oreg_url.split('/')[0] if '.' in oreg_url.split('/')[0] else '' }}" +oreg_auth_credentials_path: "{{ openshift.common.data_dir }}/.docker" +oreg_auth_credentials_replace: False diff --git a/roles/openshift_master/tasks/main.yml b/roles/openshift_master/tasks/main.yml index b80941b48..ba56ac94e 100644 --- a/roles/openshift_master/tasks/main.yml +++ b/roles/openshift_master/tasks/main.yml @@ -232,6 +232,22 @@ - restart master controllers when: openshift_master_bootstrap_enabled | default(False) +- name: Check for credentials file for registry auth + stat: + path: "{{oreg_auth_credentials_path }}" + when: + - oreg_auth_user is defined + register: master_oreg_auth_credentials_stat + +- name: Create credentials for registry auth + command: "docker --config={{ oreg_auth_credentials_path }} login -u {{ oreg_auth_user }} -p {{ oreg_auth_password }} {{ oreg_host }}" + when: + - oreg_auth_user is defined + - (not master_oreg_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool + notify: + - restart master api + - restart master controllers + - include: set_loopback_context.yml when: - openshift.common.version_gte_3_2_or_1_2 diff --git a/roles/openshift_node/defaults/main.yml b/roles/openshift_node/defaults/main.yml index 973b3a619..cc000496a 100644 --- a/roles/openshift_node/defaults/main.yml +++ b/roles/openshift_node/defaults/main.yml @@ -1,6 +1,6 @@ --- -r_openshift_node_firewall_enabled: True -r_openshift_node_use_firewalld: False +r_openshift_node_firewall_enabled: "{{ os_firewall_enabled | default(True) }}" +r_openshift_node_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}" r_openshift_node_os_firewall_deny: [] r_openshift_node_os_firewall_allow: - service: Kubernetes kubelet @@ -21,3 +21,8 @@ r_openshift_node_os_firewall_allow: - service: Kubernetes service NodePort UDP port: "{{ openshift_node_port_range | default('') }}/udp" cond: "{{ openshift_node_port_range is defined }}" + +oreg_url: '' +oreg_host: "{{ oreg_url.split('/')[0] if '.' in oreg_url.split('/')[0] else '' }}" +oreg_auth_credentials_path: "{{ openshift.common.data_dir }}/.docker" +oreg_auth_credentials_replace: False diff --git a/roles/openshift_node/tasks/main.yml b/roles/openshift_node/tasks/main.yml index 81456eac9..525dd1d1a 100644 --- a/roles/openshift_node/tasks/main.yml +++ b/roles/openshift_node/tasks/main.yml @@ -4,7 +4,7 @@ msg: "SELinux is disabled, This deployment type requires that SELinux is enabled." when: - (not ansible_selinux or ansible_selinux.status != 'enabled') and deployment_type in ['enterprise', 'online', 'atomic-enterprise', 'openshift-enterprise'] - - not openshift_docker_use_crio | default(false) + - not openshift_use_crio | default(false) - name: setup firewall include: firewall.yml @@ -93,7 +93,7 @@ name: cri-o enabled: yes state: restarted - when: openshift_docker_use_crio | default(false) + when: openshift_use_crio | default(false) - name: Install conntrack-tools package package: @@ -150,6 +150,21 @@ notify: - restart node +- name: Check for credentials file for registry auth + stat: + path: "{{oreg_auth_credentials_path }}" + when: + - oreg_auth_user is defined + register: node_oreg_auth_credentials_stat + +- name: Create credentials for registry auth + command: "docker --config={{ oreg_auth_credentials_path }} login -u {{ oreg_auth_user }} -p {{ oreg_auth_password }} {{ oreg_host }}" + when: + - oreg_auth_user is defined + - (not node_oreg_auth_credentials_stat.stat.exists or oreg_auth_credentials_replace) | bool + notify: + - restart node + - name: Configure AWS Cloud Provider Settings lineinfile: dest: /etc/sysconfig/{{ openshift.common.service_type }}-node diff --git a/roles/openshift_node/tasks/openvswitch_system_container.yml b/roles/openshift_node/tasks/openvswitch_system_container.yml index dc1df9185..e09063aa5 100644 --- a/roles/openshift_node/tasks/openvswitch_system_container.yml +++ b/roles/openshift_node/tasks/openvswitch_system_container.yml @@ -1,6 +1,6 @@ --- - set_fact: - l_use_crio: "{{ openshift_docker_use_crio | default(false) }}" + l_use_crio: "{{ openshift_use_crio | default(false) }}" - set_fact: l_service_name: "cri-o" diff --git a/roles/openshift_node/templates/node.service.j2 b/roles/openshift_node/templates/node.service.j2 index 3d0ae3bbd..0856737f6 100644 --- a/roles/openshift_node/templates/node.service.j2 +++ b/roles/openshift_node/templates/node.service.j2 @@ -8,7 +8,7 @@ Wants={{ openshift.docker.service_name }}.service Documentation=https://github.com/openshift/origin Requires=dnsmasq.service After=dnsmasq.service -{% if openshift.docker.use_crio %}Wants=cri-o.service{% endif %} +{% if openshift_use_crio|default(false) %}Wants=cri-o.service{% endif %} [Service] Type=notify diff --git a/roles/openshift_node/templates/node.yaml.v1.j2 b/roles/openshift_node/templates/node.yaml.v1.j2 index 93f8658b4..711afcadb 100644 --- a/roles/openshift_node/templates/node.yaml.v1.j2 +++ b/roles/openshift_node/templates/node.yaml.v1.j2 @@ -16,7 +16,7 @@ imageConfig: latest: false kind: NodeConfig kubeletArguments: {{ openshift.node.kubelet_args | default(None) | to_padded_yaml(level=1) }} -{% if openshift.docker.use_crio | default(False) %} +{% if openshift_use_crio | default(False) %} container-runtime: - remote container-runtime-endpoint: diff --git a/roles/openshift_node/templates/openshift.docker.node.dep.service b/roles/openshift_node/templates/openshift.docker.node.dep.service index c4580be1f..8734e7443 100644 --- a/roles/openshift_node/templates/openshift.docker.node.dep.service +++ b/roles/openshift_node/templates/openshift.docker.node.dep.service @@ -3,7 +3,7 @@ Requires={{ openshift.docker.service_name }}.service After={{ openshift.docker.service_name }}.service PartOf={{ openshift.common.service_type }}-node.service Before={{ openshift.common.service_type }}-node.service -{% if openshift.docker.use_crio %}Wants=cri-o.service{% endif %} +{% if openshift_use_crio|default(false) %}Wants=cri-o.service{% endif %} [Service] ExecStart=/bin/bash -c "if [[ -f /usr/bin/docker-current ]]; then echo \"DOCKER_ADDTL_BIND_MOUNTS=--volume=/usr/bin/docker-current:/usr/bin/docker-current:ro --volume=/etc/sysconfig/docker:/etc/sysconfig/docker:ro\" > /etc/sysconfig/{{ openshift.common.service_type }}-node-dep; else echo \"#DOCKER_ADDTL_BIND_MOUNTS=\" > /etc/sysconfig/{{ openshift.common.service_type }}-node-dep; fi" diff --git a/roles/openshift_storage_glusterfs/defaults/main.yml b/roles/openshift_storage_glusterfs/defaults/main.yml index a5887465e..8d21a3f27 100644 --- a/roles/openshift_storage_glusterfs/defaults/main.yml +++ b/roles/openshift_storage_glusterfs/defaults/main.yml @@ -52,8 +52,8 @@ openshift_storage_glusterfs_registry_heketi_ssh_port: "{{ openshift_storage_glus openshift_storage_glusterfs_registry_heketi_ssh_user: "{{ openshift_storage_glusterfs_heketi_ssh_user }}" openshift_storage_glusterfs_registry_heketi_ssh_sudo: "{{ openshift_storage_glusterfs_heketi_ssh_sudo }}" openshift_storage_glusterfs_registry_heketi_ssh_keyfile: "{{ openshift_storage_glusterfs_heketi_ssh_keyfile | default(omit) }}" -r_openshift_master_firewall_enabled: True -r_openshift_master_use_firewalld: False +r_openshift_master_firewall_enabled: "{{ os_firewall_enabled | default(True) }}" +r_openshift_master_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}" r_openshift_storage_glusterfs_os_firewall_deny: [] r_openshift_storage_glusterfs_os_firewall_allow: - service: glusterfs_sshd diff --git a/roles/openshift_storage_nfs/defaults/main.yml b/roles/openshift_storage_nfs/defaults/main.yml index 4a2bc6141..e7e0b331b 100644 --- a/roles/openshift_storage_nfs/defaults/main.yml +++ b/roles/openshift_storage_nfs/defaults/main.yml @@ -1,6 +1,6 @@ --- -r_openshift_storage_nfs_firewall_enabled: True -r_openshift_storage_nfs_use_firewalld: False +r_openshift_storage_nfs_firewall_enabled: "{{ os_firewall_enabled | default(True) }}" +r_openshift_storage_nfs_use_firewalld: "{{ os_firewall_use_firewalld | default(False) }}" r_openshift_storage_nfs_os_firewall_deny: [] r_openshift_storage_nfs_os_firewall_allow: diff --git a/roles/openshift_version/tasks/main.yml b/roles/openshift_version/tasks/main.yml index a6b8a40c8..c0ea00f34 100644 --- a/roles/openshift_version/tasks/main.yml +++ b/roles/openshift_version/tasks/main.yml @@ -60,13 +60,16 @@ # It also allows for optional trailing data which: # - must start with a dash # - may contain numbers + # - may containe dots (https://github.com/openshift/openshift-ansible/issues/5192) + # - name: (Enterprise) Verify openshift_image_tag is valid when: openshift.common.deployment_type == 'openshift-enterprise' assert: that: - - "{{ openshift_image_tag|match('(^v\\d+\\.\\d+[\\.\\d+]*(-\\d+)?$)') }}" + - "{{ openshift_image_tag|match('(^v\\d+\\.\\d+(\\.\\d+)*(-\\d+(\\.\\d+)*)?$)') }}" msg: |- - openshift_image_tag must be in the format v#.#[.#[.#]]. Examples: v1.2, v3.4.1, v3.5.1.3, v1.2-1, v1.2.3-4 + openshift_image_tag must be in the format v#.#[.#[.#]]. Examples: v1.2, v3.4.1, v3.5.1.3, + v3.5.1.3.4, v1.2-1, v1.2.3-4, v1.2.3-4.5, v1.2.3-4.5.6 You specified openshift_image_tag={{ openshift_image_tag }} # Make sure we copy this to a fact if given a var: diff --git a/roles/openshift_version/tasks/set_version_containerized.yml b/roles/openshift_version/tasks/set_version_containerized.yml index 4d9f72f01..a2a579e9d 100644 --- a/roles/openshift_version/tasks/set_version_containerized.yml +++ b/roles/openshift_version/tasks/set_version_containerized.yml @@ -1,6 +1,6 @@ --- - set_fact: - l_use_crio: "{{ openshift_docker_use_crio | default(false) }}" + l_use_crio: "{{ openshift_use_crio | default(false) }}" - name: Set containerized version to configure if openshift_image_tag specified set_fact: diff --git a/roles/os_firewall/defaults/main.yml b/roles/os_firewall/defaults/main.yml index f96a80f1c..2cae94411 100644 --- a/roles/os_firewall/defaults/main.yml +++ b/roles/os_firewall/defaults/main.yml @@ -2,4 +2,4 @@ os_firewall_enabled: True # firewalld is not supported on Atomic Host # https://bugzilla.redhat.com/show_bug.cgi?id=1403331 -os_firewall_use_firewalld: "{{ False }}" +os_firewall_use_firewalld: False |