Check missing parameters during stack create

Add missing parameters checking logic to Parameter validation. It
has to be optional, since template validation makes use of the same
Parameter validation code.

Fixes bug #1198670

Change-Id: I4c85ebf496b19999e47cf3838e6ca160aa194f20
This commit is contained in:
Liang Chen 2013-07-16 23:24:16 +08:00
parent d2dbee8d85
commit 89a648d7ad
11 changed files with 108 additions and 55 deletions

View File

@ -264,6 +264,7 @@ def map_remote_error(ex):
'StackValidationFailed', 'StackValidationFailed',
'InvalidTemplateReference', 'InvalidTemplateReference',
'UnknownUserParameter', 'UnknownUserParameter',
'UserParameterMissing',
) )
denied_errors = ('Forbidden', 'NotAuthorized') denied_errors = ('Forbidden', 'NotAuthorized')
already_exists_errors = ('StackExists') already_exists_errors = ('StackExists')

View File

@ -86,6 +86,7 @@ def remote_error(ex):
'InvalidTemplateReference': exc.HTTPBadRequest, 'InvalidTemplateReference': exc.HTTPBadRequest,
'UnknownUserParameter': exc.HTTPBadRequest, 'UnknownUserParameter': exc.HTTPBadRequest,
'MissingCredentialError': exc.HTTPBadRequest, 'MissingCredentialError': exc.HTTPBadRequest,
'UserParameterMissing': exc.HTTPBadRequest,
} }
Exc = error_map.get(ex.exc_type, exc.HTTPInternalServerError) Exc = error_map.get(ex.exc_type, exc.HTTPInternalServerError)

View File

@ -44,7 +44,7 @@ PSEUDO_PARAMETERS = (
class Parameter(object): class Parameter(object):
'''A template parameter.''' '''A template parameter.'''
def __new__(cls, name, schema, value=None): def __new__(cls, name, schema, value=None, validate_value=True):
'''Create a new Parameter of the appropriate type.''' '''Create a new Parameter of the appropriate type.'''
if cls is not Parameter: if cls is not Parameter:
return super(Parameter, cls).__new__(cls) return super(Parameter, cls).__new__(cls)
@ -61,9 +61,9 @@ class Parameter(object):
else: else:
raise ValueError('Invalid Parameter type "%s"' % param_type) raise ValueError('Invalid Parameter type "%s"' % param_type)
return ParamClass(name, schema, value) return ParamClass(name, schema, value, validate_value)
def __init__(self, name, schema, value=None): def __init__(self, name, schema, value=None, validate_value=True):
''' '''
Initialise the Parameter with a name, schema and optional user-supplied Initialise the Parameter with a name, schema and optional user-supplied
value. value.
@ -76,8 +76,11 @@ class Parameter(object):
if self.has_default(): if self.has_default():
self._validate(self.default()) self._validate(self.default())
if validate_value:
if self.user_value is not None: if self.user_value is not None:
self._validate(self.user_value) self._validate(self.user_value)
elif not self.has_default():
raise exception.UserParameterMissing(key=self.name)
def _error_msg(self, message): def _error_msg(self, message):
return '%s %s' % (self.name, self._constraint_error or message) return '%s %s' % (self.name, self._constraint_error or message)
@ -272,7 +275,8 @@ class Parameters(collections.Mapping):
The parameters of a stack, with type checking, defaults &c. specified by The parameters of a stack, with type checking, defaults &c. specified by
the stack's template. the stack's template.
''' '''
def __init__(self, stack_name, tmpl, user_params={}, stack_id=None): def __init__(self, stack_name, tmpl, user_params={}, stack_id=None,
validate_value=True):
''' '''
Create the parameter container for a stack from the stack name and Create the parameter container for a stack from the stack name and
template, optionally setting the user-supplied parameter values. template, optionally setting the user-supplied parameter values.
@ -298,7 +302,8 @@ class Parameters(collections.Mapping):
'ap-northeast-1']}) 'ap-northeast-1']})
for name, schema in tmpl[template.PARAMETERS].iteritems(): for name, schema in tmpl[template.PARAMETERS].iteritems():
yield Parameter(name, schema, user_params.get(name)) yield Parameter(name, schema, user_params.get(name),
validate_value)
self.tmpl = tmpl self.tmpl = tmpl
self._validate(user_params) self._validate(user_params)

View File

@ -346,6 +346,7 @@ class LoadBalancer(stack_resource.StackResource):
param = {'KeyName': self.stack.parameters['KeyName']} param = {'KeyName': self.stack.parameters['KeyName']}
except KeyError: except KeyError:
del templ['Resources']['LB_instance']['Properties']['KeyName'] del templ['Resources']['LB_instance']['Properties']['KeyName']
del templ['Parameters']['KeyName']
param = {} param = {}
return self.create_with_template(templ, param) return self.create_with_template(templ, param)

View File

@ -310,7 +310,7 @@ class EngineService(service.Service):
except Exception as ex: except Exception as ex:
return {'Error': str(ex)} return {'Error': str(ex)}
tmpl_params = parser.Parameters(None, tmpl) tmpl_params = parser.Parameters(None, tmpl, validate_value=False)
format_validate_parameter = lambda p: dict(p.schema) format_validate_parameter = lambda p: dict(p.schema)
is_real_param = lambda p: p.name not in parameters.PSEUDO_PARAMETERS is_real_param = lambda p: p.name not in parameters.PSEUDO_PARAMETERS
params = tmpl_params.map(format_validate_parameter, is_real_param) params = tmpl_params.map(format_validate_parameter, is_real_param)

View File

@ -555,6 +555,16 @@ class CfnStackControllerTest(HeatTestCase):
'args': engine_args}, 'args': engine_args},
'version': self.api_version}, None 'version': self.api_version}, None
).AndRaise(rpc_common.RemoteError("UnknownUserParameter")) ).AndRaise(rpc_common.RemoteError("UnknownUserParameter"))
rpc.call(dummy_req.context, self.topic,
{'namespace': None,
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'params': engine_parms,
'files': {},
'args': engine_args},
'version': self.api_version}, None
).AndRaise(rpc_common.RemoteError("UserParameterMissing"))
self.m.ReplayAll() self.m.ReplayAll()
@ -565,6 +575,11 @@ class CfnStackControllerTest(HeatTestCase):
result = self.controller.create(dummy_req) result = self.controller.create(dummy_req)
self.assertEqual(type(result),
exception.HeatInvalidParameterValueError)
result = self.controller.create(dummy_req)
self.assertEqual(type(result), self.assertEqual(type(result),
exception.HeatInvalidParameterValueError) exception.HeatInvalidParameterValueError)

View File

@ -507,6 +507,16 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'args': {'timeout_mins': 30}}, 'args': {'timeout_mins': 30}},
'version': self.api_version}, 'version': self.api_version},
None).AndRaise(rpc_common.RemoteError("UnknownUserParameter")) None).AndRaise(rpc_common.RemoteError("UnknownUserParameter"))
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'params': {'parameters': parameters},
'files': {},
'args': {'timeout_mins': 30}},
'version': self.api_version},
None).AndRaise(rpc_common.RemoteError("UserParameterMissing"))
self.m.ReplayAll() self.m.ReplayAll()
@ -516,6 +526,9 @@ class StackControllerTest(ControllerTest, HeatTestCase):
self.assertRaises(webob.exc.HTTPBadRequest, self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, self.controller.create,
req, tenant_id=self.tenant, body=body) req, tenant_id=self.tenant, body=body)
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create,
req, tenant_id=self.tenant, body=body)
self.m.VerifyAll() self.m.VerifyAll()

View File

@ -94,6 +94,7 @@ as_template = '''
class AutoScalingTest(HeatTestCase): class AutoScalingTest(HeatTestCase):
dummy_instance_id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' dummy_instance_id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
params = {'KeyName': 'test'}
def setUp(self): def setUp(self):
super(AutoScalingTest, self).setUp() super(AutoScalingTest, self).setUp()
@ -167,7 +168,7 @@ class AutoScalingTest(HeatTestCase):
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
properties['MinSize'] = '0' properties['MinSize'] = '0'
properties['MaxSize'] = '0' properties['MaxSize'] = '0'
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
now = timeutils.utcnow() now = timeutils.utcnow()
self.m.ReplayAll() self.m.ReplayAll()
@ -182,7 +183,7 @@ class AutoScalingTest(HeatTestCase):
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
properties['MinSize'] = '1' properties['MinSize'] = '1'
properties['MaxSize'] = '1' properties['MaxSize'] = '1'
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
self._stub_lb_reload(1) self._stub_lb_reload(1)
now = timeutils.utcnow() now = timeutils.utcnow()
@ -210,7 +211,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_group_update_replace(self): def test_scaling_group_update_replace(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
self._stub_lb_reload(1) self._stub_lb_reload(1)
now = timeutils.utcnow() now = timeutils.utcnow()
@ -231,7 +232,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_group_suspend(self): def test_scaling_group_suspend(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
self._stub_lb_reload(1) self._stub_lb_reload(1)
now = timeutils.utcnow() now = timeutils.utcnow()
@ -262,7 +263,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_group_resume(self): def test_scaling_group_resume(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
self._stub_lb_reload(1) self._stub_lb_reload(1)
now = timeutils.utcnow() now = timeutils.utcnow()
@ -297,7 +298,7 @@ class AutoScalingTest(HeatTestCase):
t = template_format.parse(as_template) t = template_format.parse(as_template)
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
properties['DesiredCapacity'] = '2' properties['DesiredCapacity'] = '2'
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
self._stub_lb_reload(2) self._stub_lb_reload(2)
now = timeutils.utcnow() now = timeutils.utcnow()
@ -332,7 +333,7 @@ class AutoScalingTest(HeatTestCase):
t = template_format.parse(as_template) t = template_format.parse(as_template)
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
properties['DesiredCapacity'] = '2' properties['DesiredCapacity'] = '2'
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
self._stub_lb_reload(2) self._stub_lb_reload(2)
now = timeutils.utcnow() now = timeutils.utcnow()
@ -367,7 +368,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_group_suspend_fail(self): def test_scaling_group_suspend_fail(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
self._stub_lb_reload(1) self._stub_lb_reload(1)
now = timeutils.utcnow() now = timeutils.utcnow()
@ -398,7 +399,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_group_resume_fail(self): def test_scaling_group_resume_fail(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
self._stub_lb_reload(1) self._stub_lb_reload(1)
now = timeutils.utcnow() now = timeutils.utcnow()
@ -431,7 +432,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_group_create_error(self): def test_scaling_group_create_error(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
self.m.StubOutWithMock(instance.Instance, 'handle_create') self.m.StubOutWithMock(instance.Instance, 'handle_create')
self.m.StubOutWithMock(instance.Instance, 'check_create_complete') self.m.StubOutWithMock(instance.Instance, 'check_create_complete')
@ -456,7 +457,7 @@ class AutoScalingTest(HeatTestCase):
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
properties['MinSize'] = '1' properties['MinSize'] = '1'
properties['MaxSize'] = '3' properties['MaxSize'] = '3'
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
self._stub_lb_reload(1) self._stub_lb_reload(1)
now = timeutils.utcnow() now = timeutils.utcnow()
@ -482,7 +483,7 @@ class AutoScalingTest(HeatTestCase):
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
properties['MinSize'] = '1' properties['MinSize'] = '1'
properties['MaxSize'] = '3' properties['MaxSize'] = '3'
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
self._stub_lb_reload(1) self._stub_lb_reload(1)
now = timeutils.utcnow() now = timeutils.utcnow()
@ -513,7 +514,7 @@ class AutoScalingTest(HeatTestCase):
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
properties['MinSize'] = '1' properties['MinSize'] = '1'
properties['MaxSize'] = '3' properties['MaxSize'] = '3'
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
self._stub_lb_reload(1) self._stub_lb_reload(1)
now = timeutils.utcnow() now = timeutils.utcnow()
@ -544,7 +545,7 @@ class AutoScalingTest(HeatTestCase):
t = template_format.parse(as_template) t = template_format.parse(as_template)
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
properties['DesiredCapacity'] = '2' properties['DesiredCapacity'] = '2'
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
self._stub_lb_reload(2) self._stub_lb_reload(2)
now = timeutils.utcnow() now = timeutils.utcnow()
@ -572,7 +573,7 @@ class AutoScalingTest(HeatTestCase):
t = template_format.parse(as_template) t = template_format.parse(as_template)
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
properties['Cooldown'] = '60' properties['Cooldown'] = '60'
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
self._stub_lb_reload(1) self._stub_lb_reload(1)
now = timeutils.utcnow() now = timeutils.utcnow()
@ -614,7 +615,7 @@ class AutoScalingTest(HeatTestCase):
self._stub_meta_expected(now, 'ExactCapacity : 1') self._stub_meta_expected(now, 'ExactCapacity : 1')
self._stub_create(1) self._stub_create(1)
self.m.ReplayAll() self.m.ReplayAll()
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup') rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual('WebServerGroup', rsrc.FnGetRefId()) self.assertEqual('WebServerGroup', rsrc.FnGetRefId())
@ -628,7 +629,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_group_adjust(self): def test_scaling_group_adjust(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
# start with 3 # start with 3
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
@ -669,7 +670,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_group_scale_up_failure(self): def test_scaling_group_scale_up_failure(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
# Create initial group # Create initial group
self._stub_lb_reload(1) self._stub_lb_reload(1)
@ -698,7 +699,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_group_nochange(self): def test_scaling_group_nochange(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
# Create initial group, 2 instances # Create initial group, 2 instances
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
@ -732,7 +733,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_group_percent(self): def test_scaling_group_percent(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
# Create initial group, 2 instances # Create initial group, 2 instances
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
@ -768,7 +769,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_group_cooldown_toosoon(self): def test_scaling_group_cooldown_toosoon(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
# Create initial group, 2 instances, Cooldown 60s # Create initial group, 2 instances, Cooldown 60s
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
@ -821,7 +822,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_group_cooldown_ok(self): def test_scaling_group_cooldown_ok(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
# Create initial group, 2 instances, Cooldown 60s # Create initial group, 2 instances, Cooldown 60s
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
@ -873,7 +874,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_group_cooldown_zero(self): def test_scaling_group_cooldown_zero(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
# Create initial group, 2 instances, Cooldown 0 # Create initial group, 2 instances, Cooldown 0
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
@ -922,7 +923,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_policy_up(self): def test_scaling_policy_up(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
# Create initial group # Create initial group
self._stub_lb_reload(1) self._stub_lb_reload(1)
@ -950,7 +951,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_policy_down(self): def test_scaling_policy_down(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
# Create initial group, 2 instances # Create initial group, 2 instances
properties = t['Resources']['WebServerGroup']['Properties'] properties = t['Resources']['WebServerGroup']['Properties']
@ -979,7 +980,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_policy_cooldown_toosoon(self): def test_scaling_policy_cooldown_toosoon(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
# Create initial group # Create initial group
self._stub_lb_reload(1) self._stub_lb_reload(1)
@ -1030,7 +1031,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_policy_cooldown_ok(self): def test_scaling_policy_cooldown_ok(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
# Create initial group # Create initial group
self._stub_lb_reload(1) self._stub_lb_reload(1)
@ -1080,7 +1081,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_policy_cooldown_zero(self): def test_scaling_policy_cooldown_zero(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
# Create initial group # Create initial group
self._stub_lb_reload(1) self._stub_lb_reload(1)
@ -1130,7 +1131,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_policy_cooldown_none(self): def test_scaling_policy_cooldown_none(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
# Create initial group # Create initial group
self._stub_lb_reload(1) self._stub_lb_reload(1)
@ -1182,7 +1183,7 @@ class AutoScalingTest(HeatTestCase):
def test_scaling_policy_update(self): def test_scaling_policy_update(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = parse_stack(t) stack = parse_stack(t, params=self.params)
# Create initial group # Create initial group
self._stub_lb_reload(1) self._stub_lb_reload(1)

View File

@ -48,9 +48,9 @@ wp_template = '''
"MySqlCloudDB": { "MySqlCloudDB": {
"Type": "Rackspace::Cloud::DBInstance", "Type": "Rackspace::Cloud::DBInstance",
"Properties" : { "Properties" : {
"InstanceName" : {"testsqlinstance"}, "InstanceName" : {"Ref": "InstanceName"},
"FlavorRef" : {"test-flavor"}, "FlavorRef" : {"Ref": "FlavorRef"},
"VolumeSize" : {"test-volume-size"}, "VolumeSize" : {"Ref": VolumeSize},
"Users" : [{"name":"testuser", "password":"testpass123"}] , "Users" : [{"name":"testuser", "password":"testpass123"}] ,
"Databases" : [{"name":"testdbonetwo"}] "Databases" : [{"name":"testdbonetwo"}]
} }
@ -87,13 +87,11 @@ class CloudDBInstanceTest(HeatTestCase):
stack = parser.Stack(None, stack = parser.Stack(None,
stack_name, stack_name,
template, template,
environment.Environment({'InstanceName': 'test'}), environment.Environment({'InstanceName': 'Test',
'FlavorRef': '1GB',
'VolumeSize': '30'}),
stack_id=uuidutils.generate_uuid()) stack_id=uuidutils.generate_uuid())
t['Resources']['MySqlCloudDB']['Properties']['InstanceName'] = 'Test'
t['Resources']['MySqlCloudDB']['Properties']['FlavorRef'] = '1GB'
t['Resources']['MySqlCloudDB']['Properties']['VolumeSize'] = '30'
if inject_property_error: if inject_property_error:
# database name given in users list is not a valid database # database name given in users list is not a valid database
t['Resources']['MySqlCloudDB']['Properties']['Databases'] = \ t['Resources']['MySqlCloudDB']['Properties']['Databases'] = \

View File

@ -22,19 +22,20 @@ from heat.engine import parameters
class ParameterTest(testtools.TestCase): class ParameterTest(testtools.TestCase):
def test_new_string(self): def test_new_string(self):
p = parameters.Parameter('p', {'Type': 'String'}) p = parameters.Parameter('p', {'Type': 'String'}, validate_value=False)
self.assertTrue(isinstance(p, parameters.StringParam)) self.assertTrue(isinstance(p, parameters.StringParam))
def test_new_number(self): def test_new_number(self):
p = parameters.Parameter('p', {'Type': 'Number'}) p = parameters.Parameter('p', {'Type': 'Number'}, validate_value=False)
self.assertTrue(isinstance(p, parameters.NumberParam)) self.assertTrue(isinstance(p, parameters.NumberParam))
def test_new_list(self): def test_new_list(self):
p = parameters.Parameter('p', {'Type': 'CommaDelimitedList'}) p = parameters.Parameter('p', {'Type': 'CommaDelimitedList'},
validate_value=False)
self.assertTrue(isinstance(p, parameters.CommaDelimitedListParam)) self.assertTrue(isinstance(p, parameters.CommaDelimitedListParam))
def test_new_json(self): def test_new_json(self):
p = parameters.Parameter('p', {'Type': 'Json'}) p = parameters.Parameter('p', {'Type': 'Json'}, validate_value=False)
self.assertTrue(isinstance(p, parameters.JsonParam)) self.assertTrue(isinstance(p, parameters.JsonParam))
def test_new_bad_type(self): def test_new_bad_type(self):
@ -101,11 +102,12 @@ class ParameterTest(testtools.TestCase):
def test_description(self): def test_description(self):
description = 'Description of the parameter' description = 'Description of the parameter'
p = parameters.Parameter('p', {'Type': 'String', p = parameters.Parameter('p', {'Type': 'String',
'Description': description}) 'Description': description},
validate_value=False)
self.assertEqual(p.description(), description) self.assertEqual(p.description(), description)
def test_no_description(self): def test_no_description(self):
p = parameters.Parameter('p', {'Type': 'String'}) p = parameters.Parameter('p', {'Type': 'String'}, validate_value=False)
self.assertEqual(p.description(), '') self.assertEqual(p.description(), '')
def test_string_len_good(self): def test_string_len_good(self):
@ -349,6 +351,12 @@ class ParameterTest(testtools.TestCase):
else: else:
self.fail("Value error not raised") self.fail("Value error not raised")
def test_missing_param(self):
'''Test missing user parameter.'''
self.assertRaises(exception.UserParameterMissing,
parameters.Parameter, 'p',
{'Type': 'String'})
params_schema = json.loads('''{ params_schema = json.loads('''{
"Parameters" : { "Parameters" : {
@ -379,10 +387,12 @@ class ParametersTest(testtools.TestCase):
def test_schema_invariance(self): def test_schema_invariance(self):
params1 = parameters.Parameters('test', params_schema, params1 = parameters.Parameters('test', params_schema,
{'Defaulted': 'wibble'}) {'User': 'foo',
'Defaulted': 'wibble'})
self.assertEqual(params1['Defaulted'], 'wibble') self.assertEqual(params1['Defaulted'], 'wibble')
params2 = parameters.Parameters('test', params_schema) params2 = parameters.Parameters('test', params_schema,
{'User': 'foo'})
self.assertEqual(params2['Defaulted'], 'foobar') self.assertEqual(params2['Defaulted'], 'foobar')
def test_to_dict(self): def test_to_dict(self):
@ -430,3 +440,11 @@ class ParametersTest(testtools.TestCase):
'test', 'test',
params_schema, params_schema,
user_params) user_params)
def test_missing_params(self):
user_params = {}
self.assertRaises(exception.UserParameterMissing,
parameters.Parameters,
'test',
params_schema,
user_params)

View File

@ -199,7 +199,7 @@ Mappings:
def test_param_ref_missing(self): def test_param_ref_missing(self):
tmpl = {'Parameters': {'foo': {'Type': 'String', 'Required': True}}} tmpl = {'Parameters': {'foo': {'Type': 'String', 'Required': True}}}
params = parameters.Parameters('test', tmpl) params = parameters.Parameters('test', tmpl, validate_value=False)
snippet = {"Ref": "foo"} snippet = {"Ref": "foo"}
self.assertRaises(exception.UserParameterMissing, self.assertRaises(exception.UserParameterMissing,
parser.Template.resolve_param_refs, parser.Template.resolve_param_refs,