Пример #1
0
 def _validate_no_group_cycles(member_graph):
     # verify no group cycles (i.e. group A in group B and vice versa)
     group_cycles = nx.recursive_simple_cycles(member_graph)
     if group_cycles:
         raise exceptions.DSLParsingLogicException(
             exceptions.ERROR_GROUP_CYCLE,
             'Illegal group cycles found: {0}'.format(group_cycles))
Пример #2
0
 def validate(self):
     if len(self.children()) < 1:
         raise exceptions.DSLParsingLogicException(
             exceptions.ERROR_NO_TARGETS,
             "Policy '{0}' has no targets groups defined for it. "
             "At least one target group is required."
             .format(self.ancestor(Policy).name))
Пример #3
0
 def validate(self, groups):
     if self.initial_value not in groups:
         raise exceptions.DSLParsingLogicException(
             exceptions.ERROR_NON_GROUP_TARGET,
             "'{0}' is not a valid policy target. Only groups are "
             "valid policy targets. Defined groups are {1}."
             .format(self.initial_value, groups))
Пример #4
0
 def validate_version(self, version, min_version):
     if self.initial_value is not None and version < min_version:
         raise exceptions.DSLParsingLogicException(
             exceptions.ERROR_CODE_DSL_DEFINITIONS_VERSION_MISMATCH,
             '{0} not supported in version {1}, it was added in {2}'.format(
                 self.name, _version.version_description(version),
                 _version.version_description(min_version)))
Пример #5
0
    def validate(self):
        if self.initial_value is None:
            raise exceptions.DSLParsingLogicException(
                27, '{0} field must appear in the main blueprint file'.format(
                    _version.VERSION))

        _version.validate_dsl_version(self.initial_value)
Пример #6
0
def _merge_parsed_into_combined(combined_parsed_dsl_holder,
                                parsed_imported_dsl_holder, version):
    merge_no_override = MERGE_NO_OVERRIDE.copy()
    if version['definitions_version'] > (1, 2):
        merge_no_override.update(MERGEABLE_FROM_DSL_VERSION_1_3)
    for key_holder, value_holder in parsed_imported_dsl_holder.value.\
            iteritems():
        if key_holder.value in IGNORE:
            pass
        elif key_holder.value not in combined_parsed_dsl_holder:
            combined_parsed_dsl_holder.value[key_holder] = value_holder
        elif key_holder.value in merge_no_override:
            _, to_dict = combined_parsed_dsl_holder.get_item(key_holder.value)
            _merge_into_dict_or_throw_on_duplicate(
                from_dict_holder=value_holder,
                to_dict_holder=to_dict,
                key_name=key_holder.value)
        else:
            if key_holder.value in MERGEABLE_FROM_DSL_VERSION_1_3:
                msg = ("Import failed: non-mergeable field: '{0}'. "
                       "{0} can be imported multiple times only from "
                       "cloudify_dsl_1_3 and above.")
            else:
                msg = "Import failed: non-mergeable field: '{0}'"
            raise exceptions.DSLParsingLogicException(
                3, msg.format(key_holder.value))
Пример #7
0
 def validate(self):
     if super(NonNegativeInstances, self).validate():
         return
     if self.initial_value is not None and self.initial_value < 0:
         raise exceptions.DSLParsingLogicException(
             exceptions.ERROR_INVALID_INSTANCES,
             '{0} should be a non negative value.'.format(self.name))
Пример #8
0
def _merge_node_templates_relationships(key_holder, key_name, to_dict_holder,
                                        from_dict_holder):
    def only_relationships_inside(element_holder):
        return (constants.RELATIONSHIPS in element_holder
                and len(element_holder.value) == 1)

    if constants.RELATIONSHIPS in to_dict_holder:
        only_relationships_in_source = only_relationships_inside(
            from_dict_holder)
        required_node_template_field = 'type'

        if (len(to_dict_holder.value) == 1
                and (required_node_template_field in from_dict_holder
                     or only_relationships_in_source)):
            # If the current parsed yaml contains only relationships element,
            # the user can only extend with more relationships or merge it
            # with required field to a set a node template.
            _extend_node_template(from_dict_holder, to_dict_holder)
            return
        elif only_relationships_in_source:
            _extend_list_with_namespaced_values(
                from_dict_holder[constants.RELATIONSHIPS].namespace,
                from_dict_holder[constants.RELATIONSHIPS],
                to_dict_holder[constants.RELATIONSHIPS])
            return
    raise exceptions.DSLParsingLogicException(
        4, "Import failed: Could not merge '{0}' due to conflict "
        "on '{1}'".format(key_name, key_holder.value))
Пример #9
0
    def _build_ordered_imports_recursive(_current_parsed_dsl_holder,
                                         _current_import):
        imports_key_holder, imports_value_holder = _current_parsed_dsl_holder.\
            get_item(constants.IMPORTS)
        if not imports_value_holder:
            return

        for another_import in imports_value_holder.restore():
            import_url = _get_resource_location(another_import,
                                                resources_base_path,
                                                _current_import)
            if import_url is None:
                ex = exceptions.DSLParsingLogicException(
                    13, "Import failed: no suitable location found for "
                    "import '{0}'".format(another_import))
                ex.failed_import = another_import
                raise ex
            if import_url in imports_graph:
                imports_graph.add_graph_dependency(import_url,
                                                   location(_current_import))
            else:
                raw_imported_dsl = resolver.fetch_import(import_url)
                imported_dsl_holder = utils.load_yaml(
                    raw_yaml=raw_imported_dsl,
                    error_message="Failed to parse import '{0}' (via '{1}')".
                    format(another_import, import_url),
                    filename=another_import)
                imports_graph.add(import_url, imported_dsl_holder,
                                  location(_current_import))
                _build_ordered_imports_recursive(imported_dsl_holder,
                                                 import_url)
Пример #10
0
    def build_ordered_imports_recursive(_current_parsed_dsl_holder,
                                        _current_import,
                                        context_namespace=None):
        imports_key_holder, imports_value_holder = _current_parsed_dsl_holder.\
            get_item(constants.IMPORTS)
        if not imports_value_holder:
            return

        for another_import in imports_value_holder.restore():
            namespace, import_url = _extract_import_parts(
                another_import, resources_base_path, _current_import)
            validate_namespace(namespace)
            if context_namespace:
                if namespace:
                    namespace = utils.generate_namespaced_value(
                        context_namespace, namespace)
                else:
                    # In case a namespace was added earlier in the import
                    # chain.
                    namespace = context_namespace
            if import_url is None:
                ex = exceptions.DSLParsingLogicException(
                    13, "Import failed: no suitable location found for "
                    "import '{0}'".format(another_import))
                ex.failed_import = another_import
                raise ex

            if utils.is_blueprint_import(import_url):
                validate_blueprint_import_namespace(namespace, import_url)
                blueprint_id = utils.remove_blueprint_import_prefix(import_url)
                blueprint_imports.add(blueprint_id)
                add_namespace_to_mapping(blueprint_id, namespace)

            import_key = resolve_import_graph_key(import_url, namespace)
            import_context = (location(_current_import), context_namespace)
            if import_key in imports_graph:
                is_cloudify_types = imports_graph[import_key]['cloudify_types']
                validate_import_namespace(namespace, is_cloudify_types,
                                          context_namespace)
                imports_graph.add_graph_dependency(import_url, import_context,
                                                   namespace)
            else:
                imported_dsl = resolver.fetch_import(import_url)
                if not is_parsed_resource(imported_dsl):
                    imported_dsl = utils.load_yaml(
                        raw_yaml=imported_dsl,
                        error_message="Failed to parse import '{0}'"
                        "(via '{1}')".format(another_import, import_url),
                        filename=import_url)
                cloudify_basic_types = is_cloudify_basic_types(imported_dsl)
                validate_import_namespace(namespace, cloudify_basic_types,
                                          context_namespace)
                if cloudify_basic_types:
                    # Remove namespace data from import
                    namespace = None
                imports_graph.add(import_url, imported_dsl,
                                  cloudify_basic_types, import_context,
                                  namespace)
                build_ordered_imports_recursive(imported_dsl, import_url,
                                                namespace)
Пример #11
0
 def validate(self, relationships):
     if self.initial_value not in relationships:
         raise exceptions.DSLParsingLogicException(
             26, "A relationship instance under node '{0}' declares an "
                 "undefined relationship type '{1}'"
                 .format(self.ancestor(NodeTemplate).name,
                         self.initial_value))
Пример #12
0
 def validate(self, node_types):
     if self.initial_value not in node_types:
         err_message = ("Could not locate node type: '{0}'; "
                        "existing types: {1}"
                        .format(self.initial_value,
                                node_types.keys()))
         raise exceptions.DSLParsingLogicException(7, err_message)
Пример #13
0
 def validate(self):
     relationship_type = self.sibling(NodeTemplateRelationshipType).name
     node_name = self.ancestor(NodeTemplate).name
     node_template_names = self.ancestor(NodeTemplates).initial_value_holder
     if self.initial_value not in node_template_names:
         raise exceptions.DSLParsingLogicException(
             25, "A relationship instance under node '{0}' of type '{1}' "
                 "declares an undefined target node '{2}'"
                 .format(node_name,
                         relationship_type,
                         self.initial_value))
     if self.initial_value == node_name:
         raise exceptions.DSLParsingLogicException(
             23, "A relationship instance under node '{0}' of type '{1}' "
                 "illegally declares the source node as the target node"
                 .format(node_name, relationship_type))
Пример #14
0
def _merge_flattened_schema_and_instance_properties(
        instance_properties, schema_properties, flattened_schema_properties,
        data_types, undefined_property_error_message,
        missing_property_error_message, node_name, path,
        raise_on_missing_property):
    path = path or []

    # validate instance properties don't
    # contain properties that are not defined
    # in the schema.
    for key in instance_properties.iterkeys():
        if key not in schema_properties:
            ex = exceptions.DSLParsingLogicException(
                exceptions.ERROR_UNDEFINED_PROPERTY,
                undefined_property_error_message.format(
                    node_name, _property_description(path, key)))
            ex.property = key
            raise ex

    merged_properties = dict(flattened_schema_properties.items() +
                             instance_properties.items())
    result = {}
    for key, property_schema in schema_properties.iteritems():
        if key not in merged_properties:
            required = property_schema.get('required', True)
            if required and raise_on_missing_property:
                ex = exceptions.DSLParsingLogicException(
                    exceptions.ERROR_MISSING_PROPERTY,
                    missing_property_error_message.format(
                        node_name, _property_description(path, key)))
                ex.property = key
                raise ex
            else:
                continue
        prop_path = copy.copy(path)
        prop_path.append(key)
        result[key] = parse_value(
            value=merged_properties.get(key),
            derived_value=flattened_schema_properties.get(key),
            type_name=property_schema.get('type'),
            data_types=data_types,
            undefined_property_error_message=undefined_property_error_message,
            missing_property_error_message=missing_property_error_message,
            node_name=node_name,
            path=prop_path,
            raise_on_missing_property=raise_on_missing_property)
    return result
Пример #15
0
 def validate(self):
     if self.initial_value and self.initial_value.get('required', True) \
             and self.initial_value.get('hidden', False) \
             and 'default' not in self.initial_value:
         raise exceptions.DSLParsingLogicException(
             exceptions.ERROR_HIDDEN_REQUIRED_INPUT_NO_DEFAULT,
             "Input is both hidden and required thus it should have a "
             "default value: '{0}'.".format(self.name))
Пример #16
0
 def validate(self, node_template_names):
     if self.initial_value not in node_template_names:
         raise exceptions.DSLParsingLogicException(
             40,
             "Member '{0}' of group '{1}' does not "
             "match any defined node".format(
                 self.initial_value,
                 self.ancestor(Group).name))
Пример #17
0
 def validate(self):
     if self.child(PluginInstall).value:
         if not (self.child(PluginSource).value
                 or self.child(PluginPackageName).value):
             raise exceptions.DSLParsingLogicException(
                 50, "Plugin '{0}' needs to be installed, "
                 "but does not declare a source or package_name property".
                 format(self.name))
Пример #18
0
 def validate_namespace(namespace):
     """
     The namespace delimiter is not allowed in the namespace.
     """
     if namespace and constants.NAMESPACE_DELIMITER in namespace:
         raise exceptions.DSLParsingLogicException(
             212, 'Invalid {0}: import\'s namespace cannot'
             'contain namespace delimiter'.format(namespace))
Пример #19
0
 def validate(self):
     scaling_policy = constants.SCALING_POLICY
     if self.initial_value != scaling_policy:
         raise exceptions.DSLParsingLogicException(
             exceptions.ERROR_UNSUPPORTED_POLICY,
             "'{0}' policy type is not implemented. "
             "Only '{1}' policy type is supported."
             .format(self.initial_value, scaling_policy))
Пример #20
0
def _validate_type_match(input_name, input_value, type_name):
    _, valid = utils.parse_simple_type_value(input_value, type_name)
    if not valid:
        raise exceptions.DSLParsingLogicException(
            exceptions.ERROR_VALUE_DOES_NOT_MATCH_TYPE,
            "Property type validation failed in '{0}': the defined "
            "type is '{1}', yet it was assigned with the "
            "value '{2}'".format(input_name, type_name, input_value))
Пример #21
0
 def validate(self, node_template_names):
     groups = self.ancestor(Groups).initial_value
     value = self.initial_value
     group_names = set(groups.keys()) if groups else set()
     if value not in node_template_names and value not in group_names:
         raise exceptions.DSLParsingLogicException(
             40, "Member '{0}' of group '{1}' does not "
             "match any defined node".format(value,
                                             self.ancestor(Group).name))
Пример #22
0
 def validate(self, policy_triggers):
     if self.initial_value not in policy_triggers:
         raise exceptions.DSLParsingLogicException(
             42, "Trigger '{0}' of policy '{1}' of group '{2}' "
             "references a non existent "
             "'policy trigger '{3}'".format(
                 self.ancestor(GroupPolicyTrigger).name,
                 self.ancestor(GroupPolicy).name,
                 self.ancestor(Group).name, self.initial_value))
Пример #23
0
 def validate(self, version, validate_version, instances_deploy):
     if validate_version:
         self.validate_version(version, (1, 3))
     if instances_deploy is not None and self.initial_value is not None:
         raise exceptions.DSLParsingLogicException(
             exceptions.ERROR_INSTANCES_DEPLOY_AND_CAPABILITIES,
             "Node '{0}' defines both instances.deploy and "
             "capabilities.scalable (Note: instances.deploy is deprecated)".
             format(self.ancestor(NodeTemplate).name))
Пример #24
0
def _merge_into_dict_or_throw_on_duplicate(from_dict_holder, to_dict_holder,
                                           key_name):
    for key_holder, value_holder in from_dict_holder.value.iteritems():
        if key_holder.value not in to_dict_holder:
            to_dict_holder.value[key_holder] = value_holder
        else:
            raise exceptions.DSLParsingLogicException(
                4, "Import failed: Could not merge '{0}' due to conflict "
                "on '{1}'".format(key_name, key_holder.value))
Пример #25
0
 def validate(self, policy_types):
     if self.initial_value not in policy_types:
         raise exceptions.DSLParsingLogicException(
             41,
             "Policy '{0}' of group '{1}' references a non existent "
             "policy type '{2}'"
             .format(self.ancestor(GroupPolicy).name,
                     self.ancestor(Group).name,
                     self.initial_value))
Пример #26
0
 def validate(self, **kwargs):
     if self.initial_value and \
             any(value not in self.valid_values
                 for value in self.initial_value):
         raise exceptions.DSLParsingLogicException(
             exceptions.ERROR_UNKNOWN_TYPE,
             "Invalid definition of 'active_node_instances' availability "
             "rule: '{0}'. Allowed values: {1}".format(
                 self.initial_value, self.valid_values))
Пример #27
0
def parse_value(value,
                type_name,
                data_types,
                undefined_property_error_message,
                missing_property_error_message,
                node_name,
                path,
                derived_value=None,
                raise_on_missing_property=True):
    if type_name is None:
        return value
    elif get_function(value):
        # intrinsic function - not validated at the moment
        return value
    elif type_name in constants.USER_PRIMITIVE_TYPES:
        result, found = parse_simple_type_value(value, type_name)
        if found:
            return result
    elif type_name in data_types:
        if isinstance(value, dict):
            data_schema = data_types[type_name]['properties']
            flattened_data_schema = flatten_schema(data_schema)
            if isinstance(derived_value, dict):
                flattened_data_schema.update(derived_value)
            undef_msg = undefined_property_error_message
            return _merge_flattened_schema_and_instance_properties(
                instance_properties=value,
                schema_properties=data_schema,
                flattened_schema_properties=flattened_data_schema,
                data_types=data_types,
                undefined_property_error_message=undef_msg,
                missing_property_error_message=missing_property_error_message,
                node_name=node_name,
                path=path,
                raise_on_missing_property=raise_on_missing_property)
    else:
        raise RuntimeError(
            "Unexpected type defined in property schema for property '{0}'"
            " - unknown type is '{1}'".format(_property_description(path),
                                              type_name))

    prop_path = _property_description(path)
    if not prop_path:
        err_msg = "Property type validation failed in '{0}': the defined " \
                  "type is '{1}', yet it was assigned with the " \
                  "value '{2}'".format(node_name, type_name, value)
    else:
        err_msg = "Property type validation failed in '{0}': property " \
                  "'{1}' type is '{2}', yet it was assigned with the " \
                  "value '{3}'".format(node_name,
                                       _property_description(path),
                                       type_name,
                                       value)

    raise exceptions.DSLParsingLogicException(
        exceptions.ERROR_VALUE_DOES_NOT_MATCH_TYPE, err_msg)
Пример #28
0
 def _validate_members_in_one_group_only(member_graph):
     # verify all group members are part of exactly one group
     for member in member_graph:
         successors = member_graph.successors(member)
         if len(successors) > 1:
             raise exceptions.DSLParsingLogicException(
                 exceptions.ERROR_MULTIPLE_GROUPS,
                 "Nodes and groups cannot be members in multiple groups, "
                 "but member '{0}' belongs to the following multiple "
                 "groups: {1}".format(member, successors))
Пример #29
0
 def validate(self):
     if self.initial_value not in [
             constants.CENTRAL_DEPLOYMENT_AGENT, constants.HOST_AGENT
     ]:
         raise exceptions.DSLParsingLogicException(
             18, "Plugin '{0}' has an illegal "
             "'{1}' value '{2}'; value "
             "must be either '{3}' or '{4}'".format(
                 self.ancestor(Plugin).name, self.name, self.initial_value,
                 constants.CENTRAL_DEPLOYMENT_AGENT, constants.HOST_AGENT))
Пример #30
0
 def validate_blueprint_import_namespace(namespace, import_url):
     """
     Blueprint import must be used with namespace, this is enforced for
     enabling the use of scripts from the imported blueprint which needs
     the namespace for maintaining the path to the scripts.
     """
     if not namespace:
         raise exceptions.DSLParsingLogicException(
             213, 'Invalid {0}: blueprint import cannot'
             'be used without namespace'.format(import_url))