diff options
39 files changed, 2834 insertions, 617 deletions
@@ -60,7 +60,7 @@ confidence= # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" -disable=import-star-module-level,old-octal-literal,oct-method,print-statement,unpacking-in-except,parameter-unpacking,backtick,old-raise-syntax,old-ne-operator,long-suffix,dict-view-method,dict-iter-method,metaclass-assignment,next-method-called,raising-string,indexing-exception,raw_input-builtin,long-builtin,file-builtin,execfile-builtin,coerce-builtin,cmp-builtin,buffer-builtin,basestring-builtin,apply-builtin,filter-builtin-not-iterating,using-cmp-argument,useless-suppression,range-builtin-not-iterating,suppressed-message,no-absolute-import,old-division,cmp-method,reload-builtin,zip-builtin-not-iterating,intern-builtin,unichr-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,input-builtin,round-builtin,hex-method,nonzero-method,map-builtin-not-iterating +#disable= [REPORTS] diff --git a/roles/lib_openshift/library/oadm_manage_node.py b/roles/lib_openshift/library/oadm_manage_node.py index f2035c973..ced04bf3d 100644 --- a/roles/lib_openshift/library/oadm_manage_node.py +++ b/roles/lib_openshift/library/oadm_manage_node.py @@ -141,6 +141,7 @@ EXAMPLES = ''' # -*- -*- -*- End included fragment: doc/manage_node -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -335,14 +336,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -383,15 +386,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -421,14 +432,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -496,7 +509,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -509,7 +524,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -518,7 +534,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -557,19 +574,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -582,17 +600,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1063,6 +1084,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1150,6 +1172,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) diff --git a/roles/lib_openshift/library/oc_adm_ca_server_cert.py b/roles/lib_openshift/library/oc_adm_ca_server_cert.py new file mode 100644 index 000000000..720a37aa0 --- /dev/null +++ b/roles/lib_openshift/library/oc_adm_ca_server_cert.py @@ -0,0 +1,1515 @@ +#!/usr/bin/env python +# pylint: disable=missing-docstring +# flake8: noqa: T001 +# ___ ___ _ _ ___ ___ _ _____ ___ ___ +# / __| __| \| | __| _ \ /_\_ _| __| \ +# | (_ | _|| .` | _|| / / _ \| | | _|| |) | +# \___|___|_|\_|___|_|_\/_/_\_\_|_|___|___/_ _____ +# | \ / _ \ | \| |/ _ \_ _| | __| \_ _|_ _| +# | |) | (_) | | .` | (_) || | | _|| |) | | | | +# |___/ \___/ |_|\_|\___/ |_| |___|___/___| |_| +# +# Copyright 2016 Red Hat, Inc. and/or its affiliates +# and other contributors as indicated by the @author tags. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# -*- -*- -*- Begin included fragment: lib/import.py -*- -*- -*- +''' + OpenShiftCLI class that wraps the oc commands in a subprocess +''' +# pylint: disable=too-many-lines + +from __future__ import print_function +import atexit +import copy +import json +import os +import re +import shutil +import subprocess +import tempfile +# pylint: disable=import-error +try: + import ruamel.yaml as yaml +except ImportError: + import yaml + +from ansible.module_utils.basic import AnsibleModule + +# -*- -*- -*- End included fragment: lib/import.py -*- -*- -*- + +# -*- -*- -*- Begin included fragment: doc/ca_server_cert -*- -*- -*- + +DOCUMENTATION = ''' +--- +module: oc_adm_ca_server_cert +short_description: Module to run openshift oc adm ca create-server-cert +description: + - Wrapper around the openshift `oc adm ca create-server-cert` command. +options: + state: + description: + - Present is the only supported state. The state present means that `oc adm ca` will generate a certificate + - and verify if the hostnames and the ClusterIP exists in the certificate. + - When create-server-cert is desired then the following parameters are passed. + - ['cert', 'key', 'signer_cert', 'signer_key', 'signer_serial'] + required: false + default: present + choices: + - present + aliases: [] + kubeconfig: + description: + - The path for the kubeconfig file to use for authentication + required: false + default: /etc/origin/master/admin.kubeconfig + aliases: [] + debug: + description: + - Turn on debug output. + required: false + default: False + aliases: [] + cert: + description: + - The certificate file. Choose a name that indicates what the service is. + required: false + default: None + aliases: [] + key: + description: + - The key file. Choose a name that indicates what the service is. + required: false + default: None + aliases: [] + force: + description: + - Force updating of the existing cert and key files + required: false + default: False + aliases: [] + signer_cert: + description: + - The signer certificate file. + required: false + default: /etc/origin/master/ca.crt + aliases: [] + signer_key: + description: + - The signer key file. + required: false + default: /etc/origin/master/ca.key + aliases: [] + signer_serial: + description: + - The signer serial file. + required: false + default: /etc/origin/master/ca.serial.txt + aliases: [] + hostnames: + description: + - Every hostname or IP that server certs should be valid for (comma-delimited list) + required: false + default: None + aliases: [] + backup: + description: + - Whether to backup the cert and key files before writing them. + required: false + default: True + aliases: [] +author: +- "Kenny Woodson <kwoodson@redhat.com>" +extends_documentation_fragment: [] +''' + +EXAMPLES = ''' +- name: Create a self-signed cert + oc_adm_ca_server_cert: + signer_cert: /etc/origin/master/ca.crt + signer_key: /etc/origin/master/ca.key + signer_serial: /etc/origin/master/ca.serial.txt + hostnames: "registry.test.openshift.com,127.0.0.1,docker-registry.default.svc.cluster.local" + cert: /etc/origin/master/registry.crt + key: /etc/origin/master/registry.key +''' + +# -*- -*- -*- End included fragment: doc/ca_server_cert -*- -*- -*- + +# -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring +# noqa: E301,E302 + + +class YeditException(Exception): + ''' Exception class for Yedit ''' + pass + + +# pylint: disable=too-many-public-methods +class Yedit(object): + ''' Class to modify yaml files ''' + re_valid_key = r"(((\[-?\d+\])|([0-9a-zA-Z%s/_-]+)).?)+$" + re_key = r"(?:\[(-?\d+)\])|([0-9a-zA-Z%s/_-]+)" + com_sep = set(['.', '#', '|', ':']) + + # pylint: disable=too-many-arguments + def __init__(self, + filename=None, + content=None, + content_type='yaml', + separator='.', + backup=False): + self.content = content + self._separator = separator + self.filename = filename + self.__yaml_dict = content + self.content_type = content_type + self.backup = backup + self.load(content_type=self.content_type) + if self.__yaml_dict is None: + self.__yaml_dict = {} + + @property + def separator(self): + ''' getter method for yaml_dict ''' + return self._separator + + @separator.setter + def separator(self): + ''' getter method for yaml_dict ''' + return self._separator + + @property + def yaml_dict(self): + ''' getter method for yaml_dict ''' + return self.__yaml_dict + + @yaml_dict.setter + def yaml_dict(self, value): + ''' setter method for yaml_dict ''' + self.__yaml_dict = value + + @staticmethod + def parse_key(key, sep='.'): + '''parse the key allowing the appropriate separator''' + common_separators = list(Yedit.com_sep - set([sep])) + return re.findall(Yedit.re_key % ''.join(common_separators), key) + + @staticmethod + def valid_key(key, sep='.'): + '''validate the incoming key''' + common_separators = list(Yedit.com_sep - set([sep])) + if not re.match(Yedit.re_valid_key % ''.join(common_separators), key): + return False + + return True + + @staticmethod + def remove_entry(data, key, sep='.'): + ''' remove data at location key ''' + if key == '' and isinstance(data, dict): + data.clear() + return True + elif key == '' and isinstance(data, list): + del data[:] + return True + + if not (key and Yedit.valid_key(key, sep)) and \ + isinstance(data, (list, dict)): + return None + + key_indexes = Yedit.parse_key(key, sep) + for arr_ind, dict_key in key_indexes[:-1]: + if dict_key and isinstance(data, dict): + data = data.get(dict_key, None) + elif (arr_ind and isinstance(data, list) and + int(arr_ind) <= len(data) - 1): + data = data[int(arr_ind)] + else: + return None + + # process last index for remove + # expected list entry + if key_indexes[-1][0]: + if isinstance(data, list) and int(key_indexes[-1][0]) <= len(data) - 1: # noqa: E501 + del data[int(key_indexes[-1][0])] + return True + + # expected dict entry + elif key_indexes[-1][1]: + if isinstance(data, dict): + del data[key_indexes[-1][1]] + return True + + @staticmethod + def add_entry(data, key, item=None, sep='.'): + ''' Get an item from a dictionary with key notation a.b.c + d = {'a': {'b': 'c'}}} + key = a#b + return c + ''' + if key == '': + pass + elif (not (key and Yedit.valid_key(key, sep)) and + isinstance(data, (list, dict))): + return None + + key_indexes = Yedit.parse_key(key, sep) + for arr_ind, dict_key in key_indexes[:-1]: + if dict_key: + if isinstance(data, dict) and dict_key in data and data[dict_key]: # noqa: E501 + data = data[dict_key] + continue + + elif data and not isinstance(data, dict): + return None + + data[dict_key] = {} + data = data[dict_key] + + elif (arr_ind and isinstance(data, list) and + int(arr_ind) <= len(data) - 1): + data = data[int(arr_ind)] + else: + return None + + if key == '': + data = item + + # process last index for add + # expected list entry + elif key_indexes[-1][0] and isinstance(data, list) and int(key_indexes[-1][0]) <= len(data) - 1: # noqa: E501 + data[int(key_indexes[-1][0])] = item + + # expected dict entry + elif key_indexes[-1][1] and isinstance(data, dict): + data[key_indexes[-1][1]] = item + + return data + + @staticmethod + def get_entry(data, key, sep='.'): + ''' Get an item from a dictionary with key notation a.b.c + d = {'a': {'b': 'c'}}} + key = a.b + return c + ''' + if key == '': + pass + elif (not (key and Yedit.valid_key(key, sep)) and + isinstance(data, (list, dict))): + return None + + key_indexes = Yedit.parse_key(key, sep) + for arr_ind, dict_key in key_indexes: + if dict_key and isinstance(data, dict): + data = data.get(dict_key, None) + elif (arr_ind and isinstance(data, list) and + int(arr_ind) <= len(data) - 1): + data = data[int(arr_ind)] + else: + return None + + return data + + @staticmethod + def _write(filename, contents): + ''' Actually write the file contents to disk. This helps with mocking. ''' + + tmp_filename = filename + '.yedit' + + with open(tmp_filename, 'w') as yfd: + yfd.write(contents) + + os.rename(tmp_filename, filename) + + def write(self): + ''' write to file ''' + if not self.filename: + raise YeditException('Please specify a filename.') + + if self.backup and self.file_exists(): + shutil.copy(self.filename, self.filename + '.orig') + + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripDumper if supported. + try: + Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) + except AttributeError: + Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) + + return (True, self.yaml_dict) + + def read(self): + ''' read from file ''' + # check if it exists + if self.filename is None or not self.file_exists(): + return None + + contents = None + with open(self.filename) as yfd: + contents = yfd.read() + + return contents + + def file_exists(self): + ''' return whether file exists ''' + if os.path.exists(self.filename): + return True + + return False + + def load(self, content_type='yaml'): + ''' return yaml file ''' + contents = self.read() + + if not contents and not self.content: + return None + + if self.content: + if isinstance(self.content, dict): + self.yaml_dict = self.content + return self.yaml_dict + elif isinstance(self.content, str): + contents = self.content + + # check if it is yaml + try: + if content_type == 'yaml' and contents: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: + self.yaml_dict = yaml.safe_load(contents) + + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + elif content_type == 'json' and contents: + self.yaml_dict = json.loads(contents) + except yaml.YAMLError as err: + # Error loading yaml or json + raise YeditException('Problem with loading yaml file. %s' % err) + + return self.yaml_dict + + def get(self, key): + ''' get a specified key''' + try: + entry = Yedit.get_entry(self.yaml_dict, key, self.separator) + except KeyError: + entry = None + + return entry + + def pop(self, path, key_or_item): + ''' remove a key, value pair from a dict or an item for a list''' + try: + entry = Yedit.get_entry(self.yaml_dict, path, self.separator) + except KeyError: + entry = None + + if entry is None: + return (False, self.yaml_dict) + + if isinstance(entry, dict): + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member + if key_or_item in entry: + entry.pop(key_or_item) + return (True, self.yaml_dict) + return (False, self.yaml_dict) + + elif isinstance(entry, list): + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member + ind = None + try: + ind = entry.index(key_or_item) + except ValueError: + return (False, self.yaml_dict) + + entry.pop(ind) + return (True, self.yaml_dict) + + return (False, self.yaml_dict) + + def delete(self, path): + ''' remove path from a dict''' + try: + entry = Yedit.get_entry(self.yaml_dict, path, self.separator) + except KeyError: + entry = None + + if entry is None: + return (False, self.yaml_dict) + + result = Yedit.remove_entry(self.yaml_dict, path, self.separator) + if not result: + return (False, self.yaml_dict) + + return (True, self.yaml_dict) + + def exists(self, path, value): + ''' check if value exists at path''' + try: + entry = Yedit.get_entry(self.yaml_dict, path, self.separator) + except KeyError: + entry = None + + if isinstance(entry, list): + if value in entry: + return True + return False + + elif isinstance(entry, dict): + if isinstance(value, dict): + rval = False + for key, val in value.items(): + if entry[key] != val: + rval = False + break + else: + rval = True + return rval + + return value in entry + + return entry == value + + def append(self, path, value): + '''append value to a list''' + try: + entry = Yedit.get_entry(self.yaml_dict, path, self.separator) + except KeyError: + entry = None + + if entry is None: + self.put(path, []) + entry = Yedit.get_entry(self.yaml_dict, path, self.separator) + if not isinstance(entry, list): + return (False, self.yaml_dict) + + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member + entry.append(value) + return (True, self.yaml_dict) + + # pylint: disable=too-many-arguments + def update(self, path, value, index=None, curr_value=None): + ''' put path, value into a dict ''' + try: + entry = Yedit.get_entry(self.yaml_dict, path, self.separator) + except KeyError: + entry = None + + if isinstance(entry, dict): + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member + if not isinstance(value, dict): + raise YeditException('Cannot replace key, value entry in ' + + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 + + entry.update(value) + return (True, self.yaml_dict) + + elif isinstance(entry, list): + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member + ind = None + if curr_value: + try: + ind = entry.index(curr_value) + except ValueError: + return (False, self.yaml_dict) + + elif index is not None: + ind = index + + if ind is not None and entry[ind] != value: + entry[ind] = value + return (True, self.yaml_dict) + + # see if it exists in the list + try: + ind = entry.index(value) + except ValueError: + # doesn't exist, append it + entry.append(value) + return (True, self.yaml_dict) + + # already exists, return + if ind is not None: + return (False, self.yaml_dict) + return (False, self.yaml_dict) + + def put(self, path, value): + ''' put path, value into a dict ''' + try: + entry = Yedit.get_entry(self.yaml_dict, path, self.separator) + except KeyError: + entry = None + + if entry == value: + return (False, self.yaml_dict) + + # deepcopy didn't work + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), + yaml.RoundTripLoader) + except AttributeError: + tmp_copy = copy.deepcopy(self.yaml_dict) + + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + + result = Yedit.add_entry(tmp_copy, path, value, self.separator) + if not result: + return (False, self.yaml_dict) + + self.yaml_dict = tmp_copy + + return (True, self.yaml_dict) + + def create(self, path, value): + ''' create a yaml file ''' + if not self.file_exists(): + # deepcopy didn't work + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), + yaml.RoundTripLoader) + except AttributeError: + tmp_copy = copy.deepcopy(self.yaml_dict) + + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + + result = Yedit.add_entry(tmp_copy, path, value, self.separator) + if result: + self.yaml_dict = tmp_copy + return (True, self.yaml_dict) + + return (False, self.yaml_dict) + + @staticmethod + def get_curr_value(invalue, val_type): + '''return the current value''' + if invalue is None: + return None + + curr_value = invalue + if val_type == 'yaml': + curr_value = yaml.load(invalue) + elif val_type == 'json': + curr_value = json.loads(invalue) + + return curr_value + + @staticmethod + def parse_value(inc_value, vtype=''): + '''determine value type passed''' + true_bools = ['y', 'Y', 'yes', 'Yes', 'YES', 'true', 'True', 'TRUE', + 'on', 'On', 'ON', ] + false_bools = ['n', 'N', 'no', 'No', 'NO', 'false', 'False', 'FALSE', + 'off', 'Off', 'OFF'] + + # It came in as a string but you didn't specify value_type as string + # we will convert to bool if it matches any of the above cases + if isinstance(inc_value, str) and 'bool' in vtype: + if inc_value not in true_bools and inc_value not in false_bools: + raise YeditException('Not a boolean type. str=[%s] vtype=[%s]' + % (inc_value, vtype)) + elif isinstance(inc_value, bool) and 'str' in vtype: + inc_value = str(inc_value) + + # If vtype is not str then go ahead and attempt to yaml load it. + if isinstance(inc_value, str) and 'str' not in vtype: + try: + inc_value = yaml.load(inc_value) + except Exception: + raise YeditException('Could not determine type of incoming ' + + 'value. value=[%s] vtype=[%s]' + % (type(inc_value), vtype)) + + return inc_value + + # pylint: disable=too-many-return-statements,too-many-branches + @staticmethod + def run_ansible(module): + '''perform the idempotent crud operations''' + yamlfile = Yedit(filename=module.params['src'], + backup=module.params['backup'], + separator=module.params['separator']) + + if module.params['src']: + rval = yamlfile.load() + + if yamlfile.yaml_dict is None and \ + module.params['state'] != 'present': + return {'failed': True, + 'msg': 'Error opening file [%s]. Verify that the ' + + 'file exists, that it is has correct' + + ' permissions, and is valid yaml.'} + + if module.params['state'] == 'list': + if module.params['content']: + content = Yedit.parse_value(module.params['content'], + module.params['content_type']) + yamlfile.yaml_dict = content + + if module.params['key']: + rval = yamlfile.get(module.params['key']) or {} + + return {'changed': False, 'result': rval, 'state': "list"} + + elif module.params['state'] == 'absent': + if module.params['content']: + content = Yedit.parse_value(module.params['content'], + module.params['content_type']) + yamlfile.yaml_dict = content + + if module.params['update']: + rval = yamlfile.pop(module.params['key'], + module.params['value']) + else: + rval = yamlfile.delete(module.params['key']) + + if rval[0] and module.params['src']: + yamlfile.write() + + return {'changed': rval[0], 'result': rval[1], 'state': "absent"} + + elif module.params['state'] == 'present': + # check if content is different than what is in the file + if module.params['content']: + content = Yedit.parse_value(module.params['content'], + module.params['content_type']) + + # We had no edits to make and the contents are the same + if yamlfile.yaml_dict == content and \ + module.params['value'] is None: + return {'changed': False, + 'result': yamlfile.yaml_dict, + 'state': "present"} + + yamlfile.yaml_dict = content + + # we were passed a value; parse it + if module.params['value']: + value = Yedit.parse_value(module.params['value'], + module.params['value_type']) + key = module.params['key'] + if module.params['update']: + # pylint: disable=line-too-long + curr_value = Yedit.get_curr_value(Yedit.parse_value(module.params['curr_value']), # noqa: E501 + module.params['curr_value_format']) # noqa: E501 + + rval = yamlfile.update(key, value, module.params['index'], curr_value) # noqa: E501 + + elif module.params['append']: + rval = yamlfile.append(key, value) + else: + rval = yamlfile.put(key, value) + + if rval[0] and module.params['src']: + yamlfile.write() + + return {'changed': rval[0], + 'result': rval[1], 'state': "present"} + + # no edits to make + if module.params['src']: + # pylint: disable=redefined-variable-type + rval = yamlfile.write() + return {'changed': rval[0], + 'result': rval[1], + 'state': "present"} + + return {'failed': True, 'msg': 'Unkown state passed'} + +# -*- -*- -*- End included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- + +# -*- -*- -*- Begin included fragment: lib/base.py -*- -*- -*- +# pylint: disable=too-many-lines +# noqa: E301,E302,E303,T001 + + +class OpenShiftCLIError(Exception): + '''Exception class for openshiftcli''' + pass + + +# pylint: disable=too-few-public-methods +class OpenShiftCLI(object): + ''' Class to wrap the command line tools ''' + def __init__(self, + namespace, + kubeconfig='/etc/origin/master/admin.kubeconfig', + verbose=False, + all_namespaces=False): + ''' Constructor for OpenshiftCLI ''' + self.namespace = namespace + self.verbose = verbose + self.kubeconfig = Utils.create_tmpfile_copy(kubeconfig) + self.all_namespaces = all_namespaces + + # Pylint allows only 5 arguments to be passed. + # pylint: disable=too-many-arguments + def _replace_content(self, resource, rname, content, force=False, sep='.'): + ''' replace the current object with the content ''' + res = self._get(resource, rname) + if not res['results']: + return res + + fname = Utils.create_tmpfile(rname + '-') + + yed = Yedit(fname, res['results'][0], separator=sep) + changes = [] + for key, value in content.items(): + changes.append(yed.put(key, value)) + + if any([change[0] for change in changes]): + yed.write() + + atexit.register(Utils.cleanup, [fname]) + + return self._replace(fname, force) + + return {'returncode': 0, 'updated': False} + + def _replace(self, fname, force=False): + '''replace the current object with oc replace''' + cmd = ['replace', '-f', fname] + if force: + cmd.append('--force') + return self.openshift_cmd(cmd) + + def _create_from_content(self, rname, content): + '''create a temporary file and then call oc create on it''' + fname = Utils.create_tmpfile(rname + '-') + yed = Yedit(fname, content=content) + yed.write() + + atexit.register(Utils.cleanup, [fname]) + + return self._create(fname) + + def _create(self, fname): + '''call oc create on a filename''' + return self.openshift_cmd(['create', '-f', fname]) + + def _delete(self, resource, rname, selector=None): + '''call oc delete on a resource''' + cmd = ['delete', resource, rname] + if selector: + cmd.append('--selector=%s' % selector) + + return self.openshift_cmd(cmd) + + def _process(self, template_name, create=False, params=None, template_data=None): # noqa: E501 + '''process a template + + template_name: the name of the template to process + create: whether to send to oc create after processing + params: the parameters for the template + template_data: the incoming template's data; instead of a file + ''' + cmd = ['process'] + if template_data: + cmd.extend(['-f', '-']) + else: + cmd.append(template_name) + if params: + param_str = ["%s=%s" % (key, value) for key, value in params.items()] + cmd.append('-v') + cmd.extend(param_str) + + results = self.openshift_cmd(cmd, output=True, input_data=template_data) + + if results['returncode'] != 0 or not create: + return results + + fname = Utils.create_tmpfile(template_name + '-') + yed = Yedit(fname, results['results']) + yed.write() + + atexit.register(Utils.cleanup, [fname]) + + return self.openshift_cmd(['create', '-f', fname]) + + def _get(self, resource, rname=None, selector=None): + '''return a resource by name ''' + cmd = ['get', resource] + if selector: + cmd.append('--selector=%s' % selector) + elif rname: + cmd.append(rname) + + cmd.extend(['-o', 'json']) + + rval = self.openshift_cmd(cmd, output=True) + + # Ensure results are retuned in an array + if 'items' in rval: + rval['results'] = rval['items'] + elif not isinstance(rval['results'], list): + rval['results'] = [rval['results']] + + return rval + + def _schedulable(self, node=None, selector=None, schedulable=True): + ''' perform oadm manage-node scheduable ''' + cmd = ['manage-node'] + if node: + cmd.extend(node) + else: + cmd.append('--selector=%s' % selector) + + cmd.append('--schedulable=%s' % schedulable) + + return self.openshift_cmd(cmd, oadm=True, output=True, output_type='raw') # noqa: E501 + + def _list_pods(self, node=None, selector=None, pod_selector=None): + ''' perform oadm list pods + + node: the node in which to list pods + selector: the label selector filter if provided + pod_selector: the pod selector filter if provided + ''' + cmd = ['manage-node'] + if node: + cmd.extend(node) + else: + cmd.append('--selector=%s' % selector) + + if pod_selector: + cmd.append('--pod-selector=%s' % pod_selector) + + cmd.extend(['--list-pods', '-o', 'json']) + + return self.openshift_cmd(cmd, oadm=True, output=True, output_type='raw') + + # pylint: disable=too-many-arguments + def _evacuate(self, node=None, selector=None, pod_selector=None, dry_run=False, grace_period=None, force=False): + ''' perform oadm manage-node evacuate ''' + cmd = ['manage-node'] + if node: + cmd.extend(node) + else: + cmd.append('--selector=%s' % selector) + + if dry_run: + cmd.append('--dry-run') + + if pod_selector: + cmd.append('--pod-selector=%s' % pod_selector) + + if grace_period: + cmd.append('--grace-period=%s' % int(grace_period)) + + if force: + cmd.append('--force') + + cmd.append('--evacuate') + + return self.openshift_cmd(cmd, oadm=True, output=True, output_type='raw') + + def _version(self): + ''' return the openshift version''' + return self.openshift_cmd(['version'], output=True, output_type='raw') + + def _import_image(self, url=None, name=None, tag=None): + ''' perform image import ''' + cmd = ['import-image'] + + image = '{0}'.format(name) + if tag: + image += ':{0}'.format(tag) + + cmd.append(image) + + if url: + cmd.append('--from={0}/{1}'.format(url, image)) + + cmd.append('-n{0}'.format(self.namespace)) + + cmd.append('--confirm') + return self.openshift_cmd(cmd) + + def _run(self, cmds, input_data): + ''' Actually executes the command. This makes mocking easier. ''' + curr_env = os.environ.copy() + curr_env.update({'KUBECONFIG': self.kubeconfig}) + proc = subprocess.Popen(cmds, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=curr_env) + + stdout, stderr = proc.communicate(input_data) + + return proc.returncode, stdout.decode(), stderr.decode() + + # pylint: disable=too-many-arguments,too-many-branches + def openshift_cmd(self, cmd, oadm=False, output=False, output_type='json', input_data=None): + '''Base command for oc ''' + cmds = [] + if oadm: + cmds = ['oadm'] + else: + cmds = ['oc'] + + if self.all_namespaces: + cmds.extend(['--all-namespaces']) + elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501 + cmds.extend(['-n', self.namespace]) + + cmds.extend(cmd) + + rval = {} + results = '' + err = None + + if self.verbose: + print(' '.join(cmds)) + + returncode, stdout, stderr = self._run(cmds, input_data) + + 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 err: + if "No JSON object could be decoded" in err.args: + err = err.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}) + + else: + rval.update({"stderr": stderr, + "stdout": stdout, + "results": {}}) + + return rval + + +class Utils(object): + ''' utilities for openshiftcli modules ''' + + @staticmethod + def _write(filename, contents): + ''' Actually write the file contents to disk. This helps with mocking. ''' + + with open(filename, 'w') as sfd: + sfd.write(contents) + + @staticmethod + def create_tmp_file_from_contents(rname, data, ftype='yaml'): + ''' create a file in tmp with name and contents''' + + tmp = Utils.create_tmpfile(prefix=rname) + + if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage + # pylint: disable=no-member + if hasattr(yaml, 'RoundTripDumper'): + Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) + else: + Utils._write(tmp, yaml.safe_dump(data, default_flow_style=False)) + + elif ftype == 'json': + Utils._write(tmp, json.dumps(data)) + else: + Utils._write(tmp, data) + + # Register cleanup when module is done + atexit.register(Utils.cleanup, [tmp]) + return tmp + + @staticmethod + def create_tmpfile_copy(inc_file): + '''create a temporary copy of a file''' + tmpfile = Utils.create_tmpfile('lib_openshift-') + Utils._write(tmpfile, open(inc_file).read()) + + # Cleanup the tmpfile + atexit.register(Utils.cleanup, [tmpfile]) + + return tmpfile + + @staticmethod + def create_tmpfile(prefix='tmp'): + ''' Generates and returns a temporary file name ''' + + with tempfile.NamedTemporaryFile(prefix=prefix, delete=False) as tmp: + return tmp.name + + @staticmethod + def create_tmp_files_from_contents(content, content_type=None): + '''Turn an array of dict: filename, content into a files array''' + if not isinstance(content, list): + content = [content] + files = [] + for item in content: + path = Utils.create_tmp_file_from_contents(item['path'] + '-', + item['data'], + ftype=content_type) + files.append({'name': os.path.basename(item['path']), + 'path': path}) + return files + + @staticmethod + def cleanup(files): + '''Clean up on exit ''' + for sfile in files: + if os.path.exists(sfile): + if os.path.isdir(sfile): + shutil.rmtree(sfile) + elif os.path.isfile(sfile): + os.remove(sfile) + + @staticmethod + def exists(results, _name): + ''' Check to see if the results include the name ''' + if not results: + return False + + if Utils.find_result(results, _name): + return True + + return False + + @staticmethod + def find_result(results, _name): + ''' Find the specified result by name''' + rval = None + for result in results: + if 'metadata' in result and result['metadata']['name'] == _name: + rval = result + break + + return rval + + @staticmethod + def get_resource_file(sfile, sfile_type='yaml'): + ''' return the service file ''' + contents = None + with open(sfile) as sfd: + contents = sfd.read() + + if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage + # pylint: disable=no-member + if hasattr(yaml, 'RoundTripLoader'): + contents = yaml.load(contents, yaml.RoundTripLoader) + else: + contents = yaml.safe_load(contents) + elif sfile_type == 'json': + contents = json.loads(contents) + + return contents + + @staticmethod + def filter_versions(stdout): + ''' filter the oc version output ''' + + version_dict = {} + version_search = ['oc', 'openshift', 'kubernetes'] + + for line in stdout.strip().split('\n'): + for term in version_search: + if not line: + continue + if line.startswith(term): + version_dict[term] = line.split()[-1] + + # horrible hack to get openshift version in Openshift 3.2 + # By default "oc version in 3.2 does not return an "openshift" version + if "openshift" not in version_dict: + version_dict["openshift"] = version_dict["oc"] + + return version_dict + + @staticmethod + def add_custom_versions(versions): + ''' create custom versions strings ''' + + versions_dict = {} + + for tech, version in versions.items(): + # clean up "-" from version + if "-" in version: + version = version.split("-")[0] + + if version.startswith('v'): + versions_dict[tech + '_numeric'] = version[1:].split('+')[0] + # "v3.3.0.33" is what we have, we want "3.3" + versions_dict[tech + '_short'] = version[1:4] + + return versions_dict + + @staticmethod + def openshift_installed(): + ''' check if openshift is installed ''' + import yum + + yum_base = yum.YumBase() + if yum_base.rpmdb.searchNevra(name='atomic-openshift'): + return True + + return False + + # Disabling too-many-branches. This is a yaml dictionary comparison function + # pylint: disable=too-many-branches,too-many-return-statements,too-many-statements + @staticmethod + def check_def_equal(user_def, result_def, skip_keys=None, debug=False): + ''' Given a user defined definition, compare it with the results given back by our query. ''' + + # Currently these values are autogenerated and we do not need to check them + skip = ['metadata', 'status'] + if skip_keys: + skip.extend(skip_keys) + + for key, value in result_def.items(): + if key in skip: + continue + + # Both are lists + if isinstance(value, list): + if key not in user_def: + if debug: + print('User data does not have key [%s]' % key) + print('User data: %s' % user_def) + return False + + if not isinstance(user_def[key], list): + if debug: + print('user_def[key] is not a list key=[%s] user_def[key]=%s' % (key, user_def[key])) + return False + + if len(user_def[key]) != len(value): + if debug: + print("List lengths are not equal.") + print("key=[%s]: user_def[%s] != value[%s]" % (key, len(user_def[key]), len(value))) + print("user_def: %s" % user_def[key]) + print("value: %s" % value) + return False + + for values in zip(user_def[key], value): + if isinstance(values[0], dict) and isinstance(values[1], dict): + if debug: + print('sending list - list') + print(type(values[0])) + print(type(values[1])) + result = Utils.check_def_equal(values[0], values[1], skip_keys=skip_keys, debug=debug) + if not result: + print('list compare returned false') + return False + + elif value != user_def[key]: + if debug: + print('value should be identical') + print(value) + print(user_def[key]) + return False + + # recurse on a dictionary + elif isinstance(value, dict): + if key not in user_def: + if debug: + print("user_def does not have key [%s]" % key) + return False + if not isinstance(user_def[key], dict): + if debug: + print("dict returned false: not instance of dict") + return False + + # before passing ensure keys match + api_values = set(value.keys()) - set(skip) + user_values = set(user_def[key].keys()) - set(skip) + if api_values != user_values: + if debug: + print("keys are not equal in dict") + print(api_values) + print(user_values) + return False + + result = Utils.check_def_equal(user_def[key], value, skip_keys=skip_keys, debug=debug) + if not result: + if debug: + print("dict returned false") + print(result) + return False + + # Verify each key, value pair is the same + else: + if key not in user_def or value != user_def[key]: + if debug: + print("value not equal; user_def does not have key") + print(key) + print(value) + if key in user_def: + print(user_def[key]) + return False + + if debug: + print('returning true') + return True + + +class OpenShiftCLIConfig(object): + '''Generic Config''' + def __init__(self, rname, namespace, kubeconfig, options): + self.kubeconfig = kubeconfig + self.name = rname + self.namespace = namespace + self._options = options + + @property + def config_options(self): + ''' return config options ''' + return self._options + + def to_option_list(self): + '''return all options as a string''' + return self.stringify() + + def stringify(self): + ''' return the options hash as cli params in a string ''' + rval = [] + for key, data in self.config_options.items(): + if data['include'] \ + and (data['value'] or isinstance(data['value'], int)): + rval.append('--%s=%s' % (key.replace('_', '-'), data['value'])) + + return rval + + +# -*- -*- -*- End included fragment: lib/base.py -*- -*- -*- + +# -*- -*- -*- Begin included fragment: class/oc_adm_ca_server_cert.py -*- -*- -*- + +class CAServerCertConfig(OpenShiftCLIConfig): + ''' CAServerCertConfig is a DTO for the oc adm ca command ''' + def __init__(self, kubeconfig, verbose, ca_options): + super(CAServerCertConfig, self).__init__('ca', None, kubeconfig, ca_options) + self.kubeconfig = kubeconfig + self.verbose = verbose + self._ca = ca_options + + +class CAServerCert(OpenShiftCLI): + ''' Class to wrap the oc adm ca create-server-cert command line''' + def __init__(self, + config, + verbose=False): + ''' Constructor for oadm ca ''' + super(CAServerCert, self).__init__(None, config.kubeconfig, verbose) + self.config = config + self.verbose = verbose + + def get(self): + '''get the current cert file + + If a file exists by the same name in the specified location then the cert exists + ''' + cert = self.config.config_options['cert']['value'] + if cert and os.path.exists(cert): + return open(cert).read() + + return None + + def create(self): + '''run openshift oc adm ca create-server-cert cmd''' + + # Added this here as a safegaurd for stomping on the + # cert and key files if they exist + if self.config.config_options['backup']['value']: + import time + ext = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time())) + date_str = "%s_" + "%s" % ext + + if os.path.exists(self.config.config_options['key']['value']): + shutil.copy(self.config.config_options['key']['value'], + date_str % self.config.config_options['key']['value']) + if os.path.exists(self.config.config_options['cert']['value']): + shutil.copy(self.config.config_options['cert']['value'], + date_str % self.config.config_options['cert']['value']) + + options = self.config.to_option_list() + + cmd = ['ca', 'create-server-cert'] + cmd.extend(options) + + return self.openshift_cmd(cmd, oadm=True) + + def exists(self): + ''' check whether the certificate exists and has the clusterIP ''' + + cert_path = self.config.config_options['cert']['value'] + if not os.path.exists(cert_path): + return False + + # Would prefer pyopenssl but is not installed. + # When we verify it is, switch this code + # Here is the code to get the subject and the SAN + # openssl x509 -text -noout -certopt \ + # no_header,no_version,no_serial,no_signame,no_validity,no_issuer,no_pubkey,no_sigdump,no_aux \ + # -in /etc/origin/master/registry.crt + # Instead of this solution we will use a regex. + cert_names = [] + hostnames = self.config.config_options['hostnames']['value'].split(',') + proc = subprocess.Popen(['openssl', 'x509', '-noout', '-text', '-in', cert_path], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + x509output, _ = proc.communicate() + if proc.returncode == 0: + regex = re.compile(r"^\s*X509v3 Subject Alternative Name:\s*?\n\s*(.*)\s*\n", re.MULTILINE) + match = regex.search(x509output) # E501 + for entry in re.split(r", *", match.group(1)): + if entry.startswith('DNS') or entry.startswith('IP Address'): + cert_names.append(entry.split(':')[1]) + # now that we have cert names let's compare + cert_set = set(cert_names) + hname_set = set(hostnames) + if cert_set.issubset(hname_set) and hname_set.issubset(cert_set): + return True + + return False + + @staticmethod + def run_ansible(params, check_mode): + '''run the idempotent ansible code''' + + config = CAServerCertConfig(params['kubeconfig'], + params['debug'], + {'cert': {'value': params['cert'], 'include': True}, + 'hostnames': {'value': ','.join(params['hostnames']), 'include': True}, + 'overwrite': {'value': True, 'include': True}, + 'key': {'value': params['key'], 'include': True}, + 'signer_cert': {'value': params['signer_cert'], 'include': True}, + 'signer_key': {'value': params['signer_key'], 'include': True}, + 'signer_serial': {'value': params['signer_serial'], 'include': True}, + 'backup': {'value': params['backup'], 'include': False}, + }) + + server_cert = CAServerCert(config) + + state = params['state'] + + if state == 'present': + ######## + # Create + ######## + if not server_cert.exists() or params['force']: + + if check_mode: + return {'changed': True, + 'msg': "CHECK_MODE: Would have created the certificate.", + 'state': state} + + api_rval = server_cert.create() + + return {'changed': True, 'results': api_rval, 'state': state} + + ######## + # Exists + ######## + api_rval = server_cert.get() + return {'changed': False, 'results': api_rval, 'state': state} + + return {'failed': True, + 'msg': 'Unknown state passed. %s' % state} + + +# -*- -*- -*- End included fragment: class/oc_adm_ca_server_cert.py -*- -*- -*- + +# -*- -*- -*- Begin included fragment: ansible/oc_adm_ca_server_cert.py -*- -*- -*- + +def main(): + ''' + ansible oc adm module for ca create-server-cert + ''' + + module = AnsibleModule( + argument_spec=dict( + state=dict(default='present', type='str', choices=['present']), + debug=dict(default=False, type='bool'), + kubeconfig=dict(default='/etc/origin/master/admin.kubeconfig', type='str'), + backup=dict(default=True, type='bool'), + force=dict(default=False, type='bool'), + # oc adm ca create-server-cert [options] + cert=dict(default=None, type='str'), + key=dict(default=None, type='str'), + signer_cert=dict(default='/etc/origin/master/ca.crt', type='str'), + signer_key=dict(default='/etc/origin/master/ca.key', type='str'), + signer_serial=dict(default='/etc/origin/master/ca.serial.txt', type='str'), + hostnames=dict(default=[], type='list'), + ), + supports_check_mode=True, + ) + + results = CAServerCert.run_ansible(module.params, module.check_mode) + if 'failed' in results: + return module.fail_json(**results) + + return module.exit_json(**results) + + +if __name__ == '__main__': + main() + +# -*- -*- -*- End included fragment: ansible/oc_adm_ca_server_cert.py -*- -*- -*- diff --git a/roles/lib_openshift/library/oc_adm_registry.py b/roles/lib_openshift/library/oc_adm_registry.py index 5be9e3e0a..fa17d0e58 100644 --- a/roles/lib_openshift/library/oc_adm_registry.py +++ b/roles/lib_openshift/library/oc_adm_registry.py @@ -245,6 +245,7 @@ EXAMPLES = ''' # -*- -*- -*- End included fragment: doc/registry -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -439,14 +440,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -487,15 +490,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -525,14 +536,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -600,7 +613,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -613,7 +628,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -622,7 +638,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -661,19 +678,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -686,17 +704,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1167,6 +1188,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1254,6 +1276,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) @@ -1511,7 +1534,6 @@ spec: super(DeploymentConfig, self).__init__(content=content) - # pylint: disable=no-member def add_env_value(self, key, value): ''' add key, value pair to env array ''' rval = False @@ -1874,7 +1896,6 @@ class Secret(Yedit): def update_secret(self, key, value): ''' update a secret''' - # pylint: disable=no-member if key in self.secrets: self.secrets[key] = value else: @@ -2255,7 +2276,7 @@ class Registry(OpenShiftCLI): # probably need to parse this # pylint thinks results is a string # pylint: disable=no-member - if results['returncode'] != 0 and results['results'].has_key('items'): + if results['returncode'] != 0 and 'items' in results['results']: return results service = None @@ -2336,7 +2357,7 @@ class Registry(OpenShiftCLI): # Currently we know that our deployment of a registry requires a few extra modifications # Modification 1 # we need specific environment variables to be set - for key, value in self.config.config_options['env_vars']['value'].items(): + for key, value in self.config.config_options['env_vars'].get('value', {}).items(): if not deploymentconfig.exists_env_key(key): deploymentconfig.add_env_value(key, value) else: diff --git a/roles/lib_openshift/library/oc_adm_router.py b/roles/lib_openshift/library/oc_adm_router.py index 673c389a5..a9e76a92e 100644 --- a/roles/lib_openshift/library/oc_adm_router.py +++ b/roles/lib_openshift/library/oc_adm_router.py @@ -270,6 +270,7 @@ EXAMPLES = ''' # -*- -*- -*- End included fragment: doc/router -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -464,14 +465,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -512,15 +515,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -550,14 +561,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -625,7 +638,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -638,7 +653,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -647,7 +663,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -686,19 +703,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -711,17 +729,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1192,6 +1213,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1279,6 +1301,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) @@ -1664,7 +1687,6 @@ spec: super(DeploymentConfig, self).__init__(content=content) - # pylint: disable=no-member def add_env_value(self, key, value): ''' add key, value pair to env array ''' rval = False @@ -2158,7 +2180,6 @@ class Secret(Yedit): def update_secret(self, key, value): ''' update a secret''' - # pylint: disable=no-member if key in self.secrets: self.secrets[key] = value else: @@ -2509,8 +2530,11 @@ class Router(OpenShiftCLI): ''' property for the prepared router''' if self.__prepared_router is None: results = self._prepare_router() - if not results: - raise RouterException('Could not perform router preparation') + if not results or 'returncode' in results and results['returncode'] != 0: + if 'stderr' in results: + raise RouterException('Could not perform router preparation: %s' % results['stderr']) + + raise RouterException('Could not perform router preparation.') self.__prepared_router = results return self.__prepared_router @@ -2640,10 +2664,14 @@ class Router(OpenShiftCLI): return deploymentconfig + # pylint: disable=too-many-branches def _prepare_router(self): '''prepare router for instantiation''' - # We need to create the pem file - if self.config.config_options['default_cert']['value'] is None: + # if cacert, key, and cert were passed, combine them into a pem file + if (self.config.config_options['cacert_file']['value'] and + self.config.config_options['cert_file']['value'] and + self.config.config_options['key_file']['value']): + router_pem = '/tmp/router.pem' with open(router_pem, 'w') as rfd: rfd.write(open(self.config.config_options['cert_file']['value']).read()) @@ -2653,8 +2681,13 @@ class Router(OpenShiftCLI): rfd.write(open(self.config.config_options['cacert_file']['value']).read()) atexit.register(Utils.cleanup, [router_pem]) + self.config.config_options['default_cert']['value'] = router_pem + elif self.config.config_options['default_cert']['value'] is None: + # No certificate was passed to us. do not pass one to oc adm router + self.config.config_options['default_cert']['include'] = False + options = self.config.to_option_list() cmd = ['router', self.config.name, '-n', self.config.namespace] @@ -2663,8 +2696,8 @@ class Router(OpenShiftCLI): results = self.openshift_cmd(cmd, oadm=True, output=True, output_type='json') - # pylint: disable=no-member - if results['returncode'] != 0 and 'items' in results['results']: + # pylint: disable=maybe-no-member + if results['returncode'] != 0 or 'items' not in results['results']: return results oc_objects = {'DeploymentConfig': {'obj': None, 'path': None, 'update': False}, @@ -2695,17 +2728,29 @@ class Router(OpenShiftCLI): oc_objects['DeploymentConfig']['obj'] = self.add_modifications(oc_objects['DeploymentConfig']['obj']) for oc_type, oc_data in oc_objects.items(): - oc_data['path'] = Utils.create_tmp_file_from_contents(oc_type, oc_data['obj'].yaml_dict) + if oc_data['obj'] is not None: + oc_data['path'] = Utils.create_tmp_file_from_contents(oc_type, oc_data['obj'].yaml_dict) return oc_objects def create(self): - '''Create a deploymentconfig ''' + '''Create a router + + This includes the different parts: + - deploymentconfig + - service + - serviceaccount + - secrets + - clusterrolebinding + ''' results = [] - # pylint: disable=no-member + import time + # pylint: disable=maybe-no-member for _, oc_data in self.prepared_router.items(): - results.append(self._create(oc_data['path'])) + if oc_data['obj'] is not None: + time.sleep(1) + results.append(self._create(oc_data['path'])) rval = 0 for result in results: @@ -2718,7 +2763,7 @@ class Router(OpenShiftCLI): '''run update for the router. This performs a replace''' results = [] - # pylint: disable=no-member + # pylint: disable=maybe-no-member for _, oc_data in self.prepared_router.items(): if oc_data['update']: results.append(self._replace(oc_data['path'])) @@ -2966,8 +3011,10 @@ def main(): mutually_exclusive=[["router_type", "images"], ["key_file", "default_cert"], ["cert_file", "default_cert"], + ["cacert_file", "default_cert"], ], + required_together=[['cacert_file', 'cert_file', 'key_file']], supports_check_mode=True, ) results = Router.run_ansible(module.params, module.check_mode) diff --git a/roles/lib_openshift/library/oc_edit.py b/roles/lib_openshift/library/oc_edit.py index e38cf443f..8901042ac 100644 --- a/roles/lib_openshift/library/oc_edit.py +++ b/roles/lib_openshift/library/oc_edit.py @@ -169,6 +169,7 @@ oc_edit: # -*- -*- -*- End included fragment: doc/edit -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -363,14 +364,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -411,15 +414,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -449,14 +460,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -524,7 +537,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -537,7 +552,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -546,7 +562,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -585,19 +602,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -610,17 +628,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1091,6 +1112,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1178,6 +1200,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) diff --git a/roles/lib_openshift/library/oc_env.py b/roles/lib_openshift/library/oc_env.py index 1e089198f..3286985c5 100644 --- a/roles/lib_openshift/library/oc_env.py +++ b/roles/lib_openshift/library/oc_env.py @@ -136,6 +136,7 @@ EXAMPLES = ''' # -*- -*- -*- End included fragment: doc/env -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -330,14 +331,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -378,15 +381,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -416,14 +427,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -491,7 +504,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -504,7 +519,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -513,7 +529,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -552,19 +569,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -577,17 +595,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1058,6 +1079,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1145,6 +1167,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) @@ -1402,7 +1425,6 @@ spec: super(DeploymentConfig, self).__init__(content=content) - # pylint: disable=no-member def add_env_value(self, key, value): ''' add key, value pair to env array ''' rval = False diff --git a/roles/lib_openshift/library/oc_label.py b/roles/lib_openshift/library/oc_label.py index 981e4ef2d..7a4d6959a 100644 --- a/roles/lib_openshift/library/oc_label.py +++ b/roles/lib_openshift/library/oc_label.py @@ -145,6 +145,7 @@ EXAMPLES = ''' # -*- -*- -*- End included fragment: doc/label -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -339,14 +340,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -387,15 +390,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -425,14 +436,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -500,7 +513,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -513,7 +528,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -522,7 +538,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -561,19 +578,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -586,17 +604,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1067,6 +1088,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1154,6 +1176,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) diff --git a/roles/lib_openshift/library/oc_obj.py b/roles/lib_openshift/library/oc_obj.py index 3b9c79fae..0f56ce983 100644 --- a/roles/lib_openshift/library/oc_obj.py +++ b/roles/lib_openshift/library/oc_obj.py @@ -148,6 +148,7 @@ register: router_output # -*- -*- -*- End included fragment: doc/obj -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -342,14 +343,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -390,15 +393,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -428,14 +439,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -503,7 +516,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -516,7 +531,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -525,7 +541,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -564,19 +581,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -589,17 +607,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1070,6 +1091,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1157,6 +1179,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) @@ -1423,7 +1446,6 @@ class OCObject(OpenShiftCLI): if objects['returncode'] != 0: return objects - # pylint: disable=no-member data = None if files: data = Utils.get_resource_file(files[0], content_type) diff --git a/roles/lib_openshift/library/oc_process.py b/roles/lib_openshift/library/oc_process.py index 996dcefa1..4f53bb5d6 100644 --- a/roles/lib_openshift/library/oc_process.py +++ b/roles/lib_openshift/library/oc_process.py @@ -137,6 +137,7 @@ EXAMPLES = ''' # -*- -*- -*- End included fragment: doc/process -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -331,14 +332,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -379,15 +382,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -417,14 +428,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -492,7 +505,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -505,7 +520,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -514,7 +530,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -553,19 +570,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -578,17 +596,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1059,6 +1080,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1146,6 +1168,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) diff --git a/roles/lib_openshift/library/oc_route.py b/roles/lib_openshift/library/oc_route.py index cc096bb88..a2cbd9b93 100644 --- a/roles/lib_openshift/library/oc_route.py +++ b/roles/lib_openshift/library/oc_route.py @@ -179,6 +179,7 @@ EXAMPLES = ''' # -*- -*- -*- End included fragment: doc/route -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -373,14 +374,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -421,15 +424,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -459,14 +470,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -534,7 +547,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -547,7 +562,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -556,7 +572,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -595,19 +612,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -620,17 +638,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1101,6 +1122,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1188,6 +1210,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) diff --git a/roles/lib_openshift/library/oc_scale.py b/roles/lib_openshift/library/oc_scale.py index b70be4dad..3523e7ea6 100644 --- a/roles/lib_openshift/library/oc_scale.py +++ b/roles/lib_openshift/library/oc_scale.py @@ -123,6 +123,7 @@ EXAMPLES = ''' # -*- -*- -*- End included fragment: doc/scale -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -317,14 +318,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -365,15 +368,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -403,14 +414,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -478,7 +491,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -491,7 +506,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -500,7 +516,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -539,19 +556,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -564,17 +582,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1045,6 +1066,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1132,6 +1154,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) @@ -1389,7 +1412,6 @@ spec: super(DeploymentConfig, self).__init__(content=content) - # pylint: disable=no-member def add_env_value(self, key, value): ''' add key, value pair to env array ''' rval = False diff --git a/roles/lib_openshift/library/oc_secret.py b/roles/lib_openshift/library/oc_secret.py index 68213d4d9..db9a3a7ec 100644 --- a/roles/lib_openshift/library/oc_secret.py +++ b/roles/lib_openshift/library/oc_secret.py @@ -169,6 +169,7 @@ EXAMPLES = ''' # -*- -*- -*- End included fragment: doc/secret -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -363,14 +364,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -411,15 +414,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -449,14 +460,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -524,7 +537,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -537,7 +552,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -546,7 +562,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -585,19 +602,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -610,17 +628,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1091,6 +1112,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1178,6 +1200,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) @@ -1457,7 +1480,6 @@ class Secret(Yedit): def update_secret(self, key, value): ''' update a secret''' - # pylint: disable=no-member if key in self.secrets: self.secrets[key] = value else: diff --git a/roles/lib_openshift/library/oc_service.py b/roles/lib_openshift/library/oc_service.py index 35c00c189..c8d4b3040 100644 --- a/roles/lib_openshift/library/oc_service.py +++ b/roles/lib_openshift/library/oc_service.py @@ -175,6 +175,7 @@ EXAMPLES = ''' # -*- -*- -*- End included fragment: doc/service -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -369,14 +370,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -417,15 +420,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -455,14 +466,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -530,7 +543,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -543,7 +558,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -552,7 +568,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -591,19 +608,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -616,17 +634,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1097,6 +1118,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1184,6 +1206,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) diff --git a/roles/lib_openshift/library/oc_serviceaccount.py b/roles/lib_openshift/library/oc_serviceaccount.py index 2feb7f32e..3e650b5f2 100644 --- a/roles/lib_openshift/library/oc_serviceaccount.py +++ b/roles/lib_openshift/library/oc_serviceaccount.py @@ -121,6 +121,7 @@ EXAMPLES = ''' # -*- -*- -*- End included fragment: doc/serviceaccount -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -315,14 +316,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -363,15 +366,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -401,14 +412,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -476,7 +489,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -489,7 +504,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -498,7 +514,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -537,19 +554,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -562,17 +580,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1043,6 +1064,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1130,6 +1152,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) diff --git a/roles/lib_openshift/library/oc_serviceaccount_secret.py b/roles/lib_openshift/library/oc_serviceaccount_secret.py index 676337149..749cf2d8e 100644 --- a/roles/lib_openshift/library/oc_serviceaccount_secret.py +++ b/roles/lib_openshift/library/oc_serviceaccount_secret.py @@ -121,6 +121,7 @@ EXAMPLES = ''' # -*- -*- -*- End included fragment: doc/serviceaccount_secret -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -315,14 +316,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -363,15 +366,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -401,14 +412,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -476,7 +489,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -489,7 +504,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -498,7 +514,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -537,19 +554,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -562,17 +580,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1043,6 +1064,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1130,6 +1152,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) diff --git a/roles/lib_openshift/library/oc_version.py b/roles/lib_openshift/library/oc_version.py index 933bcc331..e9b970967 100644 --- a/roles/lib_openshift/library/oc_version.py +++ b/roles/lib_openshift/library/oc_version.py @@ -93,6 +93,7 @@ oc_version: # -*- -*- -*- End included fragment: doc/version -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -287,14 +288,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -335,15 +338,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -373,14 +384,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -448,7 +461,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -461,7 +476,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -470,7 +486,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -509,19 +526,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -534,17 +552,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy @@ -1015,6 +1036,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -1102,6 +1124,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) diff --git a/roles/lib_openshift/src/ansible/oc_adm_ca_server_cert.py b/roles/lib_openshift/src/ansible/oc_adm_ca_server_cert.py new file mode 100644 index 000000000..c80c2eb44 --- /dev/null +++ b/roles/lib_openshift/src/ansible/oc_adm_ca_server_cert.py @@ -0,0 +1,35 @@ +# pylint: skip-file +# flake8: noqa + +def main(): + ''' + ansible oc adm module for ca create-server-cert + ''' + + module = AnsibleModule( + argument_spec=dict( + state=dict(default='present', type='str', choices=['present']), + debug=dict(default=False, type='bool'), + kubeconfig=dict(default='/etc/origin/master/admin.kubeconfig', type='str'), + backup=dict(default=True, type='bool'), + force=dict(default=False, type='bool'), + # oc adm ca create-server-cert [options] + cert=dict(default=None, type='str'), + key=dict(default=None, type='str'), + signer_cert=dict(default='/etc/origin/master/ca.crt', type='str'), + signer_key=dict(default='/etc/origin/master/ca.key', type='str'), + signer_serial=dict(default='/etc/origin/master/ca.serial.txt', type='str'), + hostnames=dict(default=[], type='list'), + ), + supports_check_mode=True, + ) + + results = CAServerCert.run_ansible(module.params, module.check_mode) + if 'failed' in results: + return module.fail_json(**results) + + return module.exit_json(**results) + + +if __name__ == '__main__': + main() diff --git a/roles/lib_openshift/src/ansible/oc_adm_router.py b/roles/lib_openshift/src/ansible/oc_adm_router.py index 48c9f0ec1..b6f8e90d0 100644 --- a/roles/lib_openshift/src/ansible/oc_adm_router.py +++ b/roles/lib_openshift/src/ansible/oc_adm_router.py @@ -51,8 +51,10 @@ def main(): mutually_exclusive=[["router_type", "images"], ["key_file", "default_cert"], ["cert_file", "default_cert"], + ["cacert_file", "default_cert"], ], + required_together=[['cacert_file', 'cert_file', 'key_file']], supports_check_mode=True, ) results = Router.run_ansible(module.params, module.check_mode) diff --git a/roles/lib_openshift/src/class/oc_adm_ca_server_cert.py b/roles/lib_openshift/src/class/oc_adm_ca_server_cert.py new file mode 100644 index 000000000..6ed1f2f35 --- /dev/null +++ b/roles/lib_openshift/src/class/oc_adm_ca_server_cert.py @@ -0,0 +1,135 @@ +# pylint: skip-file +# flake8: noqa + +class CAServerCertConfig(OpenShiftCLIConfig): + ''' CAServerCertConfig is a DTO for the oc adm ca command ''' + def __init__(self, kubeconfig, verbose, ca_options): + super(CAServerCertConfig, self).__init__('ca', None, kubeconfig, ca_options) + self.kubeconfig = kubeconfig + self.verbose = verbose + self._ca = ca_options + + +class CAServerCert(OpenShiftCLI): + ''' Class to wrap the oc adm ca create-server-cert command line''' + def __init__(self, + config, + verbose=False): + ''' Constructor for oadm ca ''' + super(CAServerCert, self).__init__(None, config.kubeconfig, verbose) + self.config = config + self.verbose = verbose + + def get(self): + '''get the current cert file + + If a file exists by the same name in the specified location then the cert exists + ''' + cert = self.config.config_options['cert']['value'] + if cert and os.path.exists(cert): + return open(cert).read() + + return None + + def create(self): + '''run openshift oc adm ca create-server-cert cmd''' + + # Added this here as a safegaurd for stomping on the + # cert and key files if they exist + if self.config.config_options['backup']['value']: + import time + ext = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time())) + date_str = "%s_" + "%s" % ext + + if os.path.exists(self.config.config_options['key']['value']): + shutil.copy(self.config.config_options['key']['value'], + date_str % self.config.config_options['key']['value']) + if os.path.exists(self.config.config_options['cert']['value']): + shutil.copy(self.config.config_options['cert']['value'], + date_str % self.config.config_options['cert']['value']) + + options = self.config.to_option_list() + + cmd = ['ca', 'create-server-cert'] + cmd.extend(options) + + return self.openshift_cmd(cmd, oadm=True) + + def exists(self): + ''' check whether the certificate exists and has the clusterIP ''' + + cert_path = self.config.config_options['cert']['value'] + if not os.path.exists(cert_path): + return False + + # Would prefer pyopenssl but is not installed. + # When we verify it is, switch this code + # Here is the code to get the subject and the SAN + # openssl x509 -text -noout -certopt \ + # no_header,no_version,no_serial,no_signame,no_validity,no_issuer,no_pubkey,no_sigdump,no_aux \ + # -in /etc/origin/master/registry.crt + # Instead of this solution we will use a regex. + cert_names = [] + hostnames = self.config.config_options['hostnames']['value'].split(',') + proc = subprocess.Popen(['openssl', 'x509', '-noout', '-text', '-in', cert_path], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + x509output, _ = proc.communicate() + if proc.returncode == 0: + regex = re.compile(r"^\s*X509v3 Subject Alternative Name:\s*?\n\s*(.*)\s*\n", re.MULTILINE) + match = regex.search(x509output) # E501 + for entry in re.split(r", *", match.group(1)): + if entry.startswith('DNS') or entry.startswith('IP Address'): + cert_names.append(entry.split(':')[1]) + # now that we have cert names let's compare + cert_set = set(cert_names) + hname_set = set(hostnames) + if cert_set.issubset(hname_set) and hname_set.issubset(cert_set): + return True + + return False + + @staticmethod + def run_ansible(params, check_mode): + '''run the idempotent ansible code''' + + config = CAServerCertConfig(params['kubeconfig'], + params['debug'], + {'cert': {'value': params['cert'], 'include': True}, + 'hostnames': {'value': ','.join(params['hostnames']), 'include': True}, + 'overwrite': {'value': True, 'include': True}, + 'key': {'value': params['key'], 'include': True}, + 'signer_cert': {'value': params['signer_cert'], 'include': True}, + 'signer_key': {'value': params['signer_key'], 'include': True}, + 'signer_serial': {'value': params['signer_serial'], 'include': True}, + 'backup': {'value': params['backup'], 'include': False}, + }) + + server_cert = CAServerCert(config) + + state = params['state'] + + if state == 'present': + ######## + # Create + ######## + if not server_cert.exists() or params['force']: + + if check_mode: + return {'changed': True, + 'msg': "CHECK_MODE: Would have created the certificate.", + 'state': state} + + api_rval = server_cert.create() + + return {'changed': True, 'results': api_rval, 'state': state} + + ######## + # Exists + ######## + api_rval = server_cert.get() + return {'changed': False, 'results': api_rval, 'state': state} + + return {'failed': True, + 'msg': 'Unknown state passed. %s' % state} + diff --git a/roles/lib_openshift/src/class/oc_adm_registry.py b/roles/lib_openshift/src/class/oc_adm_registry.py index 8cb7aea31..eb78667ca 100644 --- a/roles/lib_openshift/src/class/oc_adm_registry.py +++ b/roles/lib_openshift/src/class/oc_adm_registry.py @@ -154,7 +154,7 @@ class Registry(OpenShiftCLI): # probably need to parse this # pylint thinks results is a string # pylint: disable=no-member - if results['returncode'] != 0 and results['results'].has_key('items'): + if results['returncode'] != 0 and 'items' in results['results']: return results service = None @@ -235,7 +235,7 @@ class Registry(OpenShiftCLI): # Currently we know that our deployment of a registry requires a few extra modifications # Modification 1 # we need specific environment variables to be set - for key, value in self.config.config_options['env_vars']['value'].items(): + for key, value in self.config.config_options['env_vars'].get('value', {}).items(): if not deploymentconfig.exists_env_key(key): deploymentconfig.add_env_value(key, value) else: diff --git a/roles/lib_openshift/src/class/oc_adm_router.py b/roles/lib_openshift/src/class/oc_adm_router.py index 9d61cfdf2..66769e73b 100644 --- a/roles/lib_openshift/src/class/oc_adm_router.py +++ b/roles/lib_openshift/src/class/oc_adm_router.py @@ -49,8 +49,11 @@ class Router(OpenShiftCLI): ''' property for the prepared router''' if self.__prepared_router is None: results = self._prepare_router() - if not results: - raise RouterException('Could not perform router preparation') + if not results or 'returncode' in results and results['returncode'] != 0: + if 'stderr' in results: + raise RouterException('Could not perform router preparation: %s' % results['stderr']) + + raise RouterException('Could not perform router preparation.') self.__prepared_router = results return self.__prepared_router @@ -180,10 +183,14 @@ class Router(OpenShiftCLI): return deploymentconfig + # pylint: disable=too-many-branches def _prepare_router(self): '''prepare router for instantiation''' - # We need to create the pem file - if self.config.config_options['default_cert']['value'] is None: + # if cacert, key, and cert were passed, combine them into a pem file + if (self.config.config_options['cacert_file']['value'] and + self.config.config_options['cert_file']['value'] and + self.config.config_options['key_file']['value']): + router_pem = '/tmp/router.pem' with open(router_pem, 'w') as rfd: rfd.write(open(self.config.config_options['cert_file']['value']).read()) @@ -193,8 +200,13 @@ class Router(OpenShiftCLI): rfd.write(open(self.config.config_options['cacert_file']['value']).read()) atexit.register(Utils.cleanup, [router_pem]) + self.config.config_options['default_cert']['value'] = router_pem + elif self.config.config_options['default_cert']['value'] is None: + # No certificate was passed to us. do not pass one to oc adm router + self.config.config_options['default_cert']['include'] = False + options = self.config.to_option_list() cmd = ['router', self.config.name, '-n', self.config.namespace] @@ -203,8 +215,8 @@ class Router(OpenShiftCLI): results = self.openshift_cmd(cmd, oadm=True, output=True, output_type='json') - # pylint: disable=no-member - if results['returncode'] != 0 and 'items' in results['results']: + # pylint: disable=maybe-no-member + if results['returncode'] != 0 or 'items' not in results['results']: return results oc_objects = {'DeploymentConfig': {'obj': None, 'path': None, 'update': False}, @@ -235,17 +247,29 @@ class Router(OpenShiftCLI): oc_objects['DeploymentConfig']['obj'] = self.add_modifications(oc_objects['DeploymentConfig']['obj']) for oc_type, oc_data in oc_objects.items(): - oc_data['path'] = Utils.create_tmp_file_from_contents(oc_type, oc_data['obj'].yaml_dict) + if oc_data['obj'] is not None: + oc_data['path'] = Utils.create_tmp_file_from_contents(oc_type, oc_data['obj'].yaml_dict) return oc_objects def create(self): - '''Create a deploymentconfig ''' + '''Create a router + + This includes the different parts: + - deploymentconfig + - service + - serviceaccount + - secrets + - clusterrolebinding + ''' results = [] - # pylint: disable=no-member + import time + # pylint: disable=maybe-no-member for _, oc_data in self.prepared_router.items(): - results.append(self._create(oc_data['path'])) + if oc_data['obj'] is not None: + time.sleep(1) + results.append(self._create(oc_data['path'])) rval = 0 for result in results: @@ -258,7 +282,7 @@ class Router(OpenShiftCLI): '''run update for the router. This performs a replace''' results = [] - # pylint: disable=no-member + # pylint: disable=maybe-no-member for _, oc_data in self.prepared_router.items(): if oc_data['update']: results.append(self._replace(oc_data['path'])) diff --git a/roles/lib_openshift/src/class/oc_obj.py b/roles/lib_openshift/src/class/oc_obj.py index 21129a50c..51d3ce996 100644 --- a/roles/lib_openshift/src/class/oc_obj.py +++ b/roles/lib_openshift/src/class/oc_obj.py @@ -77,7 +77,6 @@ class OCObject(OpenShiftCLI): if objects['returncode'] != 0: return objects - # pylint: disable=no-member data = None if files: data = Utils.get_resource_file(files[0], content_type) diff --git a/roles/lib_openshift/src/doc/ca_server_cert b/roles/lib_openshift/src/doc/ca_server_cert new file mode 100644 index 000000000..a8034158e --- /dev/null +++ b/roles/lib_openshift/src/doc/ca_server_cert @@ -0,0 +1,96 @@ +# flake8: noqa +# pylint: skip-file + +DOCUMENTATION = ''' +--- +module: oc_adm_ca_server_cert +short_description: Module to run openshift oc adm ca create-server-cert +description: + - Wrapper around the openshift `oc adm ca create-server-cert` command. +options: + state: + description: + - Present is the only supported state. The state present means that `oc adm ca` will generate a certificate + - and verify if the hostnames and the ClusterIP exists in the certificate. + - When create-server-cert is desired then the following parameters are passed. + - ['cert', 'key', 'signer_cert', 'signer_key', 'signer_serial'] + required: false + default: present + choices: + - present + aliases: [] + kubeconfig: + description: + - The path for the kubeconfig file to use for authentication + required: false + default: /etc/origin/master/admin.kubeconfig + aliases: [] + debug: + description: + - Turn on debug output. + required: false + default: False + aliases: [] + cert: + description: + - The certificate file. Choose a name that indicates what the service is. + required: false + default: None + aliases: [] + key: + description: + - The key file. Choose a name that indicates what the service is. + required: false + default: None + aliases: [] + force: + description: + - Force updating of the existing cert and key files + required: false + default: False + aliases: [] + signer_cert: + description: + - The signer certificate file. + required: false + default: /etc/origin/master/ca.crt + aliases: [] + signer_key: + description: + - The signer key file. + required: false + default: /etc/origin/master/ca.key + aliases: [] + signer_serial: + description: + - The signer serial file. + required: false + default: /etc/origin/master/ca.serial.txt + aliases: [] + hostnames: + description: + - Every hostname or IP that server certs should be valid for (comma-delimited list) + required: false + default: None + aliases: [] + backup: + description: + - Whether to backup the cert and key files before writing them. + required: false + default: True + aliases: [] +author: +- "Kenny Woodson <kwoodson@redhat.com>" +extends_documentation_fragment: [] +''' + +EXAMPLES = ''' +- name: Create a self-signed cert + oc_adm_ca_server_cert: + signer_cert: /etc/origin/master/ca.crt + signer_key: /etc/origin/master/ca.key + signer_serial: /etc/origin/master/ca.serial.txt + hostnames: "registry.test.openshift.com,127.0.0.1,docker-registry.default.svc.cluster.local" + cert: /etc/origin/master/registry.crt + key: /etc/origin/master/registry.key +''' diff --git a/roles/lib_openshift/src/lib/base.py b/roles/lib_openshift/src/lib/base.py index 79ea3a6b9..2e822d8ef 100644 --- a/roles/lib_openshift/src/lib/base.py +++ b/roles/lib_openshift/src/lib/base.py @@ -324,6 +324,7 @@ class Utils(object): tmp = Utils.create_tmpfile(prefix=rname) if ftype == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripDumper'): Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) @@ -411,6 +412,7 @@ class Utils(object): contents = sfd.read() if sfile_type == 'yaml': + # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage # pylint: disable=no-member if hasattr(yaml, 'RoundTripLoader'): contents = yaml.load(contents, yaml.RoundTripLoader) diff --git a/roles/lib_openshift/src/lib/deploymentconfig.py b/roles/lib_openshift/src/lib/deploymentconfig.py index f10c6bb8b..e37475ef5 100644 --- a/roles/lib_openshift/src/lib/deploymentconfig.py +++ b/roles/lib_openshift/src/lib/deploymentconfig.py @@ -68,7 +68,6 @@ spec: super(DeploymentConfig, self).__init__(content=content) - # pylint: disable=no-member def add_env_value(self, key, value): ''' add key, value pair to env array ''' rval = False diff --git a/roles/lib_openshift/src/lib/secret.py b/roles/lib_openshift/src/lib/secret.py index 622290aa8..75c32e8b1 100644 --- a/roles/lib_openshift/src/lib/secret.py +++ b/roles/lib_openshift/src/lib/secret.py @@ -90,7 +90,6 @@ class Secret(Yedit): def update_secret(self, key, value): ''' update a secret''' - # pylint: disable=no-member if key in self.secrets: self.secrets[key] = value else: diff --git a/roles/lib_openshift/src/sources.yml b/roles/lib_openshift/src/sources.yml index fca1f4818..35f8d71b2 100644 --- a/roles/lib_openshift/src/sources.yml +++ b/roles/lib_openshift/src/sources.yml @@ -1,4 +1,14 @@ --- +oc_adm_ca_server_cert.py: +- doc/generated +- doc/license +- lib/import.py +- doc/ca_server_cert +- ../../lib_utils/src/class/yedit.py +- lib/base.py +- class/oc_adm_ca_server_cert.py +- ansible/oc_adm_ca_server_cert.py + oadm_manage_node.py: - doc/generated - doc/license diff --git a/roles/lib_utils/library/repoquery.py b/roles/lib_utils/library/repoquery.py index f31c8911b..ee98470b0 100644 --- a/roles/lib_utils/library/repoquery.py +++ b/roles/lib_utils/library/repoquery.py @@ -35,7 +35,6 @@ import os # noqa: F401 import re # noqa: F401 import shutil # noqa: F401 -# pylint: disable=import-error try: import ruamel.yaml as yaml # noqa: F401 except ImportError: diff --git a/roles/lib_utils/library/yedit.py b/roles/lib_utils/library/yedit.py index a358e980e..b1d9d6869 100644 --- a/roles/lib_utils/library/yedit.py +++ b/roles/lib_utils/library/yedit.py @@ -35,7 +35,6 @@ import os # noqa: F401 import re # noqa: F401 import shutil # noqa: F401 -# pylint: disable=import-error try: import ruamel.yaml as yaml # noqa: F401 except ImportError: @@ -186,6 +185,7 @@ EXAMPLES = ''' # -*- -*- -*- End included fragment: doc/yedit -*- -*- -*- # -*- -*- -*- Begin included fragment: class/yedit.py -*- -*- -*- +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -380,14 +380,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -428,15 +430,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -466,14 +476,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -541,7 +553,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -554,7 +568,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -563,7 +578,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -602,19 +618,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -627,17 +644,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy diff --git a/roles/lib_utils/src/class/yedit.py b/roles/lib_utils/src/class/yedit.py index 5275e84eb..74ee52fe3 100644 --- a/roles/lib_utils/src/class/yedit.py +++ b/roles/lib_utils/src/class/yedit.py @@ -1,5 +1,5 @@ # flake8: noqa -# pylint: skip-file +# pylint: disable=undefined-variable,missing-docstring # noqa: E301,E302 @@ -194,14 +194,16 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - if hasattr(yaml, 'RoundTripDumper'): - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass - # pylint: disable=no-member + # Try to use RoundTripDumper if supported. + try: Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) - else: + except AttributeError: Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False)) return (True, self.yaml_dict) @@ -242,15 +244,23 @@ class Yedit(object): # check if it is yaml try: if content_type == 'yaml' and contents: - # pylint: disable=no-member - if hasattr(yaml, 'RoundTripLoader'): - self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader) - else: + # Try to set format attributes if supported + try: + self.yaml_dict.fa.set_block_style() + except AttributeError: + pass + + # Try to use RoundTripLoader if supported. + try: + self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader) + except AttributeError: self.yaml_dict = yaml.safe_load(contents) - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): + # Try to set format attributes if supported + try: self.yaml_dict.fa.set_block_style() + except AttributeError: + pass elif content_type == 'json' and contents: self.yaml_dict = json.loads(contents) @@ -280,14 +290,16 @@ class Yedit(object): return (False, self.yaml_dict) if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if key_or_item in entry: entry.pop(key_or_item) return (True, self.yaml_dict) return (False, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None try: ind = entry.index(key_or_item) @@ -355,7 +367,9 @@ class Yedit(object): if not isinstance(entry, list): return (False, self.yaml_dict) - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to loading data from + # a serialized format. + # pylint: disable=maybe-no-member entry.append(value) return (True, self.yaml_dict) @@ -368,7 +382,8 @@ class Yedit(object): entry = None if isinstance(entry, dict): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member if not isinstance(value, dict): raise YeditException('Cannot replace key, value entry in ' + 'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501 @@ -377,7 +392,8 @@ class Yedit(object): return (True, self.yaml_dict) elif isinstance(entry, list): - # pylint: disable=no-member,maybe-no-member + # AUDIT:maybe-no-member makes sense due to fuzzy types + # pylint: disable=maybe-no-member ind = None if curr_value: try: @@ -416,19 +432,20 @@ class Yedit(object): return (False, self.yaml_dict) # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member + # Try to use ruamel.yaml and fallback to pyyaml + try: tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if not result: return (False, self.yaml_dict) @@ -441,17 +458,20 @@ class Yedit(object): ''' create a yaml file ''' if not self.file_exists(): # deepcopy didn't work - if hasattr(yaml, 'round_trip_dump'): - # pylint: disable=no-member - tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501 + # Try to use ruamel.yaml and fallback to pyyaml + try: + tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, + default_flow_style=False), yaml.RoundTripLoader) - - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - tmp_copy.fa.set_block_style() - else: + except AttributeError: tmp_copy = copy.deepcopy(self.yaml_dict) + # set the format attributes if available + try: + tmp_copy.fa.set_block_style() + except AttributeError: + pass + result = Yedit.add_entry(tmp_copy, path, value, self.separator) if result: self.yaml_dict = tmp_copy diff --git a/roles/lib_utils/src/lib/import.py b/roles/lib_utils/src/lib/import.py index ed57a68c9..b0ab7c92c 100644 --- a/roles/lib_utils/src/lib/import.py +++ b/roles/lib_utils/src/lib/import.py @@ -10,7 +10,6 @@ import os # noqa: F401 import re # noqa: F401 import shutil # noqa: F401 -# pylint: disable=import-error try: import ruamel.yaml as yaml # noqa: F401 except ImportError: diff --git a/roles/openshift_health_checker/openshift_checks/__init__.py b/roles/openshift_health_checker/openshift_checks/__init__.py index c31242624..2c70438c9 100644 --- a/roles/openshift_health_checker/openshift_checks/__init__.py +++ b/roles/openshift_health_checker/openshift_checks/__init__.py @@ -50,6 +50,7 @@ class OpenShiftCheck(object): @classmethod def subclasses(cls): """Returns a generator of subclasses of this class and its subclasses.""" + # AUDIT: no-member makes sense due to this having a metaclass for subclass in cls.__subclasses__(): # pylint: disable=no-member yield subclass for subclass in subclass.subclasses(): diff --git a/roles/openshift_health_checker/openshift_checks/mixins.py b/roles/openshift_health_checker/openshift_checks/mixins.py index 4029fba62..657e15160 100644 --- a/roles/openshift_health_checker/openshift_checks/mixins.py +++ b/roles/openshift_health_checker/openshift_checks/mixins.py @@ -2,17 +2,14 @@ from openshift_checks import get_var -class NotContainerized(object): +class NotContainerizedMixin(object): """Mixin for checks that are only active when not in containerized mode.""" @classmethod def is_active(cls, task_vars): return ( - # This mixin is meant to be used with subclasses of - # OpenShiftCheck. Pylint disables this by default on mixins, - # though it relies on the class name ending in 'mixin'. - # pylint: disable=no-member - super(NotContainerized, cls).is_active(task_vars) and + # This mixin is meant to be used with subclasses of OpenShiftCheck. + super(NotContainerizedMixin, cls).is_active(task_vars) and not cls.is_containerized(task_vars) ) diff --git a/roles/openshift_health_checker/openshift_checks/package_availability.py b/roles/openshift_health_checker/openshift_checks/package_availability.py index 8faeef5ee..771123d61 100644 --- a/roles/openshift_health_checker/openshift_checks/package_availability.py +++ b/roles/openshift_health_checker/openshift_checks/package_availability.py @@ -1,9 +1,9 @@ # pylint: disable=missing-docstring from openshift_checks import OpenShiftCheck, get_var -from openshift_checks.mixins import NotContainerized +from openshift_checks.mixins import NotContainerizedMixin -class PackageAvailability(NotContainerized, OpenShiftCheck): +class PackageAvailability(NotContainerizedMixin, OpenShiftCheck): """Check that required RPM packages are available.""" name = "package_availability" diff --git a/roles/openshift_health_checker/openshift_checks/package_update.py b/roles/openshift_health_checker/openshift_checks/package_update.py index 86b7b6245..c5a226954 100644 --- a/roles/openshift_health_checker/openshift_checks/package_update.py +++ b/roles/openshift_health_checker/openshift_checks/package_update.py @@ -1,9 +1,9 @@ # pylint: disable=missing-docstring from openshift_checks import OpenShiftCheck -from openshift_checks.mixins import NotContainerized +from openshift_checks.mixins import NotContainerizedMixin -class PackageUpdate(NotContainerized, OpenShiftCheck): +class PackageUpdate(NotContainerizedMixin, OpenShiftCheck): """Check that there are no conflicts in RPM packages.""" name = "package_update" diff --git a/roles/openshift_health_checker/openshift_checks/package_version.py b/roles/openshift_health_checker/openshift_checks/package_version.py index 7fa09cbfd..2e9d07deb 100644 --- a/roles/openshift_health_checker/openshift_checks/package_version.py +++ b/roles/openshift_health_checker/openshift_checks/package_version.py @@ -1,9 +1,9 @@ # pylint: disable=missing-docstring from openshift_checks import OpenShiftCheck, get_var -from openshift_checks.mixins import NotContainerized +from openshift_checks.mixins import NotContainerizedMixin -class PackageVersion(NotContainerized, OpenShiftCheck): +class PackageVersion(NotContainerizedMixin, OpenShiftCheck): """Check that available RPM packages match the required versions.""" name = "package_version" diff --git a/roles/openshift_hosted/tasks/registry/storage/s3.yml b/roles/openshift_hosted/tasks/registry/storage/s3.yml index 7d51594bd..16709dfef 100644 --- a/roles/openshift_hosted/tasks/registry/storage/s3.yml +++ b/roles/openshift_hosted/tasks/registry/storage/s3.yml @@ -31,8 +31,8 @@ namespace: "{{ openshift.hosted.registry.namespace | default('default') }}" name: docker-registry-s3-cloudfront contents: - path: cloudfront.pem - data: "{{ lookup('file', openshift_hosted_registry_storage_s3_cloudfront_privatekeyfile) }}" + - path: cloudfront.pem + data: "{{ lookup('file', openshift_hosted_registry_storage_s3_cloudfront_privatekeyfile) }}" - name: Add cloudfront secret to the registry deployment config command: > diff --git a/roles/openshift_logging/tasks/update_master_config.yaml b/roles/openshift_logging/tasks/update_master_config.yaml index af303c47c..cef835668 100644 --- a/roles/openshift_logging/tasks/update_master_config.yaml +++ b/roles/openshift_logging/tasks/update_master_config.yaml @@ -5,3 +5,5 @@ yaml_key: assetConfig.loggingPublicURL yaml_value: "https://{{ openshift_logging_kibana_hostname }}" notify: restart master + tags: + - update_master_config |