vFW and vDNS support added to azure-plugin
[multicloud/azure.git] / azure / aria / aria-extension-cloudify / src / aria / aria / parser / presentation / field_validators.py
diff --git a/azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/field_validators.py b/azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/field_validators.py
new file mode 100644 (file)
index 0000000..aa04913
--- /dev/null
@@ -0,0 +1,164 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+from ..validation import Issue
+from .utils import (parse_types_dict_names, report_issue_for_unknown_type,
+                    report_issue_for_parent_is_self, report_issue_for_unknown_parent_type,
+                    report_issue_for_circular_type_hierarchy)
+
+
+def type_validator(type_name, *types_dict_names):
+    """
+    Makes sure that the field refers to an existing type defined in the root presenter.
+
+    The arguments from the second onwards are used to locate a nested field under
+    ``service_template`` under the root presenter. The first of these can optionally be a function,
+    in which case it will be called to convert type names. This can be used to support shorthand
+    type names, aliases, etc.
+
+    Can be used with the :func:`field_validator` decorator.
+    """
+
+    types_dict_names, convert = parse_types_dict_names(types_dict_names)
+
+    def validator_fn(field, presentation, context):
+        field.default_validate(presentation, context)
+
+        # Make sure type exists
+        value = getattr(presentation, field.name)
+        if value is not None:
+            types_dict = context.presentation.get('service_template', *types_dict_names) or {}
+
+            if convert:
+                value = convert(context, value, types_dict)
+
+            if value not in types_dict:
+                report_issue_for_unknown_type(context, presentation, type_name, field.name)
+
+    return validator_fn
+
+
+def list_type_validator(type_name, *types_dict_names):
+    """
+    Makes sure that the field's elements refer to existing types defined in the root presenter.
+
+    Assumes that the field is a list.
+
+    The arguments from the second onwards are used to locate a nested field under
+    ``service_template`` under the root presenter. The first of these can optionally be a function,
+    in which case it will be called to convert type names. This can be used to support shorthand
+    type names, aliases, etc.
+
+    Can be used with the :func:`field_validator` decorator.
+    """
+
+    types_dict_names, convert = parse_types_dict_names(types_dict_names)
+
+    def validator_fn(field, presentation, context):
+        field.default_validate(presentation, context)
+
+        # Make sure types exist
+        values = getattr(presentation, field.name)
+        if values is not None:
+            types_dict = context.presentation.get('service_template', *types_dict_names) or {}
+
+            for value in values:
+                if convert:
+                    value = convert(context, value, types_dict)
+
+                if value not in types_dict:
+                    report_issue_for_unknown_type(context, presentation, type_name, field.name)
+
+    return validator_fn
+
+
+def list_length_validator(length):
+    """
+    Makes sure the field has exactly a specific number of elements.
+
+    Assumes that the field is a list.
+
+    Can be used with the :func:`field_validator` decorator.
+    """
+
+    def validator_fn(field, presentation, context):
+        field.default_validate(presentation, context)
+
+        # Make sure list has exactly the length
+        values = getattr(presentation, field.name)
+        if isinstance(values, list):
+            if len(values) != length:
+                context.validation.report('field "%s" does not have exactly %d elements in "%s"'
+                                          % (field.name, length, presentation._fullname),
+                                          locator=presentation._get_child_locator(field.name),
+                                          level=Issue.FIELD)
+
+    return validator_fn
+
+
+def derived_from_validator(*types_dict_names):
+    """
+    Makes sure that the field refers to a valid parent type defined in the root presenter.
+
+    Checks that we do not derive from ourselves and that we do not cause a circular hierarchy.
+
+    The arguments are used to locate a nested field under ``service_template`` under the root
+    presenter. The first of these can optionally be a function, in which case it will be called to
+    convert type names. This can be used to support shorthand type names, aliases, etc.
+
+    Can be used with the :func:`field_validator` decorator.
+    """
+
+    types_dict_names, convert = parse_types_dict_names(types_dict_names)
+
+    def validator_fn(field, presentation, context):
+        field.default_validate(presentation, context)
+
+        value = getattr(presentation, field.name)
+        if value is not None:
+            types_dict = context.presentation.get('service_template', *types_dict_names) or {}
+
+            if convert:
+                value = convert(context, value, types_dict)
+
+            # Make sure not derived from self
+            if value == presentation._name:
+                report_issue_for_parent_is_self(context, presentation, field.name)
+            # Make sure derived from type exists
+            elif value not in types_dict:
+                report_issue_for_unknown_parent_type(context, presentation, field.name)
+            else:
+                # Make sure derivation hierarchy is not circular
+                hierarchy = [presentation._name]
+                presentation_tmp = presentation
+                while presentation_tmp.derived_from is not None:
+                    derived_from = presentation_tmp.derived_from
+                    if convert:
+                        derived_from = convert(context, derived_from, types_dict)
+
+                    if derived_from == presentation_tmp._name:
+                        # This should cause a validation issue at that type
+                        break
+                    elif derived_from not in types_dict:
+                        # This should cause a validation issue at that type
+                        break
+                    presentation_tmp = types_dict[derived_from]
+                    if presentation_tmp._name in hierarchy:
+                        report_issue_for_circular_type_hierarchy(context, presentation, field.name)
+                        break
+                    hierarchy.append(presentation_tmp._name)
+
+    return validator_fn