diff --git a/heat/engine/parser.py b/heat/engine/parser.py index e441eee3b9..1266fd16c0 100644 --- a/heat/engine/parser.py +++ b/heat/engine/parser.py @@ -17,6 +17,7 @@ import eventlet import functools import re +from heat.engine import environment from heat.common import exception from heat.engine import dependencies from heat.common import identifier @@ -64,12 +65,12 @@ class Stack(object): _zones = None - def __init__(self, context, stack_name, tmpl, parameters=None, + def __init__(self, context, stack_name, tmpl, env=None, stack_id=None, state=None, state_description='', timeout_mins=60, resolve_data=True, disable_rollback=True): ''' Initialise from a context, name, Template object and (optionally) - Parameters object. The database ID may also be initialised, if the + Environment object. The database ID may also be initialised, if the stack is already in the database. ''' @@ -91,9 +92,9 @@ class Stack(object): resources.initialise() - if parameters is None: - parameters = Parameters(self.name, self.t) - self.parameters = parameters + self.env = env or environment.Environment({}) + self.parameters = Parameters(self.name, self.t, + user_params=self.env.params) self._set_param_stackid() @@ -142,8 +143,8 @@ class Stack(object): raise exception.NotFound(message) template = Template.load(context, stack.raw_template_id) - params = Parameters(stack.name, template, stack.parameters) - stack = cls(context, stack.name, template, params, + env = environment.Environment(stack.parameters) + stack = cls(context, stack.name, template, env, stack.id, stack.status, stack.status_reason, stack.timeout, resolve_data, stack.disable_rollback) @@ -159,7 +160,7 @@ class Stack(object): s = { 'name': self.name, 'raw_template_id': self.t.store(self.context), - 'parameters': self.parameters.user_parameters(), + 'parameters': self.env.user_env_as_dict(), 'owner_id': owner and owner.id, 'user_creds_id': new_creds.id, 'username': self.context.username, @@ -439,7 +440,7 @@ class Stack(object): stack_status = self.UPDATE_FAILED else: oldstack = Stack(self.context, self.name, self.t, - self.parameters) + self.env) self.update(oldstack, action=self.ROLLBACK) return else: @@ -447,12 +448,12 @@ class Stack(object): self.state_set(stack_status, reason) - # flip the template & parameters to the newstack values + # flip the template & environment to the newstack values # Note we do this on success and failure, so the current # stack resources are stored, even if one is in a failed # state (otherwise we won't remove them on delete) self.t = newstack.t - self.parameters = newstack.parameters + self.env = newstack.env template_outputs = self.t[template.OUTPUTS] self.outputs = self.resolve_static_data(template_outputs) self.store() diff --git a/heat/engine/resource.py b/heat/engine/resource.py index dd68939da2..9cb7cb6252 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -38,8 +38,11 @@ def get_types(): return iter(_resource_classes) -def get_class(resource_type): +def get_class(resource_type, resource_name=None, environment=None): '''Return the Resource class for a given resource type.''' + if environment: + resource_type = environment.get_resource_type(resource_type, + resource_name) cls = _resource_classes.get(resource_type) if cls is None: msg = "Unknown resource Type : %s" % resource_type @@ -127,7 +130,9 @@ class Resource(object): return super(Resource, cls).__new__(cls) # Select the correct subclass to instantiate - ResourceClass = get_class(json['Type']) + ResourceClass = get_class(json['Type'], + resource_name=name, + environment=stack.env) return ResourceClass(name, json, stack) def __init__(self, name, json_snippet, stack): diff --git a/heat/engine/resources/autoscaling.py b/heat/engine/resources/autoscaling.py index dd57620d4d..126f8cafa3 100644 --- a/heat/engine/resources/autoscaling.py +++ b/heat/engine/resources/autoscaling.py @@ -110,7 +110,9 @@ class InstanceGroup(resource.Resource): def _make_instance(self, name): - Instance = resource.get_class('AWS::EC2::Instance') + Instance = resource.get_class('AWS::EC2::Instance', + resource_name=name, + environment=self.stack.env) class GroupedInstance(Instance): ''' diff --git a/heat/engine/service.py b/heat/engine/service.py index dd0db0cc53..3f1030034b 100644 --- a/heat/engine/service.py +++ b/heat/engine/service.py @@ -24,6 +24,7 @@ from heat.db import api as db_api from heat.engine import api from heat.engine import clients from heat.engine.event import Event +from heat.engine import environment from heat.common import exception from heat.common import identifier from heat.engine import parameters @@ -212,12 +213,11 @@ class EngineService(service.Service): tmpl = parser.Template(template) - # Extract the template parameters, and any common query parameters - template_params = parser.Parameters(stack_name, tmpl, params) + # Extract the common query parameters common_params = api.extract_args(args) - - stack = parser.Stack(cnxt, stack_name, tmpl, template_params, - **common_params) + env = environment.Environment(params) + stack = parser.Stack(cnxt, stack_name, tmpl, + env, **common_params) stack.validate() @@ -251,11 +251,10 @@ class EngineService(service.Service): # stack definition. tmpl = parser.Template(template) stack_name = current_stack.name - template_params = parser.Parameters(stack_name, tmpl, params) common_params = api.extract_args(args) - + env = environment.Environment(params) updated_stack = parser.Stack(cnxt, stack_name, tmpl, - template_params, **common_params) + env, **common_params) updated_stack.validate() diff --git a/heat/engine/stack_resource.py b/heat/engine/stack_resource.py index b09f4a2ca6..1bab2627a8 100644 --- a/heat/engine/stack_resource.py +++ b/heat/engine/stack_resource.py @@ -14,6 +14,7 @@ # under the License. from heat.common import exception +from heat.engine import environment from heat.engine import resource from heat.engine import parser from heat.engine import scheduler @@ -52,15 +53,13 @@ class StackResource(resource.Resource): Handle the creation of the nested stack from a given JSON template. ''' template = parser.Template(child_template) - params = parser.Parameters(self.physical_resource_name(), template, - user_params) # Note we disable rollback for nested stacks, since they # should be rolled back by the parent stack on failure self._nested = parser.Stack(self.context, self.physical_resource_name(), template, - params, + environment.Environment(user_params), timeout_mins=timeout_mins, disable_rollback=True) diff --git a/heat/tests/test_engine_service.py b/heat/tests/test_engine_service.py index a6b52d8ed6..55018db675 100644 --- a/heat/tests/test_engine_service.py +++ b/heat/tests/test_engine_service.py @@ -22,6 +22,7 @@ from oslo.config import cfg from heat.common import config from heat.common import context +from heat.engine import environment from heat.common import exception from heat.tests.v1_1 import fakes import heat.engine.api as engine_api @@ -78,10 +79,8 @@ def create_context(mocks, user='stacks_test_user', def get_wordpress_stack(stack_name, ctx): t = template_format.parse(wp_template) template = parser.Template(t) - parameters = parser.Parameters(stack_name, template, - {'KeyName': 'test'}) - - stack = parser.Stack(ctx, stack_name, template, parameters) + stack = parser.Stack(ctx, stack_name, template, + environment.Environment({'KeyName': 'test'})) return stack @@ -244,15 +243,13 @@ class stackServiceCreateUpdateDeleteTest(HeatTestCase): stack = get_wordpress_stack(stack_name, self.ctx) self.m.StubOutWithMock(parser, 'Template') - self.m.StubOutWithMock(parser, 'Parameters') + self.m.StubOutWithMock(environment, 'Environment') self.m.StubOutWithMock(parser, 'Stack') parser.Template(template).AndReturn(stack.t) - parser.Parameters(stack_name, - stack.t, - params).AndReturn(stack.parameters) + environment.Environment(params).AndReturn(stack.env) parser.Stack(self.ctx, stack.name, - stack.t, stack.parameters).AndReturn(stack) + stack.t, stack.env).AndReturn(stack) self.m.StubOutWithMock(stack, 'validate') stack.validate().AndReturn(None) @@ -277,15 +274,14 @@ class stackServiceCreateUpdateDeleteTest(HeatTestCase): stack = get_wordpress_stack(stack_name, self.ctx) self.m.StubOutWithMock(parser, 'Template') - self.m.StubOutWithMock(parser, 'Parameters') + self.m.StubOutWithMock(environment, 'Environment') self.m.StubOutWithMock(parser, 'Stack') parser.Template(template).AndReturn(stack.t) - parser.Parameters(stack_name, - stack.t, - params).AndReturn(stack.parameters) + environment.Environment(params).AndReturn(stack.env) parser.Stack(self.ctx, stack.name, - stack.t, stack.parameters).AndReturn(stack) + stack.t, + stack.env).AndReturn(stack) self.m.StubOutWithMock(stack, 'validate') stack.validate().AndRaise(exception.StackValidationFailed( @@ -393,14 +389,12 @@ class stackServiceCreateUpdateDeleteTest(HeatTestCase): parser.Stack.load(self.ctx, stack=s).AndReturn(old_stack) self.m.StubOutWithMock(parser, 'Template') - self.m.StubOutWithMock(parser, 'Parameters') + self.m.StubOutWithMock(environment, 'Environment') parser.Template(template).AndReturn(stack.t) - parser.Parameters(stack_name, - stack.t, - params).AndReturn(stack.parameters) + environment.Environment(params).AndReturn(stack.env) parser.Stack(self.ctx, stack.name, - stack.t, stack.parameters).AndReturn(stack) + stack.t, stack.env).AndReturn(stack) self.m.StubOutWithMock(stack, 'validate') stack.validate().AndReturn(None) @@ -434,14 +428,12 @@ class stackServiceCreateUpdateDeleteTest(HeatTestCase): parser.Stack.load(self.ctx, stack=s).AndReturn(old_stack) self.m.StubOutWithMock(parser, 'Template') - self.m.StubOutWithMock(parser, 'Parameters') + self.m.StubOutWithMock(environment, 'Environment') parser.Template(template).AndReturn(stack.t) - parser.Parameters(stack_name, - stack.t, - params).AndReturn(stack.parameters) + environment.Environment(params).AndReturn(stack.env) parser.Stack(self.ctx, stack.name, - stack.t, stack.parameters).AndReturn(stack) + stack.t, stack.env).AndReturn(stack) self.m.StubOutWithMock(stack, 'validate') stack.validate().AndRaise(exception.StackValidationFailed( diff --git a/heat/tests/test_instance.py b/heat/tests/test_instance.py index e9e63fd62e..937e534a7f 100644 --- a/heat/tests/test_instance.py +++ b/heat/tests/test_instance.py @@ -17,6 +17,7 @@ import copy import mox +from heat.engine import environment from heat.tests.v1_1 import fakes from heat.engine.resources import instance as instances from heat.common import exception @@ -65,8 +66,8 @@ class instancesTest(HeatTestCase): def _setup_test_stack(self, stack_name): t = template_format.parse(wp_template) template = parser.Template(t) - params = parser.Parameters(stack_name, template, {'KeyName': 'test'}) - stack = parser.Stack(None, stack_name, template, params, + stack = parser.Stack(None, stack_name, template, + environment.Environment({'KeyName': 'test'}), stack_id=uuidutils.generate_uuid()) return (t, stack) diff --git a/heat/tests/test_instance_network.py b/heat/tests/test_instance_network.py index 97d8c4f625..9e1bd2a0fb 100644 --- a/heat/tests/test_instance_network.py +++ b/heat/tests/test_instance_network.py @@ -13,6 +13,7 @@ # under the License. +from heat.engine import environment from heat.tests.v1_1 import fakes from heat.engine.resources import instance as instances from heat.engine.resources import network_interface as network_interfaces @@ -156,8 +157,8 @@ class instancesTest(HeatTestCase): kwargs = {'KeyName': 'test', 'InstanceType': 'm1.large', 'SubnetId': '4156c7a5-e8c4-4aff-a6e1-8f3c7bc83861'} - params = parser.Parameters(stack_name, template, kwargs) - stack = parser.Stack(None, stack_name, template, params, + stack = parser.Stack(None, stack_name, template, + environment.Environment(kwargs), stack_id=uuidutils.generate_uuid()) t['Resources']['WebServer']['Properties']['ImageId'] = 'CentOS 5.2' @@ -197,8 +198,8 @@ class instancesTest(HeatTestCase): kwargs = {'KeyName': 'test', 'InstanceType': 'm1.large', 'SubnetId': '4156c7a5-e8c4-4aff-a6e1-8f3c7bc83861'} - params = parser.Parameters(stack_name, template, kwargs) - stack = parser.Stack(None, stack_name, template, params, + stack = parser.Stack(None, stack_name, template, + environment.Environment(kwargs), stack_id=uuidutils.generate_uuid()) t['Resources']['WebServer']['Properties']['ImageId'] = 'CentOS 5.2' diff --git a/heat/tests/test_metadata_refresh.py b/heat/tests/test_metadata_refresh.py index a44d45f641..bb9edbbb31 100644 --- a/heat/tests/test_metadata_refresh.py +++ b/heat/tests/test_metadata_refresh.py @@ -21,6 +21,7 @@ from heat.tests.common import HeatTestCase from heat.tests.utils import setup_dummy_db from heat.tests.utils import stack_delete_after +from heat.engine import environment from heat.common import identifier from heat.common import template_format from heat.engine import parser @@ -142,10 +143,10 @@ class MetadataRefreshTest(HeatTestCase): def create_stack(self, stack_name='test_stack', params={}): temp = template_format.parse(test_template_metadata) template = parser.Template(temp) - parameters = parser.Parameters(stack_name, template, params) ctx = context.get_admin_context() ctx.tenant_id = 'test_tenant' - stack = parser.Stack(ctx, stack_name, template, parameters, + stack = parser.Stack(ctx, stack_name, template, + environment.Environment(params), disable_rollback=True) self.stack_id = stack.store() @@ -207,8 +208,7 @@ class WaitCondMetadataUpdateTest(HeatTestCase): def create_stack(self, stack_name='test_stack'): temp = template_format.parse(test_template_waitcondition) template = parser.Template(temp) - parameters = parser.Parameters(stack_name, template, {}) - stack = parser.Stack(self.ctx, stack_name, template, parameters, + stack = parser.Stack(self.ctx, stack_name, template, disable_rollback=True) self.stack_id = stack.store() diff --git a/heat/tests/test_nested_stack.py b/heat/tests/test_nested_stack.py index 6f7c635df1..77d90386ed 100644 --- a/heat/tests/test_nested_stack.py +++ b/heat/tests/test_nested_stack.py @@ -67,8 +67,7 @@ Outputs: 'auth_url': 'http://localhost:5000/v2.0'}) stack_name = 'test_stack' tmpl = parser.Template(t) - params = parser.Parameters(stack_name, tmpl, {}) - stack = parser.Stack(ctx, stack_name, tmpl, params) + stack = parser.Stack(ctx, stack_name, tmpl) stack.store() return stack diff --git a/heat/tests/test_security_group.py b/heat/tests/test_security_group.py index e6e03e6b01..82611de150 100644 --- a/heat/tests/test_security_group.py +++ b/heat/tests/test_security_group.py @@ -116,8 +116,7 @@ Resources: 'auth_url': 'http://localhost:5000/v2.0'}) stack_name = 'test_stack' tmpl = parser.Template(t) - params = parser.Parameters(stack_name, tmpl, {}) - stack = parser.Stack(ctx, stack_name, tmpl, params) + stack = parser.Stack(ctx, stack_name, tmpl) stack.store() return stack diff --git a/heat/tests/test_validate.py b/heat/tests/test_validate.py index 5d3bfc1d6c..1cbe1b66c9 100644 --- a/heat/tests/test_validate.py +++ b/heat/tests/test_validate.py @@ -14,6 +14,7 @@ from testtools import skipIf +from heat.engine import environment from heat.tests.v1_1 import fakes from heat.common import exception from heat.common import template_format @@ -579,9 +580,9 @@ class validateTest(HeatTestCase): def test_unregistered_key(self): t = template_format.parse(test_unregistered_key) template = parser.Template(t) - params = parser.Parameters( - 'test_stack', template, {'KeyName': 'not_registered'}) - stack = parser.Stack(None, 'test_stack', template, params) + params = {'KeyName': 'not_registered'} + stack = parser.Stack(None, 'test_stack', template, + environment.Environment(params)) self.m.StubOutWithMock(instances.Instance, 'nova') instances.Instance.nova().AndReturn(self.fc) @@ -594,8 +595,8 @@ class validateTest(HeatTestCase): def test_invalid_security_groups_with_nics(self): t = template_format.parse(test_template_invalid_secgroups) template = parser.Template(t) - params = parser.Parameters('test_stack', template, {'KeyName': 'test'}) - stack = parser.Stack(None, 'test_stack', template, params) + stack = parser.Stack(None, 'test_stack', template, + environment.Environment({'KeyName': 'test'})) self.m.StubOutWithMock(instances.Instance, 'nova') instances.Instance.nova().AndReturn(self.fc) @@ -607,8 +608,8 @@ class validateTest(HeatTestCase): def test_invalid_security_group_ids_with_nics(self): t = template_format.parse(test_template_invalid_secgroupids) template = parser.Template(t) - params = parser.Parameters('test_stack', template, {'KeyName': 'test'}) - stack = parser.Stack(None, 'test_stack', template, params) + stack = parser.Stack(None, 'test_stack', template, + environment.Environment({'KeyName': 'test'})) self.m.StubOutWithMock(instances.Instance, 'nova') instances.Instance.nova().AndReturn(self.fc) diff --git a/heat/tests/test_vpc.py b/heat/tests/test_vpc.py index ecbabb81b3..5244ac8e83 100644 --- a/heat/tests/test_vpc.py +++ b/heat/tests/test_vpc.py @@ -82,8 +82,7 @@ class VPCTestBase(HeatTestCase): 'auth_url': 'http://localhost:5000/v2.0'}) stack_name = 'test_stack' tmpl = parser.Template(t) - params = parser.Parameters(stack_name, tmpl, {}) - stack = parser.Stack(ctx, stack_name, tmpl, params) + stack = parser.Stack(ctx, stack_name, tmpl) stack.store() return stack diff --git a/heat/tests/test_waitcondition.py b/heat/tests/test_waitcondition.py index 05b1497412..e508ef5c91 100644 --- a/heat/tests/test_waitcondition.py +++ b/heat/tests/test_waitcondition.py @@ -29,6 +29,7 @@ from heat.tests.utils import setup_dummy_db import heat.db.api as db_api from heat.common import template_format from heat.common import identifier +from heat.engine import environment from heat.engine import parser from heat.engine import resource from heat.engine import scheduler @@ -114,10 +115,10 @@ class WaitConditionTest(HeatTestCase): stub=True): temp = template_format.parse(template) template = parser.Template(temp) - parameters = parser.Parameters(stack_name, template, params) ctx = context.get_admin_context() ctx.tenant_id = 'test_tenant' - stack = parser.Stack(ctx, stack_name, template, parameters, + stack = parser.Stack(ctx, stack_name, template, + environment.Environment(params), disable_rollback=True) # Stub out the stack ID so we have a known value @@ -399,10 +400,10 @@ class WaitConditionHandleTest(HeatTestCase): def create_stack(self, stack_name='test_stack2', params={}): temp = template_format.parse(test_template_waitcondition) template = parser.Template(temp) - parameters = parser.Parameters(stack_name, template, params) ctx = context.get_admin_context() ctx.tenant_id = 'test_tenant' - stack = parser.Stack(ctx, stack_name, template, parameters, + stack = parser.Stack(ctx, stack_name, template, + environment.Environment(params), disable_rollback=True) # Stub out the UUID for this test, so we can get an expected signature with UUIDStub('STACKABCD1234'): diff --git a/heat/tests/test_watch.py b/heat/tests/test_watch.py index 92a536cf4d..46453dcec7 100644 --- a/heat/tests/test_watch.py +++ b/heat/tests/test_watch.py @@ -52,8 +52,7 @@ class WatchRuleTest(HeatTestCase): empty_tmpl = {"template": {}} tmpl = parser.Template(empty_tmpl) stack_name = 'dummystack' - params = parser.Parameters(stack_name, tmpl, {}) - dummy_stack = parser.Stack(ctx, stack_name, tmpl, params) + dummy_stack = parser.Stack(ctx, stack_name, tmpl) dummy_stack.state_set(dummy_stack.CREATE_COMPLETE, 'Testing') dummy_stack.store() diff --git a/heat/tests/utils.py b/heat/tests/utils.py index 396f549071..66567480c0 100644 --- a/heat/tests/utils.py +++ b/heat/tests/utils.py @@ -16,6 +16,7 @@ import sys import functools from heat.common import context +from heat.engine import environment from heat.engine import parser from heat.db.sqlalchemy.session import get_engine @@ -62,8 +63,8 @@ def parse_stack(t, params={}, stack_name='test_stack', stack_id=None): 'auth_url': 'http://localhost:5000/v2.0'}) template = parser.Template(t) - parameters = parser.Parameters(stack_name, template, params) - stack = parser.Stack(ctx, stack_name, template, parameters, stack_id) + stack = parser.Stack(ctx, stack_name, template, + environment.Environment(params), stack_id) stack.store() return stack