summaryrefslogtreecommitdiff
path: root/heat
diff options
context:
space:
mode:
authorVijendar Komalla <vijendar.komalla@RACKSPACE.COM>2014-09-30 13:38:52 -0500
committerZane Bitter <zbitter@redhat.com>2014-10-08 10:07:36 -0400
commit1eee0560548cafe7ca7ee533f46dfbae9a7681d2 (patch)
treee84cd9504cc0080d5a6ba111d8d2798048098e87 /heat
parentbd71400191ec117d2df2b85c6771da3145dc273d (diff)
downloadheat-1eee0560548cafe7ca7ee533f46dfbae9a7681d2.tar.gz
Template not required on stack-adopt
With this change, template is not required on stack-adopt and also parameters from the original stack are adopted. Change-Id: Id5a28400bb8e27a3b852f12d9af4c2dc7c144725 Closes-Bug: #1300336 (cherry picked from commit 8c54f483189fef2799357457c3b1e8bc0f9e87c5)
Diffstat (limited to 'heat')
-rw-r--r--heat/api/openstack/v1/stacks.py20
-rw-r--r--heat/engine/service.py7
-rw-r--r--heat/tests/test_api_openstack_v1.py79
-rw-r--r--heat/tests/test_engine_service.py33
4 files changed, 136 insertions, 3 deletions
diff --git a/heat/api/openstack/v1/stacks.py b/heat/api/openstack/v1/stacks.py
index 0dcc66474..63944f3f1 100644
--- a/heat/api/openstack/v1/stacks.py
+++ b/heat/api/openstack/v1/stacks.py
@@ -94,10 +94,24 @@ class InstantiationData(object):
def template(self):
"""
- Get template file contents, either inline or from a URL, in JSON
- or YAML format.
+ Get template file contents, either inline, from stack adopt data or
+ from a URL, in JSON or YAML format.
"""
- if self.PARAM_TEMPLATE in self.data:
+ if engine_api.PARAM_ADOPT_STACK_DATA in self.data:
+ adopt_data = self.data[engine_api.PARAM_ADOPT_STACK_DATA]
+ try:
+ adopt_data = template_format.simple_parse(adopt_data)
+
+ if not isinstance(adopt_data, dict):
+ raise exc.HTTPBadRequest(
+ _('Adopt data %s invalid. Adopt data must be a dict.')
+ % adopt_data)
+
+ return adopt_data['template']
+ except (ValueError, KeyError) as ex:
+ err_reason = _('Invalid data: %s') % ex
+ raise exc.HTTPBadRequest(err_reason)
+ elif self.PARAM_TEMPLATE in self.data:
template_data = self.data[self.PARAM_TEMPLATE]
if isinstance(template_data, dict):
return template_data
diff --git a/heat/engine/service.py b/heat/engine/service.py
index aaa098f92..cd3ab0730 100644
--- a/heat/engine/service.py
+++ b/heat/engine/service.py
@@ -535,7 +535,14 @@ class EngineService(service.Service):
tmpl = templatem.Template(template, files=files)
self._validate_new_stack(cnxt, stack_name, tmpl)
+ # If it is stack-adopt, use parameters from adopt_stack_data
common_params = api.extract_args(args)
+
+ if rpc_api.PARAM_ADOPT_STACK_DATA in common_params:
+ params[rpc_api.STACK_PARAMETERS] = common_params[
+ rpc_api.PARAM_ADOPT_STACK_DATA]['environment'][
+ rpc_api.STACK_PARAMETERS]
+
env = environment.Environment(params)
stack = parser.Stack(cnxt, stack_name, tmpl, env,
owner_id=owner_id,
diff --git a/heat/tests/test_api_openstack_v1.py b/heat/tests/test_api_openstack_v1.py
index 6b935ee18..0352a8f14 100644
--- a/heat/tests/test_api_openstack_v1.py
+++ b/heat/tests/test_api_openstack_v1.py
@@ -728,6 +728,85 @@ class StackControllerTest(ControllerTest, HeatTestCase):
self.m.VerifyAll()
+ def test_adopt(self, mock_enforce):
+ self._mock_enforce_setup(mock_enforce, 'create', True)
+ identity = identifier.HeatIdentifier(self.tenant, 'wordpress', '1')
+ template = {
+ "heat_template_version": "2013-05-23",
+ "parameters": {"app_dbx": {"type": "string"}},
+ "resources": {"res1": {"type": "GenericResourceType"}}}
+
+ parameters = {"app_dbx": "test"}
+ adopt_data = {
+ "status": "COMPLETE",
+ "name": "rtrove1",
+ "parameters": parameters,
+ "template": template,
+ "action": "CREATE",
+ "id": "8532f0d3-ea84-444e-b2bb-2543bb1496a4",
+ "resources": {"res1": {
+ "status": "COMPLETE",
+ "name": "database_password",
+ "resource_id": "yBpuUROjfGQ2gKOD",
+ "action": "CREATE",
+ "type": "GenericResourceType",
+ "metadata": {}}}}
+ body = {'template': None,
+ 'stack_name': identity.stack_name,
+ 'parameters': parameters,
+ 'timeout_mins': 30,
+ 'adopt_stack_data': str(adopt_data)}
+
+ req = self._post('/stacks', json.dumps(body))
+
+ self.m.StubOutWithMock(rpc_client.EngineClient, 'call')
+ rpc_client.EngineClient.call(
+ req.context,
+ ('create_stack',
+ {'stack_name': identity.stack_name,
+ 'template': template,
+ 'params': {'parameters': parameters,
+ 'resource_registry': {}},
+ 'files': {},
+ 'args': {'timeout_mins': 30,
+ 'adopt_stack_data': str(adopt_data)},
+ 'owner_id': None})
+ ).AndReturn(dict(identity))
+ self.m.ReplayAll()
+
+ response = self.controller.create(req,
+ tenant_id=identity.tenant,
+ body=body)
+
+ expected = {'stack':
+ {'id': '1',
+ 'links': [{'href': self._url(identity), 'rel': 'self'}]}}
+ self.assertEqual(expected, response)
+ self.m.VerifyAll()
+
+ def test_adopt_error(self, mock_enforce):
+ self._mock_enforce_setup(mock_enforce, 'create', True)
+ identity = identifier.HeatIdentifier(self.tenant, 'wordpress', '1')
+ parameters = {"app_dbx": "test"}
+ adopt_data = ["Test"]
+ body = {'template': None,
+ 'stack_name': identity.stack_name,
+ 'parameters': parameters,
+ 'timeout_mins': 30,
+ 'adopt_stack_data': str(adopt_data)}
+
+ req = self._post('/stacks', json.dumps(body))
+
+ self.m.ReplayAll()
+ resp = request_with_middleware(fault.FaultWrapper,
+ self.controller.create,
+ req, tenant_id=self.tenant,
+ body=body)
+ self.assertEqual(400, resp.status_code)
+ self.assertEqual('400 Bad Request', resp.status)
+ self.assertIn('Adopt data must be a dict.', resp.text)
+ self.m.VerifyAll()
+
def test_create_with_files(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'create', True)
identity = identifier.HeatIdentifier(self.tenant, 'wordpress', '1')
diff --git a/heat/tests/test_engine_service.py b/heat/tests/test_engine_service.py
index 15362df44..a9e55f67f 100644
--- a/heat/tests/test_engine_service.py
+++ b/heat/tests/test_engine_service.py
@@ -546,6 +546,39 @@ class StackServiceCreateUpdateDeleteTest(HeatTestCase):
self.assertEqual(ex.exc_info[0], exception.StackValidationFailed)
self.m.VerifyAll()
+ def test_stack_adopt_with_params(self):
+ template = {
+ "heat_template_version": "2013-05-23",
+ "parameters": {"app_dbx": {"type": "string"}},
+ "resources": {"res1": {"type": "GenericResourceType"}}}
+
+ environment = {'parameters': {"app_dbx": "test"}}
+ adopt_data = {
+ "status": "COMPLETE",
+ "name": "rtrove1",
+ "environment": environment,
+ "template": template,
+ "action": "CREATE",
+ "id": "8532f0d3-ea84-444e-b2bb-2543bb1496a4",
+ "resources": {"res1": {
+ "status": "COMPLETE",
+ "name": "database_password",
+ "resource_id": "yBpuUROjfGQ2gKOD",
+ "action": "CREATE",
+ "type": "GenericResourceType",
+ "metadata": {}}}}
+
+ res._register_class('GenericResourceType',
+ generic_rsrc.GenericResource)
+ result = self.man.create_stack(self.ctx, "test_adopt_stack",
+ template, {}, None,
+ {'adopt_stack_data': str(adopt_data)})
+
+ stack = db_api.stack_get(self.ctx, result['stack_id'])
+ self.assertEqual(template, stack.raw_template.template)
+ self.assertEqual(environment['parameters'],
+ stack.parameters['parameters'])
+
def test_stack_create_invalid_stack_name(self):
stack_name = 'service_create/test_stack'
stack = get_wordpress_stack('test_stack', self.ctx)