From 5faaf9cd1e48864b3ff93276f4b1015b297d0b06 Mon Sep 17 00:00:00 2001 From: Michael Gugino Date: Tue, 19 Dec 2017 14:42:06 -0500 Subject: Move sanity_checks into custom action plugin This commit moves sanity_checks tasks into a custom action plugin that is only run against a single host. This will result in a large reduction of tasks during initialization --- roles/lib_utils/action_plugins/sanity_checks.py | 96 +++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 roles/lib_utils/action_plugins/sanity_checks.py (limited to 'roles/lib_utils/action_plugins') diff --git a/roles/lib_utils/action_plugins/sanity_checks.py b/roles/lib_utils/action_plugins/sanity_checks.py new file mode 100644 index 000000000..81ffd6e3e --- /dev/null +++ b/roles/lib_utils/action_plugins/sanity_checks.py @@ -0,0 +1,96 @@ +""" +Ansible action plugin to ensure inventory variables are set +appropriately and no conflicting options have been provided. +""" +from ansible.plugins.action import ActionBase +from ansible import errors + +# Tuple of variable names and default values if undefined. +NET_PLUGIN_LIST = (('openshift_use_openshift_sdn', True), + ('openshift_use_flannel', False), + ('openshift_use_nuage', False), + ('openshift_use_contiv', False), + ('openshift_use_calico', False)) + + +def to_bool(var_to_check): + """Determine a boolean value given the multiple + ways bools can be specified in ansible.""" + yes_list = (True, 1, "True", "1", "true", "Yes", "yes") + return var_to_check in yes_list + + +class ActionModule(ActionBase): + """Action plugin to execute sanity checks.""" + def template_var(self, hostvars, host, varname): + """Retrieve a variable from hostvars and template it. + If undefined, return None type.""" + res = hostvars[host].get(varname) + if res is None: + return None + return self._templar.template(res) + + def network_plugin_check(self, hostvars, host): + """Ensure only one type of network plugin is enabled""" + res = [] + # Loop through each possible network plugin boolean, determine the + # actual boolean value, and append results into a list. + for plugin, default_val in NET_PLUGIN_LIST: + res_temp = self.template_var(hostvars, host, plugin) + if res_temp is None: + res_temp = default_val + res.append(to_bool(res_temp)) + + if sum(res) != 1: + plugin_str = list(zip([x[0] for x in NET_PLUGIN_LIST], res)) + + msg = "Host Checked: {} Only one of must be true. Found: {}".format(host, plugin_str) + raise errors.AnsibleModuleError(msg) + + def check_hostname_vars(self, hostvars, host): + """Checks to ensure openshift_hostname + and openshift_public_hostname + conform to the proper length of 63 characters or less""" + for varname in ('openshift_public_hostname', 'openshift_hostname'): + var_value = self.template_var(hostvars, host, varname) + if var_value and len(var_value) > 63: + msg = '{} must be 63 characters or less'.format(varname) + raise errors.AnsibleModuleError(msg) + + def run_checks(self, hostvars, host): + """Execute the hostvars validations against host""" + # msg = hostvars[host]['ansible_default_ipv4'] + self.network_plugin_check(hostvars, host) + self.check_hostname_vars(hostvars, host) + + def run(self, tmp=None, task_vars=None): + result = super(ActionModule, self).run(tmp, task_vars) + + # self.task_vars holds all in-scope variables. + # Ignore settting self.task_vars outside of init. + # pylint: disable=W0201 + self.task_vars = task_vars or {} + + # self._task.args holds task parameters. + # check_hosts is a parameter to this plugin, and should provide + # a list of hosts. + check_hosts = self._task.args.get('check_hosts') + if not check_hosts: + msg = "check_hosts is required" + raise errors.AnsibleModuleError(msg) + + # We need to access each host's variables + hostvars = self.task_vars.get('hostvars') + if not hostvars: + msg = hostvars + raise errors.AnsibleModuleError(msg) + + # We loop through each host in the provided list check_hosts + for host in check_hosts: + self.run_checks(hostvars, host) + + result["changed"] = False + result["failed"] = False + result["msg"] = "Sanity Checks passed" + + return result -- cgit v1.2.3 From edde00af6a5b811468fe2a0e9bff45346103be92 Mon Sep 17 00:00:00 2001 From: Michael Gugino Date: Tue, 19 Dec 2017 15:36:57 -0500 Subject: Move validate_hosts to prerequisites.yml Move more checks outside of init/main.yml for speeding up upgrades and other operational plays that need to run. --- roles/lib_utils/action_plugins/sanity_checks.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'roles/lib_utils/action_plugins') diff --git a/roles/lib_utils/action_plugins/sanity_checks.py b/roles/lib_utils/action_plugins/sanity_checks.py index 81ffd6e3e..2ddcf77e4 100644 --- a/roles/lib_utils/action_plugins/sanity_checks.py +++ b/roles/lib_utils/action_plugins/sanity_checks.py @@ -30,6 +30,19 @@ class ActionModule(ActionBase): return None return self._templar.template(res) + def check_python_version(self, hostvars, host, distro): + """Ensure python version is 3 for Fedora and python 2 for others""" + ansible_python = self.template_var(hostvars, host, 'ansible_python') + if distro == "Fedora": + if ansible_python['version']['major'] != 3: + msg = "openshift-ansible requires Python 3 for {};".format(distro) + msg += " For information on enabling Python 3 with Ansible," + msg += " see https://docs.ansible.com/ansible/python_3_support.html" + raise errors.AnsibleModuleError(msg) + else: + if ansible_python['version']['major'] != 2: + msg = "openshift-ansible requires Python 2 for {};".format(distro) + def network_plugin_check(self, hostvars, host): """Ensure only one type of network plugin is enabled""" res = [] @@ -59,7 +72,8 @@ class ActionModule(ActionBase): def run_checks(self, hostvars, host): """Execute the hostvars validations against host""" - # msg = hostvars[host]['ansible_default_ipv4'] + distro = self.template_var(hostvars, host, 'ansible_distribution') + self.check_python_version(hostvars, host, distro) self.network_plugin_check(hostvars, host) self.check_hostname_vars(hostvars, host) -- cgit v1.2.3 From e3cf9edff6d0186b09b1a112592f283fab6857d0 Mon Sep 17 00:00:00 2001 From: Michael Gugino Date: Tue, 19 Dec 2017 16:36:47 -0500 Subject: Remove references to deployment_type Move openshift_deployment_type check into sanity_check action plugin. Remove compatibility for deployment_type. deployment_type has been deprecated for some time now. --- roles/lib_utils/action_plugins/sanity_checks.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'roles/lib_utils/action_plugins') diff --git a/roles/lib_utils/action_plugins/sanity_checks.py b/roles/lib_utils/action_plugins/sanity_checks.py index 2ddcf77e4..1bf332678 100644 --- a/roles/lib_utils/action_plugins/sanity_checks.py +++ b/roles/lib_utils/action_plugins/sanity_checks.py @@ -5,6 +5,9 @@ appropriately and no conflicting options have been provided. from ansible.plugins.action import ActionBase from ansible import errors +# Valid values for openshift_deployment_type +VALID_DEPLOYMENT_TYPES = ('origin', 'openshift-enterprise') + # Tuple of variable names and default values if undefined. NET_PLUGIN_LIST = (('openshift_use_openshift_sdn', True), ('openshift_use_flannel', False), @@ -16,7 +19,10 @@ NET_PLUGIN_LIST = (('openshift_use_openshift_sdn', True), def to_bool(var_to_check): """Determine a boolean value given the multiple ways bools can be specified in ansible.""" - yes_list = (True, 1, "True", "1", "true", "Yes", "yes") + # http://yaml.org/type/bool.html + yes_list = (True, 1, "True", "1", "true", "TRUE", + "Yes", "yes", "Y", "y", "YES", + "on", "ON", "On") return var_to_check in yes_list @@ -30,6 +36,15 @@ class ActionModule(ActionBase): return None return self._templar.template(res) + def check_openshift_deployment_type(self, hostvars, host): + """Ensure a valid openshift_deployment_type is set""" + openshift_deployment_type = self.template_var(hostvars, host, + 'openshift_deployment_type') + if openshift_deployment_type not in VALID_DEPLOYMENT_TYPES: + type_strings = ", ".join(VALID_DEPLOYMENT_TYPES) + msg = "openshift_deployment_type must be defined and one of {}".format(type_strings) + raise errors.AnsibleModuleError(msg) + def check_python_version(self, hostvars, host, distro): """Ensure python version is 3 for Fedora and python 2 for others""" ansible_python = self.template_var(hostvars, host, 'ansible_python') @@ -73,6 +88,7 @@ class ActionModule(ActionBase): def run_checks(self, hostvars, host): """Execute the hostvars validations against host""" distro = self.template_var(hostvars, host, 'ansible_distribution') + self.check_openshift_deployment_type(hostvars, host) self.check_python_version(hostvars, host, distro) self.network_plugin_check(hostvars, host) self.check_hostname_vars(hostvars, host) -- cgit v1.2.3