Merge "Added tags attribute to the template parameter"
This commit is contained in:
@@ -437,6 +437,7 @@ default value defined as nested elements.
|
|||||||
constraints:
|
constraints:
|
||||||
<parameter constraints>
|
<parameter constraints>
|
||||||
immutable: <true | false>
|
immutable: <true | false>
|
||||||
|
tags: <list of parameter categories>
|
||||||
|
|
||||||
param name
|
param name
|
||||||
The name of the parameter.
|
The name of the parameter.
|
||||||
@@ -478,6 +479,11 @@ immutable
|
|||||||
set to ``true`` and the parameter value is changed.
|
set to ``true`` and the parameter value is changed.
|
||||||
This attribute is optional and defaults to ``false``.
|
This attribute is optional and defaults to ``false``.
|
||||||
|
|
||||||
|
tags
|
||||||
|
A list of strings to specify the category of a parameter. This value is
|
||||||
|
used to categorize a parameter so that users can group the parameters.
|
||||||
|
This attribute is optional.
|
||||||
|
|
||||||
The table below describes all currently supported types with examples:
|
The table below describes all currently supported types with examples:
|
||||||
|
|
||||||
+----------------------+-------------------------------+------------------+
|
+----------------------+-------------------------------+------------------+
|
||||||
|
|||||||
@@ -524,6 +524,9 @@ def format_validate_parameter(param):
|
|||||||
if param.user_value:
|
if param.user_value:
|
||||||
res[rpc_api.PARAM_VALUE] = param.user_value
|
res[rpc_api.PARAM_VALUE] = param.user_value
|
||||||
|
|
||||||
|
if param.tags():
|
||||||
|
res[rpc_api.PARAM_TAG] = param.tags()
|
||||||
|
|
||||||
_build_parameter_constraints(res, param)
|
_build_parameter_constraints(res, param)
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|||||||
@@ -80,16 +80,7 @@ class HOTParamSchema(parameters.Schema):
|
|||||||
message=_("No constraint expressed"))
|
message=_("No constraint expressed"))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, param_name, schema_dict):
|
def _constraints(cls, param_name, schema_dict):
|
||||||
"""Return a Parameter Schema object from a legacy schema dictionary.
|
|
||||||
|
|
||||||
:param param_name: name of the parameter owning the schema; used
|
|
||||||
for more verbose logging
|
|
||||||
:type param_name: str
|
|
||||||
"""
|
|
||||||
cls._validate_dict(param_name, schema_dict)
|
|
||||||
|
|
||||||
def constraints():
|
|
||||||
constraints = schema_dict.get(cls.CONSTRAINTS)
|
constraints = schema_dict.get(cls.CONSTRAINTS)
|
||||||
if constraints is None:
|
if constraints is None:
|
||||||
return
|
return
|
||||||
@@ -104,12 +95,22 @@ class HOTParamSchema(parameters.Schema):
|
|||||||
'parameter constraints')
|
'parameter constraints')
|
||||||
yield cls._constraint_from_def(constraint)
|
yield cls._constraint_from_def(constraint)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, param_name, schema_dict):
|
||||||
|
"""Return a Parameter Schema object from a legacy schema dictionary.
|
||||||
|
|
||||||
|
:param param_name: name of the parameter owning the schema; used
|
||||||
|
for more verbose logging
|
||||||
|
:type param_name: str
|
||||||
|
"""
|
||||||
|
cls._validate_dict(param_name, schema_dict)
|
||||||
|
|
||||||
# make update_allowed true by default on TemplateResources
|
# make update_allowed true by default on TemplateResources
|
||||||
# as the template should deal with this.
|
# as the template should deal with this.
|
||||||
return cls(schema_dict[cls.TYPE],
|
return cls(schema_dict[cls.TYPE],
|
||||||
description=schema_dict.get(HOTParamSchema.DESCRIPTION),
|
description=schema_dict.get(HOTParamSchema.DESCRIPTION),
|
||||||
default=schema_dict.get(HOTParamSchema.DEFAULT),
|
default=schema_dict.get(HOTParamSchema.DEFAULT),
|
||||||
constraints=list(constraints()),
|
constraints=list(cls._constraints(param_name, schema_dict)),
|
||||||
hidden=schema_dict.get(HOTParamSchema.HIDDEN, False),
|
hidden=schema_dict.get(HOTParamSchema.HIDDEN, False),
|
||||||
label=schema_dict.get(HOTParamSchema.LABEL),
|
label=schema_dict.get(HOTParamSchema.LABEL),
|
||||||
immutable=schema_dict.get(HOTParamSchema.IMMUTABLE, False))
|
immutable=schema_dict.get(HOTParamSchema.IMMUTABLE, False))
|
||||||
@@ -131,6 +132,35 @@ class HOTParamSchema20170224(HOTParamSchema):
|
|||||||
constraint)
|
constraint)
|
||||||
|
|
||||||
|
|
||||||
|
class HOTParamSchema20180302(HOTParamSchema20170224):
|
||||||
|
|
||||||
|
KEYS_20180302 = (TAGS,) = ('tags',)
|
||||||
|
KEYS = HOTParamSchema20170224.KEYS + KEYS_20180302
|
||||||
|
|
||||||
|
PARAMETER_KEYS = KEYS
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, param_name, schema_dict):
|
||||||
|
"""Return a Parameter Schema object from a legacy schema dictionary.
|
||||||
|
|
||||||
|
:param param_name: name of the parameter owning the schema; used
|
||||||
|
for more verbose logging
|
||||||
|
:type param_name: str
|
||||||
|
"""
|
||||||
|
cls._validate_dict(param_name, schema_dict)
|
||||||
|
|
||||||
|
# make update_allowed true by default on TemplateResources
|
||||||
|
# as the template should deal with this.
|
||||||
|
return cls(schema_dict[cls.TYPE],
|
||||||
|
description=schema_dict.get(HOTParamSchema.DESCRIPTION),
|
||||||
|
default=schema_dict.get(HOTParamSchema.DEFAULT),
|
||||||
|
constraints=list(cls._constraints(param_name, schema_dict)),
|
||||||
|
hidden=schema_dict.get(HOTParamSchema.HIDDEN, False),
|
||||||
|
label=schema_dict.get(HOTParamSchema.LABEL),
|
||||||
|
immutable=schema_dict.get(HOTParamSchema.IMMUTABLE, False),
|
||||||
|
tags=schema_dict.get(HOTParamSchema20180302.TAGS))
|
||||||
|
|
||||||
|
|
||||||
class HOTParameters(parameters.Parameters):
|
class HOTParameters(parameters.Parameters):
|
||||||
PSEUDO_PARAMETERS = (
|
PSEUDO_PARAMETERS = (
|
||||||
PARAM_STACK_ID, PARAM_STACK_NAME, PARAM_REGION, PARAM_PROJECT_ID
|
PARAM_STACK_ID, PARAM_STACK_NAME, PARAM_REGION, PARAM_PROJECT_ID
|
||||||
|
|||||||
@@ -695,3 +695,5 @@ class HOTemplate20180302(HOTemplate20170901):
|
|||||||
'yaql': hot_funcs.Yaql,
|
'yaql': hot_funcs.Yaql,
|
||||||
'contains': hot_funcs.Contains
|
'contains': hot_funcs.Contains
|
||||||
}
|
}
|
||||||
|
|
||||||
|
param_schema_class = parameters.HOTParamSchema20180302
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ class Schema(constr.Schema):
|
|||||||
|
|
||||||
KEYS = (
|
KEYS = (
|
||||||
TYPE, DESCRIPTION, DEFAULT, SCHEMA, CONSTRAINTS, HIDDEN,
|
TYPE, DESCRIPTION, DEFAULT, SCHEMA, CONSTRAINTS, HIDDEN,
|
||||||
LABEL, IMMUTABLE
|
LABEL, IMMUTABLE, TAGS,
|
||||||
) = (
|
) = (
|
||||||
'Type', 'Description', 'Default', 'Schema', 'Constraints', 'NoEcho',
|
'Type', 'Description', 'Default', 'Schema', 'Constraints', 'NoEcho',
|
||||||
'Label', 'Immutable'
|
'Label', 'Immutable', 'Tags',
|
||||||
)
|
)
|
||||||
|
|
||||||
PARAMETER_KEYS = PARAMETER_KEYS
|
PARAMETER_KEYS = PARAMETER_KEYS
|
||||||
@@ -59,7 +59,8 @@ class Schema(constr.Schema):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, data_type, description=None, default=None, schema=None,
|
def __init__(self, data_type, description=None, default=None, schema=None,
|
||||||
constraints=None, hidden=False, label=None, immutable=False):
|
constraints=None, hidden=False, label=None, immutable=False,
|
||||||
|
tags=None):
|
||||||
super(Schema, self).__init__(data_type=data_type,
|
super(Schema, self).__init__(data_type=data_type,
|
||||||
description=description,
|
description=description,
|
||||||
default=default,
|
default=default,
|
||||||
@@ -69,6 +70,7 @@ class Schema(constr.Schema):
|
|||||||
label=label,
|
label=label,
|
||||||
immutable=immutable)
|
immutable=immutable)
|
||||||
self.hidden = hidden
|
self.hidden = hidden
|
||||||
|
self.tags = tags
|
||||||
|
|
||||||
# Schema class validates default value for lists assuming list type. For
|
# Schema class validates default value for lists assuming list type. For
|
||||||
# comma delimited list string supported in parameters Schema class, the
|
# comma delimited list string supported in parameters Schema class, the
|
||||||
@@ -129,6 +131,11 @@ class Schema(constr.Schema):
|
|||||||
message=_("Missing parameter type for parameter: %s") %
|
message=_("Missing parameter type for parameter: %s") %
|
||||||
param_name)
|
param_name)
|
||||||
|
|
||||||
|
if not isinstance(schema_dict.get(cls.TAGS, []), list):
|
||||||
|
raise exception.InvalidSchemaError(
|
||||||
|
message=_("Tags property should be a list for parameter: %s") %
|
||||||
|
param_name)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, param_name, schema_dict):
|
def from_dict(cls, param_name, schema_dict):
|
||||||
"""Return a Parameter Schema object from a legacy schema dictionary.
|
"""Return a Parameter Schema object from a legacy schema dictionary.
|
||||||
@@ -276,6 +283,10 @@ class Parameter(object):
|
|||||||
"""Return the label or param name."""
|
"""Return the label or param name."""
|
||||||
return self.schema.label or self.name
|
return self.schema.label or self.name
|
||||||
|
|
||||||
|
def tags(self):
|
||||||
|
"""Return the tags associated with the parameter"""
|
||||||
|
return self.schema.tags or []
|
||||||
|
|
||||||
def has_default(self):
|
def has_default(self):
|
||||||
"""Return whether the parameter has a default value."""
|
"""Return whether the parameter has a default value."""
|
||||||
return (self.schema.default is not None or
|
return (self.schema.default is not None or
|
||||||
|
|||||||
@@ -193,13 +193,13 @@ VALIDATE_PARAM_KEYS = (
|
|||||||
PARAM_MIN_LENGTH, PARAM_MAX_VALUE, PARAM_MIN_VALUE,
|
PARAM_MIN_LENGTH, PARAM_MAX_VALUE, PARAM_MIN_VALUE,
|
||||||
PARAM_STEP, PARAM_OFFSET,
|
PARAM_STEP, PARAM_OFFSET,
|
||||||
PARAM_DESCRIPTION, PARAM_CONSTRAINT_DESCRIPTION, PARAM_LABEL,
|
PARAM_DESCRIPTION, PARAM_CONSTRAINT_DESCRIPTION, PARAM_LABEL,
|
||||||
PARAM_CUSTOM_CONSTRAINT, PARAM_VALUE
|
PARAM_CUSTOM_CONSTRAINT, PARAM_VALUE, PARAM_TAG
|
||||||
) = (
|
) = (
|
||||||
'Type', 'Default', 'NoEcho',
|
'Type', 'Default', 'NoEcho',
|
||||||
'AllowedValues', 'AllowedPattern', 'MaxLength',
|
'AllowedValues', 'AllowedPattern', 'MaxLength',
|
||||||
'MinLength', 'MaxValue', 'MinValue', 'Step', 'Offset',
|
'MinLength', 'MaxValue', 'MinValue', 'Step', 'Offset',
|
||||||
'Description', 'ConstraintDescription', 'Label',
|
'Description', 'ConstraintDescription', 'Label',
|
||||||
'CustomConstraint', 'Value'
|
'CustomConstraint', 'Value', 'Tags'
|
||||||
)
|
)
|
||||||
|
|
||||||
VALIDATE_PARAM_TYPES = (
|
VALIDATE_PARAM_TYPES = (
|
||||||
|
|||||||
@@ -928,6 +928,46 @@ resources:
|
|||||||
external_id: foobar
|
external_id: foobar
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
test_template_hot_parameter_tags_older = '''
|
||||||
|
heat_template_version: 2013-05-23
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
KeyName:
|
||||||
|
type: string
|
||||||
|
description: Name of an existing key pair to use for the instance
|
||||||
|
label: Nova KeyPair Name
|
||||||
|
tags:
|
||||||
|
- feature1
|
||||||
|
- feature2
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
test_template_hot_parameter_tags_pass = '''
|
||||||
|
heat_template_version: 2018-03-02
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
KeyName:
|
||||||
|
type: string
|
||||||
|
description: Name of an existing key pair to use for the instance
|
||||||
|
label: Nova KeyPair Name
|
||||||
|
tags:
|
||||||
|
- feature1
|
||||||
|
- feature2
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
test_template_hot_parameter_tags_fail = '''
|
||||||
|
heat_template_version: 2018-03-02
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
KeyName:
|
||||||
|
type: string
|
||||||
|
description: Name of an existing key pair to use for the instance
|
||||||
|
label: Nova KeyPair Name
|
||||||
|
tags: feature
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
class ValidateTest(common.HeatTestCase):
|
class ValidateTest(common.HeatTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -1942,3 +1982,39 @@ parameter_groups:
|
|||||||
self.ctx, t, {})
|
self.ctx, t, {})
|
||||||
self.assertEqual(dependencies.CircularDependencyException,
|
self.assertEqual(dependencies.CircularDependencyException,
|
||||||
exc.exc_info[0])
|
exc.exc_info[0])
|
||||||
|
|
||||||
|
def test_validate_hot_parameter_tags_older(self):
|
||||||
|
t = template_format.parse(test_template_hot_parameter_tags_older)
|
||||||
|
|
||||||
|
exc = self.assertRaises(dispatcher.ExpectedException,
|
||||||
|
self.engine.validate_template,
|
||||||
|
self.ctx, t, {})
|
||||||
|
self.assertEqual(exception.InvalidSchemaError,
|
||||||
|
exc.exc_info[0])
|
||||||
|
|
||||||
|
def test_validate_hot_parameter_tags_pass(self):
|
||||||
|
t = template_format.parse(test_template_hot_parameter_tags_pass)
|
||||||
|
|
||||||
|
res = dict(self.engine.validate_template(self.ctx, t, {}))
|
||||||
|
parameters = res['Parameters']
|
||||||
|
|
||||||
|
expected = {'KeyName': {
|
||||||
|
'Description': 'Name of an existing key pair to use for the '
|
||||||
|
'instance',
|
||||||
|
'NoEcho': 'false',
|
||||||
|
'Label': 'Nova KeyPair Name',
|
||||||
|
'Type': 'String',
|
||||||
|
'Tags': [
|
||||||
|
'feature1',
|
||||||
|
'feature2'
|
||||||
|
]}}
|
||||||
|
self.assertEqual(expected, parameters)
|
||||||
|
|
||||||
|
def test_validate_hot_parameter_tags_fail(self):
|
||||||
|
t = template_format.parse(test_template_hot_parameter_tags_fail)
|
||||||
|
|
||||||
|
exc = self.assertRaises(dispatcher.ExpectedException,
|
||||||
|
self.engine.validate_template,
|
||||||
|
self.ctx, t, {})
|
||||||
|
self.assertEqual(exception.InvalidSchemaError,
|
||||||
|
exc.exc_info[0])
|
||||||
|
|||||||
5
releasenotes/notes/parameter-tags-148ef065616f92fc.yaml
Normal file
5
releasenotes/notes/parameter-tags-148ef065616f92fc.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Added a new schema property tags, to parameters, to categorize
|
||||||
|
parameters based on features.
|
||||||
Reference in New Issue
Block a user