def test_stack_update_with_environment_files(self): # Setup stack_name = 'service_update_env_files_stack' params = {} template = '{ "Template": "data" }' old_stack = tools.get_stack(stack_name, self.ctx) sid = old_stack.store() old_stack.set_stack_user_project_id('1234') stack_object.Stack.get_by_id(self.ctx, sid) stk = tools.get_stack(stack_name, self.ctx) # prepare mocks self.patchobject(stack, 'Stack', return_value=stk) self.patchobject(stack.Stack, 'load', return_value=old_stack) self.patchobject(templatem, 'Template', return_value=stk.t) self.patchobject(environment, 'Environment', return_value=stk.env) self.patchobject(stk, 'validate', return_value=None) self.patchobject(eventlet.queue, 'LightQueue', return_value=mock.Mock()) mock_merge = self.patchobject(self.man, '_merge_environments') # Test environment_files = ['env_1'] self.man.update_stack(self.ctx, old_stack.identifier(), template, params, None, {}, environment_files=environment_files) # Verify mock_merge.assert_called_once_with(environment_files, None, params)
def test_stack_update_with_environment_files(self): # Setup stack_name = "service_update_env_files_stack" params = {} template = '{ "Template": "data" }' old_stack = tools.get_stack(stack_name, self.ctx) sid = old_stack.store() old_stack.set_stack_user_project_id("1234") stack_object.Stack.get_by_id(self.ctx, sid) stk = tools.get_stack(stack_name, self.ctx) # prepare mocks self.patchobject(stack, "Stack", return_value=stk) self.patchobject(stack.Stack, "load", return_value=old_stack) self.patchobject(templatem, "Template", return_value=stk.t) self.patchobject(environment, "Environment", return_value=stk.env) self.patchobject(stk, "validate", return_value=None) self.patchobject(grevent, "Event", return_value=mock.Mock()) mock_merge = self.patchobject(self.man, "_merge_environments") # Test environment_files = ["env_1"] self.man.update_stack( self.ctx, old_stack.identifier(), template, params, None, {}, environment_files=environment_files ) # Verify mock_merge.assert_called_once_with(environment_files, None, params)
def test_stack_create_nested(self, mock_validate, mock_tg): convergence_engine = cfg.CONF.convergence_engine stack_name = 'service_create_nested_test_stack' parent_stack = tools.get_stack(stack_name + '_parent', self.ctx) owner_id = parent_stack.store() mock_tg.return_value = tools.DummyThreadGroup() stk = tools.get_stack(stack_name, self.ctx, with_params=True, owner_id=owner_id, nested_depth=1) tmpl_id = stk.t.store(self.ctx) mock_load = self.patchobject(templatem.Template, 'load', return_value=stk.t) mock_stack = self.patchobject(stack, 'Stack', return_value=stk) result = self.man.create_stack(self.ctx, stack_name, None, None, None, {}, owner_id=owner_id, nested_depth=1, template_id=tmpl_id) self.assertEqual(stk.identifier(), result) self.assertIsInstance(result, dict) self.assertTrue(result['stack_id']) mock_load.assert_called_once_with(self.ctx, tmpl_id) mock_stack.assert_called_once_with(self.ctx, stack_name, stk.t, owner_id=owner_id, nested_depth=1, user_creds_id=None, stack_user_project_id=None, convergence=convergence_engine, parent_resource=None) mock_validate.assert_called_once_with()
def test_stack_update_verify_err(self): stack_name = "service_update_verify_err_test_stack" params = {"foo": "bar"} template = '{ "Template": "data" }' old_stack = tools.get_stack(stack_name, self.ctx) old_stack.store() sid = old_stack.store() old_stack.set_stack_user_project_id("1234") s = stack_object.Stack.get_by_id(self.ctx, sid) stk = tools.get_stack(stack_name, self.ctx) # prepare mocks mock_stack = self.patchobject(stack, "Stack", return_value=stk) mock_load = self.patchobject(stack.Stack, "load", return_value=old_stack) mock_tmpl = self.patchobject(templatem, "Template", return_value=stk.t) mock_env = self.patchobject(environment, "Environment", return_value=stk.env) ex_expected = exception.StackValidationFailed(message="fubar") mock_validate = self.patchobject(stk, "validate", side_effect=ex_expected) # do update api_args = {"timeout_mins": 60} ex = self.assertRaises( dispatcher.ExpectedException, self.man.update_stack, self.ctx, old_stack.identifier(), template, params, None, api_args, ) # assertions self.assertEqual(exception.StackValidationFailed, ex.exc_info[0]) mock_tmpl.assert_called_once_with(template, files=None, env=stk.env) mock_env.assert_called_once_with(params) mock_stack.assert_called_once_with( self.ctx, stk.name, stk.t, convergence=False, current_traversal=old_stack.current_traversal, prev_raw_template_id=None, current_deps=None, disable_rollback=True, nested_depth=0, owner_id=None, parent_resource=None, stack_user_project_id="1234", strict_validate=True, tenant_id="test_tenant_id", timeout_mins=60, user_creds_id=u"1", username="******", ) mock_load.assert_called_once_with(self.ctx, stack=s) mock_validate.assert_called_once_with()
def test_stack_update_nested(self): stack_name = 'service_update_nested_test_stack' parent_stack = tools.get_stack(stack_name + '_parent', self.ctx) owner_id = parent_stack.store() old_stack = tools.get_stack(stack_name, self.ctx, owner_id=owner_id, nested_depth=1, user_creds_id=parent_stack.user_creds_id) sid = old_stack.store() old_stack.set_stack_user_project_id('1234') s = stack_object.Stack.get_by_id(self.ctx, sid) stk = tools.get_stack(stack_name, self.ctx) tmpl_id = stk.t.store(self.ctx) # prepare mocks mock_stack = self.patchobject(stack, 'Stack', return_value=stk) mock_load = self.patchobject(stack.Stack, 'load', return_value=old_stack) mock_tmpl = self.patchobject(templatem.Template, 'load', return_value=stk.t) mock_validate = self.patchobject(stk, 'validate', return_value=None) msgq_mock = mock.Mock() self.patchobject(eventlet.queue, 'LightQueue', return_value=msgq_mock) # do update api_args = {'timeout_mins': 60} result = self.man.update_stack(self.ctx, old_stack.identifier(), None, None, None, api_args, template_id=tmpl_id) # assertions self.assertEqual(old_stack.identifier(), result) self.assertIsInstance(result, dict) self.assertTrue(result['stack_id']) self.assertEqual([msgq_mock], self.man.thread_group_mgr.msg_queues) mock_tmpl.assert_called_once_with(self.ctx, tmpl_id) mock_stack.assert_called_once_with( self.ctx, stk.name, stk.t, convergence=False, current_traversal=old_stack.current_traversal, prev_raw_template_id=None, current_deps=None, disable_rollback=True, nested_depth=1, owner_id=owner_id, parent_resource=None, stack_user_project_id='1234', strict_validate=True, tenant_id='test_tenant_id', timeout_mins=60, user_creds_id=u'1', username='******') mock_load.assert_called_once_with(self.ctx, stack=s) mock_validate.assert_called_once_with(validate_resources=False)
def _test_stack_update_preview(self, orig_template, new_template, environment_files=None): stack_name = 'service_update_test_stack_preview' params = {'foo': 'bar'} old_stack = tools.get_stack(stack_name, self.ctx, template=orig_template) sid = old_stack.store() old_stack.set_stack_user_project_id('1234') s = stack_object.Stack.get_by_id(self.ctx, sid) stk = tools.get_stack(stack_name, self.ctx, template=new_template) # prepare mocks mock_stack = self.patchobject(stack, 'Stack', return_value=stk) mock_load = self.patchobject(stack.Stack, 'load', return_value=old_stack) mock_tmpl = self.patchobject(templatem, 'Template', return_value=stk.t) mock_env = self.patchobject(environment, 'Environment', return_value=stk.env) mock_validate = self.patchobject(stk, 'validate', return_value=None) mock_merge = self.patchobject(self.man, '_merge_environments') # Patch _resolve_all_attributes or it tries to call novaclient self.patchobject(resource.Resource, '_resolve_all_attributes', return_value=None) # do preview_update_stack api_args = {'timeout_mins': 60} result = self.man.preview_update_stack( self.ctx, old_stack.identifier(), new_template, params, None, api_args, environment_files=environment_files) # assertions mock_stack.assert_called_once_with( self.ctx, stk.name, stk.t, convergence=False, current_traversal=old_stack.current_traversal, prev_raw_template_id=None, current_deps=None, disable_rollback=True, nested_depth=0, owner_id=None, parent_resource=None, stack_user_project_id='1234', strict_validate=True, tenant_id='test_tenant_id', timeout_mins=60, user_creds_id=u'1', username='******') mock_load.assert_called_once_with(self.ctx, stack=s) mock_tmpl.assert_called_once_with(new_template, files=None, env=stk.env) mock_env.assert_called_once_with(params) mock_validate.assert_called_once_with() if environment_files: mock_merge.assert_called_once_with(environment_files, None, params) return result
def test_stack_update(self): stack_name = 'service_update_test_stack' params = {'foo': 'bar'} template = '{ "Template": "data" }' old_stack = tools.get_stack(stack_name, self.ctx) sid = old_stack.store() old_stack.set_stack_user_project_id('1234') s = stack_object.Stack.get_by_id(self.ctx, sid) stk = tools.get_stack(stack_name, self.ctx) # prepare mocks mock_stack = self.patchobject(stack, 'Stack', return_value=stk) mock_load = self.patchobject(stack.Stack, 'load', return_value=old_stack) mock_tmpl = self.patchobject(templatem, 'Template', return_value=stk.t) mock_env = self.patchobject(environment, 'Environment', return_value=stk.env) mock_validate = self.patchobject(stk, 'validate', return_value=None) event_mock = mock.Mock() self.patchobject(grevent, 'Event', return_value=event_mock) # do update api_args = {'timeout_mins': 60} result = self.man.update_stack(self.ctx, old_stack.identifier(), template, params, None, api_args) # assertions self.assertEqual(old_stack.identifier(), result) self.assertIsInstance(result, dict) self.assertTrue(result['stack_id']) self.assertEqual([event_mock], self.man.thread_group_mgr.events) mock_tmpl.assert_called_once_with(template, files=None, env=stk.env) mock_env.assert_called_once_with(params) mock_stack.assert_called_once_with( self.ctx, stk.name, stk.t, convergence=False, current_traversal=old_stack.current_traversal, prev_raw_template_id=None, current_deps=None, disable_rollback=True, nested_depth=0, owner_id=None, parent_resource=None, stack_user_project_id='1234', strict_validate=True, tenant_id='test_tenant_id', timeout_mins=60, user_creds_id=u'1', username='******') mock_load.assert_called_once_with(self.ctx, stack=s) mock_validate.assert_called_once_with()
def test_stack_update_nested(self): stack_name = "service_update_nested_test_stack" old_stack = tools.get_stack(stack_name, self.ctx) sid = old_stack.store() old_stack.set_stack_user_project_id("1234") s = stack_object.Stack.get_by_id(self.ctx, sid) stk = tools.get_stack(stack_name, self.ctx) tmpl_id = stk.t.store() # prepare mocks mock_stack = self.patchobject(stack, "Stack", return_value=stk) mock_load = self.patchobject(stack.Stack, "load", return_value=old_stack) mock_tmpl = self.patchobject(templatem.Template, "load", return_value=stk.t) mock_validate = self.patchobject(stk, "validate", return_value=None) event_mock = mock.Mock() self.patchobject(grevent, "Event", return_value=event_mock) # do update api_args = {"timeout_mins": 60} result = self.man.update_stack( self.ctx, old_stack.identifier(), None, None, None, api_args, template_id=tmpl_id ) # assertions self.assertEqual(old_stack.identifier(), result) self.assertIsInstance(result, dict) self.assertTrue(result["stack_id"]) self.assertEqual([event_mock], self.man.thread_group_mgr.events) mock_tmpl.assert_called_once_with(self.ctx, tmpl_id) mock_stack.assert_called_once_with( self.ctx, stk.name, stk.t, convergence=False, current_traversal=old_stack.current_traversal, prev_raw_template_id=None, current_deps=None, disable_rollback=True, nested_depth=0, owner_id=None, parent_resource=None, stack_user_project_id="1234", strict_validate=True, tenant_id="test_tenant_id", timeout_mins=60, user_creds_id=u"1", username="******", ) mock_load.assert_called_once_with(self.ctx, stack=s) mock_validate.assert_called_once_with()
def test_stack_update_reuses_api_params(self): stack_name = "service_update_stack_reuses_api_params" params = {"foo": "bar"} template = '{ "Template": "data" }' old_stack = tools.get_stack(stack_name, self.ctx) old_stack.timeout_mins = 1 old_stack.disable_rollback = False sid = old_stack.store() old_stack.set_stack_user_project_id("1234") s = stack_object.Stack.get_by_id(self.ctx, sid) stk = tools.get_stack(stack_name, self.ctx) # prepare mocks mock_stack = self.patchobject(stack, "Stack", return_value=stk) mock_load = self.patchobject(stack.Stack, "load", return_value=old_stack) mock_tmpl = self.patchobject(templatem, "Template", return_value=stk.t) mock_env = self.patchobject(environment, "Environment", return_value=stk.env) mock_validate = self.patchobject(stk, "validate", return_value=None) # do update result = self.man.update_stack(self.ctx, old_stack.identifier(), template, params, None, {}) # assertions self.assertEqual(old_stack.identifier(), result) self.assertIsInstance(result, dict) self.assertTrue(result["stack_id"]) mock_validate.assert_called_once_with() mock_tmpl.assert_called_once_with(template, files=None, env=stk.env) mock_env.assert_called_once_with(params) mock_load.assert_called_once_with(self.ctx, stack=s) mock_stack.assert_called_once_with( self.ctx, stk.name, stk.t, convergence=False, current_traversal=old_stack.current_traversal, prev_raw_template_id=None, current_deps=None, disable_rollback=False, nested_depth=0, owner_id=None, parent_resource=None, stack_user_project_id="1234", strict_validate=True, tenant_id="test_tenant_id", timeout_mins=1, user_creds_id=u"1", username="******", )
def test_signal_no_calls_metadata_update(self, mock_get, mock_signal, mock_update): # fake keystone client self.patchobject(keystone.KeystoneClientPlugin, '_create', return_value=test_fakes.FakeKeystoneClient()) stk = tools.get_stack('signal_reception', self.ctx, policy_template) self.stack = stk stk.store() stk.create() s = stack_object.Stack.get_by_id(self.ctx, self.stack.id) mock_get.return_value = s mock_signal.return_value = None res.Resource.signal_needs_metadata_updates = False self.eng.resource_signal(self.ctx, dict(self.stack.identifier()), 'WebServerScaleDownPolicy', None, sync_call=True) mock_get.assert_called_once_with(self.ctx, self.stack.identifier()) mock_signal.assert_called_once_with(mock.ANY, False) # this will never be called self.assertEqual(0, mock_update.call_count) res.Resource.signal_needs_metadata_updates = True
def test_stack_delete_current_engine_active_lock(self, mock_expired, mock_acquire, mock_try, mock_load): cfg.CONF.set_override("error_wait_time", 0) self.man.start() stack_name = "service_delete_test_stack_current_active_lock" stack = tools.get_stack(stack_name, self.ctx) sid = stack.store() # Insert a fake lock into the db stack_lock_object.StackLock.create(self.ctx, stack.id, self.man.engine_id) st = stack_object.Stack.get_by_id(self.ctx, sid) mock_load.return_value = stack mock_try.return_value = self.man.engine_id mock_stop = self.patchobject(self.man.thread_group_mgr, "stop") mock_send = self.patchobject(self.man.thread_group_mgr, "send") mock_expired.side_effect = [False, True] self.assertIsNone(self.man.delete_stack(self.ctx, stack.identifier())) self.man.thread_group_mgr.groups[sid].wait() mock_load.assert_called_with(self.ctx, stack=st) mock_send.assert_called_once_with(stack.id, "cancel") mock_stop.assert_called_once_with(stack.id) self.assertEqual(2, len(mock_load.mock_calls)) mock_try.assert_called_with() mock_acquire.assert_called_once_with(True)
def test_stack_delete_other_dead_engine_active_lock( self, mock_expired, mock_acquire, mock_alive, mock_try, mock_load ): cfg.CONF.set_override("error_wait_time", 0) OTHER_ENGINE = "other-engine-fake-uuid" stack_name = "service_delete_test_stack_other_dead_engine" stack = tools.get_stack(stack_name, self.ctx) sid = stack.store() # Insert a fake lock into the db stack_lock_object.StackLock.create(self.ctx, stack.id, "other-engine-fake-uuid") st = stack_object.Stack.get_by_id(self.ctx, sid) mock_load.return_value = stack mock_try.return_value = OTHER_ENGINE mock_alive.return_value = False mock_expired.side_effect = [False, True] self.assertIsNone(self.man.delete_stack(self.ctx, stack.identifier())) self.man.thread_group_mgr.groups[sid].wait() mock_load.assert_called_with(self.ctx, stack=st) mock_try.assert_called_with() mock_acquire.assert_called_once_with(True) mock_alive.assert_called_with(self.ctx, OTHER_ENGINE)
def test_stack_delete_other_engine_active_lock_succeeded( self, mock_expired, mock_acquire, mock_alive, mock_try, mock_load ): cfg.CONF.set_override("error_wait_time", 0) OTHER_ENGINE = "other-engine-fake-uuid" self.man.start() stack_name = "service_delete_test_stack_other_engine_lock" stack = tools.get_stack(stack_name, self.ctx) sid = stack.store() # Insert a fake lock into the db stack_lock_object.StackLock.create(self.ctx, stack.id, OTHER_ENGINE) st = stack_object.Stack.get_by_id(self.ctx, sid) mock_load.return_value = stack mock_try.return_value = OTHER_ENGINE mock_alive.return_value = True mock_expired.side_effect = [False, True] mock_call = self.patchobject(self.man, "_remote_call", return_value=None) self.assertIsNone(self.man.delete_stack(self.ctx, stack.identifier())) self.man.thread_group_mgr.groups[sid].wait() self.assertEqual(2, len(mock_load.mock_calls)) mock_load.assert_called_with(self.ctx, stack=st) mock_try.assert_called_with() mock_alive.assert_called_with(self.ctx, OTHER_ENGINE) mock_call.assert_has_calls( [ mock.call(self.ctx, OTHER_ENGINE, mock.ANY, "send", message="cancel", stack_identity=mock.ANY), mock.call(self.ctx, OTHER_ENGINE, mock.ANY, "stop_stack", stack_identity=mock.ANY), ] ) mock_acquire.assert_called_once_with(True)
def test_stack_update_existing_parameters(self): # Use a template with existing parameters, then update the stack # with a template containing additional parameters and ensure all # are preserved. stack_name = "service_update_test_stack_existing_parameters" update_params = { "encrypted_param_names": [], "parameter_defaults": {}, "event_sinks": [], "parameters": {"newparam": 123}, "resource_registry": {"resources": {}}, } api_args = {rpc_api.PARAM_TIMEOUT: 60, rpc_api.PARAM_EXISTING: True} t = template_format.parse(tools.wp_template) stk = tools.get_stack(stack_name, self.ctx, with_params=True) stk.store() stk.set_stack_user_project_id("1234") self.assertEqual({"KeyName": "test"}, stk.t.env.params) t["parameters"]["newparam"] = {"type": "number"} with mock.patch("heat.engine.stack.Stack") as mock_stack: stk.update = mock.Mock() mock_stack.load.return_value = stk mock_stack.validate.return_value = None result = self.man.update_stack(self.ctx, stk.identifier(), t, update_params, None, api_args) tmpl = mock_stack.call_args[0][2] self.assertEqual({"KeyName": "test", "newparam": 123}, tmpl.env.params) self.assertEqual(stk.identifier(), result)
def test_stack_create_verify_err(self, mock_validate): mock_validate.side_effect = exception.StackValidationFailed(message='') stack_name = 'service_create_verify_err_test_stack' params = {'foo': 'bar'} template = '{ "Template": "data" }' stk = tools.get_stack(stack_name, self.ctx) mock_tmpl = self.patchobject(templatem, 'Template', return_value=stk.t) mock_env = self.patchobject(environment, 'Environment', return_value=stk.env) mock_stack = self.patchobject(stack, 'Stack', return_value=stk) ex = self.assertRaises(dispatcher.ExpectedException, self.man.create_stack, self.ctx, stack_name, template, params, None, {}) self.assertEqual(exception.StackValidationFailed, ex.exc_info[0]) mock_tmpl.assert_called_once_with(template, files=None, env=stk.env) mock_env.assert_called_once_with(params) mock_stack.assert_called_once_with(self.ctx, stack_name, stk.t, owner_id=None, nested_depth=0, user_creds_id=None, stack_user_project_id=None, convergence=False, parent_resource=None)
def test_update_immutable_parameter_disallowed(self): template = ''' heat_template_version: 2014-10-16 parameters: param1: type: string immutable: true default: foo ''' self.ctx = utils.dummy_context(password=None) stack_name = 'test_update_immutable_parameters' old_stack = tools.get_stack(stack_name, self.ctx, template=template) sid = old_stack.store() old_stack.set_stack_user_project_id('1234') s = stack_object.Stack.get_by_id(self.ctx, sid) # prepare mocks self.patchobject(self.man, '_get_stack', return_value=s) self.patchobject(stack, 'Stack', return_value=old_stack) self.patchobject(stack.Stack, 'load', return_value=old_stack) params = {'param1': 'bar'} exc = self.assertRaises(dispatcher.ExpectedException, self.man.update_stack, self.ctx, old_stack.identifier(), old_stack.t.t, params, None, {}) self.assertEqual(exception.ImmutableParameterModified, exc.exc_info[0]) self.assertEqual('The following parameters are immutable and may not ' 'be updated: param1', exc.exc_info[1].message)
def test_stack_update_existing_parameters(self): # Use a template with existing parameters, then update the stack # with a template containing additional parameters and ensure all # are preserved. stack_name = 'service_update_test_stack_existing_parameters' update_params = {'encrypted_param_names': [], 'parameter_defaults': {}, 'event_sinks': [], 'parameters': {'newparam': 123}, 'resource_registry': {'resources': {}}} api_args = {rpc_api.PARAM_TIMEOUT: 60, rpc_api.PARAM_EXISTING: True} t = template_format.parse(tools.wp_template) stk = tools.get_stack(stack_name, self.ctx, with_params=True) stk.store() stk.set_stack_user_project_id('1234') self.assertEqual({'KeyName': 'test'}, stk.t.env.params) with mock.patch('heat.engine.stack.Stack') as mock_stack: stk.update = mock.Mock() mock_stack.load.return_value = stk mock_stack.validate.return_value = None result = self.man.update_stack(self.ctx, stk.identifier(), t, update_params, None, api_args) tmpl = mock_stack.call_args[0][2] self.assertEqual({'KeyName': 'test', 'newparam': 123}, tmpl.env.params) self.assertEqual(stk.identifier(), result)
def test_get_best_existing_db_resource(self, mock_cr): stack = tools.get_stack('test_stack', utils.dummy_context(), template=tools.string_template_five, convergence=True) stack.store() stack.prev_raw_template_id = 2 stack.t.id = 1 dummy_res = stack.resources['A'] a_res_2 = res.Resource('A', dummy_res.t, stack) a_res_2.current_template_id = 2 a_res_2.id = 2 a_res_3 = res.Resource('A', dummy_res.t, stack) a_res_3.current_template_id = 3 a_res_3.id = 3 a_res_1 = res.Resource('A', dummy_res.t, stack) a_res_1.current_template_id = 1 a_res_1.id = 1 existing_res = {2: a_res_2, 3: a_res_3, 1: a_res_1} stack.ext_rsrcs_db = existing_res best_res = stack._get_best_existing_rsrc_db('A') # should return resource with template id 1 which is current template self.assertEqual(a_res_1.id, best_res.id) # no resource with current template id as 1 existing_res = {2: a_res_2, 3: a_res_3} stack.ext_rsrcs_db = existing_res best_res = stack._get_best_existing_rsrc_db('A') # should return resource with template id 2 which is prev template self.assertEqual(a_res_2.id, best_res.id)
def test_update_immutable_parameter_same_value(self): template = ''' heat_template_version: 2014-10-16 parameters: param1: type: string immutable: true default: foo ''' self.ctx = utils.dummy_context(password=None) stack_name = 'test_update_immutable_parameters' params = {} old_stack = tools.get_stack(stack_name, self.ctx, template=template) sid = old_stack.store() old_stack.set_stack_user_project_id('1234') s = stack_object.Stack.get_by_id(self.ctx, sid) # prepare mocks self.patchobject(self.man, '_get_stack', return_value=s) self.patchobject(stack, 'Stack', return_value=old_stack) self.patchobject(stack.Stack, 'load', return_value=old_stack) self.patchobject(templatem, 'Template', return_value=old_stack.t) self.patchobject(environment, 'Environment', return_value=old_stack.env) params = {'param1': 'foo'} result = self.man.update_stack(self.ctx, old_stack.identifier(), templatem.Template(template), params, None, {}) self.assertEqual(s.id, result['stack_id'])
def test_purge_db_does_not_delete_previous_template_when_stack_fails(self, mock_tmpl_delete, mock_cr): stack = tools.get_stack( "test_stack", utils.dummy_context(), template=tools.string_template_five, convergence=True ) stack.status = stack.FAILED stack.purge_db() self.assertFalse(mock_tmpl_delete.called)
def test_purge_db_deletes_previous_template(self, mock_tmpl_delete, mock_cr): stack = tools.get_stack( "test_stack", utils.dummy_context(), template=tools.string_template_five, convergence=True ) stack.prev_raw_template_id = 10 stack.purge_db() self.assertTrue(mock_tmpl_delete.called)
def test_stack_validate(self): stack_name = 'stack_create_test_validate' stk = tools.get_stack(stack_name, self.ctx) fc = fakes_nova.FakeClient() self.patchobject(nova.NovaClientPlugin, '_create', return_value=fc) self.patchobject(glance.GlanceClientPlugin, 'get_image_id', return_value=744) resource = stk['WebServer'] resource.properties = properties.Properties( resource.properties_schema, { 'ImageId': 'CentOS 5.2', 'KeyName': 'test', 'InstanceType': 'm1.large' }, context=self.ctx) stk.validate() resource.properties = properties.Properties( resource.properties_schema, { 'KeyName': 'test', 'InstanceType': 'm1.large' }, context=self.ctx) self.assertRaises(exception.StackValidationFailed, stk.validate)
def _test_stack_create(self, stack_name, mock_validate, mock_tg): mock_tg.return_value = tools.DummyThreadGroup() params = {'foo': 'bar'} template = '{ "Template": "data" }' stk = tools.get_stack(stack_name, self.ctx) mock_tmpl = self.patchobject(templatem, 'Template', return_value=stk.t) mock_env = self.patchobject(environment, 'Environment', return_value=stk.env) mock_stack = self.patchobject(stack, 'Stack', return_value=stk) result = self.man.create_stack(self.ctx, stack_name, template, params, None, {}) self.assertEqual(stk.identifier(), result) self.assertIsInstance(result, dict) self.assertTrue(result['stack_id']) mock_tmpl.assert_called_once_with(template, files=None, env=stk.env) mock_env.assert_called_once_with(params) mock_stack.assert_called_once_with(self.ctx, stack_name, stk.t, owner_id=None, nested_depth=0, user_creds_id=None, stack_user_project_id=None, convergence=False, parent_resource=None) mock_validate.assert_called_once_with()
def test_stack_create_invalid_stack_name(self): stack_name = 'service_create_test_stack_invalid_name' stack = tools.get_stack('test_stack', self.ctx) self.assertRaises(dispatcher.ExpectedException, self.man.create_stack, self.ctx, stack_name, stack.t.t, {}, None, {})
def test_stack_delete_other_engine_active_lock_failed(self, mock_alive, mock_try, mock_load): OTHER_ENGINE = "other-engine-fake-uuid" self.man.start() stack_name = 'service_delete_test_stack_other_engine_lock_fail' stack = tools.get_stack(stack_name, self.ctx) sid = stack.store() # Insert a fake lock into the db stack_lock_object.StackLock.create(stack.id, OTHER_ENGINE) st = stack_object.Stack.get_by_id(self.ctx, sid) mock_load.return_value = stack mock_try.return_value = OTHER_ENGINE mock_alive.return_value = True mock_call = self.patchobject(self.man, '_remote_call', return_value=False) ex = self.assertRaises(dispatcher.ExpectedException, self.man.delete_stack, self.ctx, stack.identifier()) self.assertEqual(exception.StopActionFailed, ex.exc_info[0]) mock_load.assert_called_once_with(self.ctx, stack=st) mock_try.assert_called_once_with() mock_alive.assert_called_once_with(self.ctx, OTHER_ENGINE) mock_call.assert_called_once_with(self.ctx, OTHER_ENGINE, "stop_stack", stack_identity=mock.ANY)
def test_stack_delete_other_engine_active_lock_succeeded( self, mock_acquire, mock_alive, mock_try, mock_load): OTHER_ENGINE = "other-engine-fake-uuid" self.man.start() stack_name = 'service_delete_test_stack_other_engine_lock' stack = tools.get_stack(stack_name, self.ctx) sid = stack.store() # Insert a fake lock into the db stack_lock_object.StackLock.create(stack.id, OTHER_ENGINE) st = stack_object.Stack.get_by_id(self.ctx, sid) mock_load.return_value = stack mock_try.return_value = OTHER_ENGINE mock_alive.return_value = True mock_call = self.patchobject(self.man, '_remote_call', return_value=None) self.assertIsNone(self.man.delete_stack(self.ctx, stack.identifier())) self.man.thread_group_mgr.groups[sid].wait() self.assertEqual(2, len(mock_load.mock_calls)) mock_load.assert_called_with(self.ctx, stack=st) mock_try.assert_called_once_with() mock_alive.assert_called_once_with(self.ctx, OTHER_ENGINE) mock_call.assert_called_once_with(self.ctx, OTHER_ENGINE, "stop_stack", stack_identity=mock.ANY) mock_acquire.assert_called_once_with()
def test_update_immutable_parameter_same_value(self): template = """ heat_template_version: 2014-10-16 parameters: param1: type: string immutable: true default: foo """ self.ctx = utils.dummy_context(password=None) stack_name = "test_update_immutable_parameters" params = {} old_stack = tools.get_stack(stack_name, self.ctx, template=template) sid = old_stack.store() old_stack.set_stack_user_project_id("1234") s = stack_object.Stack.get_by_id(self.ctx, sid) # prepare mocks self.patchobject(self.man, "_get_stack", return_value=s) self.patchobject(stack, "Stack", return_value=old_stack) self.patchobject(stack.Stack, "load", return_value=old_stack) self.patchobject(templatem, "Template", return_value=old_stack.t) self.patchobject(environment, "Environment", return_value=old_stack.env) params = {"param1": "foo"} result = self.man.update_stack(self.ctx, old_stack.identifier(), templatem.Template(template), params, None, {}) self.assertEqual(s.id, result["stack_id"])
def test_stack_delete_current_engine_active_lock(self, mock_acquire, mock_try, mock_load): self.man.start() stack_name = 'service_delete_test_stack_current_active_lock' stack = tools.get_stack(stack_name, self.ctx) sid = stack.store() # Insert a fake lock into the db stack_lock_object.StackLock.create(stack.id, self.man.engine_id) # Create a fake ThreadGroup too self.man.thread_group_mgr.groups[stack.id] = tools.DummyThreadGroup() st = stack_object.Stack.get_by_id(self.ctx, sid) mock_load.return_value = stack mock_try.return_value = self.man.engine_id mock_stop = self.patchobject(self.man.thread_group_mgr, 'stop') self.assertIsNone(self.man.delete_stack(self.ctx, stack.identifier())) mock_load.assert_called_with(self.ctx, stack=st) self.assertEqual(2, len(mock_load.mock_calls)) mock_try.assert_called_once_with() mock_acquire.assert_called_once_with() mock_stop.assert_called_once_with(stack.id)
def test_conv_wordpress_single_instance_stack_create(self, mock_cr): stack = tools.get_stack('test_stack', utils.dummy_context(), convergence=True) stack.store() # usually, stack is stored before converge is called stack.converge_stack(template=stack.t, action=stack.CREATE) self.assertIsNone(stack.ext_rsrcs_db) self.assertEqual('Dependencies([((1, True), None)])', repr(stack.convergence_dependencies)) stack_db = stack_object.Stack.get_by_id(stack.context, stack.id) self.assertIsNotNone(stack_db.current_traversal) self.assertIsNotNone(stack_db.raw_template_id) self.assertIsNone(stack_db.prev_raw_template_id) self.assertTrue(stack_db.convergence) self.assertEqual({'edges': [[[1, True], None]]}, stack_db.current_deps) leaves = stack.convergence_dependencies.leaves() expected_calls = [] for rsrc_id, is_update in leaves: expected_calls.append( mock.call.worker_client.WorkerClient.check_resource( stack.context, rsrc_id, stack.current_traversal, {'input_data': {}}, is_update, None)) self.assertEqual(expected_calls, mock_cr.mock_calls)
def test_migration_to_convergence_engine(self): self.ctx = utils.dummy_context() self.stack = tools.get_stack('test_stack_convg', self.ctx, template=tools.string_template_five) self.stack.store() for r in self.stack.resources.values(): r.store() self.stack.migrate_to_convergence() self.stack = self.stack.load(self.ctx, self.stack.id) self.assertTrue(self.stack.convergence) self.assertIsNone(self.stack.prev_raw_template_id) exp_required_by = {'A': ['C'], 'B': ['C'], 'C': ['D', 'E'], 'D': [], 'E': []} exp_requires = {'A': [], 'B': [], 'C': ['A', 'B'], 'D': ['C'], 'E': ['C']} exp_tmpl_id = self.stack.t.id def id_to_name(ids): names = [] for r in self.stack.resources.values(): if r.id in ids: names.append(r.name) return names for r in self.stack.resources.values(): self.assertEqual(sorted(exp_required_by[r.name]), sorted(r.required_by())) self.assertEqual(sorted(exp_requires[r.name]), sorted(id_to_name(r.requires))) self.assertEqual(exp_tmpl_id, r.current_template_id)
def test_state_set_sets_empty_curr_trvsl_for_failed_stack( self, mock_cr): stack = tools.get_stack('test_stack', utils.dummy_context(), template=tools.string_template_five, convergence=True) stack.status = stack.FAILED stack.store() stack.purge_db() self.assertEqual('', stack.current_traversal)
def setUp(self): super(MiscMethodsTest, self).setUp() cfg.CONF.set_default('convergence_engine', True) self.ctx = utils.dummy_context() self.stack = tools.get_stack( 'check_workflow_create_stack', self.ctx, template=tools.attr_cache_template, convergence=True) self.stack.converge_stack(self.stack.t) self.resource = self.stack['A']
def test_sync_with_time_throttle(self): ctx = utils.dummy_context() stack = tools.get_stack('test_stack', utils.dummy_context(), template=tools.string_template_five, convergence=True) stack.converge_stack(stack.t, action=stack.CREATE) mock_sleep_time = self.sync_with_sleep(ctx, stack) mock_sleep_time.assert_called_once_with(mock.ANY)
def test_stack_update_no_credentials(self): cfg.CONF.set_default('deferred_auth_method', 'password') stack_name = 'test_stack_update_no_credentials' params = {'foo': 'bar'} template = '{ "Template": "data" }' stk = tools.get_stack(stack_name, self.ctx) # force check for credentials on create stk['WebServer'].requires_deferred_auth = True sid = stk.store() stk.set_stack_user_project_id('1234') s = stack_object.Stack.get_by_id(self.ctx, sid) self.ctx = utils.dummy_context(password=None) # prepare mocks mock_get = self.patchobject(self.man, '_get_stack', return_value=s) mock_stack = self.patchobject(stack, 'Stack', return_value=stk) mock_load = self.patchobject(stack.Stack, 'load', return_value=stk) mock_tmpl = self.patchobject(templatem, 'Template', return_value=stk.t) mock_env = self.patchobject(environment, 'Environment', return_value=stk.env) api_args = {'timeout_mins': 60} ex = self.assertRaises(dispatcher.ExpectedException, self.man.update_stack, self.ctx, stk.identifier(), template, params, None, api_args) self.assertEqual(exception.MissingCredentialError, ex.exc_info[0]) self.assertEqual('Missing required credential: X-Auth-Key', six.text_type(ex.exc_info[1])) mock_get.assert_called_once_with(self.ctx, stk.identifier()) mock_tmpl.assert_called_once_with(template, files=None, env=stk.env) mock_env.assert_called_once_with(params) mock_stack.assert_called_once_with( self.ctx, stk.name, stk.t, convergence=False, current_traversal=stk.current_traversal, prev_raw_template_id=None, current_deps=None, disable_rollback=True, nested_depth=0, owner_id=None, parent_resource=None, stack_user_project_id='1234', strict_validate=True, tenant_id='test_tenant_id', timeout_mins=60, user_creds_id=u'1', username='******') mock_load.assert_called_once_with(self.ctx, stack=s)
def test_purge_db_deletes_previous_template(self, mock_tmpl_delete, mock_cr): stack = tools.get_stack('test_stack', utils.dummy_context(), template=tools.string_template_five, convergence=True) stack.prev_raw_template_id = 10 stack.purge_db() self.assertTrue(mock_tmpl_delete.called)
def test_mark_complete_purges_db(self, mock_cr): stack = tools.get_stack('test_stack', utils.dummy_context(), template=tools.string_template_five, convergence=True) stack.store() stack.purge_db = mock.Mock() stack.mark_complete() self.assertTrue(stack.purge_db.called)
def test_purge_db_calls_rsrc_purge_deleted(self, mock_rsrc_purge_delete, mock_cr): stack = tools.get_stack('test_stack', utils.dummy_context(), template=tools.string_template_five, convergence=True) stack.store() stack.purge_db() self.assertTrue(mock_rsrc_purge_delete.called)
def test_purge_db_deletes_sync_points(self, mock_cr): stack = tools.get_stack('test_stack', utils.dummy_context(), template=tools.string_template_five, convergence=True) stack.store() stack.purge_db() rows = sync_point_object.SyncPoint.delete_all_by_stack_and_traversal( stack.context, stack.id, stack.current_traversal) self.assertEqual(0, rows)
def test_purge_db_deletes_stack_for_deleted_stack(self, mock_stack_delete, mock_cr): stack = tools.get_stack('test_stack', utils.dummy_context(), template=tools.string_template_five, convergence=True) stack.store() stack.state_set(stack.DELETE, stack.COMPLETE, 'test reason') stack.purge_db() self.assertTrue(mock_stack_delete.called)
def test_validate_deferred_auth_context_not_required(self): stk = tools.get_stack('test_deferred_auth', self.ctx) stk['WebServer'].requires_deferred_auth = False ctx = utils.dummy_context(user=None, password=None) cfg.CONF.set_default('deferred_auth_method', 'password') # stack performs no deferred operations, so no username or # password required self.man._validate_deferred_auth_context(ctx, stk)
def test_purge_db_does_not_delete_previous_template_when_stack_fails( self, mock_tmpl_delete, mock_cr): stack = tools.get_stack('test_stack', utils.dummy_context(), template=tools.string_template_five, convergence=True) stack.status = stack.FAILED stack.purge_db() self.assertFalse(mock_tmpl_delete.called)
def test_stack_create_authorization_failure(self, mock_create): stack_name = 'stack_create_authorization_failure' stk = tools.get_stack(stack_name, self.ctx) mock_create.side_effect = exception.AuthorizationFailure ex = self.assertRaises(dispatcher.ExpectedException, self.man.create_stack, self.ctx, stack_name, stk.t.t, {}, None, {}) self.assertEqual(exception.StackValidationFailed, ex.exc_info[0])
def test_conv_string_five_instance_stack_create(self, mock_cr): stack = tools.get_stack('test_stack', utils.dummy_context(), template=tools.string_template_five, convergence=True) stack.store() stack.converge_stack(template=stack.t, action=stack.CREATE) self.assertIsNone(stack.ext_rsrcs_db) self.assertEqual('Dependencies([' '((1, True), (3, True)), ' '((2, True), (3, True)), ' '((3, True), (4, True)), ' '((3, True), (5, True))])', repr(stack.convergence_dependencies)) stack_db = stack_object.Stack.get_by_id(stack.context, stack.id) self.assertIsNotNone(stack_db.current_traversal) self.assertIsNotNone(stack_db.raw_template_id) self.assertIsNone(stack_db.prev_raw_template_id) self.assertTrue(stack_db.convergence) self.assertEqual(sorted([[[3, True], [5, True]], # C, A [[3, True], [4, True]], # C, B [[1, True], [3, True]], # E, C [[2, True], [3, True]]]), # D, C sorted(stack_db.current_deps['edges'])) # check if needed_by is stored properly expected_needed_by = {'A': [3], 'B': [3], 'C': [1, 2], 'D': [], 'E': []} rsrcs_db = resource_objects.Resource.get_all_by_stack( stack_db._context, stack_db.id ) self.assertEqual(5, len(rsrcs_db)) for rsrc_name, rsrc_obj in rsrcs_db.items(): self.assertEqual(sorted(expected_needed_by[rsrc_name]), sorted(rsrc_obj.needed_by)) self.assertEqual(stack_db.raw_template_id, rsrc_obj.current_template_id) # check if sync_points were stored for entity_id in [5, 4, 3, 2, 1, stack_db.id]: sync_point = sync_point_object.SyncPoint.get_by_key( stack_db._context, entity_id, stack_db.current_traversal, True ) self.assertIsNotNone(sync_point) self.assertEqual(stack_db.id, sync_point.stack_id) leaves = stack.convergence_dependencies.leaves() expected_calls = [] for rsrc_id, is_update in leaves: expected_calls.append( mock.call.worker_client.WorkerClient.check_resource( stack.context, rsrc_id, stack.current_traversal, {'input_data': {}}, is_update, None)) self.assertEqual(expected_calls, mock_cr.mock_calls)
def test_stack_create_no_credentials(self): cfg.CONF.set_default('deferred_auth_method', 'password') stack_name = 'test_stack_create_no_credentials' params = {'foo': 'bar'} template = '{ "Template": "data" }' stk = tools.get_stack(stack_name, self.ctx) # force check for credentials on create stk['WebServer'].requires_deferred_auth = True mock_tmpl = self.patchobject(templatem, 'Template', return_value=stk.t) mock_env = self.patchobject(environment, 'Environment', return_value=stk.env) mock_stack = self.patchobject(stack, 'Stack', return_value=stk) # test stack create using context without password ctx_no_pwd = utils.dummy_context(password=None) ex = self.assertRaises(dispatcher.ExpectedException, self.man.create_stack, ctx_no_pwd, stack_name, template, params, None, {}, None) self.assertEqual(exception.MissingCredentialError, ex.exc_info[0]) self.assertEqual('Missing required credential: X-Auth-Key', six.text_type(ex.exc_info[1])) mock_tmpl.assert_called_once_with(template, files=None, env=stk.env) mock_env.assert_called_once_with(params) mock_stack.assert_called_once_with(ctx_no_pwd, stack_name, stk.t, owner_id=None, nested_depth=0, user_creds_id=None, stack_user_project_id=None, convergence=False, parent_resource=None) mock_tmpl.reset_mock() mock_env.reset_mock() mock_stack.reset_mock() # test stack create using context without user ctx_no_pwd = utils.dummy_context(password=None) ctx_no_user = utils.dummy_context(user=None) ex = self.assertRaises(dispatcher.ExpectedException, self.man.create_stack, ctx_no_user, stack_name, template, params, None, {}) self.assertEqual(exception.MissingCredentialError, ex.exc_info[0]) self.assertEqual('Missing required credential: X-Auth-User', six.text_type(ex.exc_info[1])) mock_tmpl.assert_called_once_with(template, files=None, env=stk.env) mock_env.assert_called_once_with(params) mock_stack.assert_called_once_with(ctx_no_user, stack_name, stk.t, owner_id=None, nested_depth=0, user_creds_id=None, stack_user_project_id=None, convergence=False, parent_resource=None)
def test_stack_update_nonexist(self): stack_name = 'service_update_nonexist_test_stack' params = {'foo': 'bar'} template = '{ "Template": "data" }' stk = tools.get_stack(stack_name, self.ctx) ex = self.assertRaises(dispatcher.ExpectedException, self.man.update_stack, self.ctx, stk.identifier(), template, params, None, {}) self.assertEqual(exception.EntityNotFound, ex.exc_info[0])
def test_stack_create_nested(self, mock_validate, mock_tg): convergence_engine = cfg.CONF.convergence_engine stack_name = 'service_create_nested_test_stack' parent_stack = tools.get_stack(stack_name + '_parent', self.ctx) owner_id = parent_stack.store() mock_tg.return_value = tools.DummyThreadGroup() stk = tools.get_stack(stack_name, self.ctx, with_params=True, owner_id=owner_id, nested_depth=1) tmpl_id = stk.t.store(self.ctx) mock_load = self.patchobject(templatem.Template, 'load', return_value=stk.t) mock_stack = self.patchobject(stack, 'Stack', return_value=stk) result = self.man.create_stack(self.ctx, stack_name, None, None, None, {}, owner_id=owner_id, nested_depth=1, template_id=tmpl_id) self.assertEqual(stk.identifier(), result) self.assertIsInstance(result, dict) self.assertTrue(result['stack_id']) mock_load.assert_called_once_with(self.ctx, tmpl_id) mock_stack.assert_called_once_with(self.ctx, stack_name, stk.t, owner_id=owner_id, nested_depth=1, user_creds_id=None, stack_user_project_id=None, convergence=convergence_engine, parent_resource=None) mock_validate.assert_called_once_with(validate_resources=False)
def _stack_create(self, stack_name): self.patchobject(keystone.KeystoneClientPlugin, '_create', return_value=fake_ks.FakeKeystoneClient()) stk = tools.get_stack(stack_name, self.ctx, policy_template) stk.store() stk.create() s = stack_object.Stack.get_by_id(self.ctx, stk.id) self.patchobject(service.EngineService, '_get_stack', return_value=s) return stk
def test_purge_db_deletes_creds(self, mock_delete_stack, mock_creds_delete, mock_cr): stack = tools.get_stack('test_stack', utils.dummy_context(), template=tools.string_template_five, convergence=True) reason = 'stack delete complete' mock_creds_delete.return_value = (stack.COMPLETE, reason) stack.state_set(stack.DELETE, stack.COMPLETE, reason) stack.purge_db() self.assertTrue(mock_creds_delete.called) self.assertTrue(mock_delete_stack.called)
def test_stack_create_invalid_resource_name(self): stack_name = 'stack_create_invalid_resource_name' stk = tools.get_stack(stack_name, self.ctx) tmpl = dict(stk.t) tmpl['resources']['Web/Server'] = tmpl['resources']['WebServer'] del tmpl['resources']['WebServer'] ex = self.assertRaises(dispatcher.ExpectedException, self.man.create_stack, self.ctx, stack_name, stk.t.t, {}, None, {}) self.assertEqual(exception.StackValidationFailed, ex.exc_info[0])
def test_stack_delete(self, mock_load): stack_name = 'service_delete_test_stack' stack = tools.get_stack(stack_name, self.ctx) sid = stack.store() mock_load.return_value = stack s = stack_object.Stack.get_by_id(self.ctx, sid) self.assertIsNone(self.man.delete_stack(self.ctx, stack.identifier())) self.man.thread_group_mgr.groups[sid].wait() mock_load.assert_called_once_with(self.ctx, stack=s)
def test_stack_cancel_update_wrong_state_fails(self): stack_name = 'service_update_cancel_test_stack' stk = tools.get_stack(stack_name, self.ctx) stk.state_set(stk.UPDATE, stk.COMPLETE, 'test_override') stk.store() self.patchobject(stack.Stack, 'load', return_value=stk) ex = self.assertRaises(dispatcher.ExpectedException, self.man.stack_cancel_update, self.ctx, stk.identifier()) self.assertEqual(exception.NotSupported, ex.exc_info[0]) self.assertIn("Cancelling update when stack is " "UPDATE_COMPLETE", six.text_type(ex.exc_info[1]))
def test_purge_db_deletes_creds_failed(self, mock_delete_stack, mock_creds_delete, mock_cr): stack = tools.get_stack('test_stack', utils.dummy_context(), template=tools.string_template_five, convergence=True) reason = 'stack delete complete' failed_reason = 'Error deleting trust' mock_creds_delete.return_value = (stack.FAILED, failed_reason) stack.state_set(stack.DELETE, stack.COMPLETE, reason) stack.purge_db() self.assertTrue(mock_creds_delete.called) self.assertFalse(mock_delete_stack.called) self.assertEqual((stack.DELETE, stack.FAILED), stack.state)
def test_stack_update_with_environment_files(self): # Setup stack_name = 'service_update_env_files_stack' params = {} template = '{ "Template": "data" }' old_stack = tools.get_stack(stack_name, self.ctx) sid = old_stack.store() old_stack.set_stack_user_project_id('1234') stack_object.Stack.get_by_id(self.ctx, sid) stk = tools.get_stack(stack_name, self.ctx) # prepare mocks self.patchobject(stack, 'Stack', return_value=stk) self.patchobject(stack.Stack, 'load', return_value=old_stack) self.patchobject(templatem, 'Template', return_value=stk.t) self.patchobject(environment, 'Environment', return_value=stk.env) self.patchobject(stk, 'validate', return_value=None) self.patchobject(eventlet.queue, 'LightQueue', return_value=mock.Mock()) mock_merge = self.patchobject(env_util, 'merge_environments') # Test environment_files = ['env_1'] self.man.update_stack(self.ctx, old_stack.identifier(), template, params, None, {}, environment_files=environment_files) # Verify mock_merge.assert_called_once_with(environment_files, None, params, mock.ANY)
def setUp(self): super(CheckWorkflowUpdateTest, self).setUp() thread_group_mgr = mock.Mock() self.worker = worker.WorkerService('host-1', 'topic-1', 'engine_id', thread_group_mgr) self.worker._rpc_client = worker_client.WorkerClient() self.ctx = utils.dummy_context() self.stack = tools.get_stack( 'check_workflow_create_stack', self.ctx, template=tools.string_template_five, convergence=True) self.stack.converge_stack(self.stack.t) self.resource = self.stack['A'] self.is_update = True self.graph_key = (self.resource.id, self.is_update)
def test_stack_cancel_update_no_lock(self): stack_name = 'service_update_stack_test_cancel_same_engine' stk = tools.get_stack(stack_name, self.ctx) stk.state_set(stk.UPDATE, stk.IN_PROGRESS, 'test_override') stk.disable_rollback = False stk.store() self.patchobject(stack.Stack, 'load', return_value=stk) self.patchobject(stack_lock.StackLock, 'get_engine_id', return_value=None) self.patchobject(self.man.thread_group_mgr, 'send') self.man.stack_cancel_update(self.ctx, stk.identifier(), cancel_with_rollback=False) self.assertFalse(self.man.thread_group_mgr.send.called)
def test_stack_delete_other_engine_active_lock_succeeded( self, mock_expired, mock_acquire, mock_alive, mock_try, mock_load): cfg.CONF.set_override('error_wait_time', 0) OTHER_ENGINE = "other-engine-fake-uuid" self.man.engine_id = service_utils.generate_engine_id() self.man.listener = service.EngineListener(self.man.host, self.man.engine_id, self.man.thread_group_mgr) stack_name = 'service_delete_test_stack_other_engine_lock' stack = tools.get_stack(stack_name, self.ctx) sid = stack.store() # Insert a fake lock into the db stack_lock_object.StackLock.create(self.ctx, stack.id, OTHER_ENGINE) st = stack_object.Stack.get_by_id(self.ctx, sid) mock_load.return_value = stack mock_try.return_value = OTHER_ENGINE mock_alive.return_value = True mock_expired.side_effect = [False, True] mock_call = self.patchobject(self.man, '_remote_call', return_value=None) self.assertIsNone(self.man.delete_stack(self.ctx, stack.identifier())) self.man.thread_group_mgr.stop(sid, graceful=True) self.assertEqual(2, len(mock_load.mock_calls)) mock_load.assert_called_with(self.ctx, stack=st) mock_try.assert_called_with() mock_alive.assert_called_with(self.ctx, OTHER_ENGINE) mock_call.assert_has_calls([ mock.call(self.ctx, OTHER_ENGINE, mock.ANY, "send", message='cancel', stack_identity=mock.ANY), mock.call(self.ctx, OTHER_ENGINE, mock.ANY, "stop_stack", stack_identity=mock.ANY) ]) mock_acquire.assert_called_once_with(True)
def setUp(self): super(CheckWorkflowCleanupTest, self).setUp() thread_group_mgr = mock.Mock() self.worker = worker.WorkerService('host-1', 'topic-1', 'engine_id', thread_group_mgr) self.worker._rpc_client = worker_client.WorkerClient() self.ctx = utils.dummy_context() tstack = tools.get_stack('check_workflow_create_stack', self.ctx, template=tools.string_template_five, convergence=True) tstack.converge_stack(tstack.t, action=tstack.CREATE) self.stack = stack.Stack.load(self.ctx, stack_id=tstack.id) self.stack.converge_stack(self.stack.t, action=self.stack.DELETE) self.resource = self.stack['A'] self.is_update = False self.graph_key = (self.resource.id, self.is_update)
def _test_stack_create(self, stack_name, mock_validate, mock_tg, environment_files=None): mock_tg.return_value = tools.DummyThreadGroup() params = {'foo': 'bar'} template = '{ "Template": "data" }' stk = tools.get_stack(stack_name, self.ctx) mock_tmpl = self.patchobject(templatem, 'Template', return_value=stk.t) mock_env = self.patchobject(environment, 'Environment', return_value=stk.env) mock_stack = self.patchobject(stack, 'Stack', return_value=stk) mock_merge = self.patchobject(env_util, 'merge_environments') result = self.man.create_stack(self.ctx, stack_name, template, params, None, {}, environment_files=environment_files) self.assertEqual(stk.identifier(), result) self.assertIsInstance(result, dict) self.assertTrue(result['stack_id']) mock_tmpl.assert_called_once_with(template, files=None) mock_env.assert_called_once_with(params) mock_stack.assert_called_once_with( self.ctx, stack_name, stk.t, owner_id=None, nested_depth=0, user_creds_id=None, stack_user_project_id=None, convergence=cfg.CONF.convergence_engine, parent_resource=None) if environment_files: mock_merge.assert_called_once_with(environment_files, None, params, mock.ANY) mock_validate.assert_called_once_with(validate_resources=True)
def test_validate_deferred_auth_context_missing_credentials(self): stk = tools.get_stack('test_deferred_auth', self.ctx) stk['WebServer'].requires_deferred_auth = True cfg.CONF.set_default('deferred_auth_method', 'password') # missing username ctx = utils.dummy_context(user=None) ex = self.assertRaises(exception.MissingCredentialError, self.man._validate_deferred_auth_context, ctx, stk) self.assertEqual('Missing required credential: X-Auth-User', str(ex)) # missing password ctx = utils.dummy_context(password=None) ex = self.assertRaises(exception.MissingCredentialError, self.man._validate_deferred_auth_context, ctx, stk) self.assertEqual('Missing required credential: X-Auth-Key', str(ex))
def test_stack_delete_acquired_lock_stop_timers(self, mock_acquire, mock_load): mock_acquire.return_value = self.man.engine_id stack_name = 'service_delete_test_stack_stop_timers' stack = tools.get_stack(stack_name, self.ctx) sid = stack.store() mock_load.return_value = stack st = stack_object.Stack.get_by_id(self.ctx, sid) self.man.thread_group_mgr.add_timer(stack.id, 'test') self.assertEqual(1, len(self.man.thread_group_mgr.groups[sid].timers)) self.assertIsNone(self.man.delete_stack(self.ctx, stack.identifier())) self.assertEqual(0, len(self.man.thread_group_mgr.groups[sid].timers)) self.man.thread_group_mgr.groups[sid].wait() mock_acquire.assert_called_once_with() mock_load.assert_called_once_with(self.ctx, stack=st)