def mock_lcp_class_map(self, lcp_mappings): self.m.UnsetStubs() self.m.StubOutWithMock(resources.global_env(), 'get_stack_lifecycle_plugins') resources.global_env().get_stack_lifecycle_plugins().\ MultipleTimes().AndReturn(lcp_mappings) self.m.ReplayAll() # reset cache lifecycle_plugin_utils.pp_class_instances = None
def setUp(self): super(HeatTestCase, self).setUp() self.m = mox.Mox() self.addCleanup(self.m.UnsetStubs) self.setup_logging() scheduler.ENABLE_SLEEP = False self.useFixture(fixtures.MonkeyPatch( 'heat.common.exception._FATAL_EXCEPTION_FORMAT_ERRORS', True)) def enable_sleep(): scheduler.ENABLE_SLEEP = True self.addCleanup(enable_sleep) mod_dir = os.path.dirname(sys.modules[__name__].__file__) project_dir = os.path.abspath(os.path.join(mod_dir, '../../')) env_dir = os.path.join(project_dir, 'etc', 'heat', 'environment.d') cfg.CONF.set_default('environment_dir', env_dir) self.addCleanup(cfg.CONF.reset) messaging.setup("fake://", optional=True) self.addCleanup(messaging.cleanup) tri = resources.global_env().get_resource_info( 'AWS::RDS::DBInstance', registry_type=environment.TemplateResourceInfo) if tri is not None: cur_path = tri.template_name templ_path = os.path.join(project_dir, 'etc', 'heat', 'templates') if templ_path not in cur_path: tri.template_name = cur_path.replace('/etc/heat/templates', templ_path) # use CWLiteAlarm for testing. resources.global_env().registry.load( {"AWS::CloudWatch::Alarm": "OS::Heat::CWLiteAlarm"}) utils.setup_dummy_db() self.addCleanup(utils.reset_dummy_db) cached_wait_time = stack.ERROR_WAIT_TIME stack.ERROR_WAIT_TIME = None def replace_wait_time(): stack.ERROR_WAIT_TIME = cached_wait_time self.addCleanup(replace_wait_time)
def __init__(self, env=None, user_env=True): """Create an Environment from a dict of varying format. 1) old-school flat parameters 2) or newer {resource_registry: bla, parameters: foo} :param env: the json environment :param user_env: boolean, if false then we manage python resources too. """ if env is None: env = {} if user_env: from heat.engine import resources global_registry = resources.global_env().registry else: global_registry = None self.registry = ResourceRegistry(global_registry, self) self.registry.load(env.get(env_fmt.RESOURCE_REGISTRY, {})) if env_fmt.PARAMETER_DEFAULTS in env: self.param_defaults = env[env_fmt.PARAMETER_DEFAULTS] else: self.param_defaults = {} self.encrypted_param_names = env.get(env_fmt.ENCRYPTED_PARAM_NAMES, []) if env_fmt.PARAMETERS in env: self.params = env[env_fmt.PARAMETERS] else: self.params = dict((k, v) for (k, v) in six.iteritems(env) if k not in (env_fmt.PARAMETER_DEFAULTS, env_fmt.RESOURCE_REGISTRY)) self.constraints = {} self.stack_lifecycle_plugins = []
def __init__(self, env=None, user_env=True): """Create an Environment from a dict of varying format. 1) old-school flat parameters 2) or newer {resource_registry: bla, parameters: foo} :param env: the json environment :param user_env: boolean, if false then we manage python resources too. """ if env is None: env = {} if user_env: from heat.engine import resources global_registry = resources.global_env().registry else: global_registry = None self.registry = ResourceRegistry(global_registry) self.registry.load(env.get(RESOURCE_REGISTRY, {})) if 'parameters' in env: self.params = env['parameters'] else: self.params = dict((k, v) for (k, v) in env.iteritems() if k != RESOURCE_REGISTRY) self.constraints = {}
def test_system_template_retrieve_by_file(self): # make sure that a TemplateResource defined in the global environment # can be created and the template retrieved using the "file:" # scheme. g_env = resources.global_env() test_templ_name = 'file:///etc/heatr/frodo.yaml' g_env.load({'resource_registry': {'Test::Frodo': test_templ_name}}) stack = parser.Stack(utils.dummy_context(), 'test_stack', parser.Template(empty_template), stack_id=str(uuid.uuid4())) minimal_temp = json.dumps({'HeatTemplateFormatVersion': '2012-12-12', 'Parameters': {}, 'Resources': {}}) self.m.StubOutWithMock(urlfetch, "get") urlfetch.get(test_templ_name, allowed_schemes=('http', 'https', 'file')).AndReturn(minimal_temp) self.m.ReplayAll() definition = rsrc_defn.ResourceDefinition('test_t_res', 'Test::Frodo') temp_res = template_resource.TemplateResource('test_t_res', definition, stack) self.assertIsNone(temp_res.validate()) self.m.VerifyAll()
def test_system_template_retrieve_fail(self): # make sure that a TemplateResource defined in the global environment # fails gracefully if the template file specified is inaccessible # we should be able to create the TemplateResource object, but # validation should fail, when the second attempt to access it is # made in validate() g_env = resources.global_env() test_templ_name = 'file:///etc/heatr/frodo.yaml' g_env.load({'resource_registry': {'Test::Frodo': test_templ_name}}) stack = parser.Stack(utils.dummy_context(), 'test_stack', parser.Template(empty_template), stack_id=str(uuid.uuid4())) self.m.StubOutWithMock(urlfetch, "get") urlfetch.get(test_templ_name, allowed_schemes=('http', 'https', 'file'))\ .AndRaise(urlfetch.URLFetchError(_('Failed to retrieve template'))) self.m.ReplayAll() definition = rsrc_defn.ResourceDefinition('test_t_res', 'Test::Frodo') temp_res = template_resource.TemplateResource('test_t_res', definition, stack) self.assertRaises(exception.StackValidationFailed, temp_res.validate) self.m.VerifyAll()
def setUp(self): super(HeatTestCase, self).setUp() self.m = mox.Mox() self.addCleanup(self.m.UnsetStubs) self.setup_logging() scheduler.ENABLE_SLEEP = False self.useFixture(fixtures.MonkeyPatch("heat.common.exception._FATAL_EXCEPTION_FORMAT_ERRORS", True)) def enable_sleep(): scheduler.ENABLE_SLEEP = True self.addCleanup(enable_sleep) mod_dir = os.path.dirname(sys.modules[__name__].__file__) project_dir = os.path.abspath(os.path.join(mod_dir, "../../")) env_dir = os.path.join(project_dir, "etc", "heat", "environment.d") cfg.CONF.set_default("environment_dir", env_dir) self.addCleanup(cfg.CONF.reset) messaging.setup("fake://", optional=True) self.addCleanup(messaging.cleanup) tri = resources.global_env().get_resource_info( "AWS::RDS::DBInstance", registry_type=environment.TemplateResourceInfo ) if tri is not None: cur_path = tri.template_name templ_path = os.path.join(project_dir, "etc", "heat", "templates") if templ_path not in cur_path: tri.template_name = cur_path.replace("/etc/heat/templates", templ_path) utils.setup_dummy_db() self.addCleanup(utils.reset_dummy_db)
def _all_resources(prefix=None): g_env = resources.global_env() all_resources = g_env.get_types() for resource_type in sorted(all_resources): resource_class = g_env.get_class(resource_type) if not prefix or resource_type.startswith(prefix): yield resource_type, resource_class
def test_custom_constraint(self): class ZeroConstraint(object): def validate(self, value, context): return value == "0" env = resources.global_env() env.register_constraint("zero", ZeroConstraint) self.addCleanup(env.constraints.pop, "zero") desc = "Value must be zero" param = {"param1": {"type": "string", "constraints": [{"custom_constraint": "zero", "description": desc}]}} name = "param1" schema = param["param1"] def v(value): hot.HOTParamSchema.from_dict(schema).validate(name, value) return True value = "1" err = self.assertRaises(ValueError, v, value) self.assertEqual(desc, str(err)) value = "2" err = self.assertRaises(ValueError, v, value) self.assertEqual(desc, str(err)) value = "0" self.assertTrue(v(value))
def test_custom_constraint(self): class ZeroConstraint(object): def validate(self, value, context): return value == "0" env = resources.global_env() env.register_constraint("zero", ZeroConstraint) self.addCleanup(env.constraints.pop, "zero") desc = 'Value must be zero' param = { 'param1': { 'type': 'string', 'constraints': [ {'custom_constraint': 'zero', 'description': desc}]}} name = 'param1' schema = param['param1'] def v(value): hot_param.HOTParamSchema.from_dict(schema).validate(name, value) return True value = "1" err = self.assertRaises(ValueError, v, value) self.assertEqual(desc, str(err)) value = "2" err = self.assertRaises(ValueError, v, value) self.assertEqual(desc, str(err)) value = "0" self.assertTrue(v(value))
def setUp(self): super(HeatTestCase, self).setUp() self.m = mox.Mox() self.addCleanup(self.m.UnsetStubs) self.logger = self.useFixture(fixtures.FakeLogger(level=logging.DEBUG)) scheduler.ENABLE_SLEEP = False self.useFixture(fixtures.MonkeyPatch( 'heat.common.exception._FATAL_EXCEPTION_FORMAT_ERRORS', True)) def enable_sleep(): scheduler.ENABLE_SLEEP = True self.addCleanup(enable_sleep) mod_dir = os.path.dirname(sys.modules[__name__].__file__) project_dir = os.path.abspath(os.path.join(mod_dir, '../../')) env_dir = os.path.join(project_dir, 'etc', 'heat', 'environment.d') cfg.CONF.set_default('environment_dir', env_dir) cfg.CONF.set_override('allowed_rpc_exception_modules', ['heat.common.exception', 'exceptions']) self.addCleanup(cfg.CONF.reset) tri = resources.global_env().get_resource_info( 'AWS::RDS::DBInstance', registry_type=environment.TemplateResourceInfo) if tri is not None: cur_path = tri.template_name templ_path = os.path.join(project_dir, 'etc', 'heat', 'templates') if templ_path not in cur_path: tri.template_name = cur_path.replace('/etc/heat/templates', templ_path)
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 = resources.global_env().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() 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 get_plug_point_class_instances(): """Instances of classes that implements pre/post stack operation methods. Get list of instances of classes that (may) implement pre and post stack operation methods. The list of class instances is sorted using get_ordinal methods on the plug point classes. If class1.ordinal() < class2.ordinal(), then class1 will be before before class2 in the list. """ global pp_class_instances if pp_class_instances is None: pp_class_instances = [] pp_classes = [] try: slps = resources.global_env().get_stack_lifecycle_plugins() pp_classes = [cls for name, cls in slps] except Exception: LOG.exception("failed to get lifecycle plug point classes") for ppc in pp_classes: try: pp_class_instances.append(ppc()) except Exception: LOG.exception( "failed to instantiate stack lifecycle class %s", ppc) try: pp_class_instances = sorted(pp_class_instances, key=lambda ppci: ppci.get_ordinal()) except Exception: LOG.exception("failed to sort lifecycle plug point classes") return pp_class_instances
def test_template_as_resource(self): """ Test that the resulting resource has the right prop and attrib schema. Note that this test requires the Wordpress_Single_Instance.yaml template in the templates directory since we want to test using a non-trivial template. """ test_templ_name = "WordPress_Single_Instance.yaml" path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates', test_templ_name) # check if its in the directory list vs. exists to work around # case-insensitive file systems self.assertIn(test_templ_name, os.listdir(os.path.dirname(path))) with open(path) as test_templ_file: test_templ = test_templ_file.read() self.assertTrue(test_templ, "Empty test template") self.m.StubOutWithMock(urlfetch, "get") urlfetch.get(test_templ_name, allowed_schemes=('file',) ).AndRaise(urlfetch.URLFetchError( _('Failed to retrieve template'))) urlfetch.get(test_templ_name, allowed_schemes=('http', 'https')).AndReturn(test_templ) parsed_test_templ = template_format.parse(test_templ) self.m.ReplayAll() stack = parser.Stack(utils.dummy_context(), 'test_stack', template.Template(empty_template), stack_id=str(uuid.uuid4())) properties = { "KeyName": "mykeyname", "DBName": "wordpress1", "DBUsername": "******", "DBPassword": "******", "DBRootPassword": "******", "LinuxDistribution": "U10" } definition = rsrc_defn.ResourceDefinition("test_templ_resource", test_templ_name, properties) templ_resource = resource.Resource("test_templ_resource", definition, stack) self.m.VerifyAll() self.assertIsInstance(templ_resource, template_resource.TemplateResource) for prop in parsed_test_templ.get("Parameters", {}): self.assertIn(prop, templ_resource.properties) for attrib in parsed_test_templ.get("Outputs", {}): self.assertIn(attrib, templ_resource.attributes) for k, v in properties.items(): self.assertEqual(v, templ_resource.properties[k]) self.assertEqual( {'WordPress_Single_Instance.yaml': 'WordPress_Single_Instance.yaml', 'resources': {}}, stack.env.user_env_as_dict()["resource_registry"]) self.assertNotIn('WordPress_Single_Instance.yaml', resources.global_env().registry._registry)
def test_list_type_with_is_available_exception(self): registry = resources.global_env().registry self.patchobject( generic_resource.GenericResource, 'is_service_available', side_effect=exception.ClientNotAvailable(client_name='generic')) types = registry.get_types(utils.dummy_context()) self.assertNotIn('GenericResourceType', types)
def test_empty_env_dir(self): list_dir = "heat.engine.resources._list_environment_files" with mock.patch(list_dir) as m_ldir: m_ldir.return_value = [] env_dir = "/etc_etc/heat/environment.d" resources._load_global_environment(resources.global_env(), env_dir) m_ldir.assert_called_once_with(env_dir)
def custom_constraint(self): if self._custom_constraint is None: if self._environment is None: self._environment = resources.global_env() constraint_class = self._environment.get_constraint(self.name) if constraint_class: self._custom_constraint = constraint_class() return self._custom_constraint
def setUp(self, mock_keystone=True, mock_resource_policy=True, quieten_logging=True): super(HeatTestCase, self).setUp() self.m = mox.Mox() self.addCleanup(self.m.UnsetStubs) self.setup_logging(quieten=quieten_logging) self.warnings = self.useFixture(fixtures.WarningsCapture()) scheduler.ENABLE_SLEEP = False self.useFixture(fixtures.MonkeyPatch( 'heat.common.exception._FATAL_EXCEPTION_FORMAT_ERRORS', True)) def enable_sleep(): scheduler.ENABLE_SLEEP = True self.addCleanup(enable_sleep) mod_dir = os.path.dirname(sys.modules[__name__].__file__) project_dir = os.path.abspath(os.path.join(mod_dir, '../../')) env_dir = os.path.join(project_dir, 'etc', 'heat', 'environment.d') template_dir = os.path.join(project_dir, 'etc', 'heat', 'templates') cfg.CONF.set_default('environment_dir', env_dir) cfg.CONF.set_override('error_wait_time', None, enforce_type=True) cfg.CONF.set_default('template_dir', template_dir) self.addCleanup(cfg.CONF.reset) messaging.setup("fake://", optional=True) self.addCleanup(messaging.cleanup) tri_names = ['AWS::RDS::DBInstance', 'AWS::CloudWatch::Alarm'] tris = [] for name in tri_names: tris.append(resources.global_env().get_resource_info( name, registry_type=environment.TemplateResourceInfo)) for tri in tris: if tri is not None: cur_path = tri.template_name templ_path = os.path.join(project_dir, 'etc', 'heat', 'templates') if templ_path not in cur_path: tri.template_name = cur_path.replace( '/etc/heat/templates', templ_path) if mock_keystone: self.stub_keystoneclient() if mock_resource_policy: self.mock_resource_policy = self.patchobject( policy.ResourceEnforcer, 'enforce') utils.setup_dummy_db() self.register_test_resources() self.addCleanup(utils.reset_dummy_db)
def test_happy_path(self): list_dir = "heat.engine.resources._list_environment_files" with mock.patch(list_dir) as m_ldir: m_ldir.return_value = ["/etc_etc/heat/environment.d/a.yaml"] env_dir = "/etc_etc/heat/environment.d" env_content = '{"resource_registry": {}}' with mock.patch("heat.engine.resources.open", mock.mock_open(read_data=env_content), create=True) as m_open: resources._load_global_environment(resources.global_env(), env_dir) m_ldir.assert_called_once_with(env_dir) m_open.assert_called_once_with("%s/a.yaml" % env_dir)
def setUp(self, mock_keystone=True, mock_resource_policy=True, quieten_logging=True): super(HeatTestCase, self).setUp() self.setup_logging(quieten=quieten_logging) self.warnings = self.useFixture(fixtures.WarningsCapture()) scheduler.ENABLE_SLEEP = False self.useFixture( fixtures.MonkeyPatch( 'heat.common.exception._FATAL_EXCEPTION_FORMAT_ERRORS', True)) def enable_sleep(): scheduler.ENABLE_SLEEP = True self.addCleanup(enable_sleep) mod_dir = os.path.dirname(sys.modules[__name__].__file__) project_dir = os.path.abspath(os.path.join(mod_dir, '../../')) env_dir = os.path.join(project_dir, 'etc', 'heat', 'environment.d') template_dir = os.path.join(project_dir, 'etc', 'heat', 'templates') cfg.CONF.set_default('environment_dir', env_dir) cfg.CONF.set_override('error_wait_time', None) cfg.CONF.set_default('template_dir', template_dir) self.addCleanup(cfg.CONF.reset) messaging.setup("fake://", optional=True) self.addCleanup(messaging.cleanup) tri_names = ['AWS::RDS::DBInstance', 'AWS::CloudWatch::Alarm'] tris = [] for name in tri_names: tris.append(resources.global_env().get_resource_info( name, registry_type=environment.TemplateResourceInfo)) for tri in tris: if tri is not None: cur_path = tri.template_name templ_path = os.path.join(project_dir, 'etc', 'heat', 'templates') if templ_path not in cur_path: tri.template_name = cur_path.replace( '/etc/heat/templates', templ_path) if mock_keystone: self.stub_keystoneclient() if mock_resource_policy: self.mock_resource_policy = self.patchobject( policy.ResourceEnforcer, 'enforce') utils.setup_dummy_db() self.register_test_resources() self.addCleanup(utils.reset_dummy_db)
def test_template_as_resource(self): """ Test that the resulting resource has the right prop and attrib schema. Note that this test requires the Wordpress_Single_Instance.yaml template in the templates directory since we want to test using a non-trivial template. """ test_templ_name = "WordPress_Single_Instance.yaml" path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates', test_templ_name) # check if its in the directory list vs. exists to work around # case-insensitive file systems self.assertIn(test_templ_name, os.listdir(os.path.dirname(path))) with open(path) as test_templ_file: test_templ = test_templ_file.read() self.assertTrue(test_templ, "Empty test template") self.m.StubOutWithMock(urlfetch, "get") urlfetch.get(test_templ_name, allowed_schemes=('http', 'https')).AndReturn(test_templ) parsed_test_templ = template_format.parse(test_templ) self.m.ReplayAll() json_snippet = { "Type": test_templ_name, "Properties": { "KeyName": "mykeyname", "DBName": "wordpress1", "DBUsername": "******", "DBPassword": "******", "DBRootPassword": "******", "LinuxDistribution": "U10" } } stack = parser.Stack(None, 'test_stack', parser.Template({}), stack_id=uuidutils.generate_uuid()) templ_resource = resource.Resource("test_templ_resource", json_snippet, stack) self.m.VerifyAll() self.assertIsInstance(templ_resource, template_resource.TemplateResource) for prop in parsed_test_templ.get("Parameters", {}): self.assertIn(prop, templ_resource.properties) for attrib in parsed_test_templ.get("Outputs", {}): self.assertIn(attrib, templ_resource.attributes) for k, v in json_snippet.get("Properties").items(): self.assertEqual(v, templ_resource.properties[k]) self.assertNotIn('WordPress_Single_Instance.yaml', resources.global_env().registry._registry)
def __init__(self, exclude): self.error_count = 0 self.resources_classes = [] global_env = resources.global_env() for resource_type in global_env.get_types(): cls = global_env.get_class(resource_type) # Skip resources, which defined as template resource in environment if cls.__module__ == 'heat.engine.resources.template_resource': continue if (lambda module: True if [path for path in exclude if path in module] else False)(cls.__module__.replace('.', '/')): continue self.resources_classes.append(cls)
def __init__(self, env=None, user_env=True): """Create an Environment from an input dict. The dict may be in one of two formats: 1) old-school flat parameters; or 2) newer {resource_registry: bla, parameters: foo} :param env: the json environment :param user_env: boolean, if False then we manage python resources too. """ if env is None: env = {} if user_env: from heat.engine import resources global_env = resources.global_env() global_registry = global_env.registry event_sink_classes = global_env.event_sink_classes else: global_registry = None event_sink_classes = {} self.param_defaults = env.get(env_fmt.PARAMETER_DEFAULTS, {}) self.registry = ResourceRegistry(global_registry, self.param_defaults) self.registry.load(env.get(env_fmt.RESOURCE_REGISTRY, {})) self.encrypted_param_names = env.get(env_fmt.ENCRYPTED_PARAM_NAMES, []) if env_fmt.PARAMETERS in env: self.params = env[env_fmt.PARAMETERS] else: self.params = dict( (k, v) for (k, v) in six.iteritems(env) if k not in ( env_fmt.PARAMETER_DEFAULTS, env_fmt.ENCRYPTED_PARAM_NAMES, env_fmt.EVENT_SINKS, env_fmt.RESOURCE_REGISTRY, ) ) self.event_sink_classes = event_sink_classes self._event_sinks = [] self._built_event_sinks = [] self._update_event_sinks(env.get(env_fmt.EVENT_SINKS, [])) self.constraints = {} self.stack_lifecycle_plugins = []
def test_happy_path(self): list_dir = 'heat.engine.resources._list_environment_files' with mock.patch(list_dir) as m_ldir: m_ldir.return_value = ['/etc_etc/heat/enviroment.d/a.yaml'] env_dir = '/etc_etc/heat/enviroment.d' env_content = '{"resource_registry": {}}' with mock.patch('heat.engine.resources.open', mock.mock_open(read_data=env_content), create=True) as m_open: resources._load_global_environment(resources.global_env(), env_dir) m_ldir.assert_called_once_with(env_dir) m_open.assert_called_once_with('%s/a.yaml' % env_dir)
def __init__(self, exclude): self.error_count = 0 self.resources_classes = [] global_env = resources.global_env() for resource_type in global_env.get_types(): cls = global_env.get_class(resource_type) # Skip resources, which defined as template resource in environment if cls.__module__ == 'heat.engine.resources.template_resource': continue if (lambda module: True if [path for path in exclude if path in module] else False)(cls.__module__.replace( '.', '/')): continue self.resources_classes.append(cls)
def test_continue_on_parse_error(self): """assert we get all files processed even if there are processing exceptions. """ list_dir = "heat.engine.resources._list_environment_files" with mock.patch(list_dir) as m_ldir: m_ldir.return_value = ["/etc_etc/heat/environment.d/a.yaml", "/etc_etc/heat/environment.d/b.yaml"] env_dir = "/etc_etc/heat/environment.d" env_content = "{@$%#$%" with mock.patch("heat.engine.resources.open", mock.mock_open(read_data=env_content), create=True) as m_open: resources._load_global_environment(resources.global_env(), env_dir) m_ldir.assert_called_once_with(env_dir) expected = [mock.call("%s/a.yaml" % env_dir), mock.call("%s/b.yaml" % env_dir)] self.assertEqual(expected, m_open.call_args_list)
def __init__(self, exclude): self.error_count = 0 self.resources_classes = [] global_env = resources.global_env() for resource_type in global_env.get_types(): cls = global_env.get_class(resource_type) module = cls.__module__ # Skip resources, which defined as template resource in environment if module == 'heat.engine.resources.template_resource': continue # Skip discovered plugin resources if module == 'heat.engine.plugins': continue path = module.replace('.', '/') if any(path.startswith(excl_path) for excl_path in exclude): continue self.resources_classes.append(cls)
def setUp(self): super(HeatTestCase, self).setUp() self.m = mox.Mox() self.addCleanup(self.m.UnsetStubs) self.setup_logging() scheduler.ENABLE_SLEEP = False self.useFixture( fixtures.MonkeyPatch( 'heat.common.exception._FATAL_EXCEPTION_FORMAT_ERRORS', True)) def enable_sleep(): scheduler.ENABLE_SLEEP = True self.addCleanup(enable_sleep) mod_dir = os.path.dirname(sys.modules[__name__].__file__) project_dir = os.path.abspath(os.path.join(mod_dir, '../../')) env_dir = os.path.join(project_dir, 'etc', 'heat', 'environment.d') cfg.CONF.set_default('environment_dir', env_dir) self.addCleanup(cfg.CONF.reset) messaging.setup("fake://", optional=True) self.addCleanup(messaging.cleanup) tri = resources.global_env().get_resource_info( 'AWS::RDS::DBInstance', registry_type=environment.TemplateResourceInfo) if tri is not None: cur_path = tri.template_name templ_path = os.path.join(project_dir, 'etc', 'heat', 'templates') if templ_path not in cur_path: tri.template_name = cur_path.replace('/etc/heat/templates', templ_path) utils.setup_dummy_db() self.addCleanup(utils.reset_dummy_db) cached_wait_time = stack.ERROR_WAIT_TIME stack.ERROR_WAIT_TIME = None def replace_wait_time(): stack.ERROR_WAIT_TIME = cached_wait_time self.addCleanup(replace_wait_time)
def test_system_template_retrieve_by_file(self): # make sure that a TemplateResource defined in the global environment # can be created and the template retrieved using the "file:" # scheme. g_env = resources.global_env() test_templ_name = "file:///etc/heatr/frodo.yaml" g_env.load({"resource_registry": {"Test::Frodo": test_templ_name}}) stack = parser.Stack( utils.dummy_context(), "test_stack", parser.Template({}), stack_id=uuidutils.generate_uuid() ) minimal_temp = json.dumps({"Parameters": {}, "Resources": {}}) self.m.StubOutWithMock(urlfetch, "get") urlfetch.get(test_templ_name, allowed_schemes=("http", "https", "file")).AndReturn(minimal_temp) self.m.ReplayAll() temp_res = template_resource.TemplateResource("test_t_res", {"Type": "Test::Frodo"}, stack) self.assertEqual(None, temp_res.validate()) self.m.VerifyAll()
def __init__(self, env=None, user_env=True): """Create an Environment from an input dict. The dict may be in one of two formats: 1) old-school flat parameters; or 2) newer {resource_registry: bla, parameters: foo} :param env: the json environment :param user_env: boolean, if False then we manage python resources too. """ if env is None: env = {} if user_env: from heat.engine import resources global_env = resources.global_env() global_registry = global_env.registry event_sink_classes = global_env.event_sink_classes else: global_registry = None event_sink_classes = {} self.param_defaults = env.get(env_fmt.PARAMETER_DEFAULTS, {}) self.registry = ResourceRegistry(global_registry, self.param_defaults) self.registry.load(env.get(env_fmt.RESOURCE_REGISTRY, {})) self.encrypted_param_names = env.get(env_fmt.ENCRYPTED_PARAM_NAMES, []) if env_fmt.PARAMETERS in env: self.params = env[env_fmt.PARAMETERS] else: self.params = dict( (k, v) for (k, v) in env.items() if k not in (env_fmt.PARAMETER_DEFAULTS, env_fmt.ENCRYPTED_PARAM_NAMES, env_fmt.EVENT_SINKS, env_fmt.RESOURCE_REGISTRY)) self.event_sink_classes = event_sink_classes self._event_sinks = [] self._built_event_sinks = [] self._update_event_sinks(env.get(env_fmt.EVENT_SINKS, [])) self.constraints = {} self.stack_lifecycle_plugins = []
def test_template_as_resource(self): """ Test that the resulting resource has the right prop and attrib schema. Note that this test requires the Wordpress_Single_Instance.yaml template in the templates directory since we want to test using a non-trivial template. """ test_templ_name = "WordPress_Single_Instance.yaml" path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates", test_templ_name) # check if its in the directory list vs. exists to work around # case-insensitive file systems self.assertIn(test_templ_name, os.listdir(os.path.dirname(path))) with open(path) as test_templ_file: test_templ = test_templ_file.read() self.assertTrue(test_templ, "Empty test template") self.m.StubOutWithMock(urlfetch, "get") urlfetch.get(test_templ_name, allowed_schemes=("http", "https")).AndReturn(test_templ) parsed_test_templ = template_format.parse(test_templ) self.m.ReplayAll() json_snippet = { "Type": test_templ_name, "Properties": { "KeyName": "mykeyname", "DBName": "wordpress1", "DBUsername": "******", "DBPassword": "******", "DBRootPassword": "******", "LinuxDistribution": "U10", }, } stack = parser.Stack(None, "test_stack", parser.Template({}), stack_id=uuidutils.generate_uuid()) templ_resource = resource.Resource("test_templ_resource", json_snippet, stack) self.m.VerifyAll() self.assertIsInstance(templ_resource, template_resource.TemplateResource) for prop in parsed_test_templ.get("Parameters", {}): self.assertIn(prop, templ_resource.properties) for attrib in parsed_test_templ.get("Outputs", {}): self.assertIn(attrib, templ_resource.attributes) for k, v in json_snippet.get("Properties").items(): self.assertEqual(v, templ_resource.properties[k]) self.assertNotIn("WordPress_Single_Instance.yaml", resources.global_env().registry._registry)
def test_continue_on_parse_error(self): """assert we get all files processed even if there are processing exceptions. """ list_dir = 'heat.engine.resources._list_environment_files' with mock.patch(list_dir) as m_ldir: m_ldir.return_value = ['a.yaml', 'b.yaml'] env_dir = '/etc_etc/heat/enviroment.d' env_content = '{@$%#$%' with mock.patch('heat.engine.resources.open', mock.mock_open(read_data=env_content), create=True) as m_open: resources._load_global_environment(resources.global_env(), env_dir) m_ldir.assert_called_once_with(env_dir) expected = [mock.call('%s/a.yaml' % env_dir), mock.call('%s/b.yaml' % env_dir)] self.assertEqual(expected, m_open.call_args_list)
def test_system_template_retrieve_by_file(self): # make sure that a TemplateResource defined in the global environment # can be created and the template retrieved using the "file:" # scheme. g_env = resources.global_env() test_templ_name = "file:///etc/heatr/frodo.yaml" g_env.load({"resource_registry": {"Test::Frodo": test_templ_name}}) stack = parser.Stack( utils.dummy_context(), "test_stack", template.Template(empty_template), stack_id=str(uuid.uuid4()) ) minimal_temp = json.dumps({"HeatTemplateFormatVersion": "2012-12-12", "Parameters": {}, "Resources": {}}) self.m.StubOutWithMock(urlfetch, "get") urlfetch.get(test_templ_name, allowed_schemes=("http", "https", "file")).AndReturn(minimal_temp) self.m.ReplayAll() definition = rsrc_defn.ResourceDefinition("test_t_res", "Test::Frodo") temp_res = template_resource.TemplateResource("test_t_res", definition, stack) self.assertIsNone(temp_res.validate()) self.m.VerifyAll()
def test_continue_on_ioerror(self): """assert we get all files processed even if there are processing exceptions. """ list_dir = 'heat.engine.resources._list_environment_files' with mock.patch(list_dir) as m_ldir: m_ldir.return_value = ['a.yaml', 'b.yaml'] env_dir = '/etc_etc/heat/enviroment.d' env_content = '{}' with mock.patch('heat.engine.resources.open', mock.mock_open(read_data=env_content), create=True) as m_open: m_open.side_effect = IOError resources._load_global_environment(resources.global_env(), env_dir) m_ldir.assert_called_once_with(env_dir) expected = [mock.call('%s/a.yaml' % env_dir), mock.call('%s/b.yaml' % env_dir)] self.assertEqual(expected, m_open.call_args_list)
def test_system_template_retrieve_fail(self): # make sure that a TemplateResource defined in the global environment # fails gracefully if the template file specified is inaccessible # we should be able to create the TemplateResource object, but # validation should fail, when the second attempt to access it is # made in validate() g_env = resources.global_env() test_templ_name = "file:///etc/heatr/frodo.yaml" g_env.load({"resource_registry": {"Test::Frodo": test_templ_name}}) stack = parser.Stack( utils.dummy_context(), "test_stack", parser.Template({}), stack_id=uuidutils.generate_uuid() ) self.m.StubOutWithMock(urlfetch, "get") urlfetch.get(test_templ_name, allowed_schemes=("http", "https", "file")).AndRaise(IOError) urlfetch.get(test_templ_name, allowed_schemes=("http", "https", "file")).AndRaise(IOError) self.m.ReplayAll() temp_res = template_resource.TemplateResource("test_t_res", {"Type": "Test::Frodo"}, stack) self.assertRaises(exception.StackValidationFailed, temp_res.validate) self.m.VerifyAll()
def test_custom_constraint(self): class ZeroConstraint(object): def validate(self, value, context): return value == "0" env = resources.global_env() env.register_constraint("zero", ZeroConstraint) self.addCleanup(env.constraints.pop, "zero") desc = 'Value must be zero' param = { 'param1': { 'type': 'string', 'constraints': [{ 'custom_constraint': 'zero', 'description': desc }] } } name = 'param1' schema = param['param1'] def v(value): hot.HOTParamSchema.from_dict(schema).validate(name, value) return True value = "1" err = self.assertRaises(ValueError, v, value) self.assertEqual(desc, str(err)) value = "2" err = self.assertRaises(ValueError, v, value) self.assertEqual(desc, str(err)) value = "0" self.assertTrue(v(value))
def __init__(self, env=None, user_env=True): """Create an Environment from a dict of varing format. 1) old-school flat parameters 2) or newer {resource_registry: bla, parameters: foo} :param env: the json environment :param user_env: boolean, if false then we manage python resources too. """ if env is None: env = {} if user_env: from heat.engine import resources global_registry = resources.global_env().registry else: global_registry = None self.registry = ResourceRegistry(global_registry) self.registry.load(env.get(RESOURCE_REGISTRY, {})) if 'parameters' in env: self.params = env['parameters'] else: self.params = dict( (k, v) for (k, v) in env.iteritems() if k != RESOURCE_REGISTRY)
def __init__(self, env=None, user_env=True): """Create an Environment from a dict of varying format. Next formats are available: 1) old-school flat parameters 2) or newer {resource_registry: bla, parameters: foo} :param env: the json environment :param user_env: boolean, if false then we manage python resources too. """ if env is None: env = {} if user_env: from heat.engine import resources global_registry = resources.global_env().registry else: global_registry = None self.registry = ResourceRegistry(global_registry, self) self.registry.load(env.get(env_fmt.RESOURCE_REGISTRY, {})) if env_fmt.PARAMETER_DEFAULTS in env: self.param_defaults = env[env_fmt.PARAMETER_DEFAULTS] else: self.param_defaults = {} self.encrypted_param_names = env.get(env_fmt.ENCRYPTED_PARAM_NAMES, []) if env_fmt.PARAMETERS in env: self.params = env[env_fmt.PARAMETERS] else: self.params = dict((k, v) for (k, v) in six.iteritems(env) if k not in (env_fmt.PARAMETER_DEFAULTS, env_fmt.RESOURCE_REGISTRY)) self.constraints = {} self.stack_lifecycle_plugins = []
def test_system_template_retrieve_by_file(self): # make sure that a TemplateResource defined in the global environment # can be created and the template retrieved using the "file:" # scheme. g_env = resources.global_env() test_templ_name = 'file:///etc/heatr/frodo.yaml' g_env.load({'resource_registry': {'Test::Frodo': test_templ_name}}) stack = parser.Stack(utils.dummy_context(), 'test_stack', parser.Template({}), stack_id=uuidutils.generate_uuid()) minimal_temp = json.dumps({'Parameters': {}, 'Resources': {}}) self.m.StubOutWithMock(urlfetch, "get") urlfetch.get(test_templ_name, allowed_schemes=('http', 'https', 'file')).AndReturn(minimal_temp) self.m.ReplayAll() temp_res = template_resource.TemplateResource('test_t_res', {"Type": 'Test::Frodo'}, stack) self.assertEqual(None, temp_res.validate()) self.m.VerifyAll()
def _load_all_resources(): env = resources.global_env() for package, modules in resources._global_modules(): maps = (resources._get_all_module_resources(m) for m in modules) resources._register_resources(env, itertools.chain.from_iterable(maps))
def test_all_resource_schemata(self): for resource_type in resources.global_env().get_types(): for schema in six.itervalues( getattr(resource_type, 'attributes_schema', {})): attributes.Schema.from_attribute(schema)
def test_template_as_resource(self): """ Test that the resulting resource has the right prop and attrib schema. Note that this test requires the Wordpress_Single_Instance.yaml template in the templates directory since we want to test using a non-trivial template. """ test_templ_name = "WordPress_Single_Instance.yaml" path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates', test_templ_name) # check if its in the directory list vs. exists to work around # case-insensitive file systems self.assertIn(test_templ_name, os.listdir(os.path.dirname(path))) with open(path) as test_templ_file: test_templ = test_templ_file.read() self.assertTrue(test_templ, "Empty test template") self.m.StubOutWithMock(urlfetch, "get") urlfetch.get(test_templ_name, allowed_schemes=('file',))\ .AndRaise(urlfetch.URLFetchError(_('Failed to retrieve template'))) urlfetch.get(test_templ_name, allowed_schemes=('http', 'https')).AndReturn(test_templ) parsed_test_templ = template_format.parse(test_templ) self.m.ReplayAll() stack = parser.Stack(utils.dummy_context(), 'test_stack', parser.Template(empty_template), stack_id=str(uuid.uuid4())) properties = { "KeyName": "mykeyname", "DBName": "wordpress1", "DBUsername": "******", "DBPassword": "******", "DBRootPassword": "******", "LinuxDistribution": "U10" } definition = rsrc_defn.ResourceDefinition("test_templ_resource", test_templ_name, properties) templ_resource = resource.Resource("test_templ_resource", definition, stack) self.m.VerifyAll() self.assertIsInstance(templ_resource, template_resource.TemplateResource) for prop in parsed_test_templ.get("Parameters", {}): self.assertIn(prop, templ_resource.properties) for attrib in parsed_test_templ.get("Outputs", {}): self.assertIn(attrib, templ_resource.attributes) for k, v in properties.items(): self.assertEqual(v, templ_resource.properties[k]) self.assertEqual( { 'WordPress_Single_Instance.yaml': 'WordPress_Single_Instance.yaml', 'resources': {} }, stack.env.user_env_as_dict()["resource_registry"]) self.assertNotIn('WordPress_Single_Instance.yaml', resources.global_env().registry._registry)
def _register_class(resource_type, resource_class): resources.global_env().register_class(resource_type, resource_class)
def get_class(resource_type, resource_name=None): '''Return the Resource class for a given resource type.''' return resources.global_env().get_class(resource_type, resource_name)
def get_types(support_status): '''Return a list of valid resource types.''' return resources.global_env().get_types(support_status)
def test_list_type_with_version_none(self): registry = resources.global_env().registry types = registry.get_types(version=None) self.assertIn('ResourceTypeUnSupportedLiberty', types) self.assertIn('ResourceTypeSupportedKilo', types)
def test_list_type_find_by_status_none(self): registry = resources.global_env().registry types = registry.get_types(support_status=None) self.assertIn('ResourceTypeUnSupportedLiberty', types) self.assertIn('GenericResourceType', types)
def get_types(): '''Return an iterator over the list of valid resource types.''' return iter(resources.global_env().get_types())
def test_list_type_with_name_none(self): registry = resources.global_env().registry types = registry.get_types(type_name=None) self.assertIn('ResourceTypeUnSupportedLiberty', types) self.assertIn('GenericResourceType', types)
def test_all_resource_schemata(self): for resource_type in resources.global_env().get_types(): for schema in getattr(resource_type, 'attributes_schema', {}).itervalues(): attributes.Schema.from_attribute(schema)
def test_list_type_with_invalid_type_name(self): registry = resources.global_env().registry types = registry.get_types(type_name="r'[^\+]'") self.assertEqual([], types)
def test_list_type_with_version_invalid(self): registry = resources.global_env().registry types = registry.get_types(version='invalid') self.assertEqual([], types)
def mock_lcp_class_map(self, lcp_mappings): self.mock_get_plugins = self.patchobject(resources.global_env(), 'get_stack_lifecycle_plugins', return_value=lcp_mappings) # reset cache lifecycle_plugin_utils.pp_class_instances = None
def clear_register_class(): env = resources.global_env() env.registry._registry.pop('CWLiteAlarmForTest')
def setUp(self): super(EnvironmentTest, self).setUp() self.g_env = resources.global_env()