diff options
Diffstat (limited to 'roles')
| -rw-r--r-- | roles/lib_openshift/library/oc_clusterrole.py | 197 | 
1 files changed, 120 insertions, 77 deletions
| diff --git a/roles/lib_openshift/library/oc_clusterrole.py b/roles/lib_openshift/library/oc_clusterrole.py index 3f5d2a884..308a7d806 100644 --- a/roles/lib_openshift/library/oc_clusterrole.py +++ b/roles/lib_openshift/library/oc_clusterrole.py @@ -119,8 +119,6 @@ EXAMPLES = '''  # -*- -*- -*- End included fragment: doc/clusterrole -*- -*- -*-  # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- -# pylint: disable=undefined-variable,missing-docstring -# noqa: E301,E302  class YeditException(Exception): @@ -154,13 +152,13 @@ class Yedit(object):      @property      def separator(self): -        ''' getter method for yaml_dict ''' +        ''' getter method for separator '''          return self._separator      @separator.setter -    def separator(self): -        ''' getter method for yaml_dict ''' -        return self._separator +    def separator(self, inc_sep): +        ''' setter method for separator ''' +        self._separator = inc_sep      @property      def yaml_dict(self): @@ -176,13 +174,13 @@ class Yedit(object):      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) +        return re.findall(Yedit.re_key.format(''.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): +        if not re.match(Yedit.re_valid_key.format(''.join(common_separators)), key):              return False          return True @@ -204,7 +202,7 @@ class Yedit(object):          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) +                data = data.get(dict_key)              elif (arr_ind and isinstance(data, list) and                    int(arr_ind) <= len(data) - 1):                  data = data[int(arr_ind)] @@ -293,7 +291,7 @@ class Yedit(object):          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) +                data = data.get(dict_key)              elif (arr_ind and isinstance(data, list) and                    int(arr_ind) <= len(data) - 1):                  data = data[int(arr_ind)] @@ -393,7 +391,7 @@ class Yedit(object):                  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) +            raise YeditException('Problem with loading yaml file. {}'.format(err))          return self.yaml_dict @@ -512,8 +510,8 @@ class Yedit(object):              # 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 +                raise YeditException('Cannot replace key, value entry in dict with non-dict type. ' + +                                     'value=[{}] type=[{}]'.format(value, type(value)))              entry.update(value)              return (True, self.yaml_dict) @@ -574,7 +572,17 @@ class Yedit(object):              pass          result = Yedit.add_entry(tmp_copy, path, value, self.separator) -        if not result: +        if result is None: +            return (False, self.yaml_dict) + +        # When path equals "" it is a special case. +        # "" refers to the root of the document +        # Only update the root path (entire document) when its a list or dict +        if path == '': +            if isinstance(result, list) or isinstance(result, dict): +                self.yaml_dict = result +                return (True, self.yaml_dict) +              return (False, self.yaml_dict)          self.yaml_dict = tmp_copy @@ -600,7 +608,7 @@ class Yedit(object):                  pass              result = Yedit.add_entry(tmp_copy, path, value, self.separator) -            if result: +            if result is not None:                  self.yaml_dict = tmp_copy                  return (True, self.yaml_dict) @@ -632,114 +640,149 @@ class Yedit(object):          # 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)) +                raise YeditException('Not a boolean type. str=[{}] vtype=[{}]'.format(inc_value, vtype))          elif isinstance(inc_value, bool) and 'str' in vtype:              inc_value = str(inc_value) +        # There is a special case where '' will turn into None after yaml loading it so skip +        if isinstance(inc_value, str) and inc_value == '': +            pass          # If vtype is not str then go ahead and attempt to yaml load it. -        if isinstance(inc_value, str) and 'str' not in vtype: +        elif isinstance(inc_value, str) and 'str' not in vtype:              try: -                inc_value = yaml.load(inc_value) +                inc_value = yaml.safe_load(inc_value)              except Exception: -                raise YeditException('Could not determine type of incoming ' + -                                     'value. value=[%s] vtype=[%s]' -                                     % (type(inc_value), vtype)) +                raise YeditException('Could not determine type of incoming value. ' + +                                     'value=[{}] vtype=[{}]'.format(type(inc_value), vtype))          return inc_value +    @staticmethod +    def process_edits(edits, yamlfile): +        '''run through a list of edits and process them one-by-one''' +        results = [] +        for edit in edits: +            value = Yedit.parse_value(edit['value'], edit.get('value_type', '')) +            if edit.get('action') == 'update': +                # pylint: disable=line-too-long +                curr_value = Yedit.get_curr_value( +                    Yedit.parse_value(edit.get('curr_value')), +                    edit.get('curr_value_format')) + +                rval = yamlfile.update(edit['key'], +                                       value, +                                       edit.get('index'), +                                       curr_value) + +            elif edit.get('action') == 'append': +                rval = yamlfile.append(edit['key'], value) + +            else: +                rval = yamlfile.put(edit['key'], value) + +            if rval[0]: +                results.append({'key': edit['key'], 'edit': rval[1]}) + +        return {'changed': len(results) > 0, 'results': results} +      # pylint: disable=too-many-return-statements,too-many-branches      @staticmethod -    def run_ansible(module): +    def run_ansible(params):          '''perform the idempotent crud operations''' -        yamlfile = Yedit(filename=module.params['src'], -                         backup=module.params['backup'], -                         separator=module.params['separator']) +        yamlfile = Yedit(filename=params['src'], +                         backup=params['backup'], +                         separator=params['separator']) -        if module.params['src']: +        state = params['state'] + +        if params['src']:              rval = yamlfile.load() -            if yamlfile.yaml_dict is None and \ -               module.params['state'] != 'present': +            if yamlfile.yaml_dict is None and 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']) +                        'msg': 'Error opening file [{}].  Verify that the '.format(params['src']) + +                               'file exists, that it is has correct permissions, and is valid yaml.'} + +        if state == 'list': +            if params['content']: +                content = Yedit.parse_value(params['content'], params['content_type'])                  yamlfile.yaml_dict = content -            if module.params['key']: -                rval = yamlfile.get(module.params['key']) or {} +            if params['key']: +                rval = yamlfile.get(params['key']) or {} -            return {'changed': False, 'result': rval, 'state': "list"} +            return {'changed': False, 'result': rval, 'state': state} -        elif module.params['state'] == 'absent': -            if module.params['content']: -                content = Yedit.parse_value(module.params['content'], -                                            module.params['content_type']) +        elif state == 'absent': +            if params['content']: +                content = Yedit.parse_value(params['content'], params['content_type'])                  yamlfile.yaml_dict = content -            if module.params['update']: -                rval = yamlfile.pop(module.params['key'], -                                    module.params['value']) +            if params['update']: +                rval = yamlfile.pop(params['key'], params['value'])              else: -                rval = yamlfile.delete(module.params['key']) +                rval = yamlfile.delete(params['key']) -            if rval[0] and module.params['src']: +            if rval[0] and params['src']:                  yamlfile.write() -            return {'changed': rval[0], 'result': rval[1], 'state': "absent"} +            return {'changed': rval[0], 'result': rval[1], 'state': state} -        elif module.params['state'] == 'present': +        elif 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']) +            if params['content']: +                content = Yedit.parse_value(params['content'], 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"} +                   params['value'] is None: +                    return {'changed': False, 'result': yamlfile.yaml_dict, 'state': state}                  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 +            # If we were passed a key, value then +            # we enapsulate it in a list and process it +            # Key, Value passed to the module : Converted to Edits list # +            edits = [] +            _edit = {} +            if params['value'] is not None: +                _edit['value'] = params['value'] +                _edit['value_type'] = params['value_type'] +                _edit['key'] = params['key'] -                    rval = yamlfile.update(key, value, module.params['index'], curr_value)  # noqa: E501 +                if params['update']: +                    _edit['action'] = 'update' +                    _edit['curr_value'] = params['curr_value'] +                    _edit['curr_value_format'] = params['curr_value_format'] +                    _edit['index'] = params['index'] -                elif module.params['append']: -                    rval = yamlfile.append(key, value) -                else: -                    rval = yamlfile.put(key, value) +                elif params['append']: +                    _edit['action'] = 'append' + +                edits.append(_edit) -                if rval[0] and module.params['src']: +            elif params['edits'] is not None: +                edits = params['edits'] + +            if edits: +                results = Yedit.process_edits(edits, yamlfile) + +                # if there were changes and a src provided to us we need to write +                if results['changed'] and params['src']:                      yamlfile.write() -                return {'changed': rval[0], -                        'result': rval[1], 'state': "present"} +                return {'changed': results['changed'], 'result': results['results'], 'state': state}              # no edits to make -            if module.params['src']: +            if params['src']:                  # pylint: disable=redefined-variable-type                  rval = yamlfile.write()                  return {'changed': rval[0],                          'result': rval[1], -                        'state': "present"} +                        'state': state} +            # We were passed content but no src, key or value, or edits.  Return contents in memory +            return {'changed': False, 'result': yamlfile.yaml_dict, 'state': state}          return {'failed': True, 'msg': 'Unkown state passed'}  # -*- -*- -*- End included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- | 
