Exemple #1
0
    def test_circular_get_property_from_outputs(self):
        yaml = """
node_types:
    vm_type:
        properties:
            b: { type: string }
            c: { type: string }
node_templates:
    vm:
        type: vm_type
        properties:
            b: { get_property: [SELF, c] }
            c: [ { get_property: [SELF, b ] }, 2 ]
outputs:
    o:
        value:
            a: 1
            b: { get_property: [vm, b] }
"""
        try:
            prepare_deployment_plan(self.parse(yaml))
            self.fail()
        except RuntimeError as e:
            self.assertIn('Circular get_property function call detected',
                          str(e))
    def test_input_value_data_type_validation_raises(self):
        yaml = self.BASIC_VERSION_SECTION_DSL_1_2 + """
inputs:
    some_input:
        type: a
data_types:
    a:
        properties:
            b:
                type: b
    b:
        properties:
            c:
                type: c
    c:
        properties:
            d:
                type: integer

"""
        plan = self.parse_1_2(yaml)
        with self.assertRaisesRegex(DSLParsingException, r'b\.c\.d') as cm:
            prepare_deployment_plan(
                plan,
                inputs={'some_input': {
                    'b': {
                        'c': {
                            'd': 'should_be_int'
                        }
                    }
                }})
        self.assertEqual(ERROR_INPUT_VIOLATES_DATA_TYPE_SCHEMA,
                         cm.exception.err_code)
Exemple #3
0
    def test_get_property_from_get_input_missing_key(self):
        yaml = """
inputs:
    dict_input: {}

node_types:
    vm_type:
        properties:
            a: { type: string }
            b: { type: string }
node_templates:
    vm1:
        type: vm_type
        properties:
            a: {get_input: dict_input}
            b: {get_property: [SELF, a, key]}
"""
        try:
            prepare_deployment_plan(self.parse(yaml),
                                    inputs={'dict_input': {
                                        'other_key': 42
                                    }})
            self.fail()
        except KeyError as e:
            self.assertIn('vm1.properties.a.key', e.message)
Exemple #4
0
    def test_missing_input(self):
        yaml = """
inputs:
    port: {}
    name_i: {}
    name_j: {}
node_types:
    webserver_type:
        properties:
            port: {}
            name: {}
            name2: {}
node_templates:
    webserver:
        type: webserver_type
        properties:
            port: { get_input: port }
            name: { get_input: name_i }
            name2: { get_input: [name_j, attr1, 0] }
"""
        with self.assertRaises(MissingRequiredInputError) as cm:
            prepare_deployment_plan(self.parse(yaml), inputs={'port': '8080'})

        msg = str(cm.exception).split('-')[0]  # get first part of message
        self.assertIn('name_i', msg)
        self.assertIn('name_j', msg)
        self.assertNotIn('port', msg)

        with self.assertRaises(MissingRequiredInputError) as cm:
            prepare_deployment_plan(self.parse(yaml), inputs={})

        msg = str(cm.exception).split('-')[0]  # get first part of message
        self.assertIn('name_j', msg)
        self.assertIn('name_i', msg)
        self.assertIn('port', msg)
    def test_circular_get_property_from_outputs(self):
        yaml = """
node_types:
    vm_type:
        properties:
            b: { type: string }
            c: { type: string }
node_templates:
    vm:
        type: vm_type
        properties:
            b: { get_property: [SELF, c] }
            c: [ { get_property: [SELF, b ] }, 2 ]
outputs:
    o:
        value:
            a: 1
            b: { get_property: [vm, b] }
"""
        try:
            prepare_deployment_plan(self.parse(yaml))
            self.fail()
        except RuntimeError, e:
            self.assertIn('Circular get_property function call detected',
                          str(e))
    def test_node_template_properties_with_invalid_node_property_cycle(self):
        yaml = """
node_types:
    type:
        properties:
            property1: {}
            property2: {}
node_templates:
    node1:
        type: type
        properties:
            property1: { concat:
                [one, { get_property: [node2, property1] }, three]
            }
            property2: value1
    node2:
        type: type
        properties:
            property1: { concat:
                [one, { get_property: [node1, property1] }, three]
            }
            property2: value2
"""
        with ExpectedException(RuntimeError, '.*Circular.*'):
            prepare_deployment_plan(self.parse_1_1(yaml))
Exemple #7
0
    def test_input_value_data_type_validation_successful(self):
        yaml = self.BASIC_VERSION_SECTION_DSL_1_2 + """
inputs:
    some_input:
        type: a
data_types:
    a:
        properties:
            b:
                type: b
    b:
        properties:
            c:
                type: c
    c:
        properties:
            d:
                type: integer

"""
        prepare_deployment_plan(
            self.parse_1_2(yaml),
            inputs={'some_input': {
                'b': {
                    'c': {
                        'd': 123
                    }
                }
            }})
Exemple #8
0
    def test_node_template_properties_with_invalid_node_property_cycle(self):
        yaml = """
node_types:
    type:
        properties:
            property1: {}
            property2: {}
node_templates:
    node1:
        type: type
        properties:
            property1: { concat:
                [one, { get_property: [node2, property1] }, three]
            }
            property2: value1
    node2:
        type: type
        properties:
            property1: { concat:
                [one, { get_property: [node1, property1] }, three]
            }
            property2: value2
"""
        with ExpectedException(RuntimeError, '.*Circular.*'):
            prepare_deployment_plan(self.parse_1_1(yaml))
    def test_func_integrations(self):
        yaml = """
inputs:
    some_input:
        default: some_node
    some_input2:
        default: some_input
node_types:
    some_type:
        properties:
            prop1: {}
            concat_prop: {}
node_templates:
    some_node:
        type: some_type
        properties:
            prop1: 4
            concat_prop:
                concat:
                    - get_property:
                        - get_input:
                            get_input: some_input2
                        - prop1
                    - 2
"""
        parsed = prepare_deployment_plan(self.parse_1_1(yaml))
        some_node = self.get_node_by_name(parsed, 'some_node')
        self.assertEqual('42', some_node['properties']['concat_prop'])

        yaml = """
inputs:
    dummy_input:
        default: some_node
    some_nodesome_node:
        default: some_nodesome_node
node_types:
    some_type:
        properties:
            prop: {}
            dummy_prop: {}
node_templates:
    some_node:
        type: some_type
        properties:
            dummy_prop: dummy_value
            prop:
                get_attribute:
                    - get_input: dummy_input
                    - concat:
                        - get_attribute: [ some_node, dummy_prop ]
                    - get_input:
                        concat:
                            - get_input: dummy_input
                            - get_input: dummy_input
            """
        prepare_deployment_plan(self.parse_1_1(yaml))
    def test_get_secret_list_secret_does_not_exist(self):
        yaml = """
outputs:
  secret:
    value: { get_secret: [missing_secret, test] }
"""
        parsed = self.parse_1_3(yaml)
        get_secret_not_found = Mock(side_effect=NotFoundException)
        with self.assertRaisesRegex(exceptions.UnknownSecretError,
                                    "Required secret.*missing_secret.*"):
            prepare_deployment_plan(parsed, get_secret_not_found)
    def _test_validate_value_type_mismatch_with_deployment_plan(
            self, type_name, value):
        yaml = self.BASIC_VERSION_SECTION_DSL_1_2 + """
inputs:
    some_input:
        type: {0}
""".format(type_name)
        message_regex = (
            "Property type validation failed.*type is '{0}'".format(type_name))
        plan = self.parse(yaml)
        with self.assertRaisesRegex(DSLParsingException, message_regex):
            prepare_deployment_plan(plan, inputs={'some_input': value})
Exemple #12
0
    def _test_autocorrect_value_mismatch(self, type_name, input_value):
        yaml = self.BASIC_VERSION_SECTION_DSL_1_2 + """
inputs:
    some_input:
        type: {0}
""".format(type_name)
        message_regex = (
            "Property type validation failed.*type is '{0}'".format(type_name))
        plan = self.parse(yaml)
        self.assertEqual(plan[consts.INPUTS]['some_input'][consts.TYPE],
                         type_name)
        with self.assertRaisesRegex(DSLParsingException, message_regex):
            prepare_deployment_plan(plan, inputs={'some_input': input_value})
    def test_invalid_concat(self):
        yaml = """
node_types:
    type:
        properties:
            property: {}
node_templates:
    node:
        type: type
        properties:
            property: { concat: 1 }
"""
        with ExpectedException(ValueError, '.*Illegal.*concat.*'):
            prepare_deployment_plan(self.parse_1_1(yaml))
    def test_invalid_concat(self):
        yaml = """
node_types:
    type:
        properties:
            property: {}
node_templates:
    node:
        type: type
        properties:
            property: { concat: 1 }
"""
        with ExpectedException(ValueError, '.*Illegal.*concat.*'):
            prepare_deployment_plan(self.parse_1_1(yaml))
Exemple #15
0
    def test_get_property_doesnt_accept_runtime_func_as_args(self):
        yaml = """
node_types:
    some_type:
        properties:
            prop: {}
            dummy_prop: {}
node_templates:
    some_node:
        type: some_type
        properties:
            dummy_prop: dummy_value
            prop:
                get_property:
                    - get_attribute:
                            - some_node
                            - dummy_prop
                    - shouldn't matter
    """
        with self.assertRaisesRegexp(
                exceptions.FunctionValidationError,
                'Runtime function .+ cannot be nested within a non-runtime '
                'function \\(found in .+\\)'):
            prepare_deployment_plan(self.parse(yaml))

        yaml = """
node_types:
    some_type:
        properties:
            prop: {}
            dummy_prop: {}
node_templates:
    some_node:
        type: some_type
        properties:
            dummy_prop: dummy_value
            prop:
                get_property:
                    - concat:
                        - get_attribute:
                                - some_node
                                - dummy_prop
                    - shouldn't matter
    """
        with self.assertRaisesRegexp(
                exceptions.FunctionValidationError,
                'Runtime function .+ cannot be nested within a non-runtime '
                'function \\(found in .+\\)'):
            prepare_deployment_plan(self.parse_1_1(yaml))
    def test_recursive(self):
        yaml = """
inputs:
    i:
        default: 1
node_types:
    vm_type:
        properties:
            a: { type: string }
            b: { type: string }
            c: { type: string }
            x: { type: string }
            y: { type: string }
            z: { type: string }
node_templates:
    vm:
        type: vm_type
        properties:
            a: 0
            b: { get_property: [ SELF, a ] }
            c: { get_property: [ SELF, b ] }
            x: { get_property: [ SELF, z ] }
            y: { get_property: [ SELF, x ] }
            z: { get_input: i }
"""
        parsed = prepare_deployment_plan(self.parse(yaml))
        vm = self.get_node_by_name(parsed, 'vm')
        self.assertEqual(0, vm['properties']['b'])
        self.assertEqual(1, vm['properties']['x'])
        self.assertEqual(1, vm['properties']['y'])
        self.assertEqual(1, vm['properties']['z'])
    def test_recursive_get_property_in_outputs(self):
        yaml = """
node_types:
    vm_type:
        properties:
            a: { type: string }
            b: { type: string }
            c: { type: string }
node_templates:
    vm:
        type: vm_type
        properties:
            a: 1
            b: { get_property: [SELF, c] }
            c: [ { get_property: [SELF, a ] }, 2 ]
outputs:
    o:
        value:
            a: { get_property: [vm, b] }
            b: [0, { get_property: [vm, b] }]
"""
        parsed = prepare_deployment_plan(self.parse(yaml))
        outputs = parsed.outputs
        self.assertEqual(1, outputs['o']['value']['a'][0])
        self.assertEqual(2, outputs['o']['value']['a'][1])
        self.assertEqual(0, outputs['o']['value']['b'][0])
        self.assertEqual(1, outputs['o']['value']['b'][1][0])
        self.assertEqual(2, outputs['o']['value']['b'][1][1])
    def test_get_property_from_get_input_runtime(self):
        yaml = """
inputs:
    dict_input: {}

node_types:
    vm_type:
        properties:
            a: { type: string }
            b: { type: string }
node_templates:
    vm1:
        type: vm_type
        properties:
            a: {get_input: dict_input}
            b: {get_property: [SELF, a, key]}
"""
        inputs = {'dict_input': {'key': 'secret'}}
        plan = prepare_deployment_plan(
            self.parse(yaml),
            inputs=inputs,
            runtime_only_evaluation=True)
        # with runtime-only-evaluation, the property isn't evaluated at
        # prepare_deployment_plan time
        self.assertEqual(
            {'get_property': ['SELF', 'a', 'key']},
            plan['nodes'][0]['properties']['b'])

        evaluated = functions.evaluate_node_functions(
            plan['nodes'][0],
            self._mock_evaluation_storage(inputs=inputs)
        )
        self.assertEqual('secret', evaluated['properties']['b'])
    def test_get_property_another_node_runtime(self):
        yaml = """
node_types:
    vm_type:
        properties:
            a: { type: string }
            c: { type: string }
node_templates:
    vm1:
        type: vm_type
        properties:
            a: {get_property: [vm2, c]}
            c: secret1
    vm2:
        type: vm_type
        properties:
            a: xxx
            c: secret2
"""
        plan = prepare_deployment_plan(
            self.parse(yaml), runtime_only_evaluation=True)
        plan_node = next(n for n in plan['nodes'] if n['name'] == 'vm1')
        self.assertEqual(plan_node['properties']['a'],
                         {'get_property': ['vm2', 'c']})
        node = functions.evaluate_node_functions(
            plan_node, self._mock_evaluation_storage(nodes=plan['nodes']))
        self.assertEqual(node['properties']['a'], 'secret2')
    def test_node_template_capabilities(self):
        yaml = """
node_templates:
    node:
        type: type
        capabilities:
            scalable:
                properties:
                    default_instances: { get_property: [node, prop1] }
                    max_instances: { get_property: [SELF, prop1] }
                    min_instances: { get_input: my_input }
inputs:
    my_input:
        default: 20
node_types:
    type:
        properties:
            prop1:
                default: 10
"""
        parsed = prepare_deployment_plan(self.parse_1_3(yaml))
        node = self.get_node_by_name(parsed, 'node')
        self.assertEqual({
            'default_instances': 10,
            'min_instances': 20,
            'max_instances': 10,
            'current_instances': 10,
            'planned_instances': 10,
        }, node['capabilities']['scalable']['properties'])
Exemple #21
0
    def test_basic_namespace_multi_import(self):
        layer1_yaml = """
node_types:
    test_type:
        properties:
            key:
                default: value
node_templates:
    node:
        type: test_type
"""
        layer1_file_name = self.make_yaml_file(layer1_yaml)

        layer2_yaml = self.BASIC_VERSION_SECTION_DSL_1_3 + """
imports:
    -   {0}--{1}
""".format('middle_test', layer1_file_name)
        layer2_file_name = self.make_yaml_file(layer2_yaml)

        main_yaml = self.BASIC_VERSION_SECTION_DSL_1_3 + """
imports:
    -   {0}--{1}
""".format('test', layer2_file_name)
        main_yaml += """
outputs:
    port:
        description: the port
        value: { get_attribute: [test--middle_test--node, key] }
"""

        plan = prepare_deployment_plan(self.parse(main_yaml))
        self.assertEqual({'get_attribute': ['test--middle_test--node', 'key']},
                         plan[constants.OUTPUTS]['port']['value'])
Exemple #22
0
    def test_recursive_get_property_in_outputs(self):
        imported_yaml = """
node_types:
    vm_type:
        properties:
            a: { type: string }
            b: { type: string }
            c: { type: string }
node_templates:
    vm:
        type: vm_type
        properties:
            a: 1
            b: { get_property: [SELF, c] }
            c: [ { get_property: [SELF, a ] }, 2 ]
outputs:
    o:
        value:
            a: { get_property: [vm, b] }
            b: [0, { get_property: [vm, b] }]
"""
        import_file_name = self.make_yaml_file(imported_yaml)

        main_yaml = self.BASIC_VERSION_SECTION_DSL_1_3 + """
imports:
    -   {0}--{1}
""".format('test', import_file_name)

        plan = prepare_deployment_plan(self.parse(main_yaml))
        output_value = plan.outputs['test--o']['value']
        self.assertEqual(1, output_value['a'][0])
        self.assertEqual(2, output_value['a'][1])
        self.assertEqual(0, output_value['b'][0])
        self.assertEqual(1, output_value['b'][1][0])
        self.assertEqual(2, output_value['b'][1][1])
Exemple #23
0
    def test_inputs_provided_to_plan(self):
        yaml = """
inputs:
    port:
        default: 9000
    port2:
        default: [{'a': [9000]}]
node_types:
    webserver_type:
        properties:
            port: {}
            port2: {}
node_templates:
    webserver:
        type: webserver_type
        properties:
            port: { get_input: port }
            port2: { get_input: [port2, 0, 'a', 0] }
"""
        parsed = prepare_deployment_plan(self.parse(yaml),
                                         inputs={
                                             'port': 8000,
                                             'port2': [{
                                                 'a': [8000]
                                             }]
                                         })
        self.assertEqual(8000, parsed['nodes'][0]['properties']['port'])
        self.assertEqual(8000, parsed['nodes'][0]['properties']['port2'])
    def test_outputs(self):
        yaml = """
node_types:
    type:
        properties:
            property: {}
node_templates:
    node:
        type: type
        properties:
            property: value
outputs:
    output1:
        value: { concat: [one,
                          {get_property: [node, property]},
                          three] }
    output2:
        value:
            - item1
            - { concat: [one,
                         {get_property: [node, property]},
                         three] }
    output3:
        value: { concat: [one,
                          {get_property: [node, property]},
                          {get_attribute: [node, attribute]}] }
"""
        parsed = prepare_deployment_plan(self.parse_1_1(yaml))
        outputs = parsed['outputs']
        self.assertEqual('onevaluethree', outputs['output1']['value'])
        self.assertEqual('onevaluethree', outputs['output2']['value'][1])
        self.assertEqual({'concat':
                         ['one', 'value', {'get_attribute': ['node',
                                                             'attribute']}]},
                         outputs['output3']['value'])
    def test_get_property_from_get_secret_runtime(self):
        yaml = """

node_types:
    vm_type:
        properties:
            secret1_value: { type: string }
            b: { type: string }
node_templates:
    vm1:
        type: vm_type
        properties:
            secret1_value: secret
            b: {get_property: [SELF, {get_secret: secret1} ]}
"""
        storage = self._mock_evaluation_storage()
        plan = prepare_deployment_plan(
            self.parse(yaml),
            get_secret_method=storage.get_secret,
            runtime_only_evaluation=True)
        self.assertEqual(
            {'get_property': ['SELF', {'get_secret': 'secret1'}]},
            plan['nodes'][0]['properties']['b'])

        evaluated = functions.evaluate_node_functions(
            plan['nodes'][0],
            storage
        )
        self.assertEqual('secret', evaluated['properties']['b'])
Exemple #26
0
    def test_outputs_valid_output(self):
        yaml = """
node_templates: {}
outputs:
    port0:
        description: p0
        value: 1234
    port1:
        description: p1
        value: some_port
    port2:
        description: p2
        value: {}
    port3:
        description: p3
        value: []
    port4:
        value: false
"""
        parsed = self.parse(yaml)
        outputs = parsed['outputs']
        self.assertEqual(5, len(parsed['outputs']))
        self.assertEqual('p0', outputs['port0']['description'])
        self.assertEqual(1234, outputs['port0']['value'])
        self.assertEqual('p1', outputs['port1']['description'])
        self.assertEqual('some_port', outputs['port1']['value'])
        self.assertEqual('p2', outputs['port2']['description'])
        self.assertEqual({}, outputs['port2']['value'])
        self.assertEqual('p3', outputs['port3']['description'])
        self.assertEqual([], outputs['port3']['value'])
        self.assertNotIn('description', outputs['port4'])
        self.assertFalse(outputs['port4']['value'])
        prepared = prepare_deployment_plan(parsed)
        self.assertEqual(parsed['outputs'], prepared['outputs'])
    def test_policies_properties(self):
        yaml = """
node_templates:
    node:
        type: type
inputs:
    my_input:
        default: 20
node_types:
    type:
        properties:
            prop1:
                default: 10
groups:
    group:
        members: [node]
policies:
    policy:
        type: cloudify.policies.scaling
        targets: [group]
        properties:
            default_instances: { get_property: [node, prop1] }
            min_instances: { get_input: my_input }
"""
        parsed = prepare_deployment_plan(self.parse_1_3(yaml))
        expected = {
            'default_instances': 10,
            'min_instances': 20,
            'max_instances': -1,
            'current_instances': 10,
            'planned_instances': 10,
        }
        self.assertEqual(expected,
                         parsed['scaling_groups']['group']['properties'])
        self.assertEqual(expected, parsed['policies']['policy']['properties'])
    def test_node_template_properties(self):
        yaml = """
node_types:
    vm_type:
        properties:
            ip: {}
            ip_duplicate: {}
    server_type:
        properties:
            endpoint: {}
node_templates:
    vm:
        type: vm_type
        properties:
            ip: 10.0.0.1
            ip_duplicate: { get_property: [ SELF, ip ] }
    server:
        type: server_type
        properties:
            endpoint: { get_property: [ vm, ip ] }
"""
        parsed = prepare_deployment_plan(self.parse(yaml))
        vm = self.get_node_by_name(parsed, 'vm')
        self.assertEqual('10.0.0.1', vm['properties']['ip_duplicate'])
        server = self.get_node_by_name(parsed, 'server')
        self.assertEqual('10.0.0.1', server['properties']['endpoint'])
    def test_relationship_operation_inputs(self):
        yaml = """
plugins:
    p:
        executor: central_deployment_agent
        install: false
node_types:
    type:
        properties:
            property: {}
relationships:
    cloudify.relationships.contained_in: {}
node_templates:
    node:
        type: type
        properties:
            property: value
        relationships:
            -   type: cloudify.relationships.contained_in
                target: node2
                source_interfaces:
                    interface:
                        op:
                            implementation: p.task
                            inputs:
                                input1: { concat: [one,
                                    { get_property: [SOURCE, property] },
                                    three] }
                                input2:
                                    key1: value1
                                    key2: { concat: [one,
                                        { get_property: [SOURCE, property] },
                                        three] }
                                    key3:
                                        - item1
                                        - { concat: [one,
                                            {get_property: [TARGET, property]},
                                            three] }
                                input3: { concat: [one,
                                    {get_property: [SOURCE, property] },
                                    {get_attribute: [SOURCE, attribute] }]}
    node2:
        type: type
        properties:
            property: value2
"""
        parsed = prepare_deployment_plan(self.parse_1_1(yaml))
        inputs = self.get_node_by_name(parsed, 'node')['relationships'][0][
            'source_operations']['interface.op']['inputs']
        self.assertEqual('onevaluethree', inputs['input1'])
        self.assertEqual('onevaluethree', inputs['input2']['key2'])
        self.assertEqual('onevalue2three', inputs['input2']['key3'][1])
        self.assertEqual(
            {
                'concat': [
                    'one',
                    'value',
                    {'get_attribute': ['SOURCE', 'attribute']}]
            },
            inputs['input3'])
    def test_get_property_from_get_input_data_type(self):
        yaml = """
inputs:
    dict_input:
        type: nested
        default:
            key: secret

data_types:
    nested:
        properties:
            key: {}

node_types:
    vm_type:
        properties:
            a: { type: string }
            b: { type: string }
node_templates:
    vm1:
        type: vm_type
        properties:
            a: {get_input: dict_input}
            b: {get_property: [SELF, a, key]}
"""
        plan = prepare_deployment_plan(self.parse_1_2(yaml))
        self.assertEqual('secret', plan['nodes'][0]['properties']['b'])
    def test_func_integrations_1_0(self):
        yaml = """
inputs:
    some_input:
        default: some_node
node_types:
    some_type:
        properties:
            prop1: {}
            prop2: {}
node_templates:
    some_node:
        type: some_type
        properties:
            prop1: 4
            prop2:
                get_attribute:
                    - get_property:
                        - get_input:
                            some_input
                        - prop1
                    - 2
"""
        parsed = prepare_deployment_plan(self.parse(yaml))
        some_node = self.get_node_by_name(parsed, 'some_node')
        self.assertDictEqual(
            {'get_attribute': [4, 2]},
            some_node['properties']['prop2'])
    def test_func_integrations_within_list(self):
        yaml = """
inputs:
    some_input:
        default: some_node
node_types:
    some_type:
        properties:
            prop1: {}
            concat_prop: {}
node_templates:
    some_node:
        type: some_type
        properties:
            prop1: 4
            concat_prop:
                - concat:
                    - get_property:
                        - get_input:
                            some_input
                        - prop1
                    - 2
"""

        parsed = prepare_deployment_plan(self.parse_1_1(yaml))
        some_node = self.get_node_by_name(parsed, 'some_node')
        self.assertEqual(['42'], some_node['properties']['concat_prop'])
    def test_recursive_get_property_in_outputs(self):
        yaml = """
node_types:
    vm_type:
        properties:
            a: { type: string }
            b: { type: string }
            c: { type: string }
node_templates:
    vm:
        type: vm_type
        properties:
            a: 1
            b: { get_property: [SELF, c] }
            c: [ { get_property: [SELF, a ] }, 2 ]
outputs:
    o:
        value:
            a: { get_property: [vm, b] }
            b: [0, { get_property: [vm, b] }]
"""
        parsed = prepare_deployment_plan(self.parse(yaml))
        outputs = parsed.outputs
        self.assertEqual(1, outputs['o']['value']['a'][0])
        self.assertEqual(2, outputs['o']['value']['a'][1])
        self.assertEqual(0, outputs['o']['value']['b'][0])
        self.assertEqual(1, outputs['o']['value']['b'][1][0])
        self.assertEqual(2, outputs['o']['value']['b'][1][1])
    def test_node_template_interfaces(self):
        yaml = """
plugins:
    plugin:
        executor: central_deployment_agent
        install: false
node_types:
    vm_type:
        properties:
            ip:
                type: string
node_templates:
    vm:
        type: vm_type
        properties:
            ip: 10.0.0.1
        interfaces:
            interface:
                op:
                    implementation: plugin.op
                    inputs:
                        x: { get_property: [vm, ip] }
"""
        parsed = prepare_deployment_plan(self.parse(yaml))
        vm = self.get_node_by_name(parsed, 'vm')
        self.assertEqual('10.0.0.1', vm['operations']['op']['inputs']['x'])
        self.assertEqual('10.0.0.1',
                         vm['operations']['interface.op']['inputs']['x'])
    def test_get_property_from_get_input_data_type(self):
        yaml = """
inputs:
    dict_input:
        type: nested
        default:
            key: secret

data_types:
    nested:
        properties:
            key: {}

node_types:
    vm_type:
        properties:
            a: { type: string }
            b: { type: string }
node_templates:
    vm1:
        type: vm_type
        properties:
            a: {get_input: dict_input}
            b: {get_property: [SELF, a, key]}
"""
        plan = prepare_deployment_plan(self.parse_1_2(yaml))
        self.assertEqual('secret', plan['nodes'][0]['properties']['b'])
Exemple #36
0
    def test_outputs_valid_output(self):
        yaml = """
node_templates: {}
outputs:
    port0:
        description: p0
        value: 1234
    port1:
        description: p1
        value: some_port
    port2:
        description: p2
        value: {}
    port3:
        description: p3
        value: []
    port4:
        description: p4
        value: false
"""
        parsed = self.parse(yaml)
        outputs = parsed['outputs']
        self.assertEqual(5, len(parsed['outputs']))
        self.assertEqual('p0', outputs['port0']['description'])
        self.assertEqual(1234, outputs['port0']['value'])
        self.assertEqual('p1', outputs['port1']['description'])
        self.assertEqual('some_port', outputs['port1']['value'])
        self.assertEqual('p2', outputs['port2']['description'])
        self.assertEqual({}, outputs['port2']['value'])
        self.assertEqual('p3', outputs['port3']['description'])
        self.assertEqual([], outputs['port3']['value'])
        self.assertEqual('p4', outputs['port4']['description'])
        self.assertFalse(outputs['port4']['value'])
        prepared = prepare_deployment_plan(parsed)
        self.assertEqual(parsed['outputs'], prepared['outputs'])
    def test_node_template_capabilities(self):
        yaml = """
node_templates:
    node:
        type: type
        capabilities:
            scalable:
                properties:
                    default_instances: { get_property: [node, prop1] }
                    max_instances: { get_property: [SELF, prop1] }
                    min_instances: { get_input: my_input }
inputs:
    my_input:
        default: 20
node_types:
    type:
        properties:
            prop1:
                default: 10
"""
        parsed = prepare_deployment_plan(self.parse_1_3(yaml))
        node = self.get_node_by_name(parsed, 'node')
        self.assertEqual({
            'default_instances': 10,
            'min_instances': 20,
            'max_instances': 10,
            'current_instances': 10,
            'planned_instances': 10,
        }, node['capabilities']['scalable']['properties'])
Exemple #38
0
    def test_get_property_from_namespaced_node(self):
        imported_yaml = """
node_types:
    test_type:
        properties:
            key:
                default: value
node_templates:
    node:
        type: test_type
"""
        import_file_name = self.make_yaml_file(imported_yaml)

        main_yaml = self.BASIC_VERSION_SECTION_DSL_1_3 + """
imports:
    -   {0}--{1}
""".format('test', import_file_name)
        main_yaml += """
outputs:
    port:
        description: the port
        value: { get_property: [test--node, key] }
"""

        plan = prepare_deployment_plan(self.parse(main_yaml))
        self.assertEqual('value', plan[constants.OUTPUTS]['port']['value'])
    def test_policies_properties(self):
        yaml = """
node_templates:
    node:
        type: type
inputs:
    my_input:
        default: 20
node_types:
    type:
        properties:
            prop1:
                default: 10
groups:
    group:
        members: [node]
policies:
    policy:
        type: cloudify.policies.scaling
        targets: [group]
        properties:
            default_instances: { get_property: [node, prop1] }
            min_instances: { get_input: my_input }
"""
        parsed = prepare_deployment_plan(self.parse_1_3(yaml))
        expected = {
            'default_instances': 10,
            'min_instances': 20,
            'max_instances': -1,
            'current_instances': 10,
            'planned_instances': 10,
        }
        self.assertEqual(expected,
                         parsed['scaling_groups']['group']['properties'])
        self.assertEqual(expected, parsed['policies']['policy']['properties'])
    def test_node_template_interfaces(self):
        yaml = """
plugins:
    plugin:
        executor: central_deployment_agent
        install: false
node_types:
    vm_type:
        properties:
            ip:
                type: string
node_templates:
    vm:
        type: vm_type
        properties:
            ip: 10.0.0.1
        interfaces:
            interface:
                op:
                    implementation: plugin.op
                    inputs:
                        x: { get_property: [vm, ip] }
"""
        parsed = prepare_deployment_plan(self.parse(yaml))
        vm = self.get_node_by_name(parsed, 'vm')
        self.assertEqual('10.0.0.1', vm['operations']['op']['inputs']['x'])
        self.assertEqual('10.0.0.1',
                         vm['operations']['interface.op']['inputs']['x'])
    def test_node_template_properties(self):
        yaml = """
node_types:
    vm_type:
        properties:
            ip: {}
            ip_duplicate: {}
    server_type:
        properties:
            endpoint: {}
node_templates:
    vm:
        type: vm_type
        properties:
            ip: 10.0.0.1
            ip_duplicate: { get_property: [ SELF, ip ] }
    server:
        type: server_type
        properties:
            endpoint: { get_property: [ vm, ip ] }
"""
        parsed = prepare_deployment_plan(self.parse(yaml))
        vm = self.get_node_by_name(parsed, 'vm')
        self.assertEqual('10.0.0.1', vm['properties']['ip_duplicate'])
        server = self.get_node_by_name(parsed, 'server')
        self.assertEqual('10.0.0.1', server['properties']['endpoint'])
    def test_recursive(self):
        yaml = """
inputs:
    i:
        default: 1
node_types:
    vm_type:
        properties:
            a: { type: string }
            b: { type: string }
            c: { type: string }
            x: { type: string }
            y: { type: string }
            z: { type: string }
node_templates:
    vm:
        type: vm_type
        properties:
            a: 0
            b: { get_property: [ SELF, a ] }
            c: { get_property: [ SELF, b ] }
            x: { get_property: [ SELF, z ] }
            y: { get_property: [ SELF, x ] }
            z: { get_input: i }
"""
        parsed = prepare_deployment_plan(self.parse(yaml))
        vm = self.get_node_by_name(parsed, 'vm')
        self.assertEqual(0, vm['properties']['b'])
        self.assertEqual(1, vm['properties']['x'])
        self.assertEqual(1, vm['properties']['y'])
        self.assertEqual(1, vm['properties']['z'])
    def test_node_template_properties_simple(self):
        yaml = """
node_types:
    type:
        properties:
            property: {}
node_templates:
    node:
        type: type
        properties:
            property: { get_secret: secret }
"""
        parsed = prepare_deployment_plan(self.parse_1_3(yaml),
                                         self._get_secret_mock)
        node = self.get_node_by_name(parsed, 'node')
        self.assertEqual({'get_secret': 'secret'},
                         node['properties']['property'])

        functions.evaluate_functions(
            parsed,
            {},
            None,
            None,
            None,
            self._get_secret_mock
        )
        self.assertEqual(node['properties']['property'], 'secret_value')
    def test_invalid_version(self):
        yaml = """
node_types:
    type:
        properties:
            property: {}
node_templates:
    node:
        type: type
        properties:
            property: { concat: [1, 2] }
"""
        with ExpectedException(exceptions.FunctionEvaluationError,
                               '.*version 1_1 or greater.*'):
            prepare_deployment_plan(self.parse(
                yaml,
                dsl_version=self.BASIC_VERSION_SECTION_DSL_1_0))
 def create_deployment(self, blueprint_id, deployment_id, inputs=None):
     blueprint = self.get_blueprint(blueprint_id)
     plan = blueprint.plan
     try:
         deployment_plan = tasks.prepare_deployment_plan(plan, inputs)
     except parser_exceptions.MissingRequiredInputError, e:
         raise manager_exceptions.MissingRequiredDeploymentInputError(
             str(e))
    def test_circular_self_get_property(self):
        yaml = """
node_types:
    vm_type:
        properties:
            a: { type: string }
node_templates:
    vm:
        type: vm_type
        properties:
            a: [ { get_property: [SELF, a ] } ]
"""
        try:
            prepare_deployment_plan(self.parse(yaml))
            self.fail()
        except RuntimeError, e:
            self.assertIn('Circular get_property function call detected',
                          str(e))
    def test_relationship_operation_inputs(self):
        yaml = """
plugins:
    p:
        executor: central_deployment_agent
        install: false
node_types:
    type:
        properties:
            property: {}
relationships:
    cloudify.relationships.contained_in: {}
node_templates:
    node:
        type: type
        properties:
            property: value
        relationships:
            -   type: cloudify.relationships.contained_in
                target: node2
                source_interfaces:
                    interface:
                        op:
                            implementation: p.task
                            inputs:
                                input1: { concat: [one,
                                    { get_property: [SOURCE, property] },
                                    three] }
                                input2:
                                    key1: value1
                                    key2: { concat: [one,
                                        { get_property: [SOURCE, property] },
                                        three] }
                                    key3:
                                        - item1
                                        - { concat: [one,
                                            {get_property: [TARGET, property]},
                                            three] }
                                input3: { concat: [one,
                                    {get_property: [SOURCE, property] },
                                    {get_attribute: [SOURCE, attribute] }]}
    node2:
        type: type
        properties:
            property: value2
"""
        parsed = prepare_deployment_plan(self.parse_1_1(yaml))
        inputs = self.get_node_by_name(parsed, 'node')['relationships'][0][
            'source_operations']['interface.op']['inputs']
        self.assertEqual('onevaluethree', inputs['input1'])
        self.assertEqual('onevaluethree', inputs['input2']['key2'])
        self.assertEqual('onevalue2three', inputs['input2']['key3'][1])
        self.assertEqual({'concat':
                         ['one', 'value', {'get_attribute': ['SOURCE',
                                                             'attribute']}]},
                         inputs['input3'])
    def test_nested_property_path(self):
        yaml = """
node_types:
    vm_type:
        properties:
            endpoint: {}
            a: { type: integer }
            b: {}
            c: {}
    server_type:
        properties:
            port: { type: integer }
node_templates:
    vm:
        type: vm_type
        properties:
            endpoint:
                url:
                    protocol: http
                port: 80
                names: [site1, site2, site3]
                pairs:
                    - key: key1
                      value: value1
                    - key: key2
                      value: value2
            a: { get_property: [ SELF, endpoint, port ] }
            b: { get_property: [ SELF, endpoint, names, 0 ] }
            c: { get_property: [ SELF, endpoint, pairs, 1 , key] }
    server:
        type: server_type
        properties:
            port: { get_property: [ vm, endpoint, port ] }
outputs:
    a:
        value: { get_property: [ vm, endpoint, port ] }
    b:
        value: { get_property: [ vm, endpoint, url, protocol ] }
    c:
        value: { get_property: [ vm, endpoint, names, 1 ] }
    d:
        value: { get_property: [ vm, endpoint, pairs, 1, value] }

"""
        parsed = prepare_deployment_plan(self.parse(yaml))
        vm = self.get_node_by_name(parsed, 'vm')
        self.assertEqual(80, vm['properties']['a'])
        self.assertEqual('site1', vm['properties']['b'])
        self.assertEqual('key2', vm['properties']['c'])
        server = self.get_node_by_name(parsed, 'server')
        self.assertEqual(80, server['properties']['port'])
        outputs = parsed.outputs
        self.assertEqual(80, outputs['a']['value'])
        self.assertEqual('http', outputs['b']['value'])
        self.assertEqual('site2', outputs['c']['value'])
        self.assertEqual('value2', outputs['d']['value'])
    def test_invalid_nested_property2(self):
        yaml = """
node_types:
    vm_type:
        properties:
            a: {}
            b: {}
node_templates:
    vm:
        type: vm_type
        properties:
            a: [1,2,3]
            b: { get_property: [SELF, a, b] }
"""
        try:
            prepare_deployment_plan(self.parse(yaml))
            self.fail()
        except TypeError, e:
            self.assertIn('is expected b to be an int but it is a str', str(e))
    def test_circular_get_property_with_nesting(self):
        yaml = """
node_types:
    vm_type:
        properties:
            b: { type: string }
            c: { type: string }
node_templates:
    vm:
        type: vm_type
        properties:
            b: { get_property: [SELF, c] }
            c: [ { get_property: [SELF, b ] }, 2 ]
"""
        try:
            prepare_deployment_plan(self.parse(yaml))
            self.fail()
        except RuntimeError as e:
            self.assertIn('Circular get_property function call detected',
                          str(e))
    def test_invalid_nested_property1(self):
        yaml = """
node_types:
    vm_type:
        properties:
            a: { type: string }
node_templates:
    vm:
        type: vm_type
        properties:
            a:
                a0: { get_property: [ SELF, a, notfound ] }
"""
        try:
            prepare_deployment_plan(self.parse(yaml))
            self.fail()
        except KeyError, e:
            self.assertIn(
                "Node template property 'vm.properties.a.notfound' "
                "referenced from 'vm.properties.a.a0' doesn't exist.", str(e))
    def test_invalid_nested_property3(self):
        yaml = """
node_types:
    vm_type:
        properties:
            a: {}
            b: {}
node_templates:
    vm:
        type: vm_type
        properties:
            a: [1,2,3]
            b: { get_property: [SELF, a, 10] }
"""
        try:
            prepare_deployment_plan(self.parse(yaml))
            self.fail()
        except IndexError, e:
            self.assertIn('index is out of range. Got 10 but list size is 3',
                          str(e))
def _parse_plan(blueprint_path, inputs, ignored_modules):
    if dsl_parser is None:
        raise ImportError('cloudify-dsl-parser must be installed to '
                          'execute local workflows. '
                          '(e.g. "pip install cloudify-dsl-parser")')
    plan = dsl_tasks.prepare_deployment_plan(
        dsl_parser.parse_from_path(blueprint_path), inputs=inputs)
    nodes = [Node(node) for node in plan['nodes']]
    node_instances = [NodeInstance(instance)
                      for instance in plan['node_instances']]
    _prepare_nodes_and_instances(nodes, node_instances, ignored_modules)
    return plan, nodes, node_instances
    def test_circular_nested_property_path(self):
        yaml = """
node_types:
    vm_type:
        properties:
            a: { type: string }
            b: { type: string }
node_templates:
    vm:
        type: vm_type
        properties:
            a:
                a0: { get_property: [ SELF, b, b0 ] }
            b:
                b0: { get_property: [ SELF, a, a0 ] }
"""
        try:
            prepare_deployment_plan(self.parse(yaml))
            self.fail()
        except RuntimeError as e:
            self.assertIn('Circular get_property function call detected:',
                          str(e))
    def test_not_circular_nested_property_path(self):
        yaml = """
node_types:
    vm_type:
        properties:
            a: { type: string }
            b: { type: string }
node_templates:
    vm1:
        type: vm_type
        properties:
            a: { get_property: [ vm2, a ] }
            b: bla1
    vm2:
        type: vm_type
        properties:
            a:
                b3:
                    b4: { get_property: [ vm1, b ] }
            b: bla2
"""
        prepare_deployment_plan(self.parse(yaml))
    def test_get_property_from_get_input_missing_key(self):
        yaml = """
inputs:
    dict_input: {}

node_types:
    vm_type:
        properties:
            a: { type: string }
            b: { type: string }
node_templates:
    vm1:
        type: vm_type
        properties:
            a: {get_input: dict_input}
            b: {get_property: [SELF, a, key]}
"""
        try:
            prepare_deployment_plan(
                self.parse(yaml), inputs={'dict_input': {'other_key': 42}})
            self.fail()
        except KeyError as e:
            self.assertIn('vm1.properties.a.key', e.message)
    def stage_deployment_update(self,
                                deployment_id,
                                app_dir,
                                app_blueprint,
                                additional_inputs):
        """Stage a deployment update

        :param app_blueprint:
        :param app_dir:
        :param deployment_id: the deployment id for the update
        :return:
        """

        # enables reverting to original blueprint resources
        deployment = self.sm.get_deployment(deployment_id)
        blueprint_id = deployment.blueprint_id

        # enables reverting to original blueprint resources
        file_server_base_url = \
            '{0}/'.format(config.instance().file_server_base_uri)

        blueprint_resource_dir = os.path.join(file_server_base_url,
                                              'blueprints',
                                              blueprint_id)

        app_path = os.path.join(file_server_base_url, app_dir, app_blueprint)

        # parsing the blueprint from here
        try:
            plan = tasks.parse_dsl(
                app_path,
                resources_base_url=file_server_base_url,
                additional_resources=[blueprint_resource_dir],
                **app_context.get_parser_context())

        except parser_exceptions.DSLParsingException as ex:
            raise manager_exceptions.InvalidBlueprintError(
                'Invalid blueprint - {0}'.format(ex))

        # Updating the new inputs with the deployment inputs
        # (overriding old values and adding new ones)
        inputs = copy.deepcopy(deployment.inputs)
        inputs.update(additional_inputs)

        # applying intrinsic functions
        try:
            prepared_plan = tasks.prepare_deployment_plan(plan, inputs=inputs)
        except parser_exceptions.MissingRequiredInputError, e:
            raise manager_exceptions.MissingRequiredDeploymentInputError(
                str(e))
    def test_node_template_properties_simple(self):
        yaml = """
node_types:
    type:
        properties:
            property: {}
node_templates:
    node:
        type: type
        properties:
            property: { concat: [one, two, three] }
"""
        parsed = prepare_deployment_plan(self.parse_1_1(yaml))
        node = self.get_node_by_name(parsed, 'node')
        self.assertEqual('onetwothree', node['properties']['property'])
    def stage_deployment_update(self,
                                deployment_id,
                                app_dir,
                                app_blueprint,
                                additional_inputs,
                                new_blueprint_id=None,
                                preview=False):
        # enables reverting to original blueprint resources
        deployment = self.sm.get(models.Deployment, deployment_id)
        old_blueprint = deployment.blueprint
        file_server_root = config.instance.file_server_root
        blueprint_resource_dir = os.path.join(file_server_root,
                                              'blueprints',
                                              old_blueprint.tenant_name,
                                              old_blueprint.id)
        # The dsl parser expects a URL
        blueprint_resource_dir_url = 'file:{0}'.format(blueprint_resource_dir)
        app_path = os.path.join(file_server_root, app_dir, app_blueprint)

        # parsing the blueprint from here
        try:
            plan = tasks.parse_dsl(
                app_path,
                resources_base_path=file_server_root,
                additional_resources=[blueprint_resource_dir_url],
                **app_context.get_parser_context()
            )
        except parser_exceptions.DSLParsingException as ex:
            raise manager_exceptions.InvalidBlueprintError(
                'Invalid blueprint - {0}'.format(ex))

        # Updating the new inputs with the deployment inputs
        # (overriding old values and adding new ones)
        old_inputs = copy.deepcopy(deployment.inputs)
        new_inputs = {k: old_inputs[k]
                      for k in plan.inputs.keys() if k in old_inputs}
        new_inputs.update(additional_inputs)

        # applying intrinsic functions
        try:
            prepared_plan = tasks.prepare_deployment_plan(plan,
                                                          get_secret_method(),
                                                          inputs=new_inputs)
        except parser_exceptions.MissingRequiredInputError, e:
            raise manager_exceptions.MissingRequiredDeploymentInputError(
                str(e))
def _parse_plan(blueprint_path, inputs, ignored_modules, resolver,
                validate_version):
    if dsl_parser is None:
        raise ImportError('cloudify-dsl-parser must be installed to '
                          'execute local workflows. '
                          '(e.g. "pip install cloudify-dsl-parser") [{0}]'
                          .format(_import_error))
    plan = dsl_tasks.prepare_deployment_plan(
        dsl_parser.parse_from_path(
            dsl_file_path=blueprint_path,
            resolver=resolver,
            validate_version=validate_version),
        inputs=inputs)
    nodes = [Node(node) for node in plan['nodes']]
    node_instances = [NodeInstance(instance)
                      for instance in plan['node_instances']]
    _prepare_nodes_and_instances(nodes, node_instances, ignored_modules)
    return plan, nodes, node_instances