summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Hardy <shardy@redhat.com>2017-10-31 11:26:09 +0000
committerSteven Hardy <shardy@redhat.com>2017-11-14 17:35:52 +0000
commit313faad5f13abf0fddd85d07706fded6ed02bf38 (patch)
treec527fa30496ba621265019445e2ef8e04158d2f1
parente875186c4e491eaa7ab1bb2f602a27e0cf22f345 (diff)
downloadheat-313faad5f13abf0fddd85d07706fded6ed02bf38.tar.gz
Return Environment from validate_template
This is to enable preview of the merged environment without merging the environment on the client side. Related-Bug: #1635409 Change-Id: I7ec3af729a65164230153021f438bf226cc5e858
-rw-r--r--api-ref/source/v1/parameters.yaml8
-rw-r--r--api-ref/source/v1/samples/template-validate-response.json10
-rw-r--r--api-ref/source/v1/stack-templates.inc1
-rw-r--r--heat/engine/service.py1
-rw-r--r--heat/tests/test_validate.py99
-rw-r--r--heat_integrationtests/functional/test_template_validate.py64
-rw-r--r--heat_integrationtests/functional/test_unicode_template.py12
-rw-r--r--releasenotes/notes/environment_validate_template-fee21a03bb628446.yaml6
8 files changed, 183 insertions, 18 deletions
diff --git a/api-ref/source/v1/parameters.yaml b/api-ref/source/v1/parameters.yaml
index 7722b0f44..7c657efe7 100644
--- a/api-ref/source/v1/parameters.yaml
+++ b/api-ref/source/v1/parameters.yaml
@@ -646,6 +646,12 @@ engine_status:
in: body
required: true
type: string
+Environment:
+ description: |
+ Environment for the stack, where multiple environment files are provided this will be the merged result.
+ in: body
+ required: false
+ type: object
environment:
description: |
A JSON environment for the stack.
@@ -943,7 +949,7 @@ ParameterGroups:
type: array
Parameters:
description: |
- Key and value pairs that contain CFN template parameters.
+ Parameter schema in CFN format.
in: body
required: true
type: object
diff --git a/api-ref/source/v1/samples/template-validate-response.json b/api-ref/source/v1/samples/template-validate-response.json
index cbdf7c26f..80c9374ab 100644
--- a/api-ref/source/v1/samples/template-validate-response.json
+++ b/api-ref/source/v1/samples/template-validate-response.json
@@ -37,5 +37,13 @@
"param_name-2"
]
}
- ]
+ ],
+ "Environment": {
+ "event_sinks": [],
+ "parameter_defaults": {},
+ "parameters": {},
+ "resource_registry": {
+ "resources": {}
+ }
+ }
}
diff --git a/api-ref/source/v1/stack-templates.inc b/api-ref/source/v1/stack-templates.inc
index e9b735871..f6e0b42e9 100644
--- a/api-ref/source/v1/stack-templates.inc
+++ b/api-ref/source/v1/stack-templates.inc
@@ -145,6 +145,7 @@ Response Parameters
- Description: Description
- ParameterGroups: ParameterGroups
- Parameters: Parameters
+ - Environment: Environment
Response Example
----------------
diff --git a/heat/engine/service.py b/heat/engine/service.py
index 5c6e2eb41..fb94cb6b6 100644
--- a/heat/engine/service.py
+++ b/heat/engine/service.py
@@ -1310,6 +1310,7 @@ class EngineService(service.ServiceBase):
result.update(nested_params(stack))
+ result['Environment'] = tmpl.env.user_env_as_dict()
return result
@context.request_context
diff --git a/heat/tests/test_validate.py b/heat/tests/test_validate.py
index 128e093f3..49e8e000d 100644
--- a/heat/tests/test_validate.py
+++ b/heat/tests/test_validate.py
@@ -880,6 +880,10 @@ parameters:
type: string
description: Name of private network to be created
+ merged_param:
+ type: comma_delimited_list
+ description: A merged list of values
+
resources:
private_net:
type: OS::Neutron::Net
@@ -939,6 +943,11 @@ class ValidateTest(common.HeatTestCase):
self.mock_is_service_available = self.mock_isa.start()
self.addCleanup(self.mock_isa.stop)
self.engine = service.EngineService('a', 't')
+ self.empty_environment = {
+ 'event_sinks': [],
+ 'parameter_defaults': {},
+ 'parameters': {},
+ 'resource_registry': {'resources': {}}}
def _mock_get_image_id_success(self, imageId):
self.patchobject(glance.GlanceClientPlugin, 'find_image_by_name_or_id',
@@ -1043,7 +1052,8 @@ class ValidateTest(common.HeatTestCase):
other_template = test_template_no_default.replace(
'net_name', 'net_name2')
- files = {'env1': 'parameter_defaults:\n net_name: net1',
+ files = {'env1': 'parameter_defaults:'
+ '\n net_name: net1',
'env2': 'parameter_defaults:'
'\n net_name: net2'
'\n net_name2: net3',
@@ -1051,12 +1061,72 @@ class ValidateTest(common.HeatTestCase):
'tmpl2.yaml': other_template}
params = {'parameters': {}, 'parameter_defaults': {}}
- self.engine.validate_template(
+ ret = self.engine.validate_template(
self.ctx, t,
params=params,
files=files, environment_files=['env1', 'env2'])
self.assertEqual('net2', params['parameter_defaults']['net_name'])
self.assertEqual('net3', params['parameter_defaults']['net_name2'])
+ expected = {
+ 'Description': 'No description',
+ 'Parameters': {
+ 'size': {'AllowedValues': [1, 4, 8],
+ 'Description': '',
+ 'Label': u'size',
+ 'NoEcho': 'false',
+ 'Type': 'Number'}},
+ 'Environment': {
+ 'event_sinks': [],
+ 'parameter_defaults': {
+ 'net_name': u'net2',
+ 'net_name2': u'net3'},
+ 'parameters': {},
+ 'resource_registry': {'resources': {}}}}
+
+ self.assertEqual(expected, ret)
+
+ def test_validate_parameters_merged_env(self):
+ t = template_format.parse(test_template_allowed_integers)
+
+ other_template = test_template_no_default.replace(
+ 'net_name', 'net_name2')
+
+ files = {'env1': 'parameter_defaults:'
+ '\n net_name: net1'
+ '\n merged_param: [net1, net2]'
+ '\nparameter_merge_strategies:'
+ '\n merged_param: merge',
+ 'env2': 'parameter_defaults:'
+ '\n net_name: net2'
+ '\n net_name2: net3'
+ '\n merged_param: [net3, net4]'
+ '\nparameter_merge_strategies:'
+ '\n merged_param: merge',
+ 'tmpl1.yaml': test_template_no_default,
+ 'tmpl2.yaml': other_template}
+ params = {'parameters': {}, 'parameter_defaults': {}}
+
+ expected = {
+ 'Description': 'No description',
+ 'Parameters': {
+ 'size': {'AllowedValues': [1, 4, 8],
+ 'Description': '',
+ 'Label': u'size',
+ 'NoEcho': 'false',
+ 'Type': 'Number'}},
+ 'Environment': {
+ 'event_sinks': [],
+ 'parameter_defaults': {
+ 'net_name': u'net2',
+ 'net_name2': u'net3',
+ 'merged_param': ['net1', 'net2', 'net3', 'net4']},
+ 'parameters': {},
+ 'resource_registry': {'resources': {}}}}
+ ret = self.engine.validate_template(
+ self.ctx, t,
+ params=params,
+ files=files, environment_files=['env1', 'env2'])
+ self.assertEqual(expected, ret)
def test_validate_hot_empty_parameters_valid(self):
t = template_format.parse(
@@ -1149,7 +1219,8 @@ class ValidateTest(common.HeatTestCase):
res = dict(self.engine.validate_template(self.ctx, t, {}))
expected = {"Description": "test.",
- "Parameters": {}}
+ "Parameters": {},
+ "Environment": self.empty_environment}
self.assertEqual(expected, res)
def test_validate_hot_empty_outputs_valid(self):
@@ -1162,7 +1233,8 @@ class ValidateTest(common.HeatTestCase):
res = dict(self.engine.validate_template(self.ctx, t, {}))
expected = {"Description": "test.",
- "Parameters": {}}
+ "Parameters": {},
+ "Environment": self.empty_environment}
self.assertEqual(expected, res)
def test_validate_properties(self):
@@ -1239,7 +1311,9 @@ class ValidateTest(common.HeatTestCase):
t = template_format.parse(test_template_volume_snapshot)
res = dict(self.engine.validate_template(self.ctx, t, {}))
- self.assertEqual({'Description': u'test.', 'Parameters': {}}, res)
+ expected = {'Description': u'test.', 'Parameters': {},
+ 'Environment': self.empty_environment}
+ self.assertEqual(expected, res)
def test_validate_template_without_resources(self):
hot_tpl = template_format.parse('''
@@ -1247,7 +1321,8 @@ class ValidateTest(common.HeatTestCase):
''')
res = dict(self.engine.validate_template(self.ctx, hot_tpl, {}))
- expected = {'Description': 'No description', 'Parameters': {}}
+ expected = {'Description': 'No description', 'Parameters': {},
+ 'Environment': self.empty_environment}
self.assertEqual(expected, res)
def test_validate_template_with_invalid_resource_type(self):
@@ -1755,7 +1830,8 @@ class ValidateTest(common.HeatTestCase):
t,
{},
ignorable_errors=[exception.ResourceTypeUnavailable.error_code]))
- expected = {'Description': 'No description', 'Parameters': {}}
+ expected = {'Description': 'No description', 'Parameters': {},
+ 'Environment': self.empty_environment}
self.assertEqual(expected, res)
def test_validate_with_ignorable_errors_invalid_error_code(self):
@@ -1835,7 +1911,14 @@ parameter_groups:
'NoEcho': 'false',
'Type': 'String'}},
'Type': 'OS::Test::TestResource'}},
- }
+ 'Environment': {
+ 'event_sinks': [],
+ 'parameter_defaults': {},
+ 'parameters': {},
+ 'resource_registry': {
+ 'OS::Test::TestResource':
+ 'https://server.test/nested.template',
+ 'resources': {}}}}
self.assertEqual(expected, res)
def test_validate_allowed_external_rsrc(self):
diff --git a/heat_integrationtests/functional/test_template_validate.py b/heat_integrationtests/functional/test_template_validate.py
index e62c31b76..451de49c5 100644
--- a/heat_integrationtests/functional/test_template_validate.py
+++ b/heat_integrationtests/functional/test_template_validate.py
@@ -94,7 +94,12 @@ resources:
'Description': 'the param description',
'Label': 'aparam',
'NoEcho': 'false',
- 'Type': 'Number'}}}
+ 'Type': 'Number'}},
+ 'Environment': {
+ 'event_sinks': [],
+ 'parameter_defaults': {},
+ 'parameters': {},
+ 'resource_registry': {u'resources': {}}}}
self.assertEqual(expected, ret)
def test_template_validate_override_default(self):
@@ -108,7 +113,12 @@ resources:
'Description': 'the param description',
'Label': 'aparam',
'NoEcho': 'false',
- 'Type': 'Number'}}}
+ 'Type': 'Number'}},
+ 'Environment': {
+ 'event_sinks': [],
+ 'parameter_defaults': {},
+ 'parameters': {'aparam': 5},
+ 'resource_registry': {u'resources': {}}}}
self.assertEqual(expected, ret)
def test_template_validate_override_none(self):
@@ -122,7 +132,14 @@ resources:
'Description': 'the param description',
'Label': 'aparam',
'NoEcho': 'false',
- 'Type': 'Number'}}}
+ 'Type': 'Number'}},
+ 'Environment': {
+ 'event_sinks': [],
+ 'parameter_defaults': {},
+ 'parameters': {},
+ 'resource_registry': {
+ 'OS::Heat::RandomString': 'OS::Heat::None',
+ u'resources': {}}}}
self.assertEqual(expected, ret)
def test_template_validate_basic_required_param(self):
@@ -133,7 +150,12 @@ resources:
'aparam': {'Description': 'the param description',
'Label': 'aparam',
'NoEcho': 'false',
- 'Type': 'Number'}}}
+ 'Type': 'Number'}},
+ 'Environment': {
+ 'event_sinks': [],
+ 'parameter_defaults': {},
+ 'parameters': {},
+ 'resource_registry': {u'resources': {}}}}
self.assertEqual(expected, ret)
def test_template_validate_fail_version(self):
@@ -168,7 +190,12 @@ resources:
'Description': '',
'Label': 'cparam',
'NoEcho': 'true',
- 'Type': 'String'}}}
+ 'Type': 'String'}},
+ 'Environment': {
+ 'event_sinks': [],
+ 'parameter_defaults': {},
+ 'parameters': {},
+ 'resource_registry': {u'resources': {}}}}
self.assertEqual(expected, ret)
def test_template_validate_nested_off(self):
@@ -181,7 +208,14 @@ resources:
'Description': 'the param description',
'Label': 'pparam',
'NoEcho': 'false',
- 'Type': 'Number'}}}
+ 'Type': 'Number'}},
+ 'Environment': {
+ 'event_sinks': [],
+ 'parameter_defaults': {},
+ 'parameters': {},
+ 'resource_registry': {
+ u'mynested.yaml': u'mynested.yaml',
+ u'resources': {}}}}
self.assertEqual(expected, ret)
def test_template_validate_nested_on(self):
@@ -200,7 +234,14 @@ resources:
'Label': 'aparam',
'NoEcho': 'false',
'Type': 'Number'}},
- 'Type': 'mynested.yaml'}}}
+ 'Type': 'mynested.yaml'}},
+ 'Environment': {
+ 'event_sinks': [],
+ 'parameter_defaults': {},
+ 'parameters': {},
+ 'resource_registry': {
+ u'mynested.yaml': u'mynested.yaml',
+ u'resources': {}}}}
self.assertEqual(expected, ret)
def test_template_validate_nested_on_multiple(self):
@@ -240,5 +281,12 @@ resources:
'NoEcho': 'false',
'Type': 'Number'}},
'NestedParameters': n_param2,
- 'Type': 'mynested.yaml'}}}
+ 'Type': 'mynested.yaml'}},
+ 'Environment': {
+ 'event_sinks': [],
+ 'parameter_defaults': {},
+ 'parameters': {},
+ 'resource_registry': {
+ u'mynested.yaml': u'mynested.yaml',
+ 'resources': {}}}}
self.assertEqual(expected, ret)
diff --git a/heat_integrationtests/functional/test_unicode_template.py b/heat_integrationtests/functional/test_unicode_template.py
index 32c02a5cd..d5776a409 100644
--- a/heat_integrationtests/functional/test_unicode_template.py
+++ b/heat_integrationtests/functional/test_unicode_template.py
@@ -72,6 +72,12 @@ outputs:
'Label': u'\u6807\u7b7e',
'NoEcho': 'false',
'Type': 'Number'}
+ },
+ 'Environment': {
+ 'event_sinks': [],
+ 'parameter_defaults': {},
+ 'parameters': {},
+ 'resource_registry': {u'resources': {}}
}
}
self.assertEqual(expected, ret)
@@ -90,6 +96,12 @@ outputs:
'Label': u'\u6807\u7b7e',
'NoEcho': 'false',
'Type': 'Number'}
+ },
+ 'Environment': {
+ 'event_sinks': [],
+ 'parameter_defaults': {},
+ 'parameters': {u'\u53c2\u6570': 5},
+ 'resource_registry': {u'resources': {}}
}
}
self.assertEqual(expected, ret)
diff --git a/releasenotes/notes/environment_validate_template-fee21a03bb628446.yaml b/releasenotes/notes/environment_validate_template-fee21a03bb628446.yaml
new file mode 100644
index 000000000..e5b07970f
--- /dev/null
+++ b/releasenotes/notes/environment_validate_template-fee21a03bb628446.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ The template validate API call now returns the Environment calculated by
+ heat - this enables preview of the merged environment when using
+ parameter_merge_strategy prior to creating the stack