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 test_conv_string_five_instance_stack_update(self, mock_cr): stack = tools.get_stack('test_stack', utils.dummy_context(), template=tools.string_template_five, convergence=True) stack.store() # create stack stack.converge_stack(template=stack.t, action=stack.CREATE) curr_stack_db = stack_object.Stack.get_by_id(stack.context, stack.id) curr_stack = parser.Stack.load(curr_stack_db._context, stack=curr_stack_db) # update stack with new template t2 = template_format.parse(tools.string_template_five_update) template2 = templatem.Template(t2, env=environment.Environment( {'KeyName2': 'test2'})) # on our previous create_complete, worker would have updated the # rsrc.requires. Mock the same behavior here. self.stack = stack with mock.patch.object( parser.Stack, 'db_active_resources_get', side_effect=self._mock_convg_db_update_requires): curr_stack.thread_group_mgr = tools.DummyThreadGroupManager() curr_stack.converge_stack(template=template2, action=stack.UPDATE) self.assertIsNotNone(curr_stack.ext_rsrcs_db) self.assertEqual( 'Dependencies([' '((3, False), (1, False)), ' '((3, False), (2, False)), ' '((4, False), (3, False)), ' '((4, False), (4, True)), ' '((5, False), (3, False)), ' '((5, False), (5, True)), ' '((6, True), (8, True)), ' '((7, True), (8, True)), ' '((8, True), (4, True)), ' '((8, True), (5, True))])', repr(curr_stack.convergence_dependencies)) stack_db = stack_object.Stack.get_by_id(curr_stack.context, curr_stack.id) self.assertIsNotNone(stack_db.raw_template_id) self.assertIsNotNone(stack_db.current_traversal) self.assertIsNotNone(stack_db.prev_raw_template_id) self.assertTrue(stack_db.convergence) self.assertEqual( sorted([[[7, True], [8, True]], [[8, True], [5, True]], [[8, True], [4, True]], [[6, True], [8, True]], [[3, False], [2, False]], [[3, False], [1, False]], [[5, False], [3, False]], [[5, False], [5, True]], [[4, False], [3, False]], [[4, False], [4, True]]]), sorted(stack_db.current_deps['edges'])) ''' To visualize: G(7, True) H(6, True) \ / \ / B(4, False) A(5, False) \ / / \ / / \ / / / F(8, True) / / \ / / \ / / C(3, False) / \ / / \ / / \ / / / \ / / \ B(4, True) A(5, True) D(2, False) E(1, False) Leaves are at the bottom ''' # check if needed_by are stored properly # For A & B: # needed_by=C, F expected_needed_by = { 'A': [3, 8], 'B': [3, 8], 'C': [1, 2], 'D': [], 'E': [], 'F': [6, 7], 'G': [], 'H': [] } rsrcs_db = resource_objects.Resource.get_all_by_stack( stack_db._context, stack_db.id) self.assertEqual(8, len(rsrcs_db)) for rsrc_name, rsrc_obj in rsrcs_db.items(): self.assertEqual(sorted(expected_needed_by[rsrc_name]), sorted(rsrc_obj.needed_by)) # check if sync_points are created for forward traversal # [F, H, G, A, B, Stack] for entity_id in [8, 7, 6, 5, 4, stack_db.id]: sync_point = sync_point_object.SyncPoint.get_by_key( stack_db._context, entity_id, stack_db.current_traversal, True) self.assertIsNotNone(sync_point) self.assertEqual(stack_db.id, sync_point.stack_id) # check if sync_points are created for cleanup traversal # [A, B, C, D, E] for entity_id in [5, 4, 3, 2, 1]: sync_point = sync_point_object.SyncPoint.get_by_key( stack_db._context, entity_id, stack_db.current_traversal, False) self.assertIsNotNone(sync_point) self.assertEqual(stack_db.id, sync_point.stack_id) leaves = stack.convergence_dependencies.leaves() expected_calls = [] for rsrc_id, is_update in leaves: expected_calls.append( mock.call.worker_client.WorkerClient.check_resource( stack.context, rsrc_id, stack.current_traversal, {'input_data': {}}, is_update, None)) leaves = curr_stack.convergence_dependencies.leaves() for rsrc_id, is_update in leaves: expected_calls.append( mock.call.worker_client.WorkerClient.check_resource( curr_stack.context, rsrc_id, curr_stack.current_traversal, {'input_data': {}}, is_update, None)) self.assertEqual(expected_calls, mock_cr.mock_calls)
def _stack_with_template(self, template_def): self.ctx = utils.dummy_context() self.stack = parser.Stack(self.ctx, 'software_deploly_test_stack', template.Template(template_def)) self.deployment = self.stack['deploy_mysql']
def test_get_azs(self): tmpl = template.Template(empty_template) snippet = {"Fn::GetAZs": ""} self.assertEqual(["nova"], self.resolve(snippet, tmpl))
def test_to_parameters(self): """Tests property conversion to parameter values.""" provider = { 'HeatTemplateFormatVersion': '2012-12-12', 'Parameters': { 'Foo': { 'Type': 'String' }, 'AList': { 'Type': 'CommaDelimitedList' }, 'MemList': { '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" }, "MemList": { "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', template.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"], "MemList": [{ "key": "name", "value": "three" }, { "key": "name", "value": "four" }], "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 Member List conversion mem_exp = ('.member.0.key=name,' '.member.0.value=three,' '.member.1.key=name,' '.member.1.value=four') self.assertEqual(mem_exp, converted_params.get("MemList")) # 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 test_join(self): tmpl = template.Template(empty_template) join = {"Fn::Join": [" ", ["foo", "bar"]]} self.assertEqual("foo bar", self.resolve(join, tmpl))
def test_split_no_delim_in_str(self): tmpl = template.Template(empty_template) data = {"Fn::Split": [";", "foo, bar, achoo"]} self.assertEqual(['foo, bar, achoo'], self.resolve(data, tmpl))
def test_aws_version(self): tmpl = template.Template(mapping_template) self.assertEqual(('AWSTemplateFormatVersion', '2010-09-09'), tmpl.version)
def test_heat_version(self): tmpl = template.Template(resource_template) self.assertEqual(('HeatTemplateFormatVersion', '2012-12-12'), tmpl.version)
def _parse_child_template(self, child_template, child_env): parsed_child_template = child_template if isinstance(parsed_child_template, template.Template): parsed_child_template = parsed_child_template.t return template.Template(parsed_child_template, files=self.stack.t.files, env=child_env)
def parse_stack(self, t): stack_name = 'test_stack' tmpl = template.Template(t) stack = parser.Stack(utils.dummy_context(), stack_name, tmpl) stack.store() return stack
def test_stack_update_equals(self, ctr): stack_name = 'test_stack_update_equals_resource_limit' params = {} tpl = { 'HeatTemplateFormatVersion': '2012-12-12', 'Resources': { 'A': { 'Type': 'GenericResourceType' }, 'B': { 'Type': 'GenericResourceType' }, 'C': { 'Type': 'GenericResourceType' } } } template = templatem.Template(tpl) old_stack = stack.Stack(self.ctx, stack_name, template) sid = old_stack.store() old_stack.set_stack_user_project_id('1234') s = stack_object.Stack.get_by_id(self.ctx, sid) ctr.return_value = 3 stk = stack.Stack(self.ctx, stack_name, template) # prepare mocks mock_stack = self.patchobject(stack, 'Stack', return_value=stk) mock_load = self.patchobject(stack.Stack, 'load', return_value=old_stack) mock_tmpl = self.patchobject(templatem, 'Template', return_value=stk.t) mock_env = self.patchobject(environment, 'Environment', return_value=stk.env) mock_validate = self.patchobject(stk, 'validate', return_value=None) # do update cfg.CONF.set_override('max_resources_per_stack', 3) api_args = {'timeout_mins': 60} result = self.man.update_stack(self.ctx, old_stack.identifier(), template, params, None, api_args) # assertions self.assertEqual(old_stack.identifier(), result) self.assertIsInstance(result, dict) self.assertTrue(result['stack_id']) root_stack_id = old_stack.root_stack_id() self.assertEqual(3, old_stack.total_resources(root_stack_id)) mock_tmpl.assert_called_once_with(template, files=None, env=stk.env) mock_env.assert_called_once_with(params) mock_stack.assert_called_once_with( self.ctx, stk.name, stk.t, convergence=False, current_traversal=old_stack.current_traversal, prev_raw_template_id=None, current_deps=None, disable_rollback=True, nested_depth=0, owner_id=None, parent_resource=None, stack_user_project_id='1234', strict_validate=True, tenant_id='test_tenant_id', timeout_mins=60, user_creds_id=u'1', username='******') mock_load.assert_called_once_with(self.ctx, stack=s) mock_validate.assert_called_once_with()
def _get_resource_definition(self, template_version=('heat_template_version', '2015-04-30')): tmpl = template.Template(dict([template_version])) return tmpl.rsrc_defn_from_snippet(None, self.properties[self.RESOURCE])
def setUp(self): super(StackTest, self).setUp() self.tmpl = template.Template(copy.deepcopy(empty_template)) self.ctx = utils.dummy_context()
def test_select_from_serialized_json_map(self): tmpl = template.Template(empty_template) js = json.dumps({"red": "robin", "re": "foo"}) data = {"Fn::Select": ["re", js]} self.assertEqual("foo", self.resolve(data, tmpl))
def test_invalid_section(self): tmpl = template.Template({ 'HeatTemplateFormatVersion': '2012-12-12', 'Foo': ['Bar'] }) self.assertNotIn('Foo', tmpl)
def test_select_from_serialized_json_list(self): tmpl = template.Template(empty_template) js = json.dumps(["foo", "fee", "fum"]) data = {"Fn::Select": ["0", js]} self.assertEqual("foo", self.resolve(data, tmpl))
def test_find_in_map(self): tmpl = template.Template(mapping_template) stk = stack.Stack(self.ctx, 'test', tmpl) find = {'Fn::FindInMap': ["ValidMapping", "TestKey", "TestValue"]} self.assertEqual("wibble", self.resolve(find, tmpl, stk))
def test_split_ok(self): tmpl = template.Template(empty_template) data = {"Fn::Split": [";", "foo; bar; achoo"]} self.assertEqual(['foo', ' bar', ' achoo'], self.resolve(data, tmpl))
def test_param_refs(self): env = environment.Environment({'foo': 'bar', 'blarg': 'wibble'}) tmpl = template.Template(parameter_template, env=env) stk = stack.Stack(self.ctx, 'test', tmpl) p_snippet = {"Ref": "foo"} self.assertEqual("bar", self.resolve(p_snippet, tmpl, stk))
def test_base64(self): tmpl = template.Template(empty_template) snippet = {"Fn::Base64": "foobar"} # For now, the Base64 function just returns the original text, and # does not convert to base64 (see issue #133) self.assertEqual("foobar", self.resolve(snippet, tmpl))
def test_select_from_list_integer_index(self): tmpl = template.Template(empty_template) data = {"Fn::Select": [1, ["foo", "bar"]]} self.assertEqual("bar", self.resolve(data, tmpl))
def join(raw): tmpl = template.Template(mapping_template) return function.resolve(tmpl.parse(None, raw))
def test_select_int_from_dict(self): tmpl = template.Template(empty_template) data = {"Fn::Select": ["2", {"1": "bar", "2": "foo"}]} self.assertEqual("foo", self.resolve(data, tmpl))
def parse_stack(self, t): stack_name = 'test_stack' tmpl = template.Template(t) self.stack = stack.Stack(self.ctx, stack_name, tmpl) self.stack.validate() self.stack.store()
def test_select_from_none(self): tmpl = template.Template(empty_template) data = {"Fn::Select": ["red", None]} self.assertEqual("", self.resolve(data, tmpl))
def test_get_attribute_autoscaling(self): t = template_format.parse(heat_autoscaling_group_template) tmpl = templatem.Template(t) stack = parser.Stack(utils.dummy_context(), 'test_att', tmpl) rsrc = stack['my_autoscaling_group'] self.assertEqual(0, rsrc.FnGetAtt(rsrc.CURRENT_SIZE))
def test_select_from_dict_not_existing(self): tmpl = template.Template(empty_template) data = {"Fn::Select": ["green", {"red": "robin", "re": "foo"}]} self.assertEqual("", self.resolve(data, tmpl))
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' } tmpl = template.Template(t, env=environment.Environment(kwargs)) self.stack = parser.Stack(utils.dummy_context(), stack_name, tmpl, stack_id=str(uuid.uuid4())) image_id = 'CentOS 5.2' t['Resources']['WebServer']['Properties']['ImageId'] = image_id resource_defns = self.stack.t.resource_definitions(self.stack) nic = net_interfaces.NetworkInterface('%s_nic' % name, resource_defns['nic1'], self.stack) instance = instances.Instance('%s_name' % name, resource_defns['WebServer'], self.stack) metadata = instance.metadata_get() self._mock_get_image_id_success(image_id, 1) self.stub_SubnetConstraint_validate() self.patchobject(nic, 'client', return_value=FakeNeutron()) self.patchobject(neutron.NeutronClientPlugin, '_create', return_value=FakeNeutron()) self.patchobject(nova.NovaClientPlugin, '_create', return_value=self.fc) # need to resolve the template functions server_userdata = instance.client_plugin().build_userdata( metadata, instance.properties['UserData'], 'ec2-user') self.patchobject(nova.NovaClientPlugin, 'build_userdata', return_value=server_userdata) self.patchobject(self.fc.servers, 'create', return_value=return_server) # create network interface scheduler.TaskRunner(nic.create)() self.stack.resources["nic1"] = nic scheduler.TaskRunner(instance.create)() self.fc.servers.create.assert_called_once_with( 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) self.m_f_i.assert_called_with(image_id) nova.NovaClientPlugin.build_userdata.assert_called_once_with( metadata, instance.properties['UserData'], 'ec2-user') neutron.NeutronClientPlugin._create.assert_called_once_with() nova.NovaClientPlugin._create.assert_called_once_with() glance.GlanceClientPlugin.find_image_by_name_or_id.assert_called_with( image_id) return instance
def test_bad_input(self): tmpl = template.Template(empty_template) resolve = lambda s: TemplateTest.resolve(s, tmpl) error = self.assertRaises(self.expect, resolve, self.snippet) self.assertIn(self.snippet.keys()[0], six.text_type(error))