2
# Licensed under the Apache License, Version 2.0 (the "License"); you may
3
# not use this file except in compliance with the License. You may obtain
4
# a copy of the License at
6
# http://www.apache.org/licenses/LICENSE-2.0
8
# Unless required by applicable law or agreed to in writing, software
9
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11
# License for the specific language governing permissions and limitations
19
from heat.common import exception
20
from heat.common.i18n import _
21
from heat.engine import constraints
22
from heat.engine import properties
23
from heat.engine.resources.software_config import software_config as sc
24
from heat.engine.resources.software_config import software_deployment as sd
25
from heat.engine import support
28
class StructuredConfig(sc.SoftwareConfig):
30
This resource is like OS::Heat::SoftwareConfig except that the config
31
property is represented by a Map rather than a String.
33
This is useful for configuration tools which use YAML or JSON as their
34
configuration syntax. The resulting configuration is transferred,
35
stored and returned by the software_configs API as parsed JSON.
38
support_status = support.SupportStatus(version='2014.1')
47
sc.SoftwareConfig.GROUP,
48
sc.SoftwareConfig.CONFIG,
49
sc.SoftwareConfig.OPTIONS,
50
sc.SoftwareConfig.INPUTS,
51
sc.SoftwareConfig.OUTPUTS
55
GROUP: sc.SoftwareConfig.properties_schema[GROUP],
56
OPTIONS: sc.SoftwareConfig.properties_schema[OPTIONS],
57
INPUTS: sc.SoftwareConfig.properties_schema[INPUTS],
58
OUTPUTS: sc.SoftwareConfig.properties_schema[OUTPUTS],
59
CONFIG: properties.Schema(
60
properties.Schema.MAP,
61
_('Map representing the configuration data structure which will '
62
'be serialized to JSON format.')
67
class StructuredDeployment(sd.SoftwareDeployment):
69
A deployment resource like OS::Heat::SoftwareDeployment, but which
70
performs input value substitution on the config defined by a
71
OS::Heat::StructuredConfig resource.
73
Some configuration tools have no concept of inputs, so the input value
74
substitution needs to occur in the deployment resource. An example of this
75
is the JSON metadata consumed by the cfn-init tool.
77
Where the config contains {get_input: input_name} this will be substituted
78
with the value of input_name in this resource's input_values. If get_input
79
needs to be passed through to the substituted configuration then a
80
different input_key property value can be specified.
83
support_status = support.SupportStatus(version='2014.1')
95
sd.SoftwareDeployment.CONFIG,
96
sd.SoftwareDeployment.SERVER,
97
sd.SoftwareDeployment.INPUT_VALUES,
98
sd.SoftwareDeployment.DEPLOY_ACTIONS,
99
sd.SoftwareDeployment.NAME,
100
sd.SoftwareDeployment.SIGNAL_TRANSPORT,
102
'input_values_validate'
105
_sd_ps = sd.SoftwareDeployment.properties_schema
107
properties_schema = {
108
CONFIG: _sd_ps[CONFIG],
109
SERVER: _sd_ps[SERVER],
110
INPUT_VALUES: _sd_ps[INPUT_VALUES],
111
DEPLOY_ACTIONS: _sd_ps[DEPLOY_ACTIONS],
112
SIGNAL_TRANSPORT: _sd_ps[SIGNAL_TRANSPORT],
114
INPUT_KEY: properties.Schema(
115
properties.Schema.STRING,
116
_('Name of key to use for substituting inputs during deployment'),
119
INPUT_VALUES_VALIDATE: properties.Schema(
120
properties.Schema.STRING,
121
_('Perform a check on the input values passed to verify that '
122
'each required input has a corresponding value. '
123
'When the property is set to STRICT and no value is passed, '
124
'an exception is raised.'),
127
constraints.AllowedValues(['LAX', 'STRICT']),
132
def _build_derived_config(self, action, source,
133
derived_inputs, derived_options):
134
cfg = source.get(sc.SoftwareConfig.CONFIG)
135
input_key = self.properties.get(self.INPUT_KEY)
136
check_input_val = self.properties.get(self.INPUT_VALUES_VALIDATE)
138
inputs = dict((i['name'], i['value']) for i in derived_inputs)
140
return self.parse(inputs, input_key, cfg, check_input_val)
143
def get_input_key_arg(snippet, input_key):
144
if len(snippet) != 1:
146
fn_name, fn_arg = next(six.iteritems(snippet))
147
if (fn_name == input_key and isinstance(fn_arg, six.string_types)):
151
def get_input_key_value(fn_arg, inputs, check_input_val='LAX'):
152
if check_input_val == 'STRICT' and fn_arg not in inputs:
153
raise exception.UserParameterMissing(key=fn_arg)
154
return inputs.get(fn_arg)
157
def parse(inputs, input_key, snippet, check_input_val='LAX'):
158
parse = functools.partial(
159
StructuredDeployment.parse,
162
check_input_val=check_input_val)
164
if isinstance(snippet, collections.Mapping):
165
fn_arg = StructuredDeployment.get_input_key_arg(snippet, input_key)
166
if fn_arg is not None:
167
return StructuredDeployment.get_input_key_value(fn_arg, inputs,
171
return dict((k, parse(v)) for k, v in six.iteritems(snippet))
172
elif (not isinstance(snippet, six.string_types) and
173
isinstance(snippet, collections.Iterable)):
174
return [parse(v) for v in snippet]
179
class StructuredDeployments(sd.SoftwareDeployments):
189
INPUT_VALUES_VALIDATE,
191
sd.SoftwareDeployments.SERVERS,
192
sd.SoftwareDeployments.CONFIG,
193
sd.SoftwareDeployments.INPUT_VALUES,
194
sd.SoftwareDeployments.DEPLOY_ACTIONS,
195
sd.SoftwareDeployments.NAME,
196
sd.SoftwareDeployments.SIGNAL_TRANSPORT,
197
StructuredDeployment.INPUT_KEY,
198
StructuredDeployment.INPUT_VALUES_VALIDATE
201
_sds_ps = sd.SoftwareDeployments.properties_schema
203
properties_schema = {
204
SERVERS: _sds_ps[SERVERS],
205
CONFIG: _sds_ps[CONFIG],
206
INPUT_VALUES: _sds_ps[INPUT_VALUES],
207
DEPLOY_ACTIONS: _sds_ps[DEPLOY_ACTIONS],
208
SIGNAL_TRANSPORT: _sds_ps[SIGNAL_TRANSPORT],
210
INPUT_KEY: StructuredDeployment.properties_schema[INPUT_KEY],
211
INPUT_VALUES_VALIDATE:
212
StructuredDeployment.properties_schema[INPUT_VALUES_VALIDATE],
215
def _build_resource_definition(self, include_all=False):
218
self.RESOURCE_DEF_TYPE: 'OS::Heat::StructuredDeployment',
219
self.RESOURCE_DEF_PROPERTIES: {
220
self.CONFIG: p[self.CONFIG],
221
self.INPUT_VALUES: p[self.INPUT_VALUES],
222
self.DEPLOY_ACTIONS: p[self.DEPLOY_ACTIONS],
223
self.SIGNAL_TRANSPORT: p[self.SIGNAL_TRANSPORT],
224
self.NAME: p[self.NAME],
225
self.INPUT_KEY: p[self.INPUT_KEY],
226
self.INPUT_VALUES_VALIDATE: p[self.INPUT_VALUES_VALIDATE],
231
def resource_mapping():
233
'OS::Heat::StructuredConfig': StructuredConfig,
234
'OS::Heat::StructuredDeployment': StructuredDeployment,
235
'OS::Heat::StructuredDeployments': StructuredDeployments,