diff --git a/translator/hot/syntax/hot_resource.py b/translator/hot/syntax/hot_resource.py index 103354e1..80920234 100644 --- a/translator/hot/syntax/hot_resource.py +++ b/translator/hot/syntax/hot_resource.py @@ -183,7 +183,7 @@ class HotResource(object): return {} else: # the interface is a dict {'implemenation': xxx, 'input': yyy} - inputs = interface.value.get('input') + inputs = interface.value.get('inputs') deploy_inputs = {} if inputs: for name, value in six.iteritems(inputs): diff --git a/translator/tests/data/tosca_elk.yaml b/translator/tests/data/tosca_elk.yaml new file mode 100644 index 00000000..7e3072bc --- /dev/null +++ b/translator/tests/data/tosca_elk.yaml @@ -0,0 +1,80 @@ +tosca_definitions_version: tosca_simple_yaml_1_0_0 + +description: > + TOSCA simple profile with nodejs and mongodb. + +imports: + - ../../toscalib/tests/data/custom_types/nodejs.yaml + +dsl_definitions: + ubuntu_node: &ubuntu_node + # compute properties (flavor) + disk_size: 10 + num_cpus: 1 + mem_size: 4096 + # host image properties + os_arch: x86_64 + os_type: Linux + os_distribution: Ubuntu + os_version: 14.04 + +inputs: + my_cpus: + type: integer + description: Number of CPUs for the server. + constraints: + - valid_values: [ 1, 2, 4, 8 ] + default: 1 + github_url: + type: string + description: The URL to download nodejs. + default: https://github.com/sample.git + +node_templates: + nodejs: + type: tosca.nodes.SoftwareComponent.Nodejs + properties: + github_url: https://github.com/sample.git + requirements: + - host: app_server + - database_endpoint: mongo_dbms + interfaces: + tosca.interfaces.node.lifecycle.Standard: + create: nodejs/create.sh + configure: + implementation: nodejs/config.sh + inputs: + github_url: { get_property: [ SELF, github_url ] } + mongodb_ip: { get_attribute: [mongo_server, ip_address] } + start: nodejs/start.sh + + mongo_dbms: + type: tosca.nodes.DBMS + requirements: + - host: mongo_server + properties: + dbms_port: 27017 + interfaces: + tosca.interfaces.node.lifecycle.Standard: + create: mongodb/create.sh + configure: + implementation: mongodb/config.sh + inputs: + mongodb_ip: { get_attribute: [mongo_server, ip_address] } + start: mongodb/start.sh + + mongo_server: + type: tosca.nodes.Compute + properties: *ubuntu_node + app_server: + type: tosca.nodes.Compute + properties: *ubuntu_node + +outputs: + nodejs_url: + description: URL for the nodejs server, http://:3000 + value: { get_attribute: [app_server, ip_address] } + mongodb_url: + description: URL for the mongodb server. + value: { get_attribute: [mongo_server, ip_address] } + diff --git a/translator/tests/test_elk.py b/translator/tests/test_elk.py new file mode 100755 index 00000000..099b0dd9 --- /dev/null +++ b/translator/tests/test_elk.py @@ -0,0 +1,196 @@ +# Licensed 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. + +import os +from translator.hot.tosca_translator import TOSCATranslator +from translator.tests.base import TestCase +from translator.toscalib.tosca_template import ToscaTemplate +import translator.toscalib.utils.yamlparser + + +class ToscaMongoNodejsTest(TestCase): + parsed_params = {'storage_snapshot_id': 'test_id', + 'storage_location': '/test', 'cpus': '1', + 'storage_size': '1'} + + '''TOSCA template with nodejs, app and mongodb on 2 servers.''' + tosca_tpl = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "data/tosca_elk.yaml") + tosca = ToscaTemplate(tosca_tpl) + + def test_relationship_def(self): + expected_relationship = ['tosca.relationships.ConnectsTo', + 'tosca.relationships.HostedOn'] + expected_capabilities_names = ['database_endpoint', 'host'] + for tpl in self.tosca.nodetemplates: + if tpl.name == 'nodejs': + def_keys = tpl.type_definition.relationship.keys() + self.assertEqual( + expected_relationship, + sorted([x.type for x in def_keys])) + self.assertEqual( + expected_capabilities_names, + sorted([x.capability_name for x in def_keys])) + + def test_relationships(self): + expected_relationship = ['tosca.relationships.ConnectsTo', + 'tosca.relationships.HostedOn'] + expected_relatednodes = ['app_server', 'mongo_dbms'] + for tpl in self.tosca.nodetemplates: + rels = tpl.relationships + if rels: + if tpl.name == 'nodejs': + self.assertEqual( + expected_relationship, + sorted([x.type for x in tpl.relationships.keys()])) + self.assertEqual( + expected_relatednodes, + sorted([y.name for y in tpl.relationships.values()])) + + def test_related_nodes(self): + expected_nodejs = ['app_server', 'mongo_dbms'] + actual_nodejs = [] + expected_mongo = ['mongo_server'] + actual_mongo = [] + for tpl in self.tosca.nodetemplates: + if tpl.name == 'nodejs': + for node in tpl.related_nodes: + actual_nodejs.append(node.name) + if tpl.name == 'mongo_dbms': + for node in tpl.related_nodes: + actual_mongo.append(node.name) + self.assertEqual(sorted(actual_nodejs), expected_nodejs) + self.assertEqual(actual_mongo, expected_mongo) + + def test_translate_nodejs_mongodb(self): + translate = TOSCATranslator(self.tosca, self.parsed_params) + output = translate.translate() + + expected_resource = {'mongo_dbms_create_config': + {'properties': + {'config': + {'get_file': 'mongodb/create.sh'}, + 'group': 'script'}, + 'type': 'OS::Heat::SoftwareConfig'}, + 'mongo_dbms_configure_config': + {'properties': + {'config': + {'get_file': 'mongodb/config.sh'}, + 'group': 'script'}, + 'type': 'OS::Heat::SoftwareConfig'}, + 'mongo_dbms_start_config': + {'properties': + {'config': + {'get_file': 'mongodb/start.sh'}, + 'group': 'script'}, + 'type': 'OS::Heat::SoftwareConfig'}, + 'nodejs_create_config': + {'properties': + {'config': + {'get_file': 'nodejs/create.sh'}, + 'group': 'script'}, + 'type': 'OS::Heat::SoftwareConfig'}, + 'nodejs_configure_config': + {'properties': + {'config': + {'get_file': 'nodejs/config.sh'}, + 'group': 'script'}, + 'type': 'OS::Heat::SoftwareConfig'}, + 'nodejs_start_config': + {'properties': + {'config': + {'get_file': 'nodejs/start.sh'}, + 'group': 'script'}, + 'type': 'OS::Heat::SoftwareConfig'}, + 'mongo_dbms_create_deploy': + {'properties': + {'config': + {'get_resource': 'mongo_dbms_create_config'}, + 'server': + {'get_resource': 'mongo_server'}}, + 'type': 'OS::Heat::SoftwareDeployment'}, + 'mongo_dbms_configure_deploy': + {'type': 'OS::Heat::SoftwareDeployment', + 'depends_on': + ['mongo_dbms_create_deploy'], + 'properties': + {'config': + {'get_resource': 'mongo_dbms_configure_config'}, + 'input_values': + {'mongodb_ip': + {'get_attr': + ['mongo_server', 'networks', 'private', 0]}}, + 'server': + {'get_resource': 'mongo_server'}}}, + 'mongo_dbms_start_deploy': + {'type': 'OS::Heat::SoftwareDeployment', + 'depends_on': ['mongo_dbms_configure_deploy'], + 'properties': + {'config': + {'get_resource': 'mongo_dbms_start_config'}, + 'server': + {'get_resource': 'mongo_server'}}}, + 'nodejs_create_deploy': + {'depends_on': + ['mongo_dbms_start_deploy'], + 'properties': + {'config': + {'get_resource': 'nodejs_create_config'}, + 'server': + {'get_resource': 'app_server'}}, + 'type': 'OS::Heat::SoftwareDeployment'}, + 'nodejs_configure_deploy': + {'depends_on': + ['nodejs_create_deploy'], + 'properties': + {'config': + {'get_resource': 'nodejs_configure_config'}, + 'input_values': + {'github_url': + 'https://github.com/sample.git', + 'mongodb_ip': + {'get_attr': + ['mongo_server', 'networks', 'private', 0]}}, + 'server': + {'get_resource': 'app_server'}}, + 'type': 'OS::Heat::SoftwareDeployment'}, + 'nodejs_start_deploy': + {'depends_on': ['nodejs_configure_deploy'], + 'properties': + {'config': + {'get_resource': 'nodejs_start_config'}, + 'server': + {'get_resource': 'app_server'}}, + 'type': 'OS::Heat::SoftwareDeployment'}, + 'app_server': + {'properties': + {'flavor': 'm1.medium', + 'image': 'ubuntu-software-config-os-init', + 'key_name': 'userkey', + 'user_data_format': 'SOFTWARE_CONFIG'}, + 'type': 'OS::Nova::Server'}, + 'mongo_server': + {'properties': + {'flavor': 'm1.medium', + 'image': 'ubuntu-software-config-os-init', + 'key_name': 'userkey', + 'user_data_format': 'SOFTWARE_CONFIG'}, + 'type': 'OS::Nova::Server'}} + + output_dict = translator.toscalib.utils.yamlparser.simple_parse(output) + + resources = output_dict.get('resources') + for resource_name in resources: + translated_value = resources.get(resource_name) + expected_value = expected_resource.get(resource_name) + self.assertEqual(translated_value, expected_value) diff --git a/translator/toscalib/tpl_relationship_graph.py b/translator/toscalib/tpl_relationship_graph.py index a97086c1..1a5ea7b6 100644 --- a/translator/toscalib/tpl_relationship_graph.py +++ b/translator/toscalib/tpl_relationship_graph.py @@ -19,7 +19,8 @@ class ToscaGraph(object): self._create() def _create_vertex(self, node): - self.vertices[node.name] = node + if node not in self.vertices: + self.vertices[node.name] = node def _create_edge(self, node1, node2, relationship): if node1 not in self.vertices: @@ -38,8 +39,8 @@ class ToscaGraph(object): for node in self.nodetemplates: relation = node.relationships if relation: - for relation, nodetpls in relation.items(): + for rel, nodetpls in relation.items(): for tpl in self.nodetemplates: if tpl.name == nodetpls.name: - self._create_edge(node, tpl, relation) + self._create_edge(node, tpl, rel) self._create_vertex(node)