def _validate_and_load_imports(self): imports_names = set() if not self.importslist: msg = _('"imports" keyname is defined without including ' 'templates.') log.error(msg) ExceptionCollector.appendException(ValidationError(message=msg)) return for import_def in self.importslist: if isinstance(import_def, dict): for import_name, import_uri in import_def.items(): if import_name in imports_names: msg = (_('Duplicate import name "%s" was found.') % import_name) log.error(msg) ExceptionCollector.appendException( ValidationError(message=msg)) imports_names.add(import_name) custom_type = self._load_import_template(import_name, import_uri) namespace_prefix = None if isinstance(import_uri, dict): namespace_prefix = import_uri.get( self.NAMESPACE_PREFIX) self._update_custom_def(custom_type, namespace_prefix) else: # old style of imports custom_type = self._load_import_template(None, import_def) if custom_type: self._update_custom_def(custom_type, None)
def _validate_fields(self): if self.defs: for name in self.defs.keys(): if name not in self.SECTIONS: ExceptionCollector.appendException( UnknownFieldError(what='Group Type %s' % self.grouptype, field=name))
def __init__(self, property_name, property_type, constraint): super(Pattern, self).__init__(property_name, property_type, constraint) if not isinstance(self.constraint_value, self.valid_types): ExceptionCollector.appendException( InvalidSchemaError(message=_('The property "pattern" ' 'expects a string.'))) self.match = re.compile(self.constraint_value).match
def validate(self): if len(self.args) != 2: ExceptionCollector.appendException( ValueError(_('Illegal arguments for function "{0}". Expected ' 'arguments: "node-template-name", ' '"attribute-name"').format(GET_ATTRIBUTE))) self._find_node_template_containing_attribute()
def validate(self): if len(self.args) < 2: ExceptionCollector.appendException( ValueError(_('Expected arguments: "node-template-name", "req-or-cap" ' '(optional), "property name".')) ) return if len(self.args) == 2: found_prop = self._find_property(self.args[1]) if not found_prop: return prop = found_prop.value if not isinstance(prop, Function): get_function(self.tosca_tpl, self.context, prop) elif len(self.args) >= 3: # do not use _find_property to avoid raise KeyError # if the prop is not found # First check if there is property with this name node_tpl = self._find_node_template(self.args[0]) props = node_tpl.get_properties() if node_tpl else [] index = 2 found = [props[self.args[1]]] if self.args[1] in props else [] if found: property_value = found[0].value else: index = 3 # then check the req or caps property_value = self._find_req_or_cap_property(self.args[1], self.args[2]) if len(self.args) > index: for elem in self.args[index:]: if isinstance(property_value, list): int_elem = int(elem) property_value = self._get_index_value(property_value, int_elem) else: property_value = self._get_attribute_value(property_value, elem)
def __init__(self, name, value=None, schema=None): self.name = name self.value = value self.schema = schema try: self.schema['type'] except KeyError: msg = (_('Schema definition of "%(pname)s" must have a "type" ' 'attribute.') % dict(pname=self.name)) ExceptionCollector.appendException( InvalidSchemaError(message=msg)) if 'required' in self.schema: required = self.schema['required'] if not isinstance(required, bool): if required.lower() not in self.VALID_REQUIRED_VALUES: valid_values = ', '.join(self.VALID_REQUIRED_VALUES) msg = (_('Schema definition of "%(propname)s" has ' '"required" attribute with invalid value ' '"%(value1)s". The value must be one of ' '"%(value2)s".') % {"propname": self.name, "value1": required, "value2": valid_values}) ExceptionCollector.appendException( InvalidSchemaError(message=msg))
def validate(self): if len(self.args) < 1: ExceptionCollector.appendException( ValueError( _('Invalid arguments for function "{0}". Expected ' "at least one arguments.").format(CONCAT) ) )
def _common_validate_properties(self, entitytype, properties): allowed_props = [] required_props = [] for p in entitytype.get_properties_def_objects(): allowed_props.append(p.name) if p.required: required_props.append(p.name) if properties: self._common_validate_field(properties, allowed_props, 'properties') # make sure it's not missing any property required by a tosca type missingprop = [] for r in required_props: if r not in properties.keys(): missingprop.append(r) if missingprop: ExceptionCollector.appendException( MissingRequiredFieldError( what='"properties" of template "%s"' % self.name, required=missingprop)) else: if required_props: ExceptionCollector.appendException( MissingRequiredFieldError( what='"properties" of template "%s"' % self.name, required=missingprop))
def _validate_requirements(self): type_requires = self.type_definition.get_all_requirements() allowed_reqs = ["template"] if type_requires: for treq in type_requires: for key, value in treq.items(): allowed_reqs.append(key) if isinstance(value, dict): for key in value: allowed_reqs.append(key) requires = self.type_definition.get_value(self.REQUIREMENTS, self.entity_tpl) if requires: if not isinstance(requires, list): ExceptionCollector.appendException( TypeMismatchError( what='"requirements" of template "%s"' % self.name, type='list')) for req in requires: for r1, value in req.items(): if isinstance(value, dict): self._validate_requirements_keys(value) self._validate_requirements_properties(value) allowed_reqs.append(r1) self._common_validate_field(req, allowed_reqs, 'requirements')
def __init__(self, property_name, property_type, constraint): super(ValidValues, self).__init__(property_name, property_type, constraint) if not isinstance(self.constraint_value, collections.Sequence): ExceptionCollector.appendException( InvalidSchemaError(message=_('The property "valid_values" ' 'expects a list.')))
def _common_validate_properties(self, entitytype, properties): allowed_props = [] required_props = [] for p in entitytype.get_properties_def_objects(): allowed_props.append(p.name) # If property is 'required' and has no 'default' value then record if p.required and p.default is None: required_props.append(p.name) # validate all required properties have values if properties: req_props_no_value_or_default = [] self._common_validate_field(properties, allowed_props, 'properties') # make sure it's not missing any property required by a tosca type for r in required_props: if r not in properties.keys(): req_props_no_value_or_default.append(r) # Required properties found without value or a default value if req_props_no_value_or_default: ExceptionCollector.appendException( MissingRequiredFieldError( what='"properties" of template "%s"' % self.name, required=req_props_no_value_or_default)) else: # Required properties in schema, but not in template if required_props: ExceptionCollector.appendException( MissingRequiredFieldError( what='"properties" of template "%s"' % self.name, required=required_props))
def _validate_keys(self): """validate the keys of substitution mappings.""" for key in self.sub_mapping_def.keys(): if key not in self.SECTIONS: ExceptionCollector.appendException( UnknownFieldError(what='SubstitutionMappings', field=key))
def __init__(self, property_name, property_type, constraint): super(GreaterThan, self).__init__(property_name, property_type, constraint) if not isinstance(constraint[self.GREATER_THAN], self.valid_types): ExceptionCollector.appendException( InvalidSchemaError(message=_('The property "greater_than" ' 'expects comparable values.')))
def __init__(self, property_name, property_type, constraint): super(LessOrEqual, self).__init__(property_name, property_type, constraint) if not isinstance(self.constraint_value, self.valid_types): ExceptionCollector.appendException( InvalidSchemaError(message=_('The property "less_or_equal" ' 'expects comparable values.')))
def _validate_capabilities_properties(self, capabilities): for cap, props in capabilities.items(): capability = self.get_capability(cap) if not capability: continue capabilitydef = capability.definition self._common_validate_properties(capabilitydef, props[self.PROPERTIES]) # validating capability properties values for prop in self.get_capability(cap).get_properties_objects(): prop.validate() # TODO(srinivas_tadepalli): temporary work around to validate # default_instances until standardized in specification if cap == "scalable" and prop.name == "default_instances": prop_dict = props[self.PROPERTIES] min_instances = prop_dict.get("min_instances") max_instances = prop_dict.get("max_instances") default_instances = prop_dict.get("default_instances") if not (min_instances <= default_instances <= max_instances): err_msg = ('"properties" of template "%s": ' '"default_instances" value is not between ' '"min_instances" and "max_instances".' % self.name) ExceptionCollector.appendException( ValidationError(message=err_msg))
def validate_additional_req(properties, prop_name, custom_def=None, ): try: source = properties.get(PortSpec.SOURCE) source_range = properties.get(PortSpec.SOURCE_RANGE) target = properties.get(PortSpec.TARGET) target_range = properties.get(PortSpec.TARGET_RANGE) # verify one of the specified values is set if source is None and source_range is None and \ target is None and target_range is None: ExceptionCollector.appendException( InvalidTypeAdditionalRequirementsError( type=PortSpec.TYPE_URI)) # Validate source value is in specified range if source and source_range: validateutils.validate_value_in_range(source, source_range, PortSpec.SOURCE) else: from toscaparser.dataentity import DataEntity portdef = DataEntity('PortDef', source, None, PortSpec.SOURCE) portdef.validate() # Validate target value is in specified range if target and target_range: validateutils.validate_value_in_range(target, target_range, PortSpec.TARGET) else: from toscaparser.dataentity import DataEntity portdef = DataEntity('PortDef', source, None, PortSpec.TARGET) portdef.validate() except Exception: msg = _('"%(value)s" do not meet requirements ' 'for type "%(type)s".') \ % {'value': properties, 'type': PortSpec.SHORTNAME} ExceptionCollector.appendException( ValueError(msg))
def __init__(self, property_name, property_type, constraint): super(MaxLength, self).__init__(property_name, property_type, constraint) if not isinstance(self.constraint_value, self.valid_types): ExceptionCollector.appendException( InvalidSchemaError(message=_('The property "max_length" ' 'expects an integer.')))
def _validate_requirements_keys(self, requirement): for key in requirement.keys(): if key not in self.REQUIREMENTS_SECTION: ExceptionCollector.appendException( UnknownFieldError( what='"requirements" of template "%s"' % self.name, field=key))
def validate_range(range): # list class check validate_list(range) # validate range list has a min and max if len(range) != 2: ExceptionCollector.appendException( ValueError(_('"%s" is not a valid range.') % range)) # validate min and max are numerics or the keyword UNBOUNDED min_test = max_test = False if not range[0] == RANGE_UNBOUNDED: min = validate_numeric(range[0]) else: min_test = True if not range[1] == RANGE_UNBOUNDED: max = validate_numeric(range[1]) else: max_test = True # validate the max > min (account for UNBOUNDED) if not min_test and not max_test: # Note: min == max is allowed if min > max: ExceptionCollector.appendException( ValueError(_('"%s" is not a valid range.') % range)) return range
def _validate_interfaces(self): ifaces = self.type_definition.get_value(self.INTERFACES, self.entity_tpl) if ifaces: for name, value in ifaces.items(): if name in (LIFECYCLE, LIFECYCLE_SHORTNAME): self._common_validate_field( value, InterfacesDef. interfaces_node_lifecycle_operations, 'interfaces') elif name in (CONFIGURE, CONFIGURE_SHORTNAME): self._common_validate_field( value, InterfacesDef. interfaces_relationship_configure_operations, 'interfaces') elif name in self.type_definition.interfaces.keys(): self._common_validate_field( value, self._collect_custom_iface_operations(name), 'interfaces') else: ExceptionCollector.appendException( UnknownFieldError( what='"interfaces" of template "%s"' % self.name, field=name))
def _validate_keys(self): if self.defs: for key in self.defs.keys(): if key not in self.SECTIONS: ExceptionCollector.appendException( UnknownFieldError(what='Nodetype"%s"' % self.ntype, field=key))
def _get_capability_property(self, node_template, capability_name, property_name): """Gets a node template capability property.""" caps = node_template.get_capabilities() if caps and capability_name in caps.keys(): cap = caps[capability_name] property = None props = cap.get_properties() if props and property_name in props.keys(): property = props[property_name].value if not property: ExceptionCollector.appendException( KeyError(_('Property "%(prop)s" was not found in ' 'capability "%(cap)s" of node template ' '"%(ntpl1)s" referenced from node template ' '"%(ntpl2)s".') % {'prop': property_name, 'cap': capability_name, 'ntpl1': node_template.name, 'ntpl2': self.context.name})) return property msg = _('Requirement/Capability "{0}" referenced from node template ' '"{1}" was not found in node template "{2}".').format( capability_name, self.context.name, node_template.name) ExceptionCollector.appendException(KeyError(msg))
def _get_capability_attribute(self, node_template, capability_name, attr_name): """Gets a node template capability attribute.""" caps = node_template.get_capabilities() if caps and capability_name in caps.keys(): cap = caps[capability_name] attribute = None attrs = cap.definition.get_attributes_def() if attrs and attr_name in attrs.keys(): attribute = attrs[attr_name] if not attribute: ExceptionCollector.appendException( KeyError(_('Attribute "%(attr)s" was not found in ' 'capability "%(cap)s" of node template ' '"%(ntpl1)s" referenced from node template ' '"%(ntpl2)s".') % {'attr': attr_name, 'cap': capability_name, 'ntpl1': node_template.name, 'ntpl2': self.context.name})) return attribute msg = _('Requirement/Capability "{0}" referenced from node template ' '"{1}" was not found in node template "{2}".').format( capability_name, self.context.name, node_template.name) ExceptionCollector.appendException(KeyError(msg))
def __init__(self, node_type, interfacetype, node_template=None, name=None, value=None): self.ntype = node_type self.node_template = node_template self.type = interfacetype self.name = name self.value = value self.implementation = None self.inputs = None self.defs = {} if interfacetype == LIFECYCLE_SHORTNAME: interfacetype = LIFECYCLE if interfacetype == CONFIGURE_SHORTNAME: interfacetype = CONFIGURE if node_type: self.defs = self.TOSCA_DEF[interfacetype] if value: if isinstance(self.value, dict): for i, j in self.value.items(): if i == IMPLEMENTATION: self.implementation = j elif i == INPUTS: self.inputs = j else: what = ('"interfaces" of template "%s"' % self.node_template.name) ExceptionCollector.appendException( UnknownFieldError(what=what, field=i)) else: self.implementation = value
def _validate_type_version(self, version): if version not in self.VALID_TEMPLATE_VERSIONS: ExceptionCollector.appendException( InvalidTemplateVersion( what=version + " in " + self.import_def, valid_versions=", ".join(self.VALID_TEMPLATE_VERSIONS) ) )
def _validate_occurrences(self, occurrences): DataEntity.validate_datatype('list', occurrences) for value in occurrences: DataEntity.validate_datatype('integer', value) if len(occurrences) != 2 or not (0 <= occurrences[0] <= occurrences[1]) \ or occurrences[1] == 0: ExceptionCollector.appendException( InvalidPropertyValueError(what=(occurrences)))
def _find_interface_name(self, interface_name): if interface_name in toscaparser.elements.interfaces.SECTIONS: return interface_name else: ExceptionCollector.appendException( ValueError(_('Enter a valid interface name' ).format(GET_OPERATION_OUTPUT))) return
def validate(self): if len(self.args) != 1: ExceptionCollector.appendException( ValueError(_('Expected one argument for function "get_input" but ' 'received "%s".') % self.args) ) inputs = [input.name for input in self.tosca_tpl.inputs] if self.args[0] not in inputs: ExceptionCollector.appendException(UnknownInputError(input_name=self.args[0]))
def validate(self, value): self.value_msg = value if self.property_type in scalarunit.ScalarUnit.SCALAR_UNIT_TYPES: value = scalarunit.get_scalarunit_value(self.property_type, value) if not self._is_valid(value): err_msg = self._err_msg(value) ExceptionCollector.appendException( ValidationError(message=err_msg))
def _common_validate_field(self, schema, allowedlist, section): for name in schema: if name not in allowedlist: ExceptionCollector.appendException( UnknownFieldError( what=('"%(section)s" of template "%(nodename)s"' % {'section': section, 'nodename': self.name}), field=name))
def validate(self): '''Validate the value by the definition of the datatype.''' # A datatype can not have both 'type' and 'properties' definitions. # If the datatype has 'type' definition log.debug("{}: Data type validate: {}, {}".format( self.datatype.type, self.datatype.value_type, self.value)) if self.datatype.value_type: self.value = DataEntity.validate_datatype(self.datatype.value_type, self.value, None, self.custom_def) schema = Schema(self.property_name, self.datatype.defs) for constraint in schema.constraints: constraint.validate(self.value) # If the datatype has 'properties' definition else: if not isinstance(self.value, dict): ExceptionCollector.appendException( TypeMismatchError(what=self.value, type=self.datatype.type)) allowed_props = [] required_props = [] default_props = {} if self.schema: allowed_props = self.schema.keys() for name, prop_def in self.schema.items(): if prop_def.required: required_props.append(name) if prop_def.default: default_props[name] = prop_def.default # check allowed field try: for value_key in list(self.value.keys()): if value_key not in allowed_props: log.info("Unknown field data {}: {}".format( self.datatype.type, value_key)) ExceptionCollector.appendException( UnknownFieldError( what=(_('Data value of type "%s"') % self.datatype.type), field=value_key)) except Exception as e: log.error("Value: {}: {}".format(self.value, e)) raise e # check default field for def_key, def_value in list(default_props.items()): if def_key not in list(self.value.keys()): self.value[def_key] = def_value # check missing field missingprop = [] for req_key in required_props: if req_key not in list(self.value.keys()): missingprop.append(req_key) if missingprop: log.info("Missing field data {}: {}".format( self.datatype.type, missingprop)) ExceptionCollector.appendException( MissingRequiredFieldError( what=(_('Data value of type "%s"') % self.datatype.type), required=missingprop)) # check every field for name, value in list(self.value.items()): schema_name = self._find_schema(name) if not schema_name: continue log.debug("Name: {}, Schema: {}".format(name, schema_name)) prop_schema = Schema(name, schema_name) # check if field value meets type defined DataEntity.validate_datatype(prop_schema.type, value, prop_schema.entry_schema, self.custom_def) # check if field value meets constraints defined if not a function from toscaparser.functions import is_function if prop_schema.constraints and is_function(value) is False: for constraint in prop_schema.constraints: if isinstance(value, list): for val in value: constraint.validate(val) else: constraint.validate(value) return self.value
def __init__(self, property_name, property_type, constraint): super(Enum, self).__init__(property_name, property_type, constraint) if not isinstance(self.constraint_value, self.valid_types): ExceptionCollector.appendException( InvalidSchemaError(message=f'The property "enum expects a list of dict.'))
def validate_list(value): if not isinstance(value, list): ExceptionCollector.appendException( ValueError(_('"%s" is not a list.') % value)) return value
def _validate_field(self): for name in self.schema.schema: if name not in self.INPUTFIELD: ExceptionCollector.appendException( UnknownFieldError(what='Input "%s"' % self.name, field=name))
def _validate_fields(self, nodetemplate): for name in nodetemplate.keys(): if name not in self.SECTIONS and name not in self.SPECIAL_SECTIONS: ExceptionCollector.appendException( UnknownFieldError(what='Node template "%s"' % self.name, field=name))
def restructure_value(mapping_value, self, if_format_str=True, if_upper=True): """ Recursive function which processes the mapping_value to become parameter:value format :param mapping_value: the map of non normative parameter:value :param self: the function used to store normative parameter, value and other values :param if_format_str: :param if_upper: detects if the parameter value must be saved :return: dict in the end of recursion, because the first is always (parameter, value) keys """ if isinstance(mapping_value, dict): flat_mapping_value = dict() for key in MAPPING_VALUE_KEYS: mapping_sub_value = mapping_value.get(key) if mapping_sub_value is not None: restructured_value = restructure_value(mapping_sub_value, self, key != PARAMETER, False) if restructured_value is None: ExceptionCollector.appendException( ToscaParametersMappingFailed(what=mapping_value)) return flat_mapping_value[key] = restructured_value # NOTE: the case when value has keys ERROR and REASON if flat_mapping_value.get(ERROR, False): ExceptionCollector.appendException( UnsupportedToscaParameterUsage( what=flat_mapping_value.get(REASON).format(self=self))) # NOTE: the case when value has keys PARAMETER, VALUE, KEYNAME parameter = flat_mapping_value.get(PARAMETER) value = flat_mapping_value.get(VALUE) keyname = flat_mapping_value.get(KEYNAME) if value is None: # The case when variable is indivisible # This case parameter and keyname are None too or they doesn't have sense filled_value = dict() for k, v in mapping_value.items(): filled_k = restructure_value(k, self, if_upper=False) filled_v = restructure_value(v, self, if_upper=False) filled_value[filled_k] = filled_v return filled_value if parameter is not None: if not isinstance(parameter, six.string_types): ExceptionCollector.appendException( ToscaParametersMappingFailed(what=parameter)) if parameter[:6] == '{self[' and parameter[-1] == '}': ExceptionCollector.appendException( ToscaParametersMappingFailed(what=parameter)) r = dict() r[parameter] = value if if_upper: # r[PARAMETER] = parameter if keyname: r[KEYNAME] = keyname return r # NOTE: the case when value has keys SOURCE, PARAMETERS, EXTRA, VALUE, EXECUTOR source_name = flat_mapping_value.get(SOURCE) parameters_dict = flat_mapping_value.get(PARAMETERS) extra_parameters = flat_mapping_value.get(EXTRA) executor_name = flat_mapping_value.get(EXECUTOR) if source_name is not None and executor_name is not None: if executor_name == PYTHON_EXECUTOR: return execute_function(PYTHON_SOURCE_DIRECTORY, source_name, parameters_dict) if not CONFIGURATION_TOOLS.get(executor_name): ExceptionCollector.appendException( UnsupportedExecutorType(what=executor_name)) if self.get(ARTIFACTS) is None: self[ARTIFACTS] = [] tool = CONFIGURATION_TOOLS[executor_name]() extension = tool.get_artifact_extension() seed(time()) artifact_name = '_'.join([ self[NAME], executor_name, source_name, str(randint(ARTIFACT_RANGE_START, ARTIFACT_RANGE_END)) ]) + extension flat_mapping_value.update(name=artifact_name, configuration_tool=executor_name) self[ARTIFACTS].append(flat_mapping_value) # return the name of artifact return artifact_name ExceptionCollector.appendException( ToscaParametersMappingFailed(what=mapping_value)) return elif isinstance(mapping_value, list): return [ restructure_value(v, self, if_upper=False) for v in mapping_value ] if isinstance(mapping_value, str) and if_format_str: # NOTE: the process is needed because using only format function makes string from json mapping_value = format_value(mapping_value, self) return mapping_value
def get_resulted_mapping_values(parameter, mapping_value, value, self): """ Manage the case when mapping value has multiple structures in mapping_value :param parameter: :param mapping_value: :param value: :return: """ mapping_value = copy.deepcopy(mapping_value) if isinstance(mapping_value, six.string_types): mapping_value = {PARAMETER: mapping_value, VALUE: "{self[value]}"} mapping_value_parameter = mapping_value.get(PARAMETER) mapping_value_value = mapping_value.get(VALUE) # NOTE at first check if parameter self[buffer] parameter if mapping_value_parameter and mapping_value_parameter[:6] == '{self[' and \ mapping_value_parameter[-1] == '}': self[VALUE] = value self[PARAMETER] = parameter # The case when variable is written to the parameter self! # Inside string can be more self parameters format_parameter = mapping_value_parameter[6:-2].format(self=self) params_parameter = format_parameter.split('][') if isinstance(mapping_value_value, dict): if mapping_value_value.get(VALUE) and mapping_value_value.get(EXECUTOR) == PYTHON_EXECUTOR and \ mapping_value_value.get(SOURCE): mapping_value_value = execute_function( PYTHON_SOURCE_DIRECTORY, mapping_value_value[SOURCE], {'self': self}) iter_value = format_value(mapping_value_value, self) iter_num = len(params_parameter) for i in range(iter_num - 1, 0, -1): temp_param = dict() temp_param[params_parameter[i]] = iter_value iter_value = temp_param self = deep_update_dict(self, {params_parameter[0]: iter_value}) return [] elif mapping_value_parameter: splitted_mapping_value_parameter = mapping_value_parameter.split( SEPARATOR) has_section = False for v in splitted_mapping_value_parameter: if v in NODE_TEMPLATE_KEYS: has_section = True break if not has_section: mapping_value_value = mapping_value.get(VALUE) if isinstance(mapping_value_value, list) and len(mapping_value_value) > 1: r = [] for v in mapping_value_value: mapping_value[VALUE] = v item = get_resulted_mapping_values(parameter, mapping_value, value, self) if isinstance(item, list): if len(item) == 1: item = [item] else: item = [item] r.extend(item) return r if isinstance(mapping_value_value, six.string_types): splitted_mapping_value_value = mapping_value_value.split( SEPARATOR) for i in range(len(splitted_mapping_value_value)): if splitted_mapping_value_value[i] in NODE_TEMPLATE_KEYS: # parameter_tag = SEPARATOR.join(splitted_mapping_value_value[:i+1]) # value_new = SEPARATOR.join(splitted_mapping_value_value[i-1:]) # mapping_value[PARAMETER] = mapping_value_parameter + SEPARATOR + parameter_tag # mapping_value[VALUE] = value_new mapping_value[ PARAMETER] = mapping_value_parameter + SEPARATOR + mapping_value_value mapping_value[VALUE] = "{self[value]}" return dict(parameter=parameter, map=mapping_value, value=value) if isinstance(mapping_value_value, dict): # NOTE the only valid case when the value is parameter-value structure mapping_value_value_parameter = mapping_value_value.get( PARAMETER) mapping_value_value_value = mapping_value_value.get(VALUE) if mapping_value_value_parameter and mapping_value_value_value: mapping_value_value_keyname = mapping_value_value.get( KEYNAME) if mapping_value_value_keyname: mapping_value[KEYNAME] = mapping_value_value_keyname mapping_value[ PARAMETER] = mapping_value_parameter + SEPARATOR + mapping_value_value_parameter mapping_value[VALUE] = mapping_value_value_value r = get_resulted_mapping_values(parameter, mapping_value, value, self) return r ExceptionCollector.appendException( ToscaParametersMappingFailed(what=mapping_value)) return dict(parameter=parameter, map=mapping_value, value=value)
def sort_nodes_by_dependency(self): """ Use dependency requirement between nodes of the same type, check dependency of different types :param self.template_dependencies :param self.relationship_templates_by_name :param self.provider_node_names_by_priority :param self.provider_nodes_by_name :return: List of nodes sorted by priority """ template_names = [] relation_names = list(self.relationship_templates_by_name.keys()) group_by_templ_name = dict() group = 0 for priority in range(0, len(self.provider_node_names_by_priority)): nodes_in_priority = [] nodes_left_next = set(self.provider_node_names_by_priority[priority]) infinite_error = False while len(nodes_left_next) or infinite_error > 0: nodes_left = copy.copy(nodes_left_next) infinite_error = True for templ_name in nodes_left: set_intersection = nodes_left_next.intersection(self.template_dependencies.get(templ_name, set())) if len(set_intersection) == 0: infinite_error = False nodes_in_priority.append(templ_name) nodes_left_next.remove(templ_name) group_by_templ_name[templ_name] = group group += 1 # Here we added nodes of the same priority if infinite_error: ExceptionCollector.appendException(TemplateDependencyError( what="of priority " + str(priority) )) for templ_name in nodes_in_priority: # Add relationships for every node node_dependencies = self.template_dependencies.get(templ_name, set()) for dep_name in node_dependencies: if dep_name in relation_names and not dep_name in template_names: template_names.append(dep_name) elif dep_name in template_names: pass else: ExceptionCollector.appendException(TemplateDependencyError( what=dep_name )) template_names.append(templ_name) templates = [] for templ_name in template_names: templ = self.provider_nodes_by_name.get(templ_name, self.relationship_templates_by_name.get(templ_name)) if templ is None: ExceptionCollector.appendException(TemplateDependencyError( what=templ_name )) if group_by_templ_name.get(templ_name): templ.dependency_order = group_by_templ_name[templ_name] templates.append(templ) return templates
def _resolve_import_template(self, import_name, import_uri_def): short_import_notation = False if isinstance(import_uri_def, dict): self._validate_import_keys(import_name, import_uri_def) file_name = import_uri_def.get(self.FILE) repository = import_uri_def.get(self.REPOSITORY) repos = self.repositories.keys() if repository is not None: if repository not in repos: ExceptionCollector.appendException( ValidationError( message=_('Repository not found: "%s"') % repository ) ) return None, None, None else: file_name = import_uri_def repository = None short_import_notation = True if file_name is None: msg = _( "A template file name is not provided with import " 'definition "%(import_name)s".' ) % {"import_name": import_name} log.error(msg) ExceptionCollector.appendException(ValidationError(message=msg)) return None, None, None if toscaparser.utils.urlutils.UrlUtils.validate_url(file_name): # it's an absolute URL return self.resolver.get_url(self, repository, file_name, False) if not repository: fragment = None import_template = None if self.path: if toscaparser.utils.urlutils.UrlUtils.validate_url(self.path): if os.path.isabs(file_name): msg = _( 'Absolute file name "%(name)s" cannot be ' "used in a URL-based input template " '"%(template)s".' ) % {"name": file_name, "template": self.path} log.error(msg) ExceptionCollector.appendException(ImportError(msg)) return None, None, None import_template = toscaparser.utils.urlutils.UrlUtils.join_url( self.path, file_name ) assert import_template a_file = False else: a_file = True main_a_file = os.path.isfile(self.path) if "#" in file_name: file_name, sep, fragment = file_name.rpartition("#") if os.path.isabs(file_name): import_template = file_name elif os.path.isdir(self.path): import_template = os.path.join(self.path, file_name) elif main_a_file: if os.path.isfile(file_name): import_template = file_name else: full_path = os.path.join( os.path.dirname(os.path.abspath(self.path)), file_name ) if os.path.isfile(full_path): import_template = full_path else: file_path = file_name.rpartition(os.path.sep) dir_path = os.path.dirname(os.path.abspath(self.path)) if file_path[0] != "" and dir_path.endswith( file_path[0] ): import_template = os.path.join( dir_path, file_path[2] ) if not os.path.isfile(import_template): msg = _( '"%(import_template)s" is' "not a valid file" ) % {"import_template": import_template} log.error(msg) ExceptionCollector.appendException (ValueError(msg)) else: import_template = full_path # try anyway else: # template is pre-parsed if os.path.isabs(file_name) and os.path.isfile(file_name): a_file = True import_template = file_name else: msg = _( 'Relative file name "%(name)s" cannot be used ' "in a pre-parsed input template." ) % {"name": file_name} log.error(msg) ExceptionCollector.appendException(ImportError(msg)) return None, None, None if not import_template: ExceptionCollector.appendException( ImportError(_('Import "%s" is not valid.') % import_uri_def) ) return None, None, None url_info = self.resolver.get_url(self, repository, import_template, a_file) if not url_info: log.error(_('Import "%s" is not valid.') % import_uri_def) ExceptionCollector.appendException( ImportError(_('Import "%s" is not valid.') % import_uri_def) ) return None, None, None return url_info[0], url_info[1], fragment if short_import_notation: log.error('Import "%(name)s" is not valid.' % import_uri_def) ExceptionCollector.appendException( ImportError(_('Import "%s" is not valid.') % import_uri_def) ) return None, None, None assert repository return self._resolve_from_repository(repository, import_name, file_name)
def validate(self): if len(self.args) < 2: ExceptionCollector.appendException( ValueError( _('Illegal arguments for function "{0}". Expected ' 'arguments: "node-template-name", "req-or-cap"' '(optional), "property name"').format(GET_ATTRIBUTE))) return elif len(self.args) == 2: self._find_node_template_containing_attribute() else: node_tpl = self._find_node_template(self.args[0]) if node_tpl is None: return index = 2 attrs = node_tpl.type_definition.get_attributes_def() found = [attrs[self.args[1]]] if self.args[1] in attrs else [] if found: attr = found[0] else: index = 3 # then check the req or caps attr = self._find_req_or_cap_attribute(self.args[1], self.args[2]) if not attr: return value_type = attr.schema['type'] if len(self.args) > index: for elem in self.args[index:]: if value_type == "list": if not isinstance(elem, int): ExceptionCollector.appendException( ValueError( _('Illegal arguments for function' ' "{0}". "{1}" Expected positive' ' integer argument').format( GET_ATTRIBUTE, elem))) value_type = attr.schema['entry_schema']['type'] elif value_type == "map": value_type = attr.schema['entry_schema']['type'] elif value_type in Schema.PROPERTY_TYPES: ExceptionCollector.appendException( ValueError( _('Illegal arguments for function' ' "{0}". Unexpected attribute/' 'index value "{1}"').format( GET_ATTRIBUTE, elem))) return else: # It is a complex type data_type = DataType(value_type) props = data_type.get_properties_def() found = [props[elem]] if elem in props else [] if found: prop = found[0] value_type = prop.schema['type'] else: ExceptionCollector.appendException( KeyError( _('Illegal arguments for function' ' "{0}". Attribute name "{1}" not' ' found in "{2}"').format( GET_ATTRIBUTE, elem, value_type)))
def _find_node_template(self, node_template_name): # if the node_template_name has the long format if isinstance(node_template_name, dict): # get only the node name if 'node' in node_template_name: node_template_name = node_template_name['node'] else: ExceptionCollector.appendException( ValueError(_(' No node name in the relationship.'))) return if node_template_name == HOST: # Currently this is the only way to tell whether the function # is used within the outputs section of the TOSCA template. if isinstance(self.context, list): ExceptionCollector.appendException( ValueError( _('"get_attribute: [ HOST, ... ]" is not allowed in ' '"outputs" section of the TOSCA template.'))) return node_tpl = self._find_host_containing_attribute() if not node_tpl: ExceptionCollector.appendException( ValueError( _('"get_attribute: [ HOST, ... ]" was used in node ' 'template "{0}" but "{1}" was not found in ' 'the relationship chain.').format( self.context.name, HOSTED_ON))) return return node_tpl if node_template_name == TARGET: if not isinstance(self.context.type_definition, RelationshipType): ExceptionCollector.appendException( KeyError( _('"TARGET" keyword can only be used in context' ' to "Relationships" target node'))) return return self.context.target if node_template_name == SOURCE: if not isinstance(self.context.type_definition, RelationshipType): ExceptionCollector.appendException( KeyError( _('"SOURCE" keyword can only be used in context' ' to "Relationships" source node'))) return return self.context.source name = self.context.name \ if node_template_name == SELF and \ not isinstance(self.context, list) \ else node_template_name for node_template in self.tosca_tpl.nodetemplates: if node_template.name == name or node_template.is_derived_from( name): return node_template ExceptionCollector.appendException( KeyError( _('Node template "{0}" was not found.').format( node_template_name)))
def _find_node_template(self, node_template_name): # if the node_template_name has the long format if isinstance(node_template_name, dict): # get only the node name if 'node' in node_template_name: node_template_name = node_template_name['node'] else: ExceptionCollector.appendException( ValueError(_(' No node name in the relationship.'))) return if node_template_name == SELF: return self.context # enable the HOST value in the function if node_template_name == HOST: node = self._find_host_containing_property() if node is None: if len(self.args) == 2: ExceptionCollector.appendException( KeyError( _("Property '{0}' not found on host when referenced from node template '{1}'" ).format(self.args[1], self.context.name))) else: ExceptionCollector.appendException( KeyError( _("Property '{0}' not found in capability/requirement" " '{1}' referenced from node template '{2}'"). format(self.args[2], self.args[1], self.context.name))) return None else: return node if node_template_name == TARGET: if not isinstance(self.context.type_definition, RelationshipType): ExceptionCollector.appendException( KeyError( _('"TARGET" keyword can only be used in context' ' to "Relationships" target node'))) return return self.context.target if node_template_name == SOURCE: if not isinstance(self.context.type_definition, RelationshipType): ExceptionCollector.appendException( KeyError( _('"SOURCE" keyword can only be used in context' ' to "Relationships" source node'))) return return self.context.source if not hasattr(self.tosca_tpl, 'nodetemplates'): return for node_template in self.tosca_tpl.nodetemplates: if node_template.name == node_template_name or node_template.is_derived_from( node_template_name): return node_template ExceptionCollector.appendException( KeyError( _('Node template "{0}" was not found.' ' referenced from node template {1}').format( node_template_name, self.context.name)))
def validate_type(self, input_type): if input_type not in Schema.PROPERTY_TYPES: ExceptionCollector.appendException( ValueError(_('Invalid type "%s".') % type))
def get_structure_of_mapped_param(mapped_param, value, input_value=None, indivisible=False, if_list_type=False): if mapped_param is None: # NOTE The case when parameter was 'input_value' return [], None if input_value is None: input_value = value if isinstance(mapped_param, str): splitted_mapped_param = mapped_param.split(SEPARATOR) if splitted_mapped_param[-1] in INDIVISIBLE_KEYS: indivisible = True if not indivisible: if isinstance(value, list): r = [] len_v = len(value) if len_v == 1: param, _ = get_structure_of_mapped_param(mapped_param, value[0], input_value, if_list_type=True) return param, None for v in value: if isinstance(v, str): param, _ = get_structure_of_mapped_param( SEPARATOR.join([mapped_param, v]), input_value, input_value) else: param, _ = get_structure_of_mapped_param( mapped_param, v, input_value) r += param return r, None if isinstance(value, dict): r = dict() for k, v in value.items(): param, _ = get_structure_of_mapped_param(k, v, input_value) for p in param: r = deep_update_dict(r, p) r, _ = get_structure_of_mapped_param(mapped_param, r, input_value, indivisible=True, if_list_type=if_list_type) return r, None # NOTE: end of recursion structure = value if if_list_type: structure = [value] for i in range(len(splitted_mapped_param), 0, -1): structure = {splitted_mapped_param[i - 1]: structure} return [structure], None if isinstance(mapped_param, list): r = [] for p in mapped_param: param, _ = get_structure_of_mapped_param(p, value, input_value) r += param return r, None if isinstance(mapped_param, dict): # NOTE: Assert number of keys! Always start of recursion? num_of_keys = len(mapped_param.keys()) # if mapped_param.get(PARAMETER) and (num_of_keys == 2 or num_of_keys == 3 and KEYNAME in mapped_param.keys()): if num_of_keys == 1 or num_of_keys == 2 and KEYNAME in mapped_param.keys( ): for k, v in mapped_param.items(): if k != PARAMETER and k != KEYNAME: param, _ = get_structure_of_mapped_param(k, v, input_value) if isinstance(param, tuple): (param, keyname) = param if mapped_param.get(KEYNAME): mapped_param[KEYNAME] = keyname return param, mapped_param.get(KEYNAME) else: # TODO find the cases assert False ExceptionCollector.appendException( ToscaParametersMappingFailed(what=mapped_param))
def _load_import_template(self, import_name, import_uri_def): """Handle custom types defined in imported template files This method loads the custom type definitions referenced in "imports" section of the TOSCA YAML template by determining whether each import is specified via a file reference (by relative or absolute path) or a URL reference. Possibilities: +----------+--------+------------------------------+ | template | import | comment | +----------+--------+------------------------------+ | file | file | OK | | file | URL | OK | | preparsed| file | file must be a full path | | preparsed| URL | OK | | URL | file | file must be a relative path | | URL | URL | OK | +----------+--------+------------------------------+ """ short_import_notation = False if isinstance(import_uri_def, dict): self._validate_import_keys(import_name, import_uri_def) file_name = import_uri_def.get(self.FILE) repository = import_uri_def.get(self.REPOSITORY) repos = self.repositories.keys() if repository is not None: if repository not in repos: ExceptionCollector.appendException( InvalidPropertyValueError( what=_('Repository is not found in "%s"') % repos)) else: file_name = import_uri_def repository = None short_import_notation = True if not file_name: msg = (_('A template file name is not provided with import ' 'definition "%(import_name)s".') % {'import_name': import_name}) log.error(msg) ExceptionCollector.appendException(ValidationError(message=msg)) return None, None if toscaparser.utils.urlutils.UrlUtils.validate_url(file_name): return file_name, YAML_LOADER(file_name, False) elif not repository: import_template = None if self.path: if toscaparser.utils.urlutils.UrlUtils.validate_url(self.path): if os.path.isabs(file_name): msg = (_('Absolute file name "%(name)s" cannot be ' 'used in a URL-based input template ' '"%(template)s".') % {'name': file_name, 'template': self.path}) log.error(msg) ExceptionCollector.appendException(ImportError(msg)) return None, None import_template = toscaparser.utils.urlutils.UrlUtils.\ join_url(self.path, file_name) a_file = False else: a_file = True main_a_file = os.path.isfile(self.path) if main_a_file: if os.path.isfile(file_name): import_template = file_name else: full_path = os.path.join( os.path.dirname(os.path.abspath(self.path)), file_name) if os.path.isfile(full_path): import_template = full_path else: file_path = file_name.rpartition("/") dir_path = os.path.dirname(os.path.abspath( self.path)) if file_path[0] != '' and dir_path.endswith( file_path[0]): import_template = dir_path + "/" +\ file_path[2] if not os.path.isfile(import_template): msg = (_('"%(import_template)s" is' 'not a valid file') % {'import_template': import_template}) log.error(msg) ExceptionCollector.appendException (ValueError(msg)) else: # template is pre-parsed if os.path.isabs(file_name) and os.path.isfile(file_name): a_file = True import_template = file_name else: msg = (_('Relative file name "%(name)s" cannot be used ' 'in a pre-parsed input template.') % {'name': file_name}) log.error(msg) ExceptionCollector.appendException(ImportError(msg)) return None, None if not import_template: log.error(_('Import "%(name)s" is not valid.') % {'name': import_uri_def}) ExceptionCollector.appendException( ImportError(_('Import "%s" is not valid.') % import_uri_def)) return None, None return import_template, YAML_LOADER(import_template, a_file) if short_import_notation: log.error(_('Import "%(name)s" is not valid.') % import_uri_def) ExceptionCollector.appendException( ImportError(_('Import "%s" is not valid.') % import_uri_def)) return None, None full_url = "" if repository: if self.repositories: for repo_name, repo_def in self.repositories.items(): if repo_name == repository: # Remove leading, ending spaces and strip # the last character if "/" repo_url = ((repo_def['url']).strip()).rstrip("//") full_url = repo_url + "/" + file_name if not full_url: msg = (_('referenced repository "%(n_uri)s" in import ' 'definition "%(tpl)s" not found.') % {'n_uri': repository, 'tpl': import_name}) log.error(msg) ExceptionCollector.appendException(ImportError(msg)) return None, None if toscaparser.utils.urlutils.UrlUtils.validate_url(full_url): return full_url, YAML_LOADER(full_url, False) else: msg = (_('repository url "%(n_uri)s" is not valid in import ' 'definition "%(tpl)s".') % {'n_uri': repo_url, 'tpl': import_name}) log.error(msg) ExceptionCollector.appendException(ImportError(msg))
def get_source_structure_from_facts(condition, fact_name, value, arguments, executor, target_parameter, source_parameter, source_value): """ :param condition: :param fact_name: :param value: :param arguments: :param executor :param target_parameter: :param source_parameter: :param source_value: :return: """ if isinstance(fact_name, six.string_types): fact_name_splitted = fact_name.split(SEPARATOR) source_name = fact_name_splitted[0] facts_result = "facts_result" if len(fact_name_splitted) > 1: facts_result += "[\"" + "\"][\"".join( fact_name_splitted[1:]) + "\"]" facts_result = "{{{{ " + facts_result + " }}}}" new_global_elements_map_total_implementation = [{ SOURCE: source_name, VALUE: "facts_result", EXECUTOR: executor, PARAMETERS: {} }, { SOURCE: SET_FACT_SOURCE, PARAMETERS: { "target_objects": facts_result }, VALUE: "tmp_value", EXECUTOR: executor }] else: new_global_elements_map_total_implementation = fact_name target_parameter_splitted = target_parameter.split(SEPARATOR) relationship_name = "{self[name]}_server_" + snake_case.convert( target_parameter_splitted[-1]) provider = target_parameter_splitted[0] target_interface_name = "Target" target_relationship_type = SEPARATOR.join( [provider, RELATIONSHIPS, "DependsOn"]) target_type = None target_short_parameter = None for i in range(len(target_parameter_splitted)): if target_parameter_splitted[i] in NODE_TEMPLATE_KEYS: target_type = SEPARATOR.join(target_parameter_splitted[:i]) target_short_parameter = '_'.join(target_parameter_splitted[i:]) break if not target_type or not target_short_parameter: ExceptionCollector.appendException( ToscaParametersMappingFailed(what=target_parameter)) tag_operation_name = None if isinstance(fact_name, six.string_types): tag_operation_name = fact_name.replace(SEPARATOR, '_') elif isinstance(fact_name, dict): for k, v in fact_name: tag_operation_name = k.replace(SEPARATOR, '_') break elif isinstance(fact_name, list): if isinstance(fact_name[0], dict): for k, v in fact_name[0].items(): tag_operation_name = k.replace(SEPARATOR, '_') break else: tag_operation_name = str(fact_name[0]).replace(SEPARATOR, '_') else: tag_operation_name = str(fact_name).replace(SEPARATOR, '_') choose_operation_name = "choose_" + tag_operation_name total_operation_name = "total_" + tag_operation_name target_total_parameter_new = SEPARATOR.join([ target_relationship_type, INTERFACES, target_interface_name, total_operation_name ]) target_choose_parameter_new = SEPARATOR.join([ target_relationship_type, INTERFACES, target_interface_name, choose_operation_name ]) new_elements_map = { GET_OPERATION_OUTPUT: [ relationship_name, target_interface_name, choose_operation_name, value ] } new_global_elements_map_total = { PARAMETER: target_total_parameter_new, KEYNAME: relationship_name, VALUE: { IMPLEMENTATION: new_global_elements_map_total_implementation } } new_global_elements_map_choose = { PARAMETER: target_choose_parameter_new, KEYNAME: relationship_name, VALUE: { IMPLEMENTATION: [ condition + ".yaml", { SOURCE: SET_FACT_SOURCE, PARAMETERS: { value: "{{{{ matched_object[\"" + value + "\"] }}}}" }, VALUE: "tmp_value", EXECUTOR: executor } ], INPUTS: { "input_facts": { GET_OPERATION_OUTPUT: [ SELF, target_interface_name, total_operation_name, "target_objects" ] }, "input_args": arguments } } } new_global_elements_map = [{ PARAMETER: source_parameter, MAP_KEY: new_global_elements_map_choose, VALUE: source_value }, { PARAMETER: source_parameter, MAP_KEY: new_global_elements_map_total, VALUE: source_value }] return new_elements_map, new_global_elements_map
def _validate_type_version(self, version): if version not in self.VALID_TEMPLATE_VERSIONS: ExceptionCollector.appendException( InvalidTemplateVersion( what=version + ' in ' + str(self.import_def), valid_versions='", "'. join(self.VALID_TEMPLATE_VERSIONS)))
def restructure_mapping_facts(elements_map, extra_elements_map=None, target_parameter=None, source_parameter=None, source_value=None): """ Function is used to restructure mapping values with the case of `facts`, `condition`, `arguments`, `value` keys :param elements_map: :param extra_elements_map: :param target_parameter: :param source_parameter: :param source_value: :return: """ conditions = [] elements_map = copy.deepcopy(elements_map) if not extra_elements_map: extra_elements_map = [] if isinstance(elements_map, dict): cur_parameter = elements_map.get(PARAMETER) if cur_parameter and isinstance(cur_parameter, str): if elements_map.get(MAP_KEY): source_parameter = cur_parameter source_value = elements_map.get(VALUE) elif target_parameter: target_parameter += SEPARATOR + cur_parameter else: target_parameter = cur_parameter new_elements_map = dict() for k, v in elements_map.items(): cur_elements, extra_elements_map, new_conditions = restructure_mapping_facts( v, extra_elements_map, target_parameter, source_parameter, source_value) new_elements_map.update({k: cur_elements}) conditions.extend(new_conditions) if isinstance(new_elements_map.get(PARAMETER, ''), dict): separated_target_parameter = target_parameter.split(SEPARATOR) target_type = None target_short_parameter = None for i in range(len(separated_target_parameter)): if separated_target_parameter[i] in NODE_TEMPLATE_KEYS: target_type = SEPARATOR.join( separated_target_parameter[:i]) target_short_parameter = '_'.join( separated_target_parameter[i:]) break if not target_short_parameter or not target_type: ExceptionCollector.appendException( ToscaParametersMappingFailed(what=target_parameter)) input_parameter = new_elements_map[PARAMETER] input_value = new_elements_map[VALUE] input_keyname = new_elements_map.get(KEYNAME) provider = separated_target_parameter[0] target_relationship_type = SEPARATOR.join( [provider, RELATIONSHIPS, "DependsOn"]) relationship_name = "{self[name]}_server_" + snake_case.convert( separated_target_parameter[-1]) operation_name = 'modify_' + target_short_parameter value_name = 'modified_' + target_short_parameter interface_name = 'Extra' new_elements_map = { GET_OPERATION_OUTPUT: [ relationship_name, interface_name, operation_name, value_name ] } cur_target_parameter = SEPARATOR.join([ target_relationship_type, INTERFACES, interface_name, operation_name ]) cur_extra_element = { PARAMETER: source_parameter, MAP_KEY: { PARAMETER: cur_target_parameter, KEYNAME: relationship_name, VALUE: { IMPLEMENTATION: { SOURCE: SET_FACT_SOURCE, VALUE: "default_value", EXECUTOR: ANSIBLE, PARAMETERS: { value_name: "{{{{ {{ input_parameter: input_value }} }}}}" # so many braces because format # uses braces and replace '{{' with '{' } }, INPUTS: { "input_parameter": input_parameter, "input_value": input_value } } }, VALUE: source_value } if input_keyname: # TODO add keyname to the parameter outside the new_elements_map cur_extra_element[map][KEYNAME] = input_keyname extra_elements_map.append(cur_extra_element) if_facts_structure = False keys = new_elements_map.keys() if len(keys) > 0: if_facts_structure = True for k in FACTS_MAPPING_VALUE_STRUCTURE: if k not in keys: if_facts_structure = False if if_facts_structure: # NOTE: end of recursion assert target_parameter condition = new_elements_map[CONDITION] fact_name = new_elements_map[FACTS] value = new_elements_map[VALUE] arguments = new_elements_map[ARGUMENTS] executor = new_elements_map[EXECUTOR] if executor not in CONFIGURATION_TOOLS.keys(): ExceptionCollector.appendException( UnsupportedExecutorType(what=executor)) new_elements_map, cur_extra_elements = get_source_structure_from_facts( condition, fact_name, value, arguments, executor, target_parameter, source_parameter, source_value) conditions.append(condition) extra_elements_map.extend(cur_extra_elements) return new_elements_map, extra_elements_map, conditions if isinstance(elements_map, list): new_elements_map = [] for k in elements_map: cur_elements, extra_elements_map, new_conditions = restructure_mapping_facts( k, extra_elements_map, target_parameter, source_parameter, source_value) new_elements_map.append(cur_elements) conditions.extend(new_conditions) return new_elements_map, extra_elements_map, conditions return elements_map, extra_elements_map, conditions
def _get_explicit_relationship(self, req, value): """Handle explicit relationship For example, - req: node: DBMS relationship: tosca.relationships.HostedOn """ explicit_relation = {} node = value.get('node') if isinstance(value, dict) else value if node: # TODO(spzala) implement look up once Glance meta data is available # to find a matching TOSCA node using the TOSCA types msg = _('Lookup by TOSCA types is not supported. ' 'Requirement for "%s" can not be full-filled.') % self.name if (node in list(self.type_definition.TOSCA_DEF.keys()) or node in self.custom_def): ExceptionCollector.appendException(NotImplementedError(msg)) return if node not in self.templates: ExceptionCollector.appendException( KeyError(_('Node template "%s" was not found.') % node)) return related_tpl = NodeTemplate(node, self.templates, self.custom_def) relationship = value.get('relationship') \ if isinstance(value, dict) else None # check if it's type has relationship defined if not relationship: parent_reqs = self.type_definition.get_all_requirements() if parent_reqs is None: ExceptionCollector.appendException( ValidationError(message='parent_req is ' + str(parent_reqs))) else: for key in req.keys(): for req_dict in parent_reqs: if key in req_dict.keys(): relationship = ( req_dict.get(key).get('relationship')) break if relationship: found_relationship_tpl = False # apply available relationship templates if found if self.available_rel_tpls: for tpl in self.available_rel_tpls: if tpl.name == relationship: rtype = RelationshipType(tpl.type, None, self.custom_def) explicit_relation[rtype] = related_tpl self.relationship_tpl.append(tpl) found_relationship_tpl = True # create relationship template object. rel_prfx = self.type_definition.RELATIONSHIP_PREFIX if not found_relationship_tpl: if isinstance(relationship, dict): relationship = relationship.get('type') if relationship: if self.available_rel_types and \ relationship in self.available_rel_types.keys(): pass elif not relationship.startswith(rel_prfx): relationship = rel_prfx + relationship else: ExceptionCollector.appendException( MissingRequiredFieldError( what=_('"relationship" used in template ' '"%s"') % related_tpl.name, required=self.TYPE)) for rtype in self.type_definition.relationship.keys(): if rtype.type == relationship: explicit_relation[rtype] = related_tpl related_tpl._add_relationship_template( req, rtype.type) elif self.available_rel_types: if relationship in self.available_rel_types.keys(): rel_type_def = self.available_rel_types.\ get(relationship) if 'derived_from' in rel_type_def: super_type = \ rel_type_def.get('derived_from') if not super_type.startswith(rel_prfx): super_type = rel_prfx + super_type if rtype.type == super_type: explicit_relation[rtype] = related_tpl related_tpl.\ _add_relationship_template( req, rtype.type) return explicit_relation
def _validate_keys(self): for key in self.trigger_tpl.keys(): if key not in SECTIONS: ExceptionCollector.appendException( UnknownFieldError(what='Triggers "%s"' % self.name, field=key))
def validate_string(value): if not isinstance(value, str): ExceptionCollector.appendException( ValueError(_('"%s" is not a string.') % value)) return value
def _validate_condition(self): for key in self.get_condition(): if key not in CONDITION_KEYNAMES: ExceptionCollector.appendException( UnknownFieldError(what='Triggers "%s"' % self.name, field=key))
def validate_numeric(value): if not isinstance(value, numbers.Number): ExceptionCollector.appendException( ValueError(_('"%s" is not a numeric.') % value)) return value
def __init__(self, property_name, property_type, constraint): super(Length, self).__init__(property_name, property_type, constraint) if not isinstance(self.constraint_value, self.valid_types): ExceptionCollector.appendException( InvalidSchemaError(message=_('The property "length" expects ' 'an integer.')))
def validate_map(value): if not isinstance(value, collections.Mapping): ExceptionCollector.appendException( ValueError(_('"%s" is not a map.') % value)) return value
def _validate_and_load_imports(self): imports_names = set() log.debug("Imports list: {}".format(self.importslist)) if not self.importslist: msg = _('"imports" keyname is defined without including ' 'templates.') log.error(msg) ExceptionCollector.appendException(ValidationError(message=msg)) return def update_import_entry(fpath, defs): if 'imports' in defs: dirname = os.path.dirname(fpath) imports = [] for f in defs['imports']: if isinstance(f, dict): imp = f if 'file' in imp: fn = imp['file'] if fn.startswith('http') is False: dname = os.path.dirname(fn) imp['file'] = os.path.abspath( os.path.join(dirname, dname, os.path.basename(fn))) imports.append(imp) else: dname = os.path.dirname(f) fn = os.path.abspath( os.path.join(dirname, dname, os.path.basename(f))) imports.append(fn) return imports for import_def in self.importslist: if isinstance(import_def, dict): full_file_name, custom_type, namespace_prefix = None, None, None if self.version == TypeValidation.STANDARD_TEMPLATE_VERSIONS[0] or \ self.version not in TypeValidation.STANDARD_TEMPLATE_VERSIONS: # Assume tosca_simple_yaml_1_0 import format for import_name, import_uri in import_def.items(): log.debug("Import {}: {}".format( import_name, import_uri)) if import_name in imports_names: msg = (_('Duplicate import name "%s" was found.') % import_name) log.error(msg) ExceptionCollector.appendException( ValidationError(message=msg)) imports_names.add(import_name) full_file_name, custom_type = self._load_import_template( import_name, import_uri) if isinstance(import_uri, dict): namespace_prefix = import_uri.get( self.NAMESPACE_PREFIX) else: full_file_name, custom_type = self._load_import_template( None, import_def) namespace_prefix = import_def.get(self.NAMESPACE_PREFIX) if custom_type: imp = update_import_entry(full_file_name, custom_type) if imp: custom_type['imports'] = imp TypeValidation(custom_type, import_def) self._update_custom_def(custom_type, namespace_prefix) else: # old style of imports log.debug("Import old style: {}".format(import_def)) full_file_name, custom_type = self._load_import_template( None, import_def) if custom_type: imp = update_import_entry(full_file_name, custom_type) if imp: custom_type['imports'] = imp TypeValidation(custom_type, import_def) self._update_custom_def(custom_type, None) self._update_nested_tosca_tpls(full_file_name, custom_type)
def _validate_keys(self): for key in self.defs.keys(): if key not in self.SECTIONS: ExceptionCollector.appendException( UnknownFieldError(what='Relationshiptype "%s"' % self.type, field=key))
def validate(self): if len(self.args) < 1: ExceptionCollector.appendException( ValueError( _('Invalid arguments for function "{0}". Expected ' 'at least one arguments.').format(CONCAT)))
def load_yaml(self, importLoader, path, isFile=True, fragment=None): try: logger.trace("attempting to load YAML %s: %s", "file" if isFile else "url", path) originalPath = path f = importLoader.stream if not f: try: if isFile: ignoreFileNotFound = self.ignoreFileNotFound if ignoreFileNotFound and not os.path.isfile(path): return None if self.loader: # show == True if file was decrypted contents, show = self.loader._get_file_contents( path) f = six.StringIO(codecs.decode(contents)) else: f = codecs.open(path, encoding="utf-8", errors="strict") else: f = urllib.request.urlopen(path) except urllib.error.URLError as e: if hasattr(e, "reason"): msg = _( ('Failed to reach server "%(path)s". Reason is: ' + "%(reason)s.")) % { "path": path, "reason": e.reason } ExceptionCollector.appendException( URLException(what=msg)) return elif hasattr(e, "code"): msg = _(( 'The server "%(path)s" couldn\'t fulfill the request. ' + 'Error code: "%(code)s".')) % { "path": path, "code": e.code } ExceptionCollector.appendException( URLException(what=msg)) return else: raise with f: doc = yaml.load(f.read()) if isinstance(doc, CommentedMap): if self.expand: includes, doc = expand_doc(doc, cls=make_map_with_base( doc, get_base_dir(path))) doc.includes = includes doc.path = path if fragment and doc: return _refResolver.resolve_fragment(doc, fragment) else: return doc except: if path != originalPath: msg = f'Could not load "{path}" (originally "{originalPath}")' else: msg = f'Could not load "{path}"' raise UnfurlError(msg, True)
def _validate_targets(self, targets_list, custom_def): for nodetype in targets_list: if nodetype not in custom_def: ExceptionCollector.appendException( InvalidTypeError(what='"%s" defined in targets for ' 'policy "%s"' % (nodetype, self.type)))