def construct_yaml_map(self, node): # Check for duplicate keys on the current level, this is not desirable # because a dict does not support this. It overwrites it with the last # occurance, which can give unexpected results mapping = {} self.flatten_mapping(node) for key_node, value_node in node.value: key = self.construct_object(key_node, False) value = self.construct_object(value_node, False) if key in mapping: raise CfnParseError(self.filename, [ build_match( filename=self.filename, message='Duplicate resource found "{}" (line {})'. format(key, key_node.start_mark.line + 1), line_number=key_node.start_mark.line, column_number=key_node.start_mark.column, key=key), build_match( filename=self.filename, message='Duplicate resource found "{}" (line {})'. format(key, mapping[key].start_mark.line + 1), line_number=mapping[key].start_mark.line, column_number=mapping[key].start_mark.column, key=key) ]) mapping[key] = value obj, = SafeConstructor.construct_yaml_map(self, node) return dict_node(obj, node.start_mark, node.end_mark)
def multi_constructor(loader, tag_suffix, node): """ Deal with !Ref style function format """ if tag_suffix not in UNCONVERTED_SUFFIXES: tag_suffix = '{}{}'.format(FN_PREFIX, tag_suffix) constructor = None if tag_suffix == 'Fn::GetAtt': constructor = construct_getatt elif isinstance(node, ScalarNode): constructor = loader.construct_scalar elif isinstance(node, SequenceNode): constructor = loader.construct_sequence elif isinstance(node, MappingNode): constructor = loader.construct_mapping else: raise 'Bad tag: !{}'.format(tag_suffix) if tag_suffix == 'Fn::Sub': return sub_node({tag_suffix: constructor(node)}, node.start_mark, node.end_mark) return dict_node({tag_suffix: constructor(node)}, node.start_mark, node.end_mark)
def get_value_from_scenario(self, obj, scenario): """ Get object values from a provided scenario """ def get_value(value, scenario): # pylint: disable=R0911 """ Get the value based on the scenario resolving nesting """ if isinstance(value, dict): if len(value) == 1: if 'Fn::If' in value: if_values = value.get('Fn::If') if len(if_values) == 3: if_path = scenario.get(if_values[0], None) if if_path is not None: if if_path: return get_value(if_values[1], scenario) return get_value(if_values[2], scenario) elif value.get('Ref') == 'AWS::NoValue': return None else: return value return value if isinstance(value, list): new_list = [] for item in value: new_value = get_value(item, scenario) if new_value is not None: new_list.append(get_value(item, scenario)) return new_list return value result = dict_node({}, obj.start_mark, obj.end_mark) if isinstance(obj, dict): if len(obj) == 1: if obj.get('Fn::If'): new_value = get_value(obj, scenario) if new_value is not None: result = new_value else: for key, value in obj.items(): new_value = get_value(value, scenario) if new_value is not None: result[key] = new_value else: for key, value in obj.items(): new_value = get_value(value, scenario) if new_value is not None: result[key] = new_value return result
def check_duplicates(ordered_pairs, beg_mark, end_mark): """ Check for duplicate keys on the current level, this is not desirable because a dict does not support this. It overwrites it with the last occurance, which can give unexpected results """ mapping = dict_node({}, beg_mark, end_mark) for key, value in ordered_pairs: if value is None: raise NullError('"{}"'.format(key)) if key in mapping: raise DuplicateError('"{}"'.format(key)) mapping[key] = value return mapping
def _correct_objects_loop(self, template): """ Looping for dynamic depths and types """ if isinstance(template, dict): if not isinstance(template, dict_node): template = dict_node(template, (0, 0), (0, 0)) for k, v in template.items(): template[k] = self._correct_objects_loop(v) elif isinstance(template, list): if not isinstance(template, list_node): template = list_node(template, (0, 0), (0, 0)) for i, v in enumerate(template): template[i] = self._correct_objects_loop(v) return template
def convert_dict(template, start_mark=(0, 0), end_mark=(0, 0)): """Convert dict to template""" if isinstance(template, dict): if not isinstance(template, dict_node): template = dict_node(template, start_mark, end_mark) for k, v in template.copy().items(): k_start_mark = start_mark k_end_mark = end_mark if isinstance(k, str_node): k_start_mark = k.start_mark k_end_mark = k.end_mark new_k = str_node(k, k_start_mark, k_end_mark) del template[k] template[new_k] = convert_dict(v, k_start_mark, k_end_mark) elif isinstance(template, list): if not isinstance(template, list_node): template = list_node(template, start_mark, end_mark) for i, v in enumerate(template): template[i] = convert_dict(v, start_mark, end_mark) return template