def test_to_parameters(self): """Tests property conversion to parameter values.""" utils.setup_dummy_db() stack = parser.Stack(utils.dummy_context(), 'test_stack', parser.Template({}), stack_id=uuidutils.generate_uuid()) class DummyResource(object): attributes_schema = {"Foo": "A test attribute"} properties_schema = { "Foo": { "Type": "String" }, "AList": { "Type": "List" }, "ANum": { "Type": "Number" }, "AMap": { "Type": "Map" } } map_prop_val = { "key1": "val1", "key2": ["lval1", "lval2", "lval3"], "key3": { "key4": 4, "key5": False } } json_snippet = { "Type": "test_resource.template", "Properties": { "Foo": "Bar", "AList": ["one", "two", "three"], "ANum": 5, "AMap": map_prop_val } } self.m.StubOutWithMock(template_resource.resource, "get_class") (template_resource.resource.get_class( "test_resource.template").AndReturn(DummyResource)) self.m.ReplayAll() temp_res = template_resource.TemplateResource('test_t_res', json_snippet, stack) self.m.VerifyAll() converted_params = temp_res._to_parameters() self.assertTrue(converted_params) for key in DummyResource.properties_schema: self.assertIn(key, converted_params) # verify String conversion self.assertEqual("Bar", converted_params.get("Foo")) # verify List conversion self.assertEqual( ",".join(json_snippet.get("Properties", {}).get("AList", [])), converted_params.get("AList")) # verify Number conversion self.assertEqual(5, converted_params.get("ANum")) # verify Map conversion self.assertEqual(map_prop_val, converted_params.get("AMap"))
def _create_test_instance_with_nic(self, return_server, name): stack_name = '%s_s' % name t = template_format.parse(wp_template_with_nic) template = parser.Template(t) kwargs = { 'KeyName': 'test', 'InstanceType': 'm1.large', 'SubnetId': '4156c7a5-e8c4-4aff-a6e1-8f3c7bc83861' } stack = parser.Stack(utils.dummy_context(), stack_name, template, environment.Environment(kwargs), stack_id=str(uuid.uuid4())) t['Resources']['WebServer']['Properties']['ImageId'] = 'CentOS 5.2' nic = network_interfaces.NetworkInterface('%s_nic' % name, t['Resources']['nic1'], stack) instance = instances.Instance('%s_name' % name, t['Resources']['WebServer'], stack) self.m.StubOutWithMock(nic, 'neutron') nic.neutron().MultipleTimes().AndReturn(FakeNeutron()) self.m.StubOutWithMock(instance, 'nova') instance.nova().MultipleTimes().AndReturn(self.fc) self.m.StubOutWithMock(clients.OpenStackClients, 'nova') clients.OpenStackClients.nova().MultipleTimes().AndReturn(self.fc) # need to resolve the template functions server_userdata = nova_utils.build_userdata( instance, instance.t['Properties']['UserData'], 'ec2-user') self.m.StubOutWithMock(nova_utils, 'build_userdata') nova_utils.build_userdata(instance, instance.t['Properties']['UserData'], 'ec2-user').AndReturn(server_userdata) self.m.StubOutWithMock(self.fc.servers, 'create') self.fc.servers.create(image=1, flavor=3, key_name='test', name=utils.PhysName(stack_name, instance.name), security_groups=None, userdata=server_userdata, scheduler_hints=None, meta=None, nics=[{ 'port-id': '64d913c1-bcb1-42d2-8f0a-9593dbcaf251' }], availability_zone=None).AndReturn(return_server) self.m.ReplayAll() # create network interface scheduler.TaskRunner(nic.create)() stack["nic1"] = nic scheduler.TaskRunner(instance.create)() return instance
def test_to_parameters(self): """Tests property conversion to parameter values.""" provider = { 'HeatTemplateFormatVersion': '2012-12-12', 'Parameters': { 'Foo': { 'Type': 'String' }, 'AList': { 'Type': 'CommaDelimitedList' }, 'ListEmpty': { 'Type': 'CommaDelimitedList' }, 'ANum': { 'Type': 'Number' }, 'AMap': { 'Type': 'Json' }, }, 'Outputs': { 'Foo': { 'Value': 'bar' }, }, } files = {'test_resource.template': json.dumps(provider)} class DummyResource(object): attributes_schema = {"Foo": "A test attribute"} properties_schema = { "Foo": { "Type": "String" }, "AList": { "Type": "List" }, "ListEmpty": { "Type": "List" }, "ANum": { "Type": "Number" }, "AMap": { "Type": "Map" } } env = environment.Environment() resource._register_class('DummyResource', DummyResource) env.load( {'resource_registry': { 'DummyResource': 'test_resource.template' }}) stack = parser.Stack(utils.dummy_context(), 'test_stack', parser.Template({}, files=files), env=env, stack_id=str(uuid.uuid4())) map_prop_val = { "key1": "val1", "key2": ["lval1", "lval2", "lval3"], "key3": { "key4": 4, "key5": False } } json_snippet = { "Type": "DummyResource", "Properties": { "Foo": "Bar", "AList": ["one", "two", "three"], "ListEmpty": [], "ANum": 5, "AMap": map_prop_val } } temp_res = template_resource.TemplateResource('test_t_res', json_snippet, stack) temp_res.validate() converted_params = temp_res.child_params() self.assertTrue(converted_params) for key in DummyResource.properties_schema: self.assertIn(key, converted_params) # verify String conversion self.assertEqual("Bar", converted_params.get("Foo")) # verify List conversion self.assertEqual( ",".join(json_snippet.get("Properties", {}).get("AList", [])), converted_params.get("AList")) # verify Number conversion self.assertEqual(5, converted_params.get("ANum")) # verify Map conversion self.assertEqual(map_prop_val, converted_params.get("AMap"))
def test_validate_volumeattach_valid(self): t = template_format.parse(test_template_volumeattach % 'vdq') stack = parser.Stack(self.ctx, 'test_stack', parser.Template(t)) volumeattach = stack['MountPoint'] self.assertIsNone(volumeattach.validate())
def _create_test_instance_with_nic(self, return_server, name): stack_name = '%s_s' % name t = template_format.parse(wp_template_with_nic) kwargs = { 'KeyName': 'test', 'InstanceType': 'm1.large', 'SubnetId': '4156c7a5-e8c4-4aff-a6e1-8f3c7bc83861' } template = parser.Template(t, env=environment.Environment(kwargs)) stack = parser.Stack(utils.dummy_context(), stack_name, template, stack_id=str(uuid.uuid4())) image_id = 'CentOS 5.2' t['Resources']['WebServer']['Properties']['ImageId'] = image_id resource_defns = stack.t.resource_definitions(stack) nic = net_interfaces.NetworkInterface('%s_nic' % name, resource_defns['nic1'], stack) instance = instances.Instance('%s_name' % name, resource_defns['WebServer'], stack) metadata = instance.metadata_get() self._mock_get_image_id_success(image_id, 1) self.stub_SubnetConstraint_validate() self.m.StubOutWithMock(nic, 'neutron') nic.neutron().MultipleTimes().AndReturn(FakeNeutron()) self.m.StubOutWithMock(neutron.NeutronClientPlugin, '_create') neutron.NeutronClientPlugin._create().MultipleTimes().AndReturn( FakeNeutron()) self.m.StubOutWithMock(nova.NovaClientPlugin, '_create') nova.NovaClientPlugin._create().AndReturn(self.fc) # need to resolve the template functions server_userdata = instance.client_plugin().build_userdata( metadata, instance.t['Properties']['UserData'], 'ec2-user') self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata') nova.NovaClientPlugin.build_userdata( metadata, instance.t['Properties']['UserData'], 'ec2-user').AndReturn(server_userdata) self.m.StubOutWithMock(self.fc.servers, 'create') self.fc.servers.create( image=1, flavor=3, key_name='test', name=utils.PhysName(stack_name, instance.name), security_groups=None, userdata=server_userdata, scheduler_hints=None, meta=None, nics=[{ 'port-id': '64d913c1-bcb1-42d2-8f0a-9593dbcaf251' }], availability_zone=None, block_device_mapping=None).AndReturn(return_server) self.m.ReplayAll() # create network interface scheduler.TaskRunner(nic.create)() stack.resources["nic1"] = nic scheduler.TaskRunner(instance.create)() return instance
def parse_stack(self, t): stack_name = 'test_stack' tmpl = parser.Template(t) self.stack = parser.Stack(self.ctx, stack_name, tmpl) self.stack.validate() self.stack.store()
def test_lb(self): tmpl = template_format.parse(as_template) network_body = { "network": { "id": str(uuid.uuid4()), "name": "testnet", "admin_state_up": True } } subnet_body = { "subnet": { "name": "testsubnet", "id": str(uuid.uuid4()), "network_id": network_body['network']['id'], "ip_version": 4, "cidr": "10.0.3.0/24", "allocation_pools": [{ "start": "10.0.3.20", "end": "10.0.3.150" }], "gateway_ip": "10.0.3.1" } } self.params["SubnetId"] = subnet_body['subnet']['id'] mon_block = { 'health_monitor': tmpl['Resources']['myMonitor']['Properties'] } mon_block['health_monitor']['admin_state_up'] = True mon_ret_block = copy.deepcopy(mon_block) mon_ret_block['health_monitor']['id'] = str(uuid.uuid4()) mon_ret_block['health_monitor']['status'] = 'ACTIVE' pool_block = {'pool': {}} tmp_pool_block = tmpl['Resources']['myPool']['Properties'] for val in ['lb_method', 'protocol', 'name', 'description']: pool_block['pool'][val] = tmp_pool_block[val] pool_block['pool']['admin_state_up'] = True pool_block['pool']['subnet_id'] = self.params['SubnetId'] pool_block['pool']['admin_state_up'] = True pool_ret_block = copy.deepcopy(pool_block) pool_ret_block['pool']['id'] = str(uuid.uuid4()) pool_ret_block['pool']['status'] = 'ACTIVE' tmp_vip_block = tmp_pool_block.pop('vip') vip_block = { 'vip': { 'protocol': pool_block['pool']['protocol'], 'description': tmp_vip_block['description'], 'admin_state_up': True, 'subnet_id': self.params['SubnetId'], 'connection_limit': tmp_vip_block['connection_limit'], 'pool_id': pool_ret_block['pool']['id'], 'address': tmp_vip_block['address'], 'protocol_port': tmp_vip_block['protocol_port'], 'name': tmp_vip_block['name'] } } vip_ret_block = copy.deepcopy(vip_block) vip_ret_block['vip']['id'] = str(uuid.uuid4()) vip_ret_block['vip']['status'] = 'ACTIVE' port_block = { 'port': { 'network_id': network_body['network']['id'], 'fixed_ips': [{ 'subnet_id': subnet_body['subnet']['id'], }], 'admin_state_up': True } } port_ret_block = copy.deepcopy(port_block) port_ret_block['port']['id'] = str(uuid.uuid4()) membera_block = { 'member': { 'protocol_port': 8080, 'pool_id': pool_ret_block['pool']['id'], 'address': '1.2.3.4' } } membera_ret_block = copy.deepcopy(membera_block) membera_ret_block['member']['id'] = str(uuid.uuid4()) memberb_block = { 'member': { 'protocol_port': 8080, 'pool_id': pool_ret_block['pool']['id'], 'address': '1.2.3.5' } } memberb_ret_block = copy.deepcopy(memberb_block) memberb_ret_block['member']['id'] = str(uuid.uuid4()) memberc_block = { 'member': { 'protocol_port': 8080, 'pool_id': pool_ret_block['pool']['id'], 'address': '1.2.3.6' } } memberc_ret_block = copy.deepcopy(memberc_block) memberc_ret_block['member']['id'] = str(uuid.uuid4()) class id_type(object): def __init__(self, id, name): self.id = id self.name = name instances = {} clients.OpenStackClients.keystone().AndReturn( fakes.FakeKeystoneClient()) clients.neutronclient.Client.create_health_monitor(mon_block).\ AndReturn(mon_ret_block) clients.neutronclient.Client.create_pool(pool_block).\ AndReturn(pool_ret_block) clients.neutronclient.Client.associate_health_monitor( pool_ret_block['pool']['id'], { 'health_monitor': { 'id': mon_ret_block['health_monitor']['id'] } }).AndReturn(None) clients.neutronclient.Client.create_vip(vip_block).\ AndReturn(vip_ret_block) clients.neutronclient.Client.show_pool(pool_ret_block['pool']['id']).\ AndReturn(pool_ret_block) clients.neutronclient.Client.show_vip(vip_ret_block['vip']['id']).\ AndReturn(vip_ret_block) clients.OpenStackClients.keystone().AndReturn( fakes.FakeKeystoneClient()) clients.OpenStackClients.keystone().AndReturn( fakes.FakeKeystoneClient()) parser.Stack.validate() instid = str(uuid.uuid4()) instance.Instance.handle_create().AndReturn(instid) instance.Instance.check_create_complete(mox.IgnoreArg())\ .AndReturn(False) instance.Instance.check_create_complete(mox.IgnoreArg())\ .AndReturn(True) image.ImageConstraint.validate( mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(True) nova_utils.server_to_ipaddress(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn('1.2.3.4') clients.neutronclient.Client.create_member(membera_block).\ AndReturn(membera_ret_block) instances[instid] = membera_ret_block['member']['id'] # Start of update clients.OpenStackClients.keystone().AndReturn( fakes.FakeKeystoneClient()) parser.Stack.validate() instid = str(uuid.uuid4()) instance.Instance.handle_create().AndReturn(instid) instance.Instance.check_create_complete(mox.IgnoreArg())\ .AndReturn(False) instance.Instance.check_create_complete(mox.IgnoreArg())\ .AndReturn(True) instances[instid] = memberb_ret_block['member']['id'] instid = str(uuid.uuid4()) instance.Instance.handle_create().AndReturn(instid) instance.Instance.check_create_complete(mox.IgnoreArg())\ .AndReturn(False) instance.Instance.check_create_complete(mox.IgnoreArg())\ .AndReturn(True) nova_utils.server_to_ipaddress(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn('1.2.3.5') clients.neutronclient.Client.create_member(memberb_block).\ AndReturn(memberb_ret_block) nova_utils.server_to_ipaddress(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn('1.2.3.6') clients.neutronclient.Client.create_member(memberc_block).\ AndReturn(memberc_ret_block) self.m.ReplayAll() # Start of stack create env = {'parameters': self.params} tmpl = template_format.parse(as_template) stack = parser.Stack(self.ctx, 'update_test_stack', template.Template(tmpl), environment.Environment(env)) stack.store() stack.create() self.assertEqual((parser.Stack.CREATE, parser.Stack.COMPLETE), stack.state) # Start of stack update stack2 = parser.Stack.load(self.ctx, stack_id=stack.id) tmpl2 = copy.deepcopy(tmpl) tmpl2['Resources']['SvrGrp']['Properties']['DesiredCapacity'] = '3' update_stack = parser.Stack(self.ctx, 'update_test_stack', template.Template(tmpl2), environment.Environment(env)) stack2.update(update_stack) self.assertEqual((parser.Stack.UPDATE, parser.Stack.COMPLETE), stack2.state) members = db_api.resource_data_get_all(stack['ElasticLoadBalancer']) self.assertEqual(3, len(members.keys())) self.m.VerifyAll()
def create_stack(self, cnxt, stack_name, template, params, files, args): """ The create_stack method creates a new stack using the template provided. Note that at this stage the template has already been fetched from the heat-api process if using a template-url. :param cnxt: RPC context. :param stack_name: Name of the stack you want to create. :param template: Template of stack you want to create. :param params: Stack Input Params :param files: Files referenced from the template :param args: Request parameters/args passed from API """ logger.info(_('template is %s') % template) def _stack_create(stack): # Create/Adopt a stack, and create the periodic task if successful if stack.adopt_stack_data: stack.adopt() else: stack.create() if (stack.action in (stack.CREATE, stack.ADOPT) and stack.status == stack.COMPLETE): # Schedule a periodic watcher task for this stack self._start_watch_task(stack.id, cnxt) else: logger.warning(_("Stack create failed, status %s") % stack.status) if db_api.stack_get_by_name(cnxt, stack_name): raise exception.StackExists(stack_name=stack_name) tenant_limit = cfg.CONF.max_stacks_per_tenant if db_api.stack_count_all_by_tenant(cnxt) >= tenant_limit: message = _("You have reached the maximum stacks per tenant, %d." " Please delete some stacks.") % tenant_limit raise exception.RequestLimitExceeded(message=message) tmpl = parser.Template(template, files=files) if len(tmpl[tmpl.RESOURCES]) > cfg.CONF.max_resources_per_stack: raise exception.RequestLimitExceeded( message=exception.StackResourceLimitExceeded.msg_fmt) # Extract the common query parameters common_params = api.extract_args(args) env = environment.Environment(params) stack = parser.Stack(cnxt, stack_name, tmpl, env, **common_params) self._validate_deferred_auth_context(cnxt, stack) stack.validate() stack.store() self.thread_group_mgr.start_with_lock(cnxt, stack, self.engine_id, _stack_create, stack) return dict(stack.identifier())
def test_state_defaults(self): stack = parser.Stack(None, 'test_stack', parser.Template({})) self.assertEqual(stack.state, None) self.assertEqual(stack.state_description, '')
def test_created_time(self): self.stack = parser.Stack(self.ctx, 'creation_time_test', parser.Template({})) self.assertEqual(self.stack.created_time, None) self.stack.store() self.assertNotEqual(self.stack.created_time, None)
def test_update_by_reference_and_rollback_2(self): ''' assertion: check that rollback still works with dynamic metadata this test fails the second instance ''' # patch in a dummy property schema for GenericResource dummy_schema = {'Foo': {'Type': 'String'}} generic_rsrc.GenericResource.properties_schema = dummy_schema tmpl = { 'Resources': { 'AResource': { 'Type': 'GenericResourceType', 'Properties': { 'Foo': 'abc' } }, 'BResource': { 'Type': 'GenericResourceType', 'Properties': { 'Foo': { 'Ref': 'AResource' } } } } } tmpl2 = { 'Resources': { 'AResource': { 'Type': 'GenericResourceType', 'Properties': { 'Foo': 'smelly' } }, 'BResource': { 'Type': 'GenericResourceType', 'Properties': { 'Foo': { 'Ref': 'AResource' } } } } } self.stack = parser.Stack(self.ctx, 'update_test_stack', template.Template(tmpl), disable_rollback=False) self.m.StubOutWithMock(scheduler.TaskRunner, '_sleep') scheduler.TaskRunner._sleep(mox.IsA(int)).AndReturn(None) self.m.ReplayAll() self.stack.store() self.stack.create() self.m.VerifyAll() self.assertEqual(self.stack.state, parser.Stack.CREATE_COMPLETE) self.assertEqual(self.stack['AResource'].properties['Foo'], 'abc') self.assertEqual(self.stack['BResource'].properties['Foo'], 'AResource') self.m.StubOutWithMock(generic_rsrc.GenericResource, 'FnGetRefId') self.m.StubOutWithMock(generic_rsrc.GenericResource, 'handle_create') # Calls to GenericResource.handle_update will raise # resource.UpdateReplace because we've not specified the modified # key/property in update_allowed_keys/update_allowed_properties generic_rsrc.GenericResource.FnGetRefId().AndReturn('AResource') generic_rsrc.GenericResource.FnGetRefId().AndReturn('inst-007') # self.state_set(self.UPDATE_IN_PROGRESS) generic_rsrc.GenericResource.FnGetRefId().AndReturn('inst-007') # self.state_set(self.DELETE_IN_PROGRESS) generic_rsrc.GenericResource.FnGetRefId().AndReturn('inst-007') # self.state_set(self.DELETE_COMPLETE) generic_rsrc.GenericResource.FnGetRefId().AndReturn('inst-007') # self.properties.validate() generic_rsrc.GenericResource.FnGetRefId().AndReturn('inst-007') # self.state_set(self.CREATE_IN_PROGRESS) generic_rsrc.GenericResource.FnGetRefId().AndReturn('inst-007') # mock to make the replace fail when creating the second # replacement resource generic_rsrc.GenericResource.handle_create().AndReturn(None) generic_rsrc.GenericResource.handle_create().AndRaise(Exception) # Calls to GenericResource.handle_update will raise # resource.UpdateReplace because we've not specified the modified # key/property in update_allowed_keys/update_allowed_properties # self.state_set(self.DELETE_IN_PROGRESS) generic_rsrc.GenericResource.FnGetRefId().AndReturn('inst-007') # self.state_set(self.DELETE_IN_PROGRESS) generic_rsrc.GenericResource.FnGetRefId().AndReturn('inst-007') generic_rsrc.GenericResource.handle_create().AndReturn(None) generic_rsrc.GenericResource.handle_create().AndReturn(None) # reverting to AResource generic_rsrc.GenericResource.FnGetRefId().MultipleTimes().AndReturn( 'AResource') self.m.ReplayAll() updated_stack = parser.Stack(self.ctx, 'updated_stack', template.Template(tmpl2), disable_rollback=False) self.stack.update(updated_stack) self.assertEqual(self.stack.state, parser.Stack.ROLLBACK_COMPLETE) self.assertEqual(self.stack['AResource'].properties['Foo'], 'abc') self.m.VerifyAll()
def test_update_replace_by_reference(self): ''' assertion: changes in dynamic attributes, due to other resources been updated are not ignored and can cause dependant resources to be updated. ''' # patch in a dummy property schema for GenericResource dummy_schema = {'Foo': {'Type': 'String'}} generic_rsrc.GenericResource.properties_schema = dummy_schema tmpl = { 'Resources': { 'AResource': { 'Type': 'GenericResourceType', 'Properties': { 'Foo': 'abc' } }, 'BResource': { 'Type': 'GenericResourceType', 'Properties': { 'Foo': { 'Ref': 'AResource' } } } } } tmpl2 = { 'Resources': { 'AResource': { 'Type': 'GenericResourceType', 'Properties': { 'Foo': 'smelly' } }, 'BResource': { 'Type': 'GenericResourceType', 'Properties': { 'Foo': { 'Ref': 'AResource' } } } } } self.stack = parser.Stack(self.ctx, 'update_test_stack', template.Template(tmpl)) self.m.StubOutWithMock(scheduler.TaskRunner, '_sleep') scheduler.TaskRunner._sleep(mox.IsA(int)).AndReturn(None) self.m.ReplayAll() self.stack.store() self.stack.create() self.m.VerifyAll() self.assertEqual(self.stack.state, parser.Stack.CREATE_COMPLETE) self.assertEqual(self.stack['AResource'].properties['Foo'], 'abc') self.assertEqual(self.stack['BResource'].properties['Foo'], 'AResource') # Calls to GenericResource.handle_update will raise # resource.UpdateReplace because we've not specified the modified # key/property in update_allowed_keys/update_allowed_properties self.m.StubOutWithMock(generic_rsrc.GenericResource, 'FnGetRefId') generic_rsrc.GenericResource.FnGetRefId().AndReturn('AResource') generic_rsrc.GenericResource.FnGetRefId().MultipleTimes().AndReturn( 'inst-007') self.m.ReplayAll() updated_stack = parser.Stack(self.ctx, 'updated_stack', template.Template(tmpl2)) self.stack.update(updated_stack) self.assertEqual(self.stack.state, parser.Stack.UPDATE_COMPLETE) self.assertEqual(self.stack['AResource'].properties['Foo'], 'smelly') self.assertEqual(self.stack['BResource'].properties['Foo'], 'inst-007') self.m.VerifyAll()
def test_template_as_resource(self): """ Test that the resulting resource has the right prop and attrib schema. Note that this test requires the Wordpress_Single_Instance.yaml template in the templates directory since we want to test using a non-trivial template. """ test_templ_name = "WordPress_Single_Instance.yaml" path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates', test_templ_name) # check if its in the directory list vs. exists to work around # case-insensitive file systems self.assertIn(test_templ_name, os.listdir(os.path.dirname(path))) with open(path) as test_templ_file: test_templ = test_templ_file.read() self.assertTrue(test_templ, "Empty test template") self.m.StubOutWithMock(urlfetch, "get") urlfetch.get(test_templ_name, allowed_schemes=('file',))\ .AndRaise(urlfetch.URLFetchError(_('Failed to retrieve template'))) urlfetch.get(test_templ_name, allowed_schemes=('http', 'https')).AndReturn(test_templ) parsed_test_templ = template_format.parse(test_templ) self.m.ReplayAll() stack = parser.Stack(utils.dummy_context(), 'test_stack', parser.Template(empty_template), stack_id=str(uuid.uuid4())) properties = { "KeyName": "mykeyname", "DBName": "wordpress1", "DBUsername": "******", "DBPassword": "******", "DBRootPassword": "******", "LinuxDistribution": "U10" } definition = rsrc_defn.ResourceDefinition("test_templ_resource", test_templ_name, properties) templ_resource = resource.Resource("test_templ_resource", definition, stack) self.m.VerifyAll() self.assertIsInstance(templ_resource, template_resource.TemplateResource) for prop in parsed_test_templ.get("Parameters", {}): self.assertIn(prop, templ_resource.properties) for attrib in parsed_test_templ.get("Outputs", {}): self.assertIn(attrib, templ_resource.attributes) for k, v in properties.items(): self.assertEqual(v, templ_resource.properties[k]) self.assertEqual( { 'WordPress_Single_Instance.yaml': 'WordPress_Single_Instance.yaml', 'resources': {} }, stack.env.user_env_as_dict()["resource_registry"]) self.assertNotIn('WordPress_Single_Instance.yaml', resources.global_env().registry._registry)
def test_to_parameters(self): """Tests property conversion to parameter values.""" provider = { 'HeatTemplateFormatVersion': '2012-12-12', 'Parameters': { 'Foo': {'Type': 'String'}, 'AList': {'Type': 'CommaDelimitedList'}, 'ListEmpty': {'Type': 'CommaDelimitedList'}, 'ANum': {'Type': 'Number'}, 'AMap': {'Type': 'Json'}, }, 'Outputs': { 'Foo': {'Value': 'bar'}, }, } files = {'test_resource.template': json.dumps(provider)} class DummyResource(object): support_status = support.SupportStatus() attributes_schema = {"Foo": attributes.Schema("A test attribute")} properties_schema = { "Foo": {"Type": "String"}, "AList": {"Type": "List"}, "ListEmpty": {"Type": "List"}, "ANum": {"Type": "Number"}, "AMap": {"Type": "Map"} } env = environment.Environment() resource._register_class('DummyResource', DummyResource) env.load({'resource_registry': {'DummyResource': 'test_resource.template'}}) stack = parser.Stack(utils.dummy_context(), 'test_stack', parser.Template(empty_template, files=files), env=env, stack_id=str(uuid.uuid4())) map_prop_val = { "key1": "val1", "key2": ["lval1", "lval2", "lval3"], "key3": { "key4": 4, "key5": False } } prop_vals = { "Foo": "Bar", "AList": ["one", "two", "three"], "ListEmpty": [], "ANum": 5, "AMap": map_prop_val, } definition = rsrc_defn.ResourceDefinition('test_t_res', 'DummyResource', prop_vals) temp_res = template_resource.TemplateResource('test_t_res', definition, stack) temp_res.validate() converted_params = temp_res.child_params() self.assertTrue(converted_params) for key in DummyResource.properties_schema: self.assertIn(key, converted_params) # verify String conversion self.assertEqual("Bar", converted_params.get("Foo")) # verify List conversion self.assertEqual("one,two,three", converted_params.get("AList")) # verify Number conversion self.assertEqual(5, converted_params.get("ANum")) # verify Map conversion self.assertEqual(map_prop_val, converted_params.get("AMap")) with mock.patch.object(properties.Properties, '__getitem__') as m_get: m_get.side_effect = ValueError('boom') # If the property doesn't exist on INIT, return default value temp_res.action = temp_res.INIT converted_params = temp_res.child_params() for key in DummyResource.properties_schema: self.assertIn(key, converted_params) self.assertEqual({}, converted_params['AMap']) self.assertEqual(0, converted_params['ANum']) # If the property doesn't exist past INIT, then error out temp_res.action = temp_res.CREATE self.assertRaises(ValueError, temp_res.child_params)
def check_user_data(self, template_file): return # until TODO is fixed # transport = self.ssh.get_transport() # channel = transport.open_session() # channel.get_pty() # channel.invoke_shell() # sudo requires tty # channel.sendall('sudo chmod 777 \ # sudo chmod 777 /var/lib/cloud/instance/user-data.txt.i\n') # time.sleep(1) # necessary for sendall to complete f = open(basepath + '/templates/' + template_file) t = json.loads(f.read()) f.close() template = parser.Template(t) params = parser.Parameters('test', t, {'KeyName': 'required_parameter', 'DBUsername': self.dbusername, 'DBPassword': self.creds['password']}) stack = parser.Stack(None, 'test', template, params) parsed_t = stack.resolve_static_data(t) remote_file = self.sftp.open('/var/lib/cloud/data/cfn-userdata') remote_file_list = remote_file.read().split('\n') remote_file_list_u = map(unicode, remote_file_list) remote_file.close() # TODO: make server name generic t_data = parsed_t['Resources']['WikiDatabase']['Properties'] t_data = t_data['UserData']['Fn::Base64']['Fn::Join'].pop() joined_t_data = ''.join(t_data) t_data_list = joined_t_data.split('\n') # must match user data injection t_data_list.insert(len(t_data_list) - 1, u'touch /var/lib/cloud/instance/provision-finished') self.testcase.assertEqual(t_data_list, remote_file_list_u) remote_file = self.sftp.open('/var/lib/cloud/instance/user-data.txt.i') msg = email.message_from_file(remote_file) remote_file.close() filepaths = { 'cloud-config': basepath + '/heat/cloudinit/config', 'part-handler.py': basepath + '/heat/cloudinit/part-handler.py' } # check multipart mime accuracy for part in msg.walk(): # multipart/* are just containers if part.get_content_maintype() == 'multipart': continue file = part.get_filename() data = part.get_payload() if file in filepaths.keys(): with open(filepaths[file]) as f: self.testcase.assertEqual(data, f.read())
def parse_stack(self, t): stack_name = 'test_stack' tmpl = parser.Template(t) stack = parser.Stack(utils.dummy_context(), stack_name, tmpl) stack.store() return stack
def setUp(self): self.stack = parser.Stack(None, 'test_stack', parser.Template({}), stack_id=-1)