def test_create_job_with_successful_hook(self): GlobalCommandHookRegistry.reset() command_hook = HookForTesting(True) GlobalCommandHookRegistry.register_command_hook(command_hook) mock_context = FakeAuroraCommandContext() with patch("apache.aurora.client.cli.jobs.Job.create_context", return_value=mock_context): mock_query = self.create_query() mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.INIT)) mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.RUNNING)) mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.RUNNING)) mock_context.get_api("west").check_status.side_effect = ( lambda x: self.create_mock_status_query_result(ScheduleStatus.RUNNING)) api = mock_context.get_api("west") api.create_job.return_value = self.get_createjob_response() api.get_tier_configs.return_value = self.get_mock_tier_configurations() with temporary_file() as fp: fp.write(self.get_valid_config()) fp.flush() cmd = AuroraCommandLine() cmd.execute(["job", "create", "--wait-until=RUNNING", "west/bozo/test/hello", fp.name]) self.assert_create_job_called(api) self.assert_scheduler_called(api, mock_query, 1) assert command_hook.ran_pre assert command_hook.ran_post
def test_create_job_with_failed_hook(self): GlobalCommandHookRegistry.reset() command_hook = HookForTesting(False) GlobalCommandHookRegistry.register_command_hook(command_hook) mock_context = FakeAuroraCommandContext() with patch("apache.aurora.client.cli.jobs.Job.create_context", return_value=mock_context): mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.INIT)) mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.RUNNING)) api = mock_context.get_api("west") api.create_job.return_value = self.get_createjob_response() with temporary_file() as fp: fp.write(self.get_valid_config()) fp.flush() cmd = AuroraCommandLine() result = cmd.execute([ "job", "create", "--wait-until=RUNNING", "west/bozo/test/hello", fp.name ]) assert result == 1 assert api.create_job.call_count == 0 assert command_hook.ran_pre assert not command_hook.ran_post
def test_create_job_with_successful_hook(self): GlobalCommandHookRegistry.reset() command_hook = HookForTesting(True) GlobalCommandHookRegistry.register_command_hook(command_hook) mock_context = FakeAuroraCommandContext() with patch("apache.aurora.client.cli.jobs.Job.create_context", return_value=mock_context): mock_query = self.create_query() mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.INIT)) mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.RUNNING)) mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.RUNNING)) mock_context.get_api("west").check_status.side_effect = ( lambda x: self.create_mock_status_query_result(ScheduleStatus. RUNNING)) api = mock_context.get_api("west") api.create_job.return_value = self.get_createjob_response() api.get_tier_configs.return_value = self.get_mock_tier_configurations( ) with temporary_file() as fp: fp.write(self.get_valid_config()) fp.flush() cmd = AuroraCommandLine() cmd.execute([ "job", "create", "--wait-until=RUNNING", "west/bozo/test/hello", fp.name ]) self.assert_create_job_called(api) self.assert_scheduler_called(api, mock_query, 1) assert command_hook.ran_pre assert command_hook.ran_post
def test_dynamic_hook_exec_error(self): with patch("logging.warn") as log_patch: GlobalCommandHookRegistry.reset() GlobalCommandHookRegistry.load_project_hooks( "./src/test/python/apache/aurora/client/cli/hook_test_data/exec_error") log_patch.assert_called_with("Warning: error loading hooks file " "./src/test/python/apache/aurora/client/cli/hook_test_data/exec_error/AuroraHooks: " "integer division or modulo by zero")
def test_dynamic_hook_syntax_error(self): with patch("logging.warn") as log_patch: GlobalCommandHookRegistry.reset() GlobalCommandHookRegistry.load_project_hooks( "./src/test/python/apache/aurora/client/cli/hook_test_data/bad_syntax") log_patch.assert_called_with("Error compiling hooks file " "./src/test/python/apache/aurora/client/cli/hook_test_data/bad_syntax/AuroraHooks: " "invalid syntax (AuroraHooks, line 15)")
def assert_skip_forbidden(self, context, skip_opt, user, noun, verb, args): """Checks that a hook would NOT be allowed to be skipped in a command invocation""" try: # assertRaises doesn't work with classmethods. context.args = args GlobalCommandHookRegistry.get_required_hooks(context, skip_opt, noun, verb, user) self.fail("Should have thrown an error.") except context.CommandError: pass
def test_dynamic_hook_syntax_error(self): with patch("logging.warn") as log_patch: GlobalCommandHookRegistry.reset() GlobalCommandHookRegistry.load_project_hooks( "./src/test/python/apache/aurora/client/cli/hook_test_data/bad_syntax" ) log_patch.assert_called_with( "Error compiling hooks file " "./src/test/python/apache/aurora/client/cli/hook_test_data/bad_syntax/AuroraHooks: " "invalid syntax (AuroraHooks, line 15)")
def assert_skip_forbidden(self, context, skip_opt, user, noun, verb, args): """Checks that a hook would NOT be allowed to be skipped in a command invocation""" try: # assertRaises doesn't work with classmethods. context.args = args GlobalCommandHookRegistry.get_required_hooks( context, skip_opt, noun, verb, user) self.fail("Should have thrown an error.") except context.CommandError: pass
def test_dynamic_hook_exec_error(self): with patch("logging.warn") as log_patch: GlobalCommandHookRegistry.reset() GlobalCommandHookRegistry.load_project_hooks( "./src/test/python/apache/aurora/client/cli/hook_test_data/exec_error" ) log_patch.assert_called_with( "Warning: error loading hooks file " "./src/test/python/apache/aurora/client/cli/hook_test_data/exec_error/AuroraHooks: " "integer division or modulo by zero")
def test_skip_hooks_in_create(self): """Run a test of create, with a hook that should forbid running create, but with a user who's covered by one of the hook skip exception rules - so it should succeed. """ GlobalCommandHookRegistry.reset() command_hook = HookForTesting(True) GlobalCommandHookRegistry.register_command_hook(command_hook) command_hook_two = SecondHookForTesting(False) GlobalCommandHookRegistry.register_command_hook(command_hook_two) mock_response = Mock() mock_context = FakeAuroraCommandContext() with contextlib.nested( patch("apache.aurora.client.cli.jobs.Job.create_context", return_value=mock_context), patch("requests.get", return_value=mock_response), patch("getpass.getuser", return_value="bozo")): mock_response.json.return_value = { "a": { "users": ["bozo", "clown"], "commands": { "job": ["killall", "create"] }, "hooks": ["test_hook", "second"] }, "b": { "commands": { "user": ["kick"] }, } } mock_query = self.create_mock_query() mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.INIT)) mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.RUNNING)) api = mock_context.get_api("west") api.create_job.return_value = self.get_createjob_response() GlobalCommandHookRegistry.setup("http://foo.bar") with temporary_file() as fp: fp.write(self.get_valid_config()) fp.flush() cmd = AuroraCommandLine() result = cmd.execute([ "job", "create", "--skip-hooks=second", "--wait-until=RUNNING", "west/bozo/test/hello", fp.name ]) assert result == 0 self.assert_create_job_called(api) self.assert_scheduler_called(api, mock_query, 1) assert command_hook.ran_pre assert command_hook.ran_post
def test_skip_hooks_in_create(self): """Run a test of create, with a hook that should forbid running create, but with a user who's covered by one of the hook skip exception rules - so it should succeed. """ GlobalCommandHookRegistry.reset() command_hook = HookForTesting(True) GlobalCommandHookRegistry.register_command_hook(command_hook) command_hook_two = SecondHookForTesting(False) GlobalCommandHookRegistry.register_command_hook(command_hook_two) mock_response = Mock() mock_context = FakeAuroraCommandContext() with contextlib.nested( patch("apache.aurora.client.cli.jobs.Job.create_context", return_value=mock_context), patch("requests.get", return_value=mock_response), patch("getpass.getuser", return_value="bozo")): mock_response.json.return_value = { "a": { "users": ["bozo", "clown"], "commands": {"job": ["killall", "create"]}, "hooks": ["test_hook", "second"] }, "b": { "commands": {"user": ["kick"]}, } } mock_query = self.create_mock_query() mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.INIT)) mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.RUNNING)) mock_context.get_api("west").check_status.side_effect = ( lambda x: self.create_mock_status_query_result(ScheduleStatus.RUNNING)) api = mock_context.get_api("west") api.create_job.return_value = self.get_createjob_response() GlobalCommandHookRegistry.setup("http://foo.bar") with temporary_file() as fp: fp.write(self.get_valid_config()) fp.flush() cmd = AuroraCommandLine() result = cmd.execute(["job", "create", "--skip-hooks=second", "--wait-until=RUNNING", "west/bozo/test/hello", fp.name]) assert result == 0 self.assert_create_job_called(api) self.assert_scheduler_called(api, mock_query, 1) assert command_hook.ran_pre assert command_hook.ran_post
def test_cannot_skip_hooks_in_create(self): """This time, the hook shouldn't be skippable, because we use a username who isn't allowed by the hook exception rule. """ GlobalCommandHookRegistry.reset() command_hook = HookForTesting(True) GlobalCommandHookRegistry.register_command_hook(command_hook) command_hook_two = SecondHookForTesting(False) GlobalCommandHookRegistry.register_command_hook(command_hook_two) mock_response = Mock() mock_context = FakeAuroraCommandContext() with contextlib.nested( patch("apache.aurora.client.cli.jobs.Job.create_context", return_value=mock_context), patch("requests.get", return_value=mock_response), patch("getpass.getuser", return_value="beezus")): mock_response.json.return_value = { "a": { "users": ["bozo", "clown"], "commands": { "job": ["killall", "create"] }, "hooks": ["test_hook", "second"] }, "b": { "commands": { "user": ["kick"] }, } } mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.INIT)) mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.RUNNING)) api = mock_context.get_api("west") api.create_job.return_value = self.get_createjob_response() GlobalCommandHookRegistry.setup("http://foo.bar") with temporary_file() as fp: fp.write(self.get_valid_config()) fp.flush() cmd = AuroraCommandLine() result = cmd.execute([ "job", "create", "--skip-hooks=second", "--wait-until=RUNNING", "west/bozo/test/hello", fp.name ]) # Check that it returns the right error code, and that create_job didn't get called. assert result == EXIT_PERMISSION_VIOLATION assert api.create_job.call_count == 0
def test_json_skip_rules(self): """Load up a set of skips, specified in JSON, and then check a bunch of different cases to see that the skip rules work correctly. """ mock_response = Mock() mock_context = FakeAuroraCommandContext() with patch("requests.get", return_value=mock_response): mock_response.json.return_value = { "a": { "users": ["bozo", "clown"], "commands": { "job": ["killall"] }, "hooks": ["test_hook", "second"] }, "b": { "commands": { "user": ["kick"] }, } } GlobalCommandHookRegistry.reset() GlobalCommandHookRegistry.setup("http://foo.bar") command_hook_one = HookForTesting(False) GlobalCommandHookRegistry.register_command_hook(command_hook_one) command_hook_two = SecondHookForTesting(True) GlobalCommandHookRegistry.register_command_hook(command_hook_two) assert len(GlobalCommandHookRegistry.SKIP_HOOK_RULES) == 2 # Should not be allowed: no skip rule permitting skipping hooks on job kill self.assert_skip_forbidden(mock_context, "all", "beezus", "job", "kill", ["a", "b", "c"]) # Should not be allowed: there are hooks on "job killall", and beezus doesn't satisfy # their exception rules self.assert_skip_forbidden(mock_context, "all", "beezus", "job", "kill", ["a", "b", "c"]) # Should be allowed: there's a rule allowing bozo to skip test_hook on job killall. self.assert_skip_allowed(mock_context, "test_hook", "bozo", "job", "killall", ["a", "b", "c"]) # Should be allowed: since there's only one hook on killall, this is equivalent to # the previous. self.assert_skip_allowed(mock_context, "all", "bozo", "job", "killall", ["a", "b", "c"]) # Should be allowed: there's a rule allowing anyone to skip any hook on "user kick". self.assert_skip_allowed(mock_context, "test_hook,something_else", "nobody", "user", "kick", ["a", "b", "c"]) # should be allowed: there are no hooks in place for "user kick", so all is acceptable. self.assert_skip_allowed(mock_context, "all", "nobody", "user", "kick", ["a", "b", "c"])
def test_create_job_with_failed_hook(self): GlobalCommandHookRegistry.reset() command_hook = HookForTesting(False) GlobalCommandHookRegistry.register_command_hook(command_hook) mock_context = FakeAuroraCommandContext() with patch("apache.aurora.client.cli.jobs.Job.create_context", return_value=mock_context): mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.INIT)) mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.RUNNING)) api = mock_context.get_api("west") api.create_job.return_value = self.get_createjob_response() with temporary_file() as fp: fp.write(self.get_valid_config()) fp.flush() cmd = AuroraCommandLine() result = cmd.execute(["job", "create", "--wait-until=RUNNING", "west/bozo/test/hello", fp.name]) assert result == 1 assert api.create_job.call_count == 0 assert command_hook.ran_pre assert not command_hook.ran_post
def test_cannot_skip_hooks_in_create(self): """This time, the hook shouldn't be skippable, because we use a username who isn't allowed by the hook exception rule. """ GlobalCommandHookRegistry.reset() command_hook = HookForTesting(True) GlobalCommandHookRegistry.register_command_hook(command_hook) command_hook_two = SecondHookForTesting(False) GlobalCommandHookRegistry.register_command_hook(command_hook_two) mock_response = Mock() mock_context = FakeAuroraCommandContext() with contextlib.nested( patch("apache.aurora.client.cli.jobs.Job.create_context", return_value=mock_context), patch("requests.get", return_value=mock_response), patch("getpass.getuser", return_value="beezus")): mock_response.json.return_value = { "a": { "users": ["bozo", "clown"], "commands": {"job": ["killall", "create"]}, "hooks": ["test_hook", "second"] }, "b": { "commands": {"user": ["kick"]}, } } mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.INIT)) mock_context.add_expected_status_query_result( self.create_mock_status_query_result(ScheduleStatus.RUNNING)) api = mock_context.get_api("west") api.create_job.return_value = self.get_createjob_response() GlobalCommandHookRegistry.setup("http://foo.bar") with temporary_file() as fp: fp.write(self.get_valid_config()) fp.flush() cmd = AuroraCommandLine() result = cmd.execute(["job", "create", "--skip-hooks=second", "--wait-until=RUNNING", "west/bozo/test/hello", fp.name]) # Check that it returns the right error code, and that create_job didn't get called. assert result == EXIT_PERMISSION_VIOLATION assert api.create_job.call_count == 0
def test_json_skip_rules(self): """Load up a set of skips, specified in JSON, and then check a bunch of different cases to see that the skip rules work correctly. """ mock_response = Mock() mock_context = FakeAuroraCommandContext() with patch("requests.get", return_value=mock_response): mock_response.json.return_value = { "a": { "users": ["bozo", "clown"], "commands": {"job": ["killall"]}, "hooks": ["test_hook", "second"] }, "b": { "commands": {"user": ["kick"]}, } } GlobalCommandHookRegistry.reset() GlobalCommandHookRegistry.setup("http://foo.bar") command_hook_one = HookForTesting(False) GlobalCommandHookRegistry.register_command_hook(command_hook_one) command_hook_two = SecondHookForTesting(True) GlobalCommandHookRegistry.register_command_hook(command_hook_two) assert len(GlobalCommandHookRegistry.SKIP_HOOK_RULES) == 2 # Should not be allowed: no skip rule permitting skipping hooks on job kill self.assert_skip_forbidden(mock_context, "all", "beezus", "job", "kill", ["a", "b", "c"]) # Should not be allowed: there are hooks on "job killall", and beezus doesn't satisfy # their exception rules self.assert_skip_forbidden(mock_context, "all", "beezus", "job", "kill", ["a", "b", "c"]) # Should be allowed: there's a rule allowing bozo to skip test_hook on job killall. self.assert_skip_allowed(mock_context, "test_hook", "bozo", "job", "killall", ["a", "b", "c"]) # Should be allowed: since there's only one hook on killall, this is equivalent to # the previous. self.assert_skip_allowed(mock_context, "all", "bozo", "job", "killall", ["a", "b", "c"]) # Should be allowed: there's a rule allowing anyone to skip any hook on "user kick". self.assert_skip_allowed(mock_context, "test_hook,something_else", "nobody", "user", "kick", ["a", "b", "c"]) # should be allowed: there are no hooks in place for "user kick", so all is acceptable. self.assert_skip_allowed(mock_context, "all", "nobody", "user", "kick", ["a", "b", "c"])
def test_load_dynamic_hooks(self): GlobalCommandHookRegistry.reset() hook_locals = GlobalCommandHookRegistry.load_project_hooks( "./src/test/python/apache/aurora/client/cli") assert hook_locals["hooks"][ 0] in GlobalCommandHookRegistry.COMMAND_HOOKS
def assert_skip_allowed(self, context, skip_opt, user, noun, verb, args): """Checks that a hook would be allowed to be skipped in a command invocation""" GlobalCommandHookRegistry.get_required_hooks(context, skip_opt, noun, verb, user)
def test_successful_dynamic_hook(self): GlobalCommandHookRegistry.reset() hook_locals = GlobalCommandHookRegistry.load_project_hooks( "./src/test/python/apache/aurora/client/cli") self.generic_test_successful_hook(hook_locals["hooks"][0])
def test_create_job_with_successful_hook(self): GlobalCommandHookRegistry.reset() command_hook = HookForTesting(True) GlobalCommandHookRegistry.register_command_hook(command_hook) self.generic_test_successful_hook(command_hook)
def test_load_dynamic_hooks(self): GlobalCommandHookRegistry.reset() hook_locals = GlobalCommandHookRegistry.load_project_hooks( "./src/test/python/apache/aurora/client/cli") assert hook_locals["hooks"][0] in GlobalCommandHookRegistry.COMMAND_HOOKS