def test_prepare_properties(self): data = { 'admin_state_up': False, 'value_specs': { 'router:external': True } } p = properties.Properties(net.Net.properties_schema, data) props = nr.NeutronResource.prepare_properties(p, 'resource_name') self.assertEqual( { 'name': 'resource_name', 'router:external': True, 'admin_state_up': False, 'shared': False }, props)
def test_validate_properties(self): vs = {'router:external': True} data = {'admin_state_up': False, 'value_specs': vs} p = properties.Properties(net.Net.properties_schema, data) self.assertIsNone(nr.NeutronResource.validate_properties(p)) vs['foo'] = '1234' self.assertIsNone(nr.NeutronResource.validate_properties(p)) vs.pop('foo') banned_keys = {'shared': True, 'name': 'foo', 'tenant_id': '1234'} for key, val in six.iteritems(banned_keys): vs.update({key: val}) msg = '%s not allowed in value_specs' % key self.assertEqual(msg, nr.NeutronResource.validate_properties(p)) vs.pop(key)
def test_add_rule_list_with_custom_value_path(self): schema = { 'far': properties.Schema(properties.Schema.LIST, schema=properties.Schema( properties.Schema.MAP, schema={ 'red': properties.Schema( properties.Schema.LIST, schema=properties.Schema( properties.Schema.STRING)), 'blue': properties.Schema(properties.Schema.MAP) })) } data = { 'far': [{ 'blue': { 'black': { 'white': 'daisy', 'check': ['one'] } } }, { 'red': ['roses'] }] } props = properties.Properties(schema, data) rule = translation.TranslationRule( props, translation.TranslationRule.ADD, ['far', 'red'], value_name='blue', custom_value_path=['black', 'check']) tran = translation.Translation(props) tran.set_rules([rule]) self.assertTrue(tran.has_translation('far.0.red')) result = tran.translate('far.0.red', data['far'][0].get('red'), data['far'][0]) self.assertEqual(['one'], result) self.assertEqual(['one'], tran.resolved_translations['far.0.red']) self.assertEqual(['roses'], tran.translate('far.1.red', data['far'][1]['red'], data['far'][1]))
def validate(self): """Validate any of the provided params.""" res = super(CloudLoadBalancer, self).validate() if res: return res if self.properties.get(self.HALF_CLOSED): if not (self.properties[self.PROTOCOL] == 'TCP' or self.properties[self.PROTOCOL] == 'TCP_CLIENT_FIRST'): message = (_('The %s property is only available for the TCP ' 'or TCP_CLIENT_FIRST protocols') % self.HALF_CLOSED) raise exception.StackValidationFailed(message=message) # health_monitor connect and http types require completely different # schema if self.properties.get(self.HEALTH_MONITOR): prop_val = self.properties[self.HEALTH_MONITOR] health_monitor = self._remove_none(prop_val) schema = self._health_monitor_schema if health_monitor[self.HEALTH_MONITOR_TYPE] == 'CONNECT': schema = dict((k, v) for k, v in schema.items() if k in self._HEALTH_MONITOR_CONNECT_KEYS) properties.Properties(schema, health_monitor, function.resolve, self.name).validate() # validate if HTTPS_REDIRECT is true self._validate_https_redirect() # if a vip specifies and id, it can't specify version or type; # otherwise version and type are required for vip in self.properties[self.VIRTUAL_IPS]: has_id = vip.get(self.VIRTUAL_IP_ID) is not None has_version = vip.get(self.VIRTUAL_IP_IP_VERSION) is not None has_type = vip.get(self.VIRTUAL_IP_TYPE) is not None if has_id: if (has_version or has_type): message = _("Cannot specify type or version if VIP id is" " specified.") raise exception.StackValidationFailed(message=message) elif not (has_version and has_type): message = _("Must specify VIP type and version if no id " "specified.") raise exception.StackValidationFailed(message=message)
def test_replace_rule_str(self): schema = { 'far': properties.Schema(properties.Schema.STRING), 'bar': properties.Schema(properties.Schema.STRING) } data = {'far': 'one', 'bar': 'two'} props = properties.Properties(schema, data) rule = translation.TranslationRule(props, translation.TranslationRule.REPLACE, ['bar'], props.get('far')) rule.execute_rule() self.assertEqual('one', props.get('bar')) self.assertEqual('one', props.get('far'))
def test_resolve_rule_other(self): client_plugin, schema = self._test_resolve_rule() data = {'far': 'one'} props = properties.Properties(schema, data) rule = translation.TranslationRule( props, translation.TranslationRule.RESOLVE, ['far'], client_plugin=client_plugin, finder='find_name_id') tran = translation.Translation(props) tran.set_rules([rule]) self.assertTrue(tran.has_translation('far')) result = tran.translate('far', data['far']) self.assertEqual('yellow', result) self.assertEqual('yellow', tran.resolved_translations['far'])
def test_resolve_rule_other_with_function(self): client_plugin, schema = self._test_resolve_rule() join_func = cfn_funcs.Join(None, 'Fn::Join', ['.', ['bar', 'baz']]) data = {'far': join_func} props = properties.Properties(schema, data) rule = translation.TranslationRule(props, translation.TranslationRule.RESOLVE, ['far'], client_plugin=client_plugin, finder='find_name_id') tran = translation.Translation(props) tran.set_rules([rule]) self.assertTrue(tran.has_translation('far')) result = tran.translate('far', data['far']) self.assertEqual('yellow', result) self.assertEqual('yellow', tran.resolved_translations['far'])
def validate_template(self, cnxt, template): """ The validate_template method uses the stack parser to check the validity of a template. arg1 -> RPC context. arg3 -> Template of stack you want to create. arg4 -> Stack Input Params """ logger.info('validate_template') if template is None: msg = _("No Template provided.") return webob.exc.HTTPBadRequest(explanation=msg) tmpl = parser.Template(template) tmpl_resources = template.get('Resources', []) if not tmpl_resources: return {'Error': 'At least one Resources member must be defined.'} for res in tmpl_resources.values(): if not res.get('Type'): return { 'Error': 'Every Resources object must contain a Type member.' } ResourceClass = resource.get_class(res['Type']) props = properties.Properties(ResourceClass.properties_schema, res.get('Properties', {})) try: ResourceClass.validate_deletion_policy(res) props.validate(with_value=False) except Exception as ex: return {'Error': str(ex)} tmpl_params = parser.Parameters(None, tmpl) format_validate_parameter = lambda p: dict(p.schema) is_real_param = lambda p: p.name not in parameters.PSEUDO_PARAMETERS params = tmpl_params.map(format_validate_parameter, is_real_param) result = { 'Description': template.get('Description', ''), 'Parameters': params, } return result
def test_replace_rule_list_same(self): schema = { 'far': properties.Schema( properties.Schema.LIST, schema=properties.Schema( properties.Schema.MAP, schema={ 'red': properties.Schema( properties.Schema.STRING ), 'blue': properties.Schema( properties.Schema.STRING ) } ) )} data = { 'far': [{'blue': 'white'}, {'red': 'roses'}] } props = properties.Properties(schema, data) rule = translation.TranslationRule( props, translation.TranslationRule.REPLACE, ['far', 'red'], None, 'blue') tran = translation.Translation(props) tran.set_rules([rule]) self.assertTrue(tran.has_translation('far.0.red')) result = tran.translate('far.0.red', data['far'][0].get('red'), data['far'][0]) self.assertEqual('white', result) self.assertEqual('white', tran.resolved_translations['far.0.red']) self.assertIsNone(tran.resolved_translations['far.0.blue']) self.assertTrue(tran.has_translation('far.1.red')) result = tran.translate('far.1.red', data['far'][1]['red'], data['far'][1]) self.assertEqual('roses', result) self.assertEqual('roses', tran.resolved_translations['far.1.red']) self.assertIsNone(tran.resolved_translations['far.1.blue'])
def test_replace_rule_str_invalid(self): schema = { 'far': properties.Schema(properties.Schema.STRING), 'bar': properties.Schema(properties.Schema.INTEGER) } data = {'far': 'one', 'bar': 2} props = properties.Properties(schema, data) rule = translation.TranslationRule(props, translation.TranslationRule.REPLACE, ['bar'], props.get('far')) props.update_translation([rule]) exc = self.assertRaises(exception.StackValidationFailed, props.validate) self.assertEqual("Property error: bar: Value 'one' is not an integer", six.text_type(exc))
def test_resolve_rule_list_strings(self): client_plugin, schema = self._test_resolve_rule() data = {'far': ['one', 'rose']} schema = { 'far': properties.Schema(properties.Schema.LIST, schema=properties.Schema( properties.Schema.STRING)) } props = properties.Properties(schema, data) rule = translation.TranslationRule(props, translation.TranslationRule.RESOLVE, ['far'], client_plugin=client_plugin, finder='find_name_id') rule.execute_rule() self.assertEqual(['yellow', 'pink'], props.get('far'))
def test_translation_rule(self): for r in translation.TranslationRule.RULE_KEYS: props = properties.Properties({}, {}) rule = translation.TranslationRule( props, r, ['any'], ['value'] if r == 'Add' else 'value', 'value_name' if r == 'Replace' else None, 'client_plugin' if r == 'Resolve' else None, 'finder' if r == 'Resolve' else None) self.assertEqual(rule.properties, props) self.assertEqual(rule.rule, r) if r == 'Add': self.assertEqual(['value'], rule.value) else: self.assertEqual('value', rule.value) if r == 'Replace': self.assertEqual('value_name', rule.value_name) else: self.assertIsNone(rule.value_name)
def test_resolve_rule_list_populated(self): client_plugin, schema = self._test_resolve_rule(is_list=True) data = { 'far': [{'red': 'blue'}, {'red': 'roses'}], } props = properties.Properties(schema, data) rule = translation.TranslationRule( props, translation.TranslationRule.RESOLVE, ['far', 'red'], client_plugin=client_plugin, finder='find_name_id' ) rule.execute_rule() self.assertEqual([{'red': 'yellow'}, {'red': 'yellow'}], props.get('far'))
def test_replace_rule_str_value_path_error(self): schema = { 'far': properties.Schema(properties.Schema.STRING), 'bar': properties.Schema(properties.Schema.STRING) } data = {'far': 'one', 'bar': 'two'} props = properties.Properties(schema, data) rule = translation.TranslationRule( props, translation.TranslationRule.REPLACE, ['bar'], value_path=['far']) ex = self.assertRaises(ValueError, rule.execute_rule) self.assertEqual('Cannot use bar and far at the same time.', six.text_type(ex))
def setUp(self): schema = { 'int': {'Type': 'Integer'}, 'string': {'Type': 'String'}, 'required_int': {'Type': 'Integer', 'Required': True}, 'bad_int': {'Type': 'Integer'}, 'missing': {'Type': 'Integer'}, 'defaulted': {'Type': 'Integer', 'Default': 1}, 'default_override': {'Type': 'Integer', 'Default': 1}, } data = { 'int': 21, 'string': 'foo', 'bad_int': 'foo', 'default_override': 21, } double = lambda d: d * 2 self.props = properties.Properties(schema, data, double, 'wibble')
def test_replace_rule_list_with_custom_value_path(self): schema = { 'far': properties.Schema(properties.Schema.LIST, schema=properties.Schema( properties.Schema.MAP, schema={ 'red': properties.Schema( properties.Schema.STRING), 'blue': properties.Schema(properties.Schema.MAP) })) } data = { 'far': [{ 'blue': { 'black': { 'white': 'daisy' } } }, { 'red': 'roses' }] } props = properties.Properties(schema, data) rule = translation.TranslationRule( props, translation.TranslationRule.REPLACE, ['far', 'red'], value_name='blue', custom_value_path=['black', 'white']) rule.execute_rule() self.assertEqual([{ 'red': 'daisy', 'blue': { 'black': {} } }, { 'blue': None, 'red': 'roses' }], props.get('far'))
def test_property_json_param_correct_translation(self): """Test case when property with sub-schema takes json param.""" schema = { 'far': properties.Schema(properties.Schema.MAP, schema={ 'bar': properties.Schema( properties.Schema.STRING, ), 'dar': properties.Schema( properties.Schema.STRING ) }) } class DummyStack(dict): @property def parameters(self): return mock.Mock() param = hot_funcs.GetParam(DummyStack(json_far='json_far'), 'get_param', 'json_far') param.parameters = { 'json_far': parameters.JsonParam( 'json_far', {'Type': 'Json'}, '{"dar": "rad"}').value()} data = {'far': param} props = properties.Properties(schema, data, resolver=function.resolve) rule = translation.TranslationRule( props, translation.TranslationRule.REPLACE, ['far', 'bar'], value_path=['far', 'dar']) tran = translation.Translation(props) tran.set_rules([rule]) self.assertTrue(tran.has_translation('far.bar')) prop_data = props['far'] result = tran.translate('far.bar', prop_data['bar'], prop_data) self.assertEqual('rad', result) self.assertEqual('rad', tran.resolved_translations['far.bar'])
def test_property_commadelimitedlist_param_correct_translation(self): """Test when property with sub-schema takes comma_delimited_list.""" schema = { 'far': properties.Schema( properties.Schema.LIST, schema=properties.Schema( properties.Schema.STRING, ) ), 'boo': properties.Schema( properties.Schema.STRING )} class DummyStack(dict): @property def parameters(self): return mock.Mock() param = hot_funcs.GetParam(DummyStack(list_far='list_far'), 'get_param', 'list_far') param.parameters = { 'list_far': parameters.CommaDelimitedListParam( 'list_far', {'Type': 'CommaDelimitedList'}, "white,roses").value()} data = {'far': param, 'boo': 'chrysanthemums'} props = properties.Properties(schema, data, resolver=function.resolve) rule = translation.TranslationRule( props, translation.TranslationRule.ADD, ['far'], [props.get('boo')]) tran = translation.Translation(props) tran.set_rules([rule]) self.assertTrue(tran.has_translation('far')) result = tran.translate('far', props['far']) self.assertEqual(['white', 'roses', 'chrysanthemums'], result) self.assertEqual(['white', 'roses', 'chrysanthemums'], tran.resolved_translations['far'])
def test_replace_rule_str_value_path_error(self): schema = { 'far': properties.Schema(properties.Schema.STRING), 'bar': properties.Schema(properties.Schema.STRING) } data = {'far': 'one', 'bar': 'two'} props = properties.Properties(schema, data) rule = translation.TranslationRule(props, translation.TranslationRule.REPLACE, ['bar'], value_path=['far']) ex = self.assertRaises(exception.ResourcePropertyConflict, rule.execute_rule) self.assertEqual( "Cannot define the following properties at the " "same time: ['bar', 'far'].", six.text_type(ex))
def test_delete_rule_other(self): schema = { 'far': properties.Schema(properties.Schema.STRING) } data = {'far': 'one'} props = properties.Properties(schema, data) rule = translation.TranslationRule( props, translation.TranslationRule.DELETE, ['far']) tran = translation.Translation(props) tran.set_rules([rule]) self.assertTrue(tran.has_translation('far')) self.assertIsNone(tran.translate('far')) self.assertIsNone(tran.resolved_translations['far'])
def test_property_no_translation_removed_function(self): """Test case when list property with sub-schema takes json param.""" schema = { 'far': properties.Schema(properties.Schema.LIST, schema=properties.Schema( properties.Schema.MAP, schema={ 'bar': properties.Schema( properties.Schema.STRING, ), 'dar': properties.Schema( properties.Schema.STRING ) } )) } class DummyStack(dict): @property def parameters(self): return mock.Mock() param = hot_funcs.Removed(DummyStack(json_far='json_far'), 'Ref', 'json_far') param.parameters = { 'json_far': parameters.JsonParam( 'json_far', {'Type': 'Json'}, '{"dar": "rad"}').value()} data = {'far': [param]} props = properties.Properties(schema, data) rule = translation.TranslationRule( props, translation.TranslationRule.REPLACE, ['far', 'bar'], value_name='dar') rule.execute_rule() self.assertEqual([param], props.data.get('far'))
def test_replace_rule_map_dont_exist(self): schema = { 'far': properties.Schema( properties.Schema.MAP, schema={'red': properties.Schema(properties.Schema.STRING)}), 'bar': properties.Schema(properties.Schema.STRING) } data = {'bar': 'dak'} props = properties.Properties(schema, data) rule = translation.TranslationRule(props, translation.TranslationRule.REPLACE, ['far', 'red'], props.get('bar')) rule.execute_rule() self.assertEqual({'red': 'dak'}, props.get('far'))
def handle_update(self, json_snippet, tmpl_diff, prop_diff): if self.resource_id and prop_diff: snippet = json_snippet.get('Properties', {}) self.properties = properties.Properties(self.properties_schema, snippet, function.resolve, self.name) params = self.properties[self.PARAMETERS] env = environment.get_child_environment(self.stack.env, params) tmpl = template_format.parse(self.properties[self.TEMPLATE]) fields = { 'stack_id': self.resource_id, 'parameters': params, 'template': tmpl, 'timeout_mins': self.properties[self.TIMEOUT], 'disable_rollback': self.stack.disable_rollback, 'files': self.stack.t.files, 'environment': env.user_env_as_dict(), } self.heat().stacks.update(**fields)
def test_resolve_rule_list_with_function(self): client_plugin, schema = self._test_resolve_rule(is_list=True) join_func = cfn_funcs.Join(None, 'Fn::Join', ['.', ['bar', 'baz']]) data = { 'far': [{'red': 'blue'}, {'red': join_func}], } props = properties.Properties(schema, data) rule = translation.TranslationRule( props, translation.TranslationRule.RESOLVE, ['far', 'red'], client_plugin=client_plugin, finder='find_name_id' ) rule.execute_rule() self.assertEqual([{'red': 'yellow'}, {'red': 'yellow'}], props.get('far'))
def test_add_rule_invalid(self): schema = { 'far': properties.Schema( properties.Schema.MAP, schema={'red': properties.Schema(properties.Schema.STRING)}), 'bar': properties.Schema(properties.Schema.STRING) } data = {'far': 'tran', 'bar': 'dak'} props = properties.Properties(schema, data) rule = translation.TranslationRule(props, translation.TranslationRule.ADD, ['far'], [props.get('bar')]) exc = self.assertRaises(ValueError, rule.execute_rule) self.assertEqual('Add rule must be used only for lists.', six.text_type(exc))
def _generate_schema(self, props): self._parsed_nested = None try: tmpl = template.Template(self.child_template()) except ValueError as download_error: self.validation_exception = download_error tmpl = template.Template({}) # re-generate the properties and attributes from the template. self.properties_schema = (properties.Properties.schema_from_params( tmpl.param_schemata())) self.attributes_schema = (attributes.Attributes.schema_from_outputs( tmpl[tmpl.OUTPUTS])) self.properties = properties.Properties(self.properties_schema, props, self._resolve_runtime_data, self.name, self.context) self.attributes = attributes.Attributes(self.name, self.attributes_schema, self._resolve_attribute)
def test_resolve_rule_other_with_ref(self): client_plugin, schema = self._test_resolve_rule() class rsrc(object): action = INIT = "INIT" class DummyStack(dict): pass stack = DummyStack(another_res=rsrc()) ref = cfn_funcs.ResourceRef(stack, 'get_resource', 'another_res') data = {'far': ref} props = properties.Properties(schema, data) rule = translation.TranslationRule(props, translation.TranslationRule.RESOLVE, ['far'], client_plugin=client_plugin, finder='find_name_id') rule.execute_rule() self.assertEqual(data, props.data)
def test_replace_rule_str(self): schema = { 'far': properties.Schema(properties.Schema.STRING), 'bar': properties.Schema(properties.Schema.STRING) } data = {'far': 'one', 'bar': 'two'} props = properties.Properties(schema, data) rule = translation.TranslationRule(props, translation.TranslationRule.REPLACE, ['bar'], props.get('far')) tran = translation.Translation(props) tran.set_rules([rule]) self.assertTrue(tran.has_translation('bar')) result = tran.translate('bar', data['bar']) self.assertEqual('one', result) self.assertEqual('one', tran.resolved_translations['bar'])
def test_property_json_param_correct_translation(self): """Test case when property with sub-schema takes json param.""" schema = { 'far': properties.Schema(properties.Schema.MAP, schema={ 'bar': properties.Schema( properties.Schema.STRING, ), 'dar': properties.Schema( properties.Schema.STRING ) }) } class DummyStack(dict): @property def parameters(self): return mock.Mock() param = hot_funcs.GetParam(DummyStack(json_far='json_far'), 'get_param', 'json_far') param.parameters = { 'json_far': parameters.JsonParam( 'json_far', {'Type': 'Json'}, '{"dar": "rad"}').value()} data = {'far': param} props = properties.Properties(schema, data) rule = translation.TranslationRule( props, translation.TranslationRule.REPLACE, ['far', 'bar'], value_path=['far', 'dar']) rule.execute_rule() self.assertEqual('rad', props.get('far').get('bar'))
def test_replace_rule_list_with_custom_value_path(self): schema = { 'far': properties.Schema(properties.Schema.LIST, schema=properties.Schema( properties.Schema.MAP, schema={ 'red': properties.Schema( properties.Schema.STRING), 'blue': properties.Schema(properties.Schema.MAP) })) } data = { 'far': [{ 'blue': { 'black': { 'white': 'daisy' } } }, { 'red': 'roses' }] } props = properties.Properties(schema, data) rule = translation.TranslationRule( props, translation.TranslationRule.REPLACE, ['far', 'red'], value_name='blue', custom_value_path=['black', 'white']) tran = translation.Translation(props) tran.set_rules([rule]) self.assertTrue(tran.has_translation('far.0.red')) result = tran.translate('far.0.red', prop_data=data['far'][0]) self.assertEqual('daisy', result) self.assertEqual('daisy', tran.resolved_translations['far.0.red'])