diff --git a/toscaparser/policy.py b/toscaparser/policy.py index 50cd9882..8c9e00a0 100644 --- a/toscaparser/policy.py +++ b/toscaparser/policy.py @@ -89,3 +89,8 @@ class Policy(EntityTemplate): ExceptionCollector.appendException( UnknownFieldError(what='Policy "%s"' % self.name, field=key)) + + def validate(self): + self._validate_properties(self.entity_tpl, self.type_definition) + for prop in self.get_properties_objects(): + prop.validate() diff --git a/toscaparser/tests/data/custom_types/custom_policy.yaml b/toscaparser/tests/data/custom_types/custom_policy.yaml new file mode 100644 index 00000000..ab4472f3 --- /dev/null +++ b/toscaparser/tests/data/custom_types/custom_policy.yaml @@ -0,0 +1,13 @@ +tosca_definitions_version: tosca_simple_yaml_1_1 + +policy_types: + tosca.policies.somePolicy: + derived_from: tosca.policies.Root + properties: + name: + type: string + required: true + value: + type: integer + required: false + default: 100 diff --git a/toscaparser/tests/data/policies/test_policies_without_required_property.yaml b/toscaparser/tests/data/policies/test_policies_without_required_property.yaml new file mode 100644 index 00000000..7bc6364e --- /dev/null +++ b/toscaparser/tests/data/policies/test_policies_without_required_property.yaml @@ -0,0 +1,102 @@ +tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0 + +description: sample-tosca-vnfd-scaling + +imports: + - tacker_defs.yaml + - tacker_nfv_defs.yaml + +metadata: + template_name: sample-tosca-vnfd-scaling + +topology_template: + node_templates: + VDU1: + type: tosca.nodes.nfv.VDU.Tacker + properties: + image: cirros-0.3.4-x86_64-uec + mgmt_driver: noop + availability_zone: nova + flavor: m1.tiny + + CP1: + type: tosca.nodes.nfv.CP.Tacker + properties: + management: true + order: 0 + anti_spoofing_protection: false + requirements: + - virtualLink: + node: VL1 + - virtualBinding: + node: VDU1 + + VDU2: + type: tosca.nodes.nfv.VDU.Tacker + properties: + image: cirros-0.3.4-x86_64-uec + mgmt_driver: noop + availability_zone: nova + flavor: m1.tiny + + CP2: + type: tosca.nodes.nfv.CP.Tacker + properties: + management: true + order: 0 + anti_spoofing_protection: false + requirements: + - virtualLink: + node: VL1 + - virtualBinding: + node: VDU2 + + VL1: + type: tosca.nodes.nfv.VL + properties: + network_name: net_mgmt + vendor: Tacker + + policies: + - SP1: + type: tosca.policies.tacker.Scaling + targets: [VDU1] + properties: + increment: 1 + cooldown: 120 + min_instances: 1 + max_instances: 2 + default_instances: 1 + targets: [VDU1] + + - SP2: + type: tosca.policies.tacker.Scaling + targets: [VDU2] + properties: + #increment: 1 + cooldown: 120 + min_instances: 1 + max_instances: 2 + default_instances: 1 + targets: [VDU2] + + - ALRM1: + type: tosca.policies.tacker.Monitoring + triggers: + resize_compute: + event_type: + type: tosca.events.resource.utilization + implementation: ceilometer + condition: + constraint: 50 + granularity: 600 + evaluations: 1 + aggregation_method: mean + resource_type: instance + action: + resize_compute: + action_name: SP1 + properties: + name: alrm1 + actions: + resize_compute: "action_name: SP1" diff --git a/toscaparser/tests/data/policies/test_tosca_nfv_multiple_policies.yaml b/toscaparser/tests/data/policies/test_tosca_nfv_multiple_policies.yaml index 48e90cf5..55778b22 100644 --- a/toscaparser/tests/data/policies/test_tosca_nfv_multiple_policies.yaml +++ b/toscaparser/tests/data/policies/test_tosca_nfv_multiple_policies.yaml @@ -67,6 +67,7 @@ topology_template: min_instances: 1 max_instances: 2 default_instances: 1 + targets: [VDU1] - SP2: type: tosca.policies.tacker.Scaling @@ -77,6 +78,7 @@ topology_template: min_instances: 1 max_instances: 2 default_instances: 1 + targets: [VDU2] - ALRM1: type: tosca.policies.tacker.Monitoring @@ -94,3 +96,7 @@ topology_template: action: resize_compute: action_name: SP1 + properties: + name: alrm1 + actions: + resize_compute: "action_name: SP1" diff --git a/toscaparser/tests/test_toscatpl.py b/toscaparser/tests/test_toscatpl.py index 5e965508..84efd901 100644 --- a/toscaparser/tests/test_toscatpl.py +++ b/toscaparser/tests/test_toscatpl.py @@ -1006,3 +1006,10 @@ class ToscaTemplateTest(TestCase): rel_tpls = trgt.get_relationship_template() self.assertEqual(rel_tpls[0].type, "MyAttachesTo") + + def test_policies_without_required_property(self): + tosca_tpl = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "data/policies/test_policies_without_required_property.yaml") + self.assertRaises(exception.ValidationError, ToscaTemplate, + tosca_tpl, None) diff --git a/toscaparser/tests/test_toscatplvalidation.py b/toscaparser/tests/test_toscatplvalidation.py index 6982cfd7..bf2506f1 100644 --- a/toscaparser/tests/test_toscatplvalidation.py +++ b/toscaparser/tests/test_toscatplvalidation.py @@ -774,6 +774,18 @@ heat-translator/master/translator/tests/data/custom_types/wordpress.yaml custom_types[name] = defintion return custom_types + def _custom_types_policy(self): + custom_types = {} + def_file = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "data/custom_types/custom_policy.yaml") + custom_type = toscaparser.utils.yamlparser.load_yaml(def_file) + policy_types = custom_type['policy_types'] + for name in policy_types: + defintion = policy_types[name] + custom_types[name] = defintion + return custom_types + def _single_node_template_content_test(self, tpl_snippet): nodetemplates = (toscaparser.utils.yamlparser. simple_ordered_parse(tpl_snippet))['node_templates'] @@ -1746,6 +1758,26 @@ heat-translator/master/translator/tests/data/custom_types/wordpress.yaml lambda: Policy(name, policies[name], None, None)) self.assertEqual(expectedmessage, err.__str__()) + def test_policy_without_required_property(self): + tpl_snippet = ''' + policies: + - some_policy: + type: tosca.policies.somePolicy + properties: + value: 100 + ''' + policies = (toscaparser.utils.yamlparser. + simple_parse(tpl_snippet))['policies'][0] + name = list(policies.keys())[0] + policyObj = Policy(name, policies[name], None, None, + self._custom_types_policy()) + expectedmessage = _('"properties" of template "some_policy" is ' + 'missing required field "[\'name\']".') + err = self.assertRaises( + exception.MissingRequiredFieldError, + policyObj.validate) + self.assertEqual(expectedmessage, err.__str__()) + def test_credential_datatype(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), diff --git a/toscaparser/topology_template.py b/toscaparser/topology_template.py index fb3dcb0c..8a4fe359 100644 --- a/toscaparser/topology_template.py +++ b/toscaparser/topology_template.py @@ -140,7 +140,15 @@ class TopologyTemplate(object): policyObj = Policy(policy_name, policy_tpl, target_objects, targets_type, self.custom_defs) - policies.append(policyObj) + # If the policyObj.type is defined in TOSCA_definition_1_0.yaml + # or is defined as a custom definition, validate the properties + # before adding it to the policies list. + if (policyObj.type_definition and + (policyObj.type in policyObj.type_definition.TOSCA_DEF or + (policyObj.type not in policyObj.type_definition.TOSCA_DEF + and bool(policyObj.custom_def)))): + policyObj.validate() + policies.append(policyObj) return policies def _groups(self):