Added tags attribute to the template parameter
In some scenarios, it is required to categorize the parameter. Associating tags with the parameter, it is will be easy to categorize the parameter and add simple validations to users. This patch introduces a new attribute 'tags' with the parameters, which is a list of strings. Change-Id: I20fc95d606b0b8a08d3b46bf33f4860bff49c74f
This commit is contained in:
parent
554add6004
commit
a1a0609e8e
@ -437,6 +437,7 @@ default value defined as nested elements.
|
||||
constraints:
|
||||
<parameter constraints>
|
||||
immutable: <true | false>
|
||||
tags: <list of parameter categories>
|
||||
|
||||
param name
|
||||
The name of the parameter.
|
||||
@ -478,6 +479,11 @@ immutable
|
||||
set to ``true`` and the parameter value is changed.
|
||||
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:
|
||||
|
||||
+----------------------+-------------------------------+------------------+
|
||||
|
@ -524,6 +524,9 @@ def format_validate_parameter(param):
|
||||
if 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)
|
||||
|
||||
return res
|
||||
|
@ -79,6 +79,22 @@ class HOTParamSchema(parameters.Schema):
|
||||
raise exception.InvalidSchemaError(
|
||||
message=_("No constraint expressed"))
|
||||
|
||||
@classmethod
|
||||
def _constraints(cls, param_name, schema_dict):
|
||||
constraints = schema_dict.get(cls.CONSTRAINTS)
|
||||
if constraints is None:
|
||||
return
|
||||
|
||||
if not isinstance(constraints, list):
|
||||
raise exception.InvalidSchemaError(
|
||||
message=_("Invalid parameter constraints for parameter "
|
||||
"%s, expected a list") % param_name)
|
||||
|
||||
for constraint in constraints:
|
||||
cls._check_dict(constraint, PARAM_CONSTRAINTS,
|
||||
'parameter constraints')
|
||||
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.
|
||||
@ -89,27 +105,12 @@ class HOTParamSchema(parameters.Schema):
|
||||
"""
|
||||
cls._validate_dict(param_name, schema_dict)
|
||||
|
||||
def constraints():
|
||||
constraints = schema_dict.get(cls.CONSTRAINTS)
|
||||
if constraints is None:
|
||||
return
|
||||
|
||||
if not isinstance(constraints, list):
|
||||
raise exception.InvalidSchemaError(
|
||||
message=_("Invalid parameter constraints for parameter "
|
||||
"%s, expected a list") % param_name)
|
||||
|
||||
for constraint in constraints:
|
||||
cls._check_dict(constraint, PARAM_CONSTRAINTS,
|
||||
'parameter constraints')
|
||||
yield cls._constraint_from_def(constraint)
|
||||
|
||||
# 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(constraints()),
|
||||
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))
|
||||
@ -131,6 +132,35 @@ class HOTParamSchema20170224(HOTParamSchema):
|
||||
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):
|
||||
PSEUDO_PARAMETERS = (
|
||||
PARAM_STACK_ID, PARAM_STACK_NAME, PARAM_REGION, PARAM_PROJECT_ID
|
||||
|
@ -695,3 +695,5 @@ class HOTemplate20180302(HOTemplate20170901):
|
||||
'yaql': hot_funcs.Yaql,
|
||||
'contains': hot_funcs.Contains
|
||||
}
|
||||
|
||||
param_schema_class = parameters.HOTParamSchema20180302
|
||||
|
@ -42,10 +42,10 @@ class Schema(constr.Schema):
|
||||
|
||||
KEYS = (
|
||||
TYPE, DESCRIPTION, DEFAULT, SCHEMA, CONSTRAINTS, HIDDEN,
|
||||
LABEL, IMMUTABLE
|
||||
LABEL, IMMUTABLE, TAGS,
|
||||
) = (
|
||||
'Type', 'Description', 'Default', 'Schema', 'Constraints', 'NoEcho',
|
||||
'Label', 'Immutable'
|
||||
'Label', 'Immutable', 'Tags',
|
||||
)
|
||||
|
||||
PARAMETER_KEYS = PARAMETER_KEYS
|
||||
@ -59,7 +59,8 @@ class Schema(constr.Schema):
|
||||
)
|
||||
|
||||
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,
|
||||
description=description,
|
||||
default=default,
|
||||
@ -69,6 +70,7 @@ class Schema(constr.Schema):
|
||||
label=label,
|
||||
immutable=immutable)
|
||||
self.hidden = hidden
|
||||
self.tags = tags
|
||||
|
||||
# Schema class validates default value for lists assuming list type. For
|
||||
# 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") %
|
||||
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
|
||||
def from_dict(cls, param_name, schema_dict):
|
||||
"""Return a Parameter Schema object from a legacy schema dictionary.
|
||||
@ -276,6 +283,10 @@ class Parameter(object):
|
||||
"""Return the label or param 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):
|
||||
"""Return whether the parameter has a default value."""
|
||||
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_STEP, PARAM_OFFSET,
|
||||
PARAM_DESCRIPTION, PARAM_CONSTRAINT_DESCRIPTION, PARAM_LABEL,
|
||||
PARAM_CUSTOM_CONSTRAINT, PARAM_VALUE
|
||||
PARAM_CUSTOM_CONSTRAINT, PARAM_VALUE, PARAM_TAG
|
||||
) = (
|
||||
'Type', 'Default', 'NoEcho',
|
||||
'AllowedValues', 'AllowedPattern', 'MaxLength',
|
||||
'MinLength', 'MaxValue', 'MinValue', 'Step', 'Offset',
|
||||
'Description', 'ConstraintDescription', 'Label',
|
||||
'CustomConstraint', 'Value'
|
||||
'CustomConstraint', 'Value', 'Tags'
|
||||
)
|
||||
|
||||
VALIDATE_PARAM_TYPES = (
|
||||
|
@ -924,6 +924,46 @@ resources:
|
||||
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):
|
||||
def setUp(self):
|
||||
@ -1859,3 +1899,39 @@ parameter_groups:
|
||||
self.ctx, t, {})
|
||||
self.assertEqual(dependencies.CircularDependencyException,
|
||||
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.
|
Loading…
Reference in New Issue
Block a user