def test_env_register_while_get_resource_info(self): env_test = {u'resource_registry': { u'OS::Test::Dummy': self.resource_type}} env = environment.Environment() env.load(env_test) env.get_resource_info('OS::Test::Dummy') self.assertEqual({'OS::Test::Dummy': self.resource_type, 'resources': {}}, env.user_env_as_dict().get( environment_format.RESOURCE_REGISTRY)) env_test = {u'resource_registry': { u'resources': {u'test': {u'OS::Test::Dummy': self.resource_type}}}} env.load(env_test) env.get_resource_info('OS::Test::Dummy') self.assertEqual({u'OS::Test::Dummy': self.resource_type, 'resources': {u'test': {u'OS::Test::Dummy': self.resource_type}}}, env.user_env_as_dict().get( environment_format.RESOURCE_REGISTRY))
def test_env_load(self): new_env = { u'resource_registry': { u'resources': { u'my_fip': { u'OS::Networking::FloatingIP': 'ip.yaml' } } } } env = environment.Environment() self.assertIsNone( env.get_resource_info('OS::Networking::FloatingIP', 'my_fip')) env.load(new_env) self.assertEqual( 'ip.yaml', env.get_resource_info('OS::Networking::FloatingIP', 'my_fip').value)
def test_env_load(self): new_env = { u'resource_registry': { u'resources': { u'my_fip': { u'OS::Networking::FloatingIP': 'ip.yaml' } } } } env = environment.Environment() self.assertRaises(exception.EntityNotFound, env.get_resource_info, 'OS::Networking::FloatingIP', 'my_fip') env.load(new_env) self.assertEqual( 'ip.yaml', env.get_resource_info('OS::Networking::FloatingIP', 'my_fip').value)
def test_properties_normal(self): provider = { 'HeatTemplateFormatVersion': '2012-12-12', 'Parameters': { 'Foo': { 'Type': 'String' }, 'Blarg': { 'Type': 'String', 'Default': 'wibble' }, }, } files = {'test_resource.template': json.dumps(provider)} class DummyResource(object): support_status = support.SupportStatus() properties_schema = { "Foo": properties.Schema(properties.Schema.STRING, required=True) } attributes_schema = {} 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())) definition = rsrc_defn.ResourceDefinition('test_t_res', "DummyResource", {"Foo": "bar"}) temp_res = template_resource.TemplateResource('test_t_res', definition, stack) self.assertIsNone(temp_res.validate())
def test_FnGetAtt_metadata_update(self, mock_get, mock_check, mock_handle, *args): temp = template_format.parse(TEST_TEMPLATE_SERVER) template = tmpl.Template(temp, env=environment.Environment({})) ctx = utils.dummy_context() stack = stk.Stack(ctx, 'test-stack', template, disable_rollback=True) stack.store() self.stub_KeypairConstraint_validate() # Note dummy addresses are from TEST-NET-1 ref rfc5737 mock_get.side_effect = ['192.0.2.1', '192.0.2.2'] # Test stack.create() self.assertEqual((stack.CREATE, stack.COMPLETE), stack.state) s1 = stack['instance1'] s2 = stack['instance2'] md = s1.metadata_get() self.assertEqual({u'template_data': '192.0.2.1'}, md) # Now set some metadata via the resource, like is done by # _populate_deployments_metadata. This should be persisted over # calls to metadata_update() new_md = {u'template_data': '192.0.2.2', 'set_by_rsrc': 'orange'} s1.metadata_set(new_md) md = s1.metadata_get(refresh=True) self.assertEqual(new_md, md) s2.attributes.reset_resolved_values() stk_defn.update_resource_data(stack.defn, s2.name, s2.node_data()) s1.metadata_update() md = s1.metadata_get(refresh=True) self.assertEqual(new_md, md) # Verify outgoing calls mock_get.assert_has_calls( [mock.call('networks'), mock.call('networks')]) self.assertEqual(2, mock_handle.call_count) self.assertEqual(2, mock_check.call_count)
def test_no_infinite_recursion(self): """Prove that we can override a python resource. And use that resource within the template resource. """ main_templ = ''' heat_template_version: 2013-05-23 resources: secret2: type: OS::Heat::RandomString outputs: secret1: value: { get_attr: [secret1, value] } ''' nested_templ = ''' heat_template_version: 2013-05-23 resources: secret2: type: OS::Heat::RandomString outputs: value: value: { get_attr: [secret2, value] } ''' env_templ = ''' resource_registry: "OS::Heat::RandomString": nested.yaml ''' env = environment.Environment() env.load(yaml.load(env_templ)) templ = parser.Template(template_format.parse(main_templ), files={'nested.yaml': nested_templ}) stack = parser.Stack(utils.dummy_context(), utils.random_name(), templ, env=env) stack.store() stack.create() self.assertEqual((stack.CREATE, stack.COMPLETE), stack.state)
def _setup_test_group(self, intags=None, nova_tags=None): stack_name = 'tag_test' t = template_format.parse(group_template) template = parser.Template(t) stack = parser.Stack(utils.dummy_context(), stack_name, template, environment.Environment({'KeyName': 'test'}), stack_id=str(uuid.uuid4())) t['Resources']['WebServer']['Properties']['Tags'] = intags # create the launch configuration conf = stack['Config'] self.assertIsNone(conf.validate()) scheduler.TaskRunner(conf.create)() self.assertEqual((conf.CREATE, conf.COMPLETE), conf.state) group = stack['WebServer'] nova_tags['metering.groupname'] = utils.PhysName( stack.name, group.name) self.m.StubOutWithMock(nova.NovaClientPlugin, '_create') nova.NovaClientPlugin._create().MultipleTimes().AndReturn(self.fc) self._mock_get_image_id_success('CentOS 5.2', 1) # need to resolve the template functions self.m.StubOutWithMock(self.fc.servers, 'create') self.fc.servers.create(image=1, flavor=1, key_name='test', name=mox.IgnoreArg(), security_groups=None, userdata=mox.IgnoreArg(), scheduler_hints=None, meta=nova_tags, nics=None, availability_zone=None).AndReturn( self.fc.servers.list()[1]) return group
def test_properties_type_mismatch(self): provider = { 'HeatTemplateFormatVersion': '2012-12-12', 'Parameters': { 'Foo': { 'Type': 'String' }, }, } files = {'test_resource.template': json.dumps(provider)} class DummyResource(object): properties_schema = { "Foo": properties.Schema(properties.Schema.MAP) } attributes_schema = {} 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( {'HeatTemplateFormatVersion': '2012-12-12'}, files=files), env=env, stack_id=str(uuid.uuid4())) definition = rsrc_defn.ResourceDefinition('test_t_res', "DummyResource", {"Foo": "bar"}) temp_res = template_resource.TemplateResource('test_t_res', definition, stack) ex = self.assertRaises(exception.StackValidationFailed, temp_res.validate) self.assertEqual( "Property Foo type mismatch between facade " "DummyResource (Map) and provider (String)", six.text_type(ex))
def load(cls, context, stack_id=None, stack=None, resolve_data=True, parent_resource=None, show_deleted=True): '''Retrieve a Stack from the database.''' if stack is None: stack = db_api.stack_get(context, stack_id, show_deleted=show_deleted, eager_load=True) if stack is None: message = _('No stack exists with id "%s"') % str(stack_id) raise exception.NotFound(message) template = Template.load(context, stack.raw_template_id, stack.raw_template) env = environment.Environment(stack.parameters) stack = cls(context, stack.name, template, env, stack.id, stack.action, stack.status, stack.status_reason, stack.timeout, resolve_data, stack.disable_rollback, parent_resource, owner_id=stack.owner_id, stack_user_project_id=stack.stack_user_project_id, created_time=stack.created_at, updated_time=stack.updated_at, user_creds_id=stack.user_creds_id, tenant_id=stack.tenant, validate_parameters=False) return stack
def _setup_test_instance(self, intags=None, nova_tags=None): stack_name = 'tag_test' t = template_format.parse(instance_template) template = parser.Template(t) stack = parser.Stack(utils.dummy_context(), stack_name, template, environment.Environment({'KeyName': 'test'}), stack_id=str(uuid.uuid4())) t['Resources']['WebServer']['Properties']['Tags'] = intags instance = instances.Instance(stack_name, t['Resources']['WebServer'], stack) 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=1, key_name='test', name=utils.PhysName(stack_name, instance.name), security_groups=None, userdata=server_userdata, scheduler_hints=None, meta=nova_tags, nics=None, availability_zone=None).AndReturn( self.fc.servers.list()[1]) return instance
def test_equals(self): tpl = template_format.parse(''' HeatTemplateFormatVersion: 2016-10-14 Parameters: env_type: Type: String Default: 'test' ''') snippet = {'Fn::Equals': [{'Ref': 'env_type'}, 'prod']} # when param 'env_type' is 'test', equals function resolve to false tmpl = template.Template(tpl) stk = stack.Stack(utils.dummy_context(), 'test_equals_false', tmpl) resolved = self.resolve(snippet, tmpl, stk) self.assertFalse(resolved) # when param 'env_type' is 'prod', equals function resolve to true tmpl = template.Template(tpl, env=environment.Environment( {'env_type': 'prod'})) stk = stack.Stack(utils.dummy_context(), 'test_equals_true', tmpl) resolved = self.resolve(snippet, tmpl, stk) self.assertTrue(resolved)
def test_constraints_registry(self): constraint_content = ''' class MyConstraint(object): pass def constraint_mapping(): return {"constraint1": MyConstraint} ''' plugin_dir = self.useFixture(fixtures.TempDir()) plugin_file = os.path.join(plugin_dir.path, 'test.py') with open(plugin_file, 'w+') as ef: ef.write(constraint_content) self.addCleanup(sys.modules.pop, "heat.engine.plugins.test") cfg.CONF.set_override('plugin_dirs', plugin_dir.path) env = environment.Environment({}) resources._load_global_environment(env) self.assertEqual("MyConstraint", env.get_constraint("constraint1").__name__) self.assertIs(None, env.get_constraint("no_constraint"))
def test_continue_on_parse_error(self): """assert we get all files processed even if there are processing exceptions. """ with mock.patch('glob.glob') as m_ldir: m_ldir.return_value = ['/etc_etc/heat/environment.d/a.yaml', '/etc_etc/heat/environment.d/b.yaml'] env_dir = '/etc_etc/heat/environment.d' env_content = '{@$%#$%' env = environment.Environment({}, user_env=False) with mock.patch('heat.engine.environment.open', mock.mock_open(read_data=env_content), create=True) as m_open: environment.read_global_environment(env, env_dir) m_ldir.assert_called_once_with(env_dir + '/*') expected = [mock.call('%s/a.yaml' % env_dir), mock.call('%s/b.yaml' % env_dir)] self.assertEqual(expected, m_open.call_args_list)
def test_user_template_retrieve_fail_ext(self): # make sure that a TemplateResource defined in the user environment # fails gracefully if the template file is the wrong extension # we should be able to create the TemplateResource object, but # validation should fail, when the second attempt to access it is # made in validate() env = environment.Environment() test_templ_name = 'http://heatr/letter_to_granny.docx' env.load({'resource_registry': {'Test::Flippy': test_templ_name}}) stack = parser.Stack(utils.dummy_context(), 'test_stack', template.Template(empty_template, env=env), stack_id=str(uuid.uuid4())) self.m.ReplayAll() definition = rsrc_defn.ResourceDefinition('test_t_res', 'Test::Flippy') temp_res = template_resource.TemplateResource('test_t_res', definition, stack) self.assertRaises(exception.StackValidationFailed, temp_res.validate) self.m.VerifyAll()
def create_stack(self, stack_name='test_stack', params={}): temp = template_format.parse(test_template_metadata) template = parser.Template(temp) ctx = utils.dummy_context() stack = parser.Stack(ctx, stack_name, template, environment.Environment(params), disable_rollback=True) self.stack_id = stack.store() self.m.StubOutWithMock(instance.Instance, 'handle_create') self.m.StubOutWithMock(instance.Instance, 'check_create_complete') for cookie in (object(), object()): instance.Instance.handle_create().AndReturn(cookie) create_complete = instance.Instance.check_create_complete(cookie) create_complete.InAnyOrder().AndReturn(True) self.m.StubOutWithMock(instance.Instance, 'FnGetAtt') return stack
def create_with_template(self, child_template, user_params, timeout_mins=None, adopt_data=None): ''' Handle the creation of the nested stack from a given JSON template. ''' if self.recursion_depth >= cfg.CONF.max_nested_stack_depth: msg = _("Recursion depth exceeds %d.") % \ cfg.CONF.max_nested_stack_depth raise exception.RequestLimitExceeded(message=msg) template = parser.Template(child_template, files=self.stack.t.files) self._validate_nested_resources(template) self._outputs_to_attribs(child_template) if timeout_mins is None: timeout_mins = self.stack.timeout_mins # Note we disable rollback for nested stacks, since they # should be rolled back by the parent stack on failure nested = parser.Stack(self.context, self.physical_resource_name(), template, environment.Environment(user_params), timeout_mins=timeout_mins, disable_rollback=True, parent_resource=self, owner_id=self.stack.id, adopt_stack_data=adopt_data) nested.validate() self._nested = nested nested_id = self._nested.store() self.resource_id_set(nested_id) action = self._nested.CREATE if adopt_data: action = self._nested.ADOPT stack_creator = scheduler.TaskRunner(self._nested.stack_task, action=action) stack_creator.start(timeout=self._nested.timeout_secs()) return stack_creator
def _setup_test_instance(self, intags=None, nova_tags=None): stack_name = 'tag_test' t = template_format.parse(instance_template) template = tmpl.Template(t, env=environment.Environment( {'KeyName': 'test'})) stack = parser.Stack(utils.dummy_context(), stack_name, template, stack_id=str(uuid.uuid4())) t['Resources']['WebServer']['Properties']['Tags'] = intags resource_defns = template.resource_definitions(stack) instance = instances.Instance(stack_name, resource_defns['WebServer'], stack) self.m.StubOutWithMock(nova.NovaClientPlugin, '_create') nova.NovaClientPlugin._create().AndReturn(self.fc) self._mock_get_image_id_success('CentOS 5.2', 1) # need to resolve the template functions metadata = instance.metadata_get() 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=1, key_name='test', name=utils.PhysName(stack_name, instance.name), security_groups=None, userdata=server_userdata, scheduler_hints=None, meta=nova_tags, nics=None, availability_zone=None, block_device_mapping=None).AndReturn( self.fc.servers.list()[1]) return instance
def setUp(self): super(ValidateGetAttTest, self).setUp() env = environment.Environment() env.load({ u'resource_registry': { u'OS::Test::GenericResource': u'GenericResourceType' } }) env.load({ u'resource_registry': { u'OS::Test::FakeResource': u'OverwrittenFnGetAttType' } }) tmpl = template.Template( { "HeatTemplateFormatVersion": "2012-12-12", "Resources": { "test_rsrc": { "Type": "OS::Test::GenericResource" }, "get_att_rsrc": { "Type": "OS::Heat::Value", "Properties": { "value": { "Fn::GetAtt": ["test_rsrc", "Foo"] } } } } }, env=env) self.stack = stack.Stack(utils.dummy_context(), 'test_stack', tmpl, stack_id=str(uuid.uuid4())) self.rsrc = self.stack['test_rsrc'] self.stack.validate()
def test_metadata_update_called(self): provider = { 'HeatTemplateFormatVersion': '2012-12-12', 'Parameters': { 'Foo': { 'Type': 'Boolean' }, }, } files = {'test_resource.template': json.dumps(provider)} class DummyResource(object): support_status = support.SupportStatus() properties_schema = { "Foo": properties.Schema(properties.Schema.BOOLEAN) } attributes_schema = {} 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( {'HeatTemplateFormatVersion': '2012-12-12'}, files=files, env=env), stack_id=str(uuid.uuid4())) definition = rsrc_defn.ResourceDefinition('test_t_res', "DummyResource", {"Foo": "False"}) temp_res = template_resource.TemplateResource('test_t_res', definition, stack) temp_res.metadata_set = mock.Mock() temp_res.metadata_update() temp_res.metadata_set.assert_called_once_with({})
def _setup_test_group_autoscaling(self, intags=None, nova_tags=None): stack_name = 'tag_as_name' t = template_format.parse(autoscaling_template) template = parser.Template(t) stack = parser.Stack(utils.dummy_context(), stack_name, template, environment.Environment({'KeyName': 'test'}), stack_id=str(uuid.uuid4())) t['Resources']['WebServer']['Properties']['Tags'] += intags # create the launch configuration conf = stack['Config'] self.assertIsNone(conf.validate()) scheduler.TaskRunner(conf.create)() self.assertEqual((conf.CREATE, conf.COMPLETE), conf.state) group = stack['WebServer'] group_refid = utils.PhysName(stack.name, group.name) nova_tags['metering.groupname'] = group_refid nova_tags['AutoScalingGroupName'] = group_refid self.m.StubOutWithMock(group, '_cooldown_timestamp') group._cooldown_timestamp(mox.IgnoreArg()).AndReturn(None) self.m.StubOutWithMock(instances.Instance, 'nova') instances.Instance.nova().MultipleTimes().AndReturn(self.fc) group.t = group.stack.resolve_runtime_data(group.t) # need to resolve the template functions self.m.StubOutWithMock(self.fc.servers, 'create') self.fc.servers.create( image=1, flavor=1, key_name='test', name=mox.IgnoreArg(), security_groups=None, userdata=mox.IgnoreArg(), scheduler_hints=None, meta=nova_tags, nics=None, availability_zone=None).AndReturn( self.fc.servers.list()[1]) return group
def update_stack(self, cnxt, stack_identity, template, params, files, args): """ The update_stack method updates an existing stack based on the provided template and parameters. Note that at this stage the template has already been fetched from the heat-api process if using a template-url. arg1 -> RPC context. arg2 -> Name of the stack you want to create. arg3 -> Template of stack you want to create. arg4 -> Stack Input Params arg4 -> Request parameters/args passed from API """ logger.info('template is %s' % template) self._validate_mandatory_credentials(cnxt) # Get the database representation of the existing stack db_stack = self._get_stack(cnxt, stack_identity) if db_stack.status != parser.Stack.COMPLETE: raise exception.ActionInProgress(stack_name=db_stack.name, action=db_stack.action) current_stack = parser.Stack.load(cnxt, stack=db_stack) # Now parse the template and any parameters for the updated # stack definition. tmpl = parser.Template(template, files=files) stack_name = current_stack.name common_params = api.extract_args(args) env = environment.Environment(params) updated_stack = parser.Stack(cnxt, stack_name, tmpl, env, **common_params) updated_stack.validate() self._start_in_thread(db_stack.id, current_stack.update, updated_stack) return dict(current_stack.identifier())
def test_properties_list_with_none(self): provider = { 'HeatTemplateFormatVersion': '2012-12-12', 'Parameters': { 'Foo': {'Type': "CommaDelimitedList"}, }, } files = {'test_resource.template': json.dumps(provider)} class DummyResource(generic_rsrc.GenericResource): support_status = support.SupportStatus() properties_schema = {"Foo": properties.Schema(properties.Schema.LIST)} attributes_schema = {} 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( {'HeatTemplateFormatVersion': '2012-12-12'}, files=files, env=env), stack_id=str(uuid.uuid4())) definition = rsrc_defn.ResourceDefinition('test_t_res', "DummyResource", {"Foo": [None, 'test', None]}) temp_res = template_resource.TemplateResource('test_t_res', definition, stack) self.assertIsNone(temp_res.validate()) definition = rsrc_defn.ResourceDefinition('test_t_res', "DummyResource", {"Foo": [None, None, None]}) temp_res = template_resource.TemplateResource('test_t_res', definition, stack) self.assertIsNone(temp_res.validate())
def _setup_test_group(self, intags=None, nova_tags=None): stack_name = 'tag_test' t = template_format.parse(group_template) template = parser.Template(t) stack = parser.Stack(utils.dummy_context(), stack_name, template, environment.Environment({'KeyName': 'test'}), stack_id=uuidutils.generate_uuid()) t['Resources']['WebServer']['Properties']['Tags'] = intags # create the launch configuration conf = stack.resources['Config'] self.assertEqual(None, conf.validate()) scheduler.TaskRunner(conf.create)() self.assertEqual((conf.CREATE, conf.COMPLETE), conf.state) group = stack.resources['WebServer'] self.m.StubOutWithMock(instances.Instance, 'nova') instances.Instance.nova().MultipleTimes().AndReturn(self.fc) group.t = group.stack.resolve_runtime_data(group.t) # need to resolve the template functions self.m.StubOutWithMock(self.fc.servers, 'create') self.fc.servers.create(image=1, flavor=1, key_name='test', name=mox.IgnoreArg(), security_groups=None, userdata=mox.IgnoreArg(), scheduler_hints=None, meta=nova_tags, nics=None, availability_zone=None).AndReturn( self.fc.servers.list()[1]) return group
def test_properties_type_mismatch(self): provider = { 'Parameters': { 'Foo': { 'Type': 'String' }, }, } files = {'test_resource.template': json.dumps(provider)} class DummyResource(object): properties_schema = { "Foo": properties.Schema(properties.Schema.MAP) } attributes_schema = {} json_snippet = { "Type": "DummyResource", "Properties": { "Foo": "bar", }, } 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( {'HeatTemplateFormatVersion': '2012-12-12'}, files=files), env=env, stack_id=str(uuid.uuid4())) temp_res = template_resource.TemplateResource('test_t_res', json_snippet, stack) self.assertRaises(exception.StackValidationFailed, temp_res.validate)
def create_stack(self, stack_name='test_stack_native', params=None): params = params or {} temp = template_format.parse(test_template_server) template = tmpl.Template(temp, env=environment.Environment(params)) ctx = utils.dummy_context() stack = parser.Stack(ctx, stack_name, template, disable_rollback=True) self.stack_id = stack.store() self.stub_ImageConstraint_validate() self.stub_KeypairConstraint_validate() self.stub_FlavorConstraint_validate() self.m.StubOutWithMock(server.Server, 'handle_create') self.m.StubOutWithMock(server.Server, 'check_create_complete') for cookie in (object(), object()): server.Server.handle_create().AndReturn(cookie) create_complete = server.Server.check_create_complete(cookie) create_complete.InAnyOrder().AndReturn(True) self.m.StubOutWithMock(server.Server, 'FnGetAtt') return stack
def test_attributes_not_parsable(self): provider = { 'HeatTemplateFormatVersion': '2012-12-12', 'Outputs': { 'Blarg': { 'Value': 'wibble' }, }, } files = {'test_resource.template': json.dumps(provider)} env = environment.Environment() 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())) definition = rsrc_defn.ResourceDefinition('test_t_res', "DummyResource") temp_res = template_resource.TemplateResource('test_t_res', definition, stack) self.assertIsNone(temp_res.validate()) nested = mock.Mock() nested.outputs = { 'Blarg': { 'Value': 'not-this', 'error_msg': 'it is all bad' } } nested.output.return_value = None temp_res._nested = nested self.assertRaises(exception.InvalidTemplateAttribute, temp_res.FnGetAtt, 'Blarg')
def setUp(self): super(TemplateResourceCrudTest, self).setUp() files = {'test_resource.template': json.dumps(self.provider)} self.ctx = utils.dummy_context() env = environment.Environment() env.load({'resource_registry': {'ResourceWithRequiredPropsAndEmptyAttrs': 'test_resource.template'}}) self.stack = parser.Stack(self.ctx, 'test_stack', template.Template(empty_template, files=files, env=env), stack_id=str(uuid.uuid4())) self.defn = rsrc_defn.ResourceDefinition( 'test_t_res', "ResourceWithRequiredPropsAndEmptyAttrs", {"Foo": "bar"}) self.res = template_resource.TemplateResource('test_t_res', self.defn, self.stack) self.assertIsNone(self.res.validate())
def get_stack(stack_name, ctx, template=None, with_params=True, convergence=False, **kwargs): if template is None: t = template_format.parse(wp_template) if with_params: env = environment.Environment({'KeyName': 'test'}) tmpl = templatem.Template(t, env=env) else: tmpl = templatem.Template(t) else: t = template_format.parse(template) tmpl = templatem.Template(t) stack = parser.Stack(ctx, stack_name, tmpl, convergence=convergence, **kwargs) return stack
def parse_stack(t, params=None, files=None, stack_name=None, stack_id=None, timeout_mins=None): params = params or {} files = files or {} ctx = dummy_context() templ = template.Template(t, files=files, env=environment.Environment(params)) templ.store() if stack_name is None: stack_name = random_name() stk = stack.Stack(ctx, stack_name, templ, stack_id=stack_id, timeout_mins=timeout_mins) stk.store() return stk
def update_with_template(self, child_template, user_params, timeout_mins=None): """Update the nested stack with the new template.""" template = parser.Template(child_template) # Note that there is no call to self._outputs_to_attribs here. # If we have a use case for updating attributes of the resource based # on updated templates we should make sure it's optional because not # all subclasses want that behavior, since they may offer custom # attributes. # Note we disable rollback for nested stacks, since they # should be rolled back by the parent stack on failure stack = parser.Stack(self.context, self.physical_resource_name(), template, environment.Environment(user_params), timeout_mins=timeout_mins, disable_rollback=True, parent_resource=self, owner_id=self.stack.id) stack.validate() nested_stack = self.nested() if nested_stack is None: raise exception.Error( _('Cannot update %s, stack not created') % self.name) if not hasattr(type(self), 'attributes_schema'): self.attributes = None self._outputs_to_attribs(child_template) nested_stack.update(stack) if nested_stack.state != (nested_stack.UPDATE, nested_stack.COMPLETE): raise exception.Error("Nested stack update failed: %s" % nested_stack.status_reason)