~ubuntu-branches/ubuntu/wily/heat/wily-proposed

« back to all changes in this revision

Viewing changes to heat/engine/resources/software_config/structured_config.py

  • Committer: Package Import Robot
  • Author(s): James Page, Corey Bryant, James Page
  • Date: 2015-03-30 11:11:18 UTC
  • mfrom: (1.1.23)
  • Revision ID: package-import@ubuntu.com-20150330111118-2qpycylx6swu4yhj
Tags: 2015.1~b3-0ubuntu1
[ Corey Bryant ]
* New upstream milestone release for OpenStack kilo:
  - d/control: Align with upstream dependencies.
  - d/p/sudoers_patch.patch: Rebased.
  - d/p/fix-requirements.patch: Rebased.

[ James Page ]
* d/p/fixup-assert-regex.patch: Tweak test to use assertRegexpMatches.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#
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
5
 
#
6
 
#         http://www.apache.org/licenses/LICENSE-2.0
7
 
#
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
12
 
#    under the License.
13
 
 
14
 
import collections
15
 
import functools
16
 
 
17
 
import six
18
 
 
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
26
 
 
27
 
 
28
 
class StructuredConfig(sc.SoftwareConfig):
29
 
    '''
30
 
    This resource is like OS::Heat::SoftwareConfig except that the config
31
 
    property is represented by a Map rather than a String.
32
 
 
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.
36
 
    '''
37
 
 
38
 
    support_status = support.SupportStatus(version='2014.1')
39
 
 
40
 
    PROPERTIES = (
41
 
        GROUP,
42
 
        CONFIG,
43
 
        OPTIONS,
44
 
        INPUTS,
45
 
        OUTPUTS
46
 
    ) = (
47
 
        sc.SoftwareConfig.GROUP,
48
 
        sc.SoftwareConfig.CONFIG,
49
 
        sc.SoftwareConfig.OPTIONS,
50
 
        sc.SoftwareConfig.INPUTS,
51
 
        sc.SoftwareConfig.OUTPUTS
52
 
    )
53
 
 
54
 
    properties_schema = {
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.')
63
 
        )
64
 
    }
65
 
 
66
 
 
67
 
class StructuredDeployment(sd.SoftwareDeployment):
68
 
    '''
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.
72
 
 
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.
76
 
 
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.
81
 
    '''
82
 
 
83
 
    support_status = support.SupportStatus(version='2014.1')
84
 
 
85
 
    PROPERTIES = (
86
 
        CONFIG,
87
 
        SERVER,
88
 
        INPUT_VALUES,
89
 
        DEPLOY_ACTIONS,
90
 
        NAME,
91
 
        SIGNAL_TRANSPORT,
92
 
        INPUT_KEY,
93
 
        INPUT_VALUES_VALIDATE
94
 
    ) = (
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,
101
 
        'input_key',
102
 
        'input_values_validate'
103
 
    )
104
 
 
105
 
    _sd_ps = sd.SoftwareDeployment.properties_schema
106
 
 
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],
113
 
        NAME: _sd_ps[NAME],
114
 
        INPUT_KEY: properties.Schema(
115
 
            properties.Schema.STRING,
116
 
            _('Name of key to use for substituting inputs during deployment'),
117
 
            default='get_input',
118
 
        ),
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.'),
125
 
            default='LAX',
126
 
            constraints=[
127
 
                constraints.AllowedValues(['LAX', 'STRICT']),
128
 
            ],
129
 
        )
130
 
    }
131
 
 
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)
137
 
 
138
 
        inputs = dict((i['name'], i['value']) for i in derived_inputs)
139
 
 
140
 
        return self.parse(inputs, input_key, cfg, check_input_val)
141
 
 
142
 
    @staticmethod
143
 
    def get_input_key_arg(snippet, input_key):
144
 
        if len(snippet) != 1:
145
 
            return None
146
 
        fn_name, fn_arg = next(six.iteritems(snippet))
147
 
        if (fn_name == input_key and isinstance(fn_arg, six.string_types)):
148
 
            return fn_arg
149
 
 
150
 
    @staticmethod
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)
155
 
 
156
 
    @staticmethod
157
 
    def parse(inputs, input_key, snippet, check_input_val='LAX'):
158
 
        parse = functools.partial(
159
 
            StructuredDeployment.parse,
160
 
            inputs,
161
 
            input_key,
162
 
            check_input_val=check_input_val)
163
 
 
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,
168
 
                                                                check_input_val
169
 
                                                                )
170
 
 
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]
175
 
        else:
176
 
            return snippet
177
 
 
178
 
 
179
 
class StructuredDeployments(sd.SoftwareDeployments):
180
 
 
181
 
    PROPERTIES = (
182
 
        SERVERS,
183
 
        CONFIG,
184
 
        INPUT_VALUES,
185
 
        DEPLOY_ACTIONS,
186
 
        NAME,
187
 
        SIGNAL_TRANSPORT,
188
 
        INPUT_KEY,
189
 
        INPUT_VALUES_VALIDATE,
190
 
    ) = (
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
199
 
    )
200
 
 
201
 
    _sds_ps = sd.SoftwareDeployments.properties_schema
202
 
 
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],
209
 
        NAME: _sds_ps[NAME],
210
 
        INPUT_KEY: StructuredDeployment.properties_schema[INPUT_KEY],
211
 
        INPUT_VALUES_VALIDATE:
212
 
        StructuredDeployment.properties_schema[INPUT_VALUES_VALIDATE],
213
 
    }
214
 
 
215
 
    def _build_resource_definition(self, include_all=False):
216
 
        p = self.properties
217
 
        return {
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],
227
 
            }
228
 
        }
229
 
 
230
 
 
231
 
def resource_mapping():
232
 
    return {
233
 
        'OS::Heat::StructuredConfig': StructuredConfig,
234
 
        'OS::Heat::StructuredDeployment': StructuredDeployment,
235
 
        'OS::Heat::StructuredDeployments': StructuredDeployments,
236
 
    }