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
This commit is contained in:
parent
e875186c4e
commit
313faad5f1
@ -646,6 +646,12 @@ engine_status:
|
|||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
type: string
|
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:
|
environment:
|
||||||
description: |
|
description: |
|
||||||
A JSON environment for the stack.
|
A JSON environment for the stack.
|
||||||
@ -943,7 +949,7 @@ ParameterGroups:
|
|||||||
type: array
|
type: array
|
||||||
Parameters:
|
Parameters:
|
||||||
description: |
|
description: |
|
||||||
Key and value pairs that contain CFN template parameters.
|
Parameter schema in CFN format.
|
||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
type: object
|
type: object
|
||||||
|
@ -37,5 +37,13 @@
|
|||||||
"param_name-2"
|
"param_name-2"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"Environment": {
|
||||||
|
"event_sinks": [],
|
||||||
|
"parameter_defaults": {},
|
||||||
|
"parameters": {},
|
||||||
|
"resource_registry": {
|
||||||
|
"resources": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,6 +145,7 @@ Response Parameters
|
|||||||
- Description: Description
|
- Description: Description
|
||||||
- ParameterGroups: ParameterGroups
|
- ParameterGroups: ParameterGroups
|
||||||
- Parameters: Parameters
|
- Parameters: Parameters
|
||||||
|
- Environment: Environment
|
||||||
|
|
||||||
Response Example
|
Response Example
|
||||||
----------------
|
----------------
|
||||||
|
@ -1310,6 +1310,7 @@ class EngineService(service.ServiceBase):
|
|||||||
|
|
||||||
result.update(nested_params(stack))
|
result.update(nested_params(stack))
|
||||||
|
|
||||||
|
result['Environment'] = tmpl.env.user_env_as_dict()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@context.request_context
|
@context.request_context
|
||||||
|
@ -880,6 +880,10 @@ parameters:
|
|||||||
type: string
|
type: string
|
||||||
description: Name of private network to be created
|
description: Name of private network to be created
|
||||||
|
|
||||||
|
merged_param:
|
||||||
|
type: comma_delimited_list
|
||||||
|
description: A merged list of values
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
private_net:
|
private_net:
|
||||||
type: OS::Neutron::Net
|
type: OS::Neutron::Net
|
||||||
@ -939,6 +943,11 @@ class ValidateTest(common.HeatTestCase):
|
|||||||
self.mock_is_service_available = self.mock_isa.start()
|
self.mock_is_service_available = self.mock_isa.start()
|
||||||
self.addCleanup(self.mock_isa.stop)
|
self.addCleanup(self.mock_isa.stop)
|
||||||
self.engine = service.EngineService('a', 't')
|
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):
|
def _mock_get_image_id_success(self, imageId):
|
||||||
self.patchobject(glance.GlanceClientPlugin, 'find_image_by_name_or_id',
|
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(
|
other_template = test_template_no_default.replace(
|
||||||
'net_name', 'net_name2')
|
'net_name', 'net_name2')
|
||||||
|
|
||||||
files = {'env1': 'parameter_defaults:\n net_name: net1',
|
files = {'env1': 'parameter_defaults:'
|
||||||
|
'\n net_name: net1',
|
||||||
'env2': 'parameter_defaults:'
|
'env2': 'parameter_defaults:'
|
||||||
'\n net_name: net2'
|
'\n net_name: net2'
|
||||||
'\n net_name2: net3',
|
'\n net_name2: net3',
|
||||||
@ -1051,12 +1061,72 @@ class ValidateTest(common.HeatTestCase):
|
|||||||
'tmpl2.yaml': other_template}
|
'tmpl2.yaml': other_template}
|
||||||
params = {'parameters': {}, 'parameter_defaults': {}}
|
params = {'parameters': {}, 'parameter_defaults': {}}
|
||||||
|
|
||||||
self.engine.validate_template(
|
ret = self.engine.validate_template(
|
||||||
self.ctx, t,
|
self.ctx, t,
|
||||||
params=params,
|
params=params,
|
||||||
files=files, environment_files=['env1', 'env2'])
|
files=files, environment_files=['env1', 'env2'])
|
||||||
self.assertEqual('net2', params['parameter_defaults']['net_name'])
|
self.assertEqual('net2', params['parameter_defaults']['net_name'])
|
||||||
self.assertEqual('net3', params['parameter_defaults']['net_name2'])
|
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):
|
def test_validate_hot_empty_parameters_valid(self):
|
||||||
t = template_format.parse(
|
t = template_format.parse(
|
||||||
@ -1149,7 +1219,8 @@ class ValidateTest(common.HeatTestCase):
|
|||||||
|
|
||||||
res = dict(self.engine.validate_template(self.ctx, t, {}))
|
res = dict(self.engine.validate_template(self.ctx, t, {}))
|
||||||
expected = {"Description": "test.",
|
expected = {"Description": "test.",
|
||||||
"Parameters": {}}
|
"Parameters": {},
|
||||||
|
"Environment": self.empty_environment}
|
||||||
self.assertEqual(expected, res)
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
def test_validate_hot_empty_outputs_valid(self):
|
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, {}))
|
res = dict(self.engine.validate_template(self.ctx, t, {}))
|
||||||
expected = {"Description": "test.",
|
expected = {"Description": "test.",
|
||||||
"Parameters": {}}
|
"Parameters": {},
|
||||||
|
"Environment": self.empty_environment}
|
||||||
self.assertEqual(expected, res)
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
def test_validate_properties(self):
|
def test_validate_properties(self):
|
||||||
@ -1239,7 +1311,9 @@ class ValidateTest(common.HeatTestCase):
|
|||||||
t = template_format.parse(test_template_volume_snapshot)
|
t = template_format.parse(test_template_volume_snapshot)
|
||||||
|
|
||||||
res = dict(self.engine.validate_template(self.ctx, t, {}))
|
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):
|
def test_validate_template_without_resources(self):
|
||||||
hot_tpl = template_format.parse('''
|
hot_tpl = template_format.parse('''
|
||||||
@ -1247,7 +1321,8 @@ class ValidateTest(common.HeatTestCase):
|
|||||||
''')
|
''')
|
||||||
|
|
||||||
res = dict(self.engine.validate_template(self.ctx, hot_tpl, {}))
|
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)
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
def test_validate_template_with_invalid_resource_type(self):
|
def test_validate_template_with_invalid_resource_type(self):
|
||||||
@ -1755,7 +1830,8 @@ class ValidateTest(common.HeatTestCase):
|
|||||||
t,
|
t,
|
||||||
{},
|
{},
|
||||||
ignorable_errors=[exception.ResourceTypeUnavailable.error_code]))
|
ignorable_errors=[exception.ResourceTypeUnavailable.error_code]))
|
||||||
expected = {'Description': 'No description', 'Parameters': {}}
|
expected = {'Description': 'No description', 'Parameters': {},
|
||||||
|
'Environment': self.empty_environment}
|
||||||
self.assertEqual(expected, res)
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
def test_validate_with_ignorable_errors_invalid_error_code(self):
|
def test_validate_with_ignorable_errors_invalid_error_code(self):
|
||||||
@ -1835,7 +1911,14 @@ parameter_groups:
|
|||||||
'NoEcho': 'false',
|
'NoEcho': 'false',
|
||||||
'Type': 'String'}},
|
'Type': 'String'}},
|
||||||
'Type': 'OS::Test::TestResource'}},
|
'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)
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
def test_validate_allowed_external_rsrc(self):
|
def test_validate_allowed_external_rsrc(self):
|
||||||
|
@ -94,7 +94,12 @@ resources:
|
|||||||
'Description': 'the param description',
|
'Description': 'the param description',
|
||||||
'Label': 'aparam',
|
'Label': 'aparam',
|
||||||
'NoEcho': 'false',
|
'NoEcho': 'false',
|
||||||
'Type': 'Number'}}}
|
'Type': 'Number'}},
|
||||||
|
'Environment': {
|
||||||
|
'event_sinks': [],
|
||||||
|
'parameter_defaults': {},
|
||||||
|
'parameters': {},
|
||||||
|
'resource_registry': {u'resources': {}}}}
|
||||||
self.assertEqual(expected, ret)
|
self.assertEqual(expected, ret)
|
||||||
|
|
||||||
def test_template_validate_override_default(self):
|
def test_template_validate_override_default(self):
|
||||||
@ -108,7 +113,12 @@ resources:
|
|||||||
'Description': 'the param description',
|
'Description': 'the param description',
|
||||||
'Label': 'aparam',
|
'Label': 'aparam',
|
||||||
'NoEcho': 'false',
|
'NoEcho': 'false',
|
||||||
'Type': 'Number'}}}
|
'Type': 'Number'}},
|
||||||
|
'Environment': {
|
||||||
|
'event_sinks': [],
|
||||||
|
'parameter_defaults': {},
|
||||||
|
'parameters': {'aparam': 5},
|
||||||
|
'resource_registry': {u'resources': {}}}}
|
||||||
self.assertEqual(expected, ret)
|
self.assertEqual(expected, ret)
|
||||||
|
|
||||||
def test_template_validate_override_none(self):
|
def test_template_validate_override_none(self):
|
||||||
@ -122,7 +132,14 @@ resources:
|
|||||||
'Description': 'the param description',
|
'Description': 'the param description',
|
||||||
'Label': 'aparam',
|
'Label': 'aparam',
|
||||||
'NoEcho': 'false',
|
'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)
|
self.assertEqual(expected, ret)
|
||||||
|
|
||||||
def test_template_validate_basic_required_param(self):
|
def test_template_validate_basic_required_param(self):
|
||||||
@ -133,7 +150,12 @@ resources:
|
|||||||
'aparam': {'Description': 'the param description',
|
'aparam': {'Description': 'the param description',
|
||||||
'Label': 'aparam',
|
'Label': 'aparam',
|
||||||
'NoEcho': 'false',
|
'NoEcho': 'false',
|
||||||
'Type': 'Number'}}}
|
'Type': 'Number'}},
|
||||||
|
'Environment': {
|
||||||
|
'event_sinks': [],
|
||||||
|
'parameter_defaults': {},
|
||||||
|
'parameters': {},
|
||||||
|
'resource_registry': {u'resources': {}}}}
|
||||||
self.assertEqual(expected, ret)
|
self.assertEqual(expected, ret)
|
||||||
|
|
||||||
def test_template_validate_fail_version(self):
|
def test_template_validate_fail_version(self):
|
||||||
@ -168,7 +190,12 @@ resources:
|
|||||||
'Description': '',
|
'Description': '',
|
||||||
'Label': 'cparam',
|
'Label': 'cparam',
|
||||||
'NoEcho': 'true',
|
'NoEcho': 'true',
|
||||||
'Type': 'String'}}}
|
'Type': 'String'}},
|
||||||
|
'Environment': {
|
||||||
|
'event_sinks': [],
|
||||||
|
'parameter_defaults': {},
|
||||||
|
'parameters': {},
|
||||||
|
'resource_registry': {u'resources': {}}}}
|
||||||
self.assertEqual(expected, ret)
|
self.assertEqual(expected, ret)
|
||||||
|
|
||||||
def test_template_validate_nested_off(self):
|
def test_template_validate_nested_off(self):
|
||||||
@ -181,7 +208,14 @@ resources:
|
|||||||
'Description': 'the param description',
|
'Description': 'the param description',
|
||||||
'Label': 'pparam',
|
'Label': 'pparam',
|
||||||
'NoEcho': 'false',
|
'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)
|
self.assertEqual(expected, ret)
|
||||||
|
|
||||||
def test_template_validate_nested_on(self):
|
def test_template_validate_nested_on(self):
|
||||||
@ -200,7 +234,14 @@ resources:
|
|||||||
'Label': 'aparam',
|
'Label': 'aparam',
|
||||||
'NoEcho': 'false',
|
'NoEcho': 'false',
|
||||||
'Type': 'Number'}},
|
'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)
|
self.assertEqual(expected, ret)
|
||||||
|
|
||||||
def test_template_validate_nested_on_multiple(self):
|
def test_template_validate_nested_on_multiple(self):
|
||||||
@ -240,5 +281,12 @@ resources:
|
|||||||
'NoEcho': 'false',
|
'NoEcho': 'false',
|
||||||
'Type': 'Number'}},
|
'Type': 'Number'}},
|
||||||
'NestedParameters': n_param2,
|
'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)
|
self.assertEqual(expected, ret)
|
||||||
|
@ -72,6 +72,12 @@ outputs:
|
|||||||
'Label': u'\u6807\u7b7e',
|
'Label': u'\u6807\u7b7e',
|
||||||
'NoEcho': 'false',
|
'NoEcho': 'false',
|
||||||
'Type': 'Number'}
|
'Type': 'Number'}
|
||||||
|
},
|
||||||
|
'Environment': {
|
||||||
|
'event_sinks': [],
|
||||||
|
'parameter_defaults': {},
|
||||||
|
'parameters': {},
|
||||||
|
'resource_registry': {u'resources': {}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.assertEqual(expected, ret)
|
self.assertEqual(expected, ret)
|
||||||
@ -90,6 +96,12 @@ outputs:
|
|||||||
'Label': u'\u6807\u7b7e',
|
'Label': u'\u6807\u7b7e',
|
||||||
'NoEcho': 'false',
|
'NoEcho': 'false',
|
||||||
'Type': 'Number'}
|
'Type': 'Number'}
|
||||||
|
},
|
||||||
|
'Environment': {
|
||||||
|
'event_sinks': [],
|
||||||
|
'parameter_defaults': {},
|
||||||
|
'parameters': {u'\u53c2\u6570': 5},
|
||||||
|
'resource_registry': {u'resources': {}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.assertEqual(expected, ret)
|
self.assertEqual(expected, ret)
|
||||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user