def test_translate_storage_notation1(self): '''TOSCA template with single BlockStorage and Attachment.''' tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "../toscalib/tests/data/storage/" "tosca_blockstorage_with_attachment_notation1.yaml") tosca = ToscaTemplate(tosca_tpl) translate = TOSCATranslator(tosca, self.parsed_params) output = translate.translate() expected_resource_1 = {'type': 'OS::Cinder::VolumeAttachment', 'properties': {'instance_uuid': 'my_web_app_tier_1', 'location': '/default_location', 'volume_id': 'my_storage'}} expected_resource_2 = {'type': 'OS::Cinder::VolumeAttachment', 'properties': {'instance_uuid': 'my_web_app_tier_2', 'location': '/some_other_data_location', 'volume_id': 'my_storage'}} output_dict = translator.toscalib.utils.yamlparser.simple_parse(output) resources = output_dict.get('resources') self.assertIn('myattachto_1', resources.keys()) self.assertIn('myattachto_2', resources.keys()) self.assertIn(expected_resource_1, resources.values()) self.assertIn(expected_resource_2, resources.values())
def test_translate_server_existing_network(self): '''TOSCA template with 1 server attached to existing network.''' tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "../toscalib/tests/data/network/" "tosca_server_on_existing_network.yaml") tosca = ToscaTemplate(tosca_tpl) translate = TOSCATranslator(tosca, self.parsed_params) output = translate.translate() expected_resource_1 = {'type': 'OS::Neutron::Port', 'properties': {'network': {'get_param': 'network_name'} }} expected_resource_2 = [{'port': {'get_resource': 'my_port'}}] output_dict = translator.toscalib.utils.yamlparser.simple_parse(output) resources = output_dict.get('resources') self.assertItemsEqual(resources.keys(), ['my_server', 'my_port']) self.assertEqual(resources.get('my_port'), expected_resource_1) self.assertIn('properties', resources.get('my_server')) self.assertIn('networks', resources.get('my_server').get('properties')) translated_resource = resources.get('my_server').\ get('properties').get('networks') self.assertEqual(translated_resource, expected_resource_2)
def __init__(self, tosca_yaml, parent_dir=None, log_to_console=False): # TOSCA will look for imports using a relative path from where the # template file is located, so we have to put the template file # in a specific place. if not parent_dir: parent_dir = os.getcwd() tmp_pathname = None try: (tmp_handle, tmp_pathname) = tempfile.mkstemp(dir=parent_dir) os.write(tmp_handle, tosca_yaml) os.close(tmp_handle) self.template = ToscaTemplate(tmp_pathname) except: traceback.print_exc() raise finally: if tmp_pathname: os.remove(tmp_pathname) self.log_to_console = log_to_console self.log_msgs = [] self.compute_dependencies() self.deferred_sync = [] self.ordered_nodetemplates = [] self.ordered_names = self.topsort_dependencies() print "ordered_names", self.ordered_names for name in self.ordered_names: if name in self.nodetemplates_by_name: self.ordered_nodetemplates.append( self.nodetemplates_by_name[name])
def test_template_requirements(self): """Test different formats of requirements The requirements can be defined in few different ways, 1. Requirement expressed as a capability with an implicit relationship. 2. Requirement expressed with explicit relationship. 3. Requirement expressed with a relationship template. 4. Requirement expressed via TOSCA types to provision a node with explicit relationship. 5. Requirement expressed via TOSCA types with a filter. """ tosca_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/test_requirements.yaml") tosca = ToscaTemplate(tosca_tpl) for node_tpl in tosca.nodetemplates: if node_tpl.name == 'my_app': expected_relationship = [ ('tosca.relationships.ConnectsTo', 'mysql_database'), ('tosca.relationships.HostedOn', 'my_webserver') ] actual_relationship = sorted([ (relation.type, node.name) for relation, node in node_tpl.relationships.items() ]) self.assertEqual(expected_relationship, actual_relationship) if node_tpl.name == 'mysql_database': self.assertEqual( [('tosca.relationships.HostedOn', 'my_dbms')], [(relation.type, node.name) for relation, node in node_tpl.relationships.items()]) if node_tpl.name == 'my_server': self.assertEqual( [('tosca.relationships.AttachesTo', 'my_storage')], [(relation.type, node.name) for relation, node in node_tpl.relationships.items()])
def test_translate_multi_storage(self): '''TOSCA template with multiple BlockStorage and Attachment.''' tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "../toscalib/tests/data/storage/" "tosca_multiple_blockstorage_with_attachment.yaml") tosca = ToscaTemplate(tosca_tpl) translated_volume_attachment = [] translate = TOSCATranslator(tosca, self.parsed_params) output = translate.translate() expected_resource_1 = {'type': 'OS::Cinder::VolumeAttachment', 'properties': {'instance_uuid': 'my_server', 'location': {'get_param': 'storage_location'}, 'volume_id': 'my_storage'}} expected_resource_2 = {'type': 'OS::Cinder::VolumeAttachment', 'properties': {'instance_uuid': 'my_server2', 'location': {'get_param': 'storage_location'}, 'volume_id': 'my_storage2'}} output_dict = translator.toscalib.utils.yamlparser.simple_parse(output) resources = output_dict.get('resources') translated_volume_attachment.append(resources.get('attachesto_1')) translated_volume_attachment.append(resources.get('attachesto_2')) self.assertIn(expected_resource_1, translated_volume_attachment) self.assertIn(expected_resource_2, translated_volume_attachment)
def test_translate_output(self): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "../../toscalib/tests/data/" "tosca_nodejs_mongodb_two_instances.yaml") tosca = ToscaTemplate(tosca_tpl) translate = TOSCATranslator(tosca, []) hot_translation = translate.translate() expected_output = {'nodejs_url': {'description': 'URL for the nodejs ' 'server, http://<IP>:3000', 'value': {'get_attr': ['app_server', 'networks', 'private', 0]}}, 'mongodb_url': {'description': 'URL for the mongodb server.', 'value': {'get_attr': ['mongo_server', 'networks', 'private', 0]}}} hot_translation_dict = \ translator.toscalib.utils.yamlparser.simple_parse(hot_translation) outputs = hot_translation_dict.get('outputs') for resource_name in outputs: translated_value = outputs.get(resource_name) expected_value = expected_output.get(resource_name) self.assertEqual(translated_value, expected_value)
def _load_template(self, filename): """Load a Tosca template from tests data folder. :param filename: Tosca template file name to load. :return: ToscaTemplate """ return ToscaTemplate(os.path.join( os.path.dirname(os.path.abspath(__file__)), 'data', filename))
def test_translate_three_networks_single_server(self): '''TOSCA template with three Networks and single Compute.''' tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "../toscalib/tests/data/network/" "tosca_one_server_three_networks.yaml") tosca = ToscaTemplate(tosca_tpl) translate = TOSCATranslator(tosca, self.parsed_params) output = translate.translate() output_dict = translator.toscalib.utils.yamlparser.simple_parse(output) resources = output_dict.get('resources') for net_num in range(1, 4): net_name = 'my_network%d' % (net_num) subnet_name = '%s_subnet' % (net_name) port_name = 'my_port%d' % (net_num) expected_resource_net = {'type': 'OS::Neutron::Net', 'properties': {'name': 'net%d' % (net_num) }} expected_resource_subnet = {'type': 'OS::Neutron::Subnet', 'properties': {'cidr': '192.168.%d.0/24' % (net_num), 'ip_version': 4, 'network': {'get_resource': net_name} }} expected_resource_port = {'type': 'OS::Neutron::Port', 'depends_on': [net_name], 'properties': {'network': {'get_resource': net_name} }} self.assertIn(net_name, resources.keys()) self.assertIn(subnet_name, resources.keys()) self.assertIn(port_name, resources.keys()) self.assertEqual(resources.get(net_name), expected_resource_net) self.assertEqual(resources.get(subnet_name), expected_resource_subnet) self.assertEqual(resources.get(port_name), expected_resource_port) self.assertIn('properties', resources.get('my_server')) self.assertIn('networks', resources.get('my_server').get('properties')) translated_resource = resources.get('my_server').\ get('properties').get('networks') expected_srv_networks = [{'port': {'get_resource': 'my_port1'}}, {'port': {'get_resource': 'my_port2'}}, {'port': {'get_resource': 'my_port3'}}] self.assertEqual(translated_resource, expected_srv_networks)
def test_translate_single_network_single_server(self): '''TOSCA template with single Network and single Compute.''' tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "../toscalib/tests/data/network/" "tosca_one_server_one_network.yaml") tosca = ToscaTemplate(tosca_tpl) translate = TOSCATranslator(tosca, self.parsed_params) output = translate.translate() expected_resource_1 = {'type': 'OS::Neutron::Net', 'properties': {'name': {'get_param': 'network_name'} }} expected_resource_2 = {'type': 'OS::Neutron::Subnet', 'properties': {'cidr': '192.168.0.0/24', 'ip_version': 4, 'allocation_pools': [{'start': '192.168.0.50', 'end': '192.168.0.200'}], 'gateway_ip': '192.168.0.1', 'network': {'get_resource': 'my_network'} }} expected_resource_3 = {'type': 'OS::Neutron::Port', 'depends_on': ['my_network'], 'properties': {'network': {'get_resource': 'my_network'} }} expected_resource_4 = [{'port': {'get_resource': 'my_port'}}] output_dict = translator.toscalib.utils.yamlparser.simple_parse(output) resources = output_dict.get('resources') self.assertIn('my_network', resources.keys()) self.assertIn('my_network_subnet', resources.keys()) self.assertIn('my_port', resources.keys()) self.assertIn('my_server', resources.keys()) self.assertEqual(resources.get('my_network'), expected_resource_1) self.assertEqual(resources.get('my_network_subnet'), expected_resource_2) self.assertEqual(resources.get('my_port'), expected_resource_3) self.assertIn('properties', resources.get('my_server')) self.assertIn('networks', resources.get('my_server').get('properties')) translated_resource = resources.get('my_server').\ get('properties').get('networks') self.assertEqual(translated_resource, expected_resource_4)
def test_relationship_interface(self): template = ToscaTemplate(self.tosca_elk_tpl) for node_tpl in template.nodetemplates: if node_tpl.name == 'nodejs': config_interface = 'tosca.interfaces.relationship.Configure' relation = node_tpl.relationships for key in relation.keys(): rel_tpl = relation.get(key).get_relationship_template() interfaces = rel_tpl[0].interfaces for interface in interfaces: self.assertEqual(config_interface, interface.type) self.assertEqual('pre_configure_source', interface.name) self.assertEqual('nodejs/pre_configure_source.sh', interface.implementation)
def test_translate_output_order(self): tosca_yaml_file = "data/tosca_single_server.yaml" tosca_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), tosca_yaml_file) parsed_params = {'cpus': 2} tosca = ToscaTemplate(tosca_tpl) translate = TOSCATranslator(tosca, parsed_params) hot_translated_output = translate.translate() #load expected hot yaml file hot_yaml_file = "data/hot_output/hot_single_server.yaml" hot_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), hot_yaml_file) with open(hot_tpl) as f: hot_expected_output = f.read() #compare generated and expected hot templates status = CompareUtils.compare_hot_yamls(hot_translated_output, hot_expected_output) self.assertEqual(status, True)
def parse_metafile(tmpdir): # Parse the TOSCA.meta file looking for yaml definitions # TODO This may be unnecessary if/when toscalib does it if not os.path.isfile(tmpdir + "/TOSCA-Metadata/TOSCA.meta"): print "Error: TOSCA.meta not found in CSAR file" sys.exit(1) try: tfile = open(tmpdir + '/TOSCA-Metadata/TOSCA.meta', 'r') except (IOError, OSError): print "Error: Couldn't open Tosca metafile" sys.exit(1) tlines = tfile.readlines() for line in tlines: if (line.startswith("Name")): attr, value = line.split(":", 2) # if it's a yaml file pointer, need to find it here, and parse it? logger.debug("Found yaml file: " + tmpdir + "/" + value.strip()) # TODO Need to handle multiple yaml files tosca_tpl = os.path.join(tmpdir + "/" + value.strip()) yamlcontent = ToscaTemplate(tosca_tpl) return yamlcontent
def test_normative_type_by_short_name(self): #test template with a short name Compute template = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/test_tosca_normative_type_by_shortname.yaml") tosca_tpl = ToscaTemplate(template) expected_type = "tosca.nodes.Compute" for tpl in tosca_tpl.nodetemplates: self.assertEqual(tpl.type, expected_type) for tpl in tosca_tpl.nodetemplates: compute_type = NodeType(tpl.type) self.assertEqual( sorted([ 'tosca.capabilities.Container', 'tosca.capabilities.OperatingSystem', 'tosca.capabilities.network.Bindable', 'tosca.capabilities.Scalable' ]), sorted( [c.type for c in compute_type.get_capabilities_objects()]))
def test_single_template_objectstore(self): tosca_yaml_file = "../toscalib/tests/data/storage/" + \ "tosca_single_object_store.yaml" tosca_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), tosca_yaml_file) parsed_params = {'objectstore_name': 'test_obj_store'} tosca = ToscaTemplate(tosca_tpl) translate = TOSCATranslator(tosca, parsed_params) hot_translated_output = translate.translate() #load expected hot yaml file hot_yaml_file = "../toscalib/tests/data/hot_output/" + \ "hot_single_object_store.yaml" hot_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), hot_yaml_file) with open(hot_tpl) as f: hot_expected_output = f.read() #compare generated and expected hot templates status = CompareUtils.compare_hot_yamls(hot_translated_output, hot_expected_output) self.assertEqual(status, True)
def test_translate_single_storage(self): '''TOSCA template with single BlockStorage and Attachment.''' tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "../toscalib/tests/data/storage/" "tosca_blockstorage_with_attachment.yaml") tosca = ToscaTemplate(tosca_tpl) translate = TOSCATranslator(tosca, self.parsed_params) output = translate.translate() expected_resouce = {'attachesto_1': {'type': 'OS::Cinder::VolumeAttachment', 'properties': {'instance_uuid': 'my_server', 'location': {'get_param': 'storage_location'}, 'volume_id': 'my_storage'}}} output_dict = translator.toscalib.utils.yamlparser.simple_parse(output) resources = output_dict.get('resources') translated_value = resources.get('attachesto_1') expected_value = expected_resouce.get('attachesto_1') self.assertEqual(translated_value, expected_value) outputs = output_dict['outputs'] self.assertIn('private_ip', outputs) self.assertEqual( 'Private IP address of the newly created compute instance.', outputs['private_ip']['description']) self.assertEqual({'get_attr': ['my_server', 'networks', 'private', 0]}, outputs['private_ip']['value']) self.assertIn('volume_id', outputs) self.assertEqual('The volume id of the block storage instance.', outputs['volume_id']['description']) self.assertEqual({'get_resource': 'my_storage'}, outputs['volume_id']['value'])
def test_translate_storage_notation2(self): '''TOSCA template with single BlockStorage and Attachment.''' tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "../toscalib/tests/data/storage/" "tosca_blockstorage_with_attachment_notation2.yaml") tosca = ToscaTemplate(tosca_tpl) translate = TOSCATranslator(tosca, self.parsed_params) output = translate.translate() expected_resource_1 = {'type': 'OS::Cinder::VolumeAttachment', 'properties': {'instance_uuid': 'my_web_app_tier_1', 'location': '/my_data_location', 'volume_id': 'my_storage'}} expected_resource_2 = {'type': 'OS::Cinder::VolumeAttachment', 'properties': {'instance_uuid': 'my_web_app_tier_2', 'location': '/some_other_data_location', 'volume_id': 'my_storage'}} output_dict = translator.toscalib.utils.yamlparser.simple_parse(output) resources = output_dict.get('resources') # Resource name suffix depends on nodetemplates order in dict, which is # not certain. So we have two possibilities of resources name. if resources.get('storage_attachesto_1_1'): self.assertIn('storage_attachesto_1_1', resources.keys()) self.assertIn('storage_attachesto_2_2', resources.keys()) else: self.assertIn('storage_attachesto_1_2', resources.keys()) self.assertIn('storage_attachesto_2_1', resources.keys()) self.assertIn(expected_resource_1, resources.values()) self.assertIn(expected_resource_2, resources.values())
class ToscaTemplateTest(TestCase): '''TOSCA template.''' tosca_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/tosca_single_instance_wordpress.yaml") tosca = ToscaTemplate(tosca_tpl) tosca_elk_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/tosca_elk.yaml") def test_version(self): self.assertEqual(self.tosca.version, "tosca_simple_yaml_1_0_0") def test_description(self): expected_description = "TOSCA simple profile with wordpress, " \ "web server and mysql on the same server." self.assertEqual(self.tosca.description, expected_description) def test_inputs(self): self.assertEqual( ['cpus', 'db_name', 'db_port', 'db_pwd', 'db_root_pwd', 'db_user'], sorted([input.name for input in self.tosca.inputs])) input_name = "db_port" expected_description = "Port for the MySQL database." for input in self.tosca.inputs: if input.name == input_name: self.assertEqual(input.description, expected_description) def test_node_tpls(self): '''Test nodetemplate names.''' self.assertEqual([ 'mysql_database', 'mysql_dbms', 'server', 'webserver', 'wordpress' ], sorted([tpl.name for tpl in self.tosca.nodetemplates])) tpl_name = "mysql_database" expected_type = "tosca.nodes.Database" expected_properties = ['db_name', 'db_password', 'db_user'] expected_capabilities = ['database_endpoint'] expected_requirements = [{'host': 'mysql_dbms'}] expected_relationshp = ['tosca.relationships.HostedOn'] expected_host = ['mysql_dbms'] expected_interface = [ifaces.LIFECYCLE] for tpl in self.tosca.nodetemplates: if tpl_name == tpl.name: '''Test node type.''' self.assertEqual(tpl.type, expected_type) '''Test properties.''' self.assertEqual(expected_properties, sorted(tpl.get_properties().keys())) '''Test capabilities.''' self.assertEqual(expected_capabilities, sorted(tpl.get_capabilities().keys())) '''Test requirements.''' self.assertEqual(expected_requirements, tpl.requirements) '''Test relationship.''' self.assertEqual(expected_relationshp, [x.type for x in tpl.relationships.keys()]) self.assertEqual(expected_host, [y.name for y in tpl.relationships.values()]) '''Test interfaces.''' self.assertEqual(expected_interface, [x.type for x in tpl.interfaces]) if tpl.name == 'server': '''Test property value''' props = tpl.get_properties() if props and 'mem_size' in props.keys(): self.assertEqual(props['mem_size'].value, '4096 MB') '''Test capability''' caps = tpl.get_capabilities() self.assertIn('os', caps.keys()) os_props_objs = None os_props = None os_type_prop = None if caps and 'os' in caps.keys(): capability = caps['os'] os_props_objs = capability.get_properties_objects() os_props = capability.get_properties() os_type_prop = capability.get_property_value('type') break self.assertEqual( ['Linux'], [p.value for p in os_props_objs if p.name == 'type']) self.assertEqual( 'Linux', os_props['type'].value if 'type' in os_props else '') self.assertEqual('Linux', os_props['type'].value) self.assertEqual('Linux', os_type_prop) def test_outputs(self): self.assertEqual(['website_url'], sorted([output.name for output in self.tosca.outputs])) def test_interfaces(self): wordpress_node = [ node for node in self.tosca.nodetemplates if node.name == 'wordpress' ][0] interfaces = wordpress_node.interfaces self.assertEqual(2, len(interfaces)) for interface in interfaces: if interface.name == 'create': self.assertEqual(ifaces.LIFECYCLE, interface.type) self.assertEqual('wordpress/wordpress_install.sh', interface.implementation) self.assertIsNone(interface.inputs) elif interface.name == 'configure': self.assertEqual(ifaces.LIFECYCLE, interface.type) self.assertEqual('wordpress/wordpress_configure.sh', interface.implementation) self.assertEqual(4, len(interface.inputs)) wp_db_port = interface.inputs['wp_db_port'] self.assertTrue(isinstance(wp_db_port, GetProperty)) self.assertEqual('get_property', wp_db_port.name) self.assertEqual(['SELF', 'database_endpoint', 'port'], wp_db_port.args) result = wp_db_port.result() self.assertTrue(isinstance(result, GetInput)) else: raise AssertionError('Unexpected interface: {0}'.format( interface.name)) def test_normative_type_by_short_name(self): #test template with a short name Compute template = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/test_tosca_normative_type_by_shortname.yaml") tosca_tpl = ToscaTemplate(template) expected_type = "tosca.nodes.Compute" for tpl in tosca_tpl.nodetemplates: self.assertEqual(tpl.type, expected_type) for tpl in tosca_tpl.nodetemplates: compute_type = NodeType(tpl.type) self.assertEqual( sorted([ 'tosca.capabilities.Container', 'tosca.capabilities.OperatingSystem', 'tosca.capabilities.network.Bindable', 'tosca.capabilities.Scalable' ]), sorted( [c.type for c in compute_type.get_capabilities_objects()])) def test_template_with_no_inputs(self): tosca_tpl = self._load_template('test_no_inputs_in_template.yaml') self.assertEqual(0, len(tosca_tpl.inputs)) def test_template_with_no_outputs(self): tosca_tpl = self._load_template('test_no_outputs_in_template.yaml') self.assertEqual(0, len(tosca_tpl.outputs)) def test_relationship_interface(self): template = ToscaTemplate(self.tosca_elk_tpl) for node_tpl in template.nodetemplates: if node_tpl.name == 'nodejs': config_interface = 'tosca.interfaces.relationship.Configure' relation = node_tpl.relationships for key in relation.keys(): rel_tpl = relation.get(key).get_relationship_template() interfaces = rel_tpl[0].interfaces for interface in interfaces: self.assertEqual(config_interface, interface.type) self.assertEqual('pre_configure_source', interface.name) self.assertEqual('nodejs/pre_configure_source.sh', interface.implementation) def test_template_macro(self): template = ToscaTemplate(self.tosca_elk_tpl) for node_tpl in template.nodetemplates: if node_tpl.name == 'mongo_server': self.assertEqual(['disk_size', 'mem_size', 'num_cpus'], sorted(node_tpl.get_properties().keys())) def test_template_requirements(self): """Test different formats of requirements The requirements can be defined in few different ways, 1. Requirement expressed as a capability with an implicit relationship. 2. Requirement expressed with explicit relationship. 3. Requirement expressed with a relationship template. 4. Requirement expressed via TOSCA types to provision a node with explicit relationship. 5. Requirement expressed via TOSCA types with a filter. """ tosca_tpl = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/test_requirements.yaml") tosca = ToscaTemplate(tosca_tpl) for node_tpl in tosca.nodetemplates: if node_tpl.name == 'my_app': expected_relationship = [ ('tosca.relationships.ConnectsTo', 'mysql_database'), ('tosca.relationships.HostedOn', 'my_webserver') ] actual_relationship = sorted([ (relation.type, node.name) for relation, node in node_tpl.relationships.items() ]) self.assertEqual(expected_relationship, actual_relationship) if node_tpl.name == 'mysql_database': self.assertEqual( [('tosca.relationships.HostedOn', 'my_dbms')], [(relation.type, node.name) for relation, node in node_tpl.relationships.items()]) if node_tpl.name == 'my_server': self.assertEqual( [('tosca.relationships.AttachesTo', 'my_storage')], [(relation.type, node.name) for relation, node in node_tpl.relationships.items()]) def test_template_requirements_not_implemented(self): #TODO(spzala) replace this test with new one once TOSCA types look up #support is implemented. """Requirements that yet need to be implemented The following requirement formats are not yet implemented, due to look up dependency: 1. Requirement expressed via TOSCA types to provision a node with explicit relationship. 2. Requirement expressed via TOSCA types with a filter. """ tpl_snippet_1 = ''' node_templates: mysql_database: type: tosca.nodes.Database description: Requires a particular node type and relationship. To be full-filled via lookup into node repository. requirements: - req1: node: tosca.nodes.DBMS relationship: tosca.relationships.HostedOn ''' tpl_snippet_2 = ''' node_templates: my_webserver: type: tosca.nodes.WebServer description: Requires a particular node type with a filter. To be full-filled via lookup into node repository. requirements: - req1: node: tosca.nodes.Compute target_filter: properties: num_cpus: { in_range: [ 1, 4 ] } mem_size: { greater_or_equal: 2 } capabilities: - tosca.capabilities.OS: properties: architecture: x86_64 type: linux ''' tpl_snippet_3 = ''' node_templates: my_webserver2: type: tosca.nodes.WebServer description: Requires a node type with a particular capability. To be full-filled via lookup into node repository. requirements: - req1: node: tosca.nodes.Compute relationship: tosca.relationships.HostedOn capability: tosca.capabilities.Container ''' self._requirements_not_implemented(tpl_snippet_1, 'mysql_database') self._requirements_not_implemented(tpl_snippet_2, 'my_webserver') self._requirements_not_implemented(tpl_snippet_3, 'my_webserver2') def _requirements_not_implemented(self, tpl_snippet, tpl_name): nodetemplates = (translator.toscalib.utils.yamlparser.simple_parse( tpl_snippet))['node_templates'] self.assertRaises( NotImplementedError, lambda: NodeTemplate(tpl_name, nodetemplates).relationships) def test_custom_capability_type_definition(self): tpl_snippet = ''' node_templates: test_app: type: tosca.nodes.WebApplication.TestApp capabilities: test_cap: properties: test: 1 ''' #custom definition with capability type definition custom_def = ''' tosca.nodes.WebApplication.TestApp: derived_from: tosca.nodes.WebApplication capabilities: test_cap: type: tosca.capabilities.TestCapability tosca.capabilities.TestCapability: derived_from: tosca.capabilities.Root properties: test: type: integer required: no ''' expected_capabilities = ['test_cap'] nodetemplates = (translator.toscalib.utils.yamlparser.simple_parse( tpl_snippet))['node_templates'] custom_def = ( translator.toscalib.utils.yamlparser.simple_parse(custom_def)) name = list(nodetemplates.keys())[0] tpl = NodeTemplate(name, nodetemplates, custom_def) self.assertEqual(expected_capabilities, sorted(tpl.get_capabilities().keys())) #custom definition without capability type definition custom_def = ''' tosca.nodes.WebApplication.TestApp: derived_from: tosca.nodes.WebApplication capabilities: test_cap: type: tosca.capabilities.TestCapability ''' custom_def = ( translator.toscalib.utils.yamlparser.simple_parse(custom_def)) tpl = NodeTemplate(name, nodetemplates, custom_def) err = self.assertRaises( exception.InvalidTypeError, lambda: NodeTemplate( name, nodetemplates, custom_def).get_capabilities_objects()) self.assertEqual( 'Type "tosca.capabilities.TestCapability" is not ' 'a valid type.', six.text_type(err))
class IntrinsicFunctionsTest(TestCase): tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_single_instance_wordpress.yaml") tosca = ToscaTemplate(tosca_tpl) def _get_node(self, node_name): return [ node for node in self.tosca.nodetemplates if node.name == node_name][0] def _get_operation(self, interfaces, operation): return [ interface for interface in interfaces if interface.name == operation][0] def _get_property(self, node_template, property_name): return [prop.value for prop in node_template.get_properties_objects() if prop.name == property_name][0] def test_get_property(self): mysql_dbms = self._get_node('mysql_dbms') operation = self._get_operation(mysql_dbms.interfaces, 'configure') db_root_password = operation.inputs['db_root_password'] self.assertTrue(isinstance(db_root_password, functions.GetProperty)) result = db_root_password.result() self.assertTrue(isinstance(result, functions.GetInput)) def test_get_requirement_property(self): wordpress = self._get_node('wordpress') operation = self._get_operation(wordpress.interfaces, 'configure') wp_db_port = operation.inputs['wp_db_port'] self.assertTrue(isinstance(wp_db_port, functions.GetProperty)) result = wp_db_port.result() self.assertTrue(isinstance(result, functions.GetInput)) self.assertEqual('db_port', result.input_name) def test_get_capability_property(self): mysql_database = self._get_node('mysql_database') operation = self._get_operation(mysql_database.interfaces, 'configure') db_port = operation.inputs['db_port'] self.assertTrue(isinstance(db_port, functions.GetProperty)) result = db_port.result() self.assertTrue(isinstance(result, functions.GetInput)) self.assertEqual('db_port', result.input_name) def test_unknown_capability_property(self): err = self.assertRaises( KeyError, self._load_template, 'functions/test_unknown_capability_property.yaml') self.assertIn("'unknown'", six.text_type(err)) self.assertIn("'database_endpoint'", six.text_type(err)) self.assertIn("'database'", six.text_type(err)) def test_get_input_in_properties(self): mysql_dbms = self._get_node('mysql_dbms') expected_inputs = ['db_root_pwd', 'db_port'] props = mysql_dbms.get_properties() for key in props.keys(): prop = props[key] self.assertTrue(isinstance(prop.value, functions.GetInput)) expected_inputs.remove(prop.value.input_name) self.assertListEqual(expected_inputs, []) def test_get_input_in_interface(self): mysql_dbms = self._get_node('mysql_dbms') operation = self._get_operation(mysql_dbms.interfaces, 'configure') db_user = operation.inputs['db_user'] self.assertTrue(isinstance(db_user, functions.GetInput)) def test_get_input_validation(self): self.assertRaises(exception.UnknownInputError, self._load_template, 'functions/test_unknown_input_in_property.yaml') self.assertRaises(exception.UnknownInputError, self._load_template, 'functions/test_unknown_input_in_interface.yaml') def test_get_input_default_value_result(self): mysql_dbms = self._get_node('mysql_dbms') dbms_port = self._get_property(mysql_dbms, 'dbms_port') self.assertEqual(3306, dbms_port.result()) dbms_root_password = self._get_property(mysql_dbms, 'dbms_root_password') self.assertIsNone(dbms_root_password.result())
def test_template_macro(self): template = ToscaTemplate(self.tosca_elk_tpl) for node_tpl in template.nodetemplates: if node_tpl.name == 'mongo_server': self.assertEqual(['disk_size', 'mem_size', 'num_cpus'], sorted(node_tpl.get_properties().keys()))
def test_well_defined_template(self): tpl_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_single_instance_wordpress.yaml") self.assertIsNotNone(ToscaTemplate(tpl_path))
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__)), "../toscalib/tests/data/tosca_nodejs_mongodb_two_instances.yaml") tosca = ToscaTemplate(tosca_tpl) def test_relationship_def(self): expected_relationship = ['tosca.relationships.HostedOn'] expected_capabilities_names = ['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.HostedOn'] expected_relatednodes = ['app_server'] 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'] actual_nodejs = [] for tpl in self.tosca.nodetemplates: if tpl.name == 'nodejs': for node in tpl.related_nodes: actual_nodejs.append(node.name) self.assertEqual(sorted(actual_nodejs), expected_nodejs) 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': { '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)
def test_datatype_in_template_positive(self): tpl_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/datatypes/test_custom_datatypes_positive.yaml") self.assertIsNotNone(ToscaTemplate(tpl_path))
def _load_template(self, filename): return ToscaTemplate(os.path.join( os.path.dirname(os.path.abspath(__file__)), 'data', filename))