Use the Environment from within the engine

at this point the concept only exists in the engine, the
api and client changes will come in later patches.

blueprint environments
Change-Id: I3e208bb72a04bf275bead2aec89006cf680b501b
This commit is contained in:
Angus Salkeld 2013-06-14 20:56:02 +10:00
parent b0585a6dad
commit ab47610468
16 changed files with 79 additions and 80 deletions

View File

@ -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()

View File

@ -37,8 +37,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
@ -131,7 +134,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):

View File

@ -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):
'''

View File

@ -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()

View File

@ -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)

View File

@ -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
@ -243,15 +242,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)
@ -276,15 +273,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(
@ -392,14 +388,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)
@ -433,14 +427,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(

View File

@ -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)

View File

@ -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'

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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'):

View File

@ -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()

View File

@ -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