def _make_instance(self, name): Instance = resource.get_class('AWS::EC2::Instance') class GroupedInstance(Instance): ''' Subclass instance.Instance to supress event transitions, since the scaling-group instances are not "real" resources, ie defined in the template, which causes problems for event handling since we can't look up the resources via parser.Stack ''' def state_set(self, new_state, reason="state changed"): self._store_or_update(new_state, reason) def check_active(self, create_data=None, override=True): ''' By default, report that the instance is active so that we won't wait for it in create(). ''' if override: return True return super(GroupedInstance, self).check_active(create_data) conf = self.properties['LaunchConfigurationName'] instance_definition = self.stack.t['Resources'][conf] return GroupedInstance(name, instance_definition, self.stack)
def _make_instance(self, name): Instance = resource.get_class('AWS::EC2::Instance') class GroupedInstance(Instance): ''' Subclass instance.Instance to supress event transitions, since the scaling-group instances are not "real" resources, ie defined in the template, which causes problems for event handling since we can't look up the resources via parser.Stack ''' def state_set(self, new_state, reason="state changed"): self._store_or_update(new_state, reason) def check_active(self, create_data=None, override=True): ''' By default, report that the instance is active so that we won't wait for it in create(). ''' if override: self._create_data = create_data return True return super(GroupedInstance, self).check_active(create_data) conf = self.properties['LaunchConfigurationName'] instance_definition = self.stack.t['Resources'][conf] return GroupedInstance(name, instance_definition, self.stack)
def test_get_os_empty_registry(self): # assertion: with an empty environment we get the correct # default class. env_str = {'resource_registry': {}} env = environment.Environment(env_str) cls = resource.get_class('OS::ResourceType', 'fred', env) self.assertEqual(cls, generic_rsrc.GenericResource)
def _make_instance(self, name): # We look up and subclass the class for AWS::EC2::Instance instead of # just importing Instance, so that if someone overrides that resource # we'll use the custom one. Instance = resource.get_class('AWS::EC2::Instance', resource_name=name, environment=self.stack.env) class GroupedInstance(Instance): ''' Subclass Instance to suppress event transitions, since the scaling-group instances are not "real" resources, ie defined in the template, which causes problems for event handling since we can't look up the resources via parser.Stack ''' def state_set(self, action, status, reason="state changed"): self._store_or_update(action, status, reason) conf = self.properties['LaunchConfigurationName'] instance_definition = self.stack.t['Resources'][conf] # honour the Tags property in the InstanceGroup and AutoScalingGroup tags = self.properties.data.get('Tags', []) instance_definition['Properties']['Tags'] = tags return GroupedInstance(name, instance_definition, self.stack)
def test_get_mine_resource_map(self): # assertion: with a global rule we get the "mycloud" class. env_str = {'resource_registry': {'resources': {'fred': { "OS::ResourceType": "myCloud::ResourceType"}}}} env = environment.Environment(env_str) cls = resource.get_class('OS::ResourceType', 'fred', env) self.assertEqual(cls, MyCloudResource)
def test_get_os_no_match(self): # assertion: make sure 'fred' doesn't match 'jerry'. env_str = {'resource_registry': {'resources': {'jerry': { "OS::ResourceType": "myCloud::ResourceType"}}}} env = environment.Environment(env_str) cls = resource.get_class('OS::ResourceType', 'fred', env) self.assertEqual(cls, generic_rsrc.GenericResource)
def resource_schema(self, cnxt, type_name): """ Return the schema of the specified type. arg1 -> RPC context. arg2 -> Name of the resource type to obtain the schema of. """ try: resource_class = resource.get_class(type_name) except exception.StackValidationFailed: raise exception.ResourceTypeNotFound(type_name=type_name) def properties_schema(): for name, schema_dict in resource_class.properties_schema.items(): schema = properties.Schema.from_legacy(schema_dict) if schema.implemented: yield name, dict(schema) def attributes_schema(): for schema_item in resource_class.attributes_schema.items(): schema = attributes.Attribute(*schema_item) yield schema.name, {schema.DESCRIPTION: schema.description} return { rpc_api.RES_SCHEMA_RES_TYPE: type_name, rpc_api.RES_SCHEMA_PROPERTIES: dict(properties_schema()), rpc_api.RES_SCHEMA_ATTRIBUTES: dict(attributes_schema()), }
def test_instance_group_custom_resource(self): """ If AWS::EC2::Instance is overridden, InstanceGroup will automatically use that overridden resource type. """ # resources may need to be initialised if this is the first test run. resources.initialise() class MyInstance(instance.Instance): """A customized Instance resource.""" original_instance = resource.get_class("AWS::EC2::Instance") resource._register_class("AWS::EC2::Instance", MyInstance) self.addCleanup(resource._register_class, "AWS::EC2::Instance", original_instance) t = template_format.parse(ig_template) stack = utils.parse_stack(t) self._stub_create(1, instance_class=MyInstance) self.m.ReplayAll() conf = self.create_resource(t, stack, 'JobServerConfig') rsrc = self.create_resource(t, stack, 'JobServerGroup') self.assertEqual('JobServerGroup', rsrc.FnGetRefId()) rsrc.delete() self.m.VerifyAll()
def test_instance_group_custom_resource(self): """ If AWS::EC2::Instance is overridden, InstanceGroup will automatically use that overridden resource type. """ # resources may need to be initialised if this is the first test run. resources.initialise() class MyInstance(instance.Instance): """A customized Instance resource.""" original_instance = resource.get_class("AWS::EC2::Instance") resource._register_class("AWS::EC2::Instance", MyInstance) self.addCleanup(resource._register_class, "AWS::EC2::Instance", original_instance) t = template_format.parse(ig_template) stack = utils.parse_stack(t) self._stub_create(1, instance_class=MyInstance) self.m.ReplayAll() conf = self.create_resource(t, stack, 'JobServerConfig') rsrc = self.create_resource(t, stack, 'JobServerGroup') self.assertEqual(utils.PhysName(stack.name, rsrc.name), rsrc.FnGetRefId()) rsrc.delete() self.m.VerifyAll()
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 = tmpl.get('Resources', []) if not tmpl_resources: return {'Error': 'At least one Resources member must be defined.'} for res in tmpl_resources.values(): try: if not res.get('Type'): return {'Error': 'Every Resource object must ' 'contain a Type member.'} except AttributeError: type_res = type(res) if isinstance(res, unicode): type_res = "string" return {'Error': 'Resources must contain Resource. ' 'Found a [%s] instead' % type_res} ResourceClass = resource.get_class(res['Type']) if ResourceClass == resources.template_resource.TemplateResource: # we can't validate a TemplateResource unless we instantiate # it as we need to download the template and convert the # paramerters into properties_schema. continue 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, validate_value=False) 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': tmpl.get('Description', ''), 'Parameters': params, } return result
def test_get_template_resource(self): # assertion: if the name matches {.yaml|.template} we get the # TemplateResource class. env_str = {'resource_registry': {'resources': {'fred': { "OS::ResourceType": "some_magic.yaml"}}}} env = environment.Environment(env_str) cls = resource.get_class('OS::ResourceType', 'fred', env) self.assertEqual(cls, template_resource.TemplateResource)
def validate_template(self, cnxt, template): """ The validate_template method uses the stack parser to check the validity of a template. :param cnxt: RPC context. :param template: Template of stack you want to create. """ logger.info(_('validate_template')) if template is None: msg = _("No Template provided.") return webob.exc.HTTPBadRequest(explanation=msg) tmpl = parser.Template(template) tmpl_resources = tmpl.get('Resources', []) if not tmpl_resources: return {'Error': 'At least one Resources member must be defined.'} for res in tmpl_resources.values(): try: if not res.get('Type'): return {'Error': 'Every Resource object must ' 'contain a Type member.'} except AttributeError: type_res = type(res) if isinstance(res, unicode): type_res = "string" return {'Error': 'Resources must contain Resource. ' 'Found a [%s] instead' % type_res} ResourceClass = resource.get_class(res['Type']) if ResourceClass == resources.template_resource.TemplateResource: # we can't validate a TemplateResource unless we instantiate # it as we need to download the template and convert the # paramerters into properties_schema. continue props = properties.Properties(ResourceClass.properties_schema, res.get('Properties', {}), context=cnxt) try: ResourceClass.validate_deletion_policy(res) props.validate(with_value=False) except Exception as ex: return {'Error': str(ex)} tmpl_params = tmpl.parameters(None, {}, validate_value=False) is_real_param = lambda p: p.name not in tmpl_params.PSEUDO_PARAMETERS params = tmpl_params.map(api.format_validate_parameter, is_real_param) result = { 'Description': tmpl.get('Description', ''), 'Parameters': params, } return result
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 = tmpl.get('Resources', []) if not tmpl_resources: return {'Error': 'At least one Resources member must be defined.'} for res in tmpl_resources.values(): try: if not res.get('Type'): return { 'Error': 'Every Resource object must ' 'contain a Type member.' } except AttributeError: type_res = type(res) if isinstance(res, unicode): type_res = "string" return { 'Error': 'Resources must contain Resource. ' 'Found a [%s] instead' % type_res } 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, validate_value=False) 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': tmpl.get('Description', ''), 'Parameters': params, } return result
def generate_template(self, cnxt, type_name): """ Generate a template based on the specified type. arg1 -> RPC context. arg2 -> Name of the resource type to generate a template for. """ try: return resource.get_class(type_name).resource_to_template(type_name) except exception.StackValidationFailed: raise exception.ResourceTypeNotFound(type_name=type_name)
def test_get_mine_type_map(self): # assertion: with a global rule we get the "mycloud" class. env_str = { 'resource_registry': { "OS::ResourceType": "myCloud::ResourceType" } } env = environment.Environment(env_str) cls = resource.get_class('OS::ResourceType', 'fred', env) self.assertEqual(cls, MyCloudResource)
def __init__(self, name, json_snippet, stack): self.template_name = stack.env.get_resource_type(json_snippet['Type'], name) # on purpose don't pass in the environment so we get # the official/facade class to copy it's schema. cls_facade = resource.get_class(json_snippet['Type']) self.properties_schema = cls_facade.properties_schema self.attributes_schema = cls_facade.attributes_schema super(TemplateResource, self).__init__(name, json_snippet, stack)
def generate_template(self, cnxt, type_name): """ Generate a template based on the specified type. arg1 -> RPC context. arg2 -> Name of the resource type to generate a template for. """ try: return \ resource.get_class(type_name).resource_to_template(type_name) except exception.StackValidationFailed: raise exception.ResourceTypeNotFound(type_name=type_name)
def test_get_os_no_match(self): # assertion: make sure 'fred' doesn't match 'jerry'. env_str = { 'resource_registry': { 'resources': { 'jerry': { "OS::ResourceType": "myCloud::ResourceType" } } } } env = environment.Environment(env_str) cls = resource.get_class('OS::ResourceType', 'fred', env) self.assertEqual(cls, generic_rsrc.GenericResource)
def test_get_template_resource(self): # assertion: if the name matches {.yaml|.template} we get the # TemplateResource class. env_str = { 'resource_registry': { 'resources': { 'fred': { "OS::ResourceType": "some_magic.yaml" } } } } env = environment.Environment(env_str) cls = resource.get_class('OS::ResourceType', 'fred', env) self.assertEqual(cls, template_resource.TemplateResource)
def _make_instance(self, name): Instance = resource.get_class('AWS::EC2::Instance') class GroupedInstance(Instance): ''' Subclass instance.Instance to supress event transitions, since the scaling-group instances are not "real" resources, ie defined in the template, which causes problems for event handling since we can't look up the resources via parser.Stack ''' def state_set(self, new_state, reason="state changed"): self._store_or_update(new_state, reason) conf = self.properties['LaunchConfigurationName'] instance_definition = self.stack.t['Resources'][conf] return GroupedInstance(name, instance_definition, self.stack)
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 = tmpl.get("Resources", []) if not tmpl_resources: return {"Error": "At least one Resources member must be defined."} for res in tmpl_resources.values(): try: if not res.get("Type"): return {"Error": "Every Resource object must " "contain a Type member."} except AttributeError: type_res = type(res) if isinstance(res, unicode): type_res = "string" return {"Error": "Resources must contain Resource. " "Found a [%s] instead" % type_res} 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, validate_value=False) 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": tmpl.get("Description", ""), "Parameters": params} return result
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 = tmpl.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, validate_value=False) 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': tmpl.get('Description', ''), 'Parameters': params, } return result
def __init__(self, name, json_snippet, stack): self.template_name = stack.env.get_resource_type(json_snippet["Type"], name) self._parsed_nested = None self.stack = stack # on purpose don't pass in the environment so we get # the official/facade class in case we need to copy it's schema. cls_facade = resource.get_class(json_snippet["Type"]) # if we're not overriding via the environment, mirror the template as # a new resource if cls_facade == self.__class__: self.properties_schema = properties.Properties.schema_from_params(self.parsed_nested.get("Parameters")) self.attributes_schema = attributes.Attributes.schema_from_outputs(self.parsed_nested.get("Outputs")) # otherwise we are overriding a resource type via the environment # and should mimic that type else: self.properties_schema = cls_facade.properties_schema self.attributes_schema = cls_facade.attributes_schema super(TemplateResource, self).__init__(name, json_snippet, stack)
def __init__(self, name, json_snippet, stack): self.template_name = stack.env.get_resource_type( json_snippet['Type'], name) self._parsed_nested = None self.stack = stack # on purpose don't pass in the environment so we get # the official/facade class in case we need to copy it's schema. cls_facade = resource.get_class(json_snippet['Type']) # if we're not overriding via the environment, mirror the template as # a new resource if cls_facade == self.__class__: self.properties_schema = (properties.Properties.schema_from_params( self.parsed_nested.get('Parameters'))) self.attributes_schema = ( attributes.Attributes.schema_from_outputs( self.parsed_nested.get('Outputs'))) # otherwise we are overriding a resource type via the environment # and should mimic that type else: self.properties_schema = cls_facade.properties_schema self.attributes_schema = cls_facade.attributes_schema super(TemplateResource, self).__init__(name, json_snippet, stack)
def test_get_class_ok(self): cls = resource.get_class('GenericResourceType') self.assertEqual(cls, generic_rsrc.GenericResource)
def test_get_class_ok(self): cls = resource.get_class("GenericResourceType") self.assertEqual(generic_rsrc.GenericResource, cls)