def setUp(self): self._command = StartUpdate() self._job_key = AuroraJobKey("cluster", "role", "env", "job") self._mock_options = mock_verb_options(self._command) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, []) self._fake_context = FakeAuroraCommandContext() self._fake_context.set_options(self._mock_options) self._mock_api = self._fake_context.get_api('UNUSED')
def setUp(self): self._command = StartUpdate() self._job_key = AuroraJobKey.from_thrift("cluster", UPDATE_KEY.job) self._mock_options = mock_verb_options(self._command) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, None) self._fake_context = FakeAuroraCommandContext() self._fake_context.set_options(self._mock_options) self._mock_api = self._fake_context.get_api('UNUSED')
def setUp(self): self._command = StartUpdate() self._job_key = AuroraJobKey("cluster", "role", "env", "job") self._mock_options = mock_verb_options(self._command) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, []) self._fake_context = FakeAuroraCommandContext() self._fake_context.set_options(self._mock_options) self._mock_api = self._fake_context.get_api("test")
class TestStartUpdateCommand(AuroraClientCommandTest): def setUp(self): self._command = StartUpdate() self._job_key = AuroraJobKey("cluster", "role", "env", "job") self._mock_options = mock_verb_options(self._command) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, []) self._fake_context = FakeAuroraCommandContext() self._fake_context.set_options(self._mock_options) self._mock_api = self._fake_context.get_api("test") @classmethod def create_mock_config(cls, is_cron=False): mock_config = create_autospec(spec=AuroraConfig, spec_set=True, instance=True) mock_raw_config = Mock() mock_raw_config.has_cron_schedule.return_value = is_cron mock_config.raw = Mock(return_value=mock_raw_config) return mock_config def test_start_update_with_lock(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_api.start_job_update.return_value = AuroraClientCommandTest.create_blank_response( ResponseCode.LOCK_ERROR, "Error.") with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) self._mock_api.start_job_update.assert_called_once_with( mock_config, self._mock_options.instance_spec.instance) self.assert_lock_message(self._fake_context) def test_update_cron_job_fails(self): mock_config = self.create_mock_config(is_cron=True) self._fake_context.get_job_config = Mock(return_value=mock_config) with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) def test_update_no_active_instance_check(self): self._mock_options.instance_spec = TaskInstanceKey(self.TEST_JOBKEY, [1]) self._mock_options.strict = True mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_api.start_job_update.return_value = self.create_simple_success_response() self._command.execute(self._fake_context) self._mock_api.start_job_update.assert_called_once_with( mock_config, self._mock_options.instance_spec.instance)
class TestStartUpdateCommand(AuroraClientCommandTest): def setUp(self): self._command = StartUpdate() self._job_key = AuroraJobKey("cluster", "role", "env", "job") self._mock_options = mock_verb_options(self._command) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, []) self._fake_context = FakeAuroraCommandContext() self._fake_context.set_options(self._mock_options) self._mock_api = self._fake_context.get_api('UNUSED') @classmethod def create_mock_config(cls, is_cron=False): mock_config = create_autospec(spec=AuroraConfig, spec_set=True, instance=True) mock_raw_config = Mock() mock_raw_config.has_cron_schedule.return_value = is_cron mock_config.raw = Mock(return_value=mock_raw_config) return mock_config def test_start_update_with_lock(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_api.start_job_update.return_value = AuroraClientCommandTest.create_blank_response( ResponseCode.LOCK_ERROR, "Error.") with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) self._mock_api.start_job_update.assert_called_once_with( mock_config, self._mock_options.instance_spec.instance) self.assert_lock_message(self._fake_context) def test_update_cron_job_fails(self): mock_config = self.create_mock_config(is_cron=True) self._fake_context.get_job_config = Mock(return_value=mock_config) with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) def test_update_no_active_instance_check(self): self._mock_options.instance_spec = TaskInstanceKey(self.TEST_JOBKEY, [1]) self._mock_options.strict = True mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_api.start_job_update.return_value = self.create_simple_success_response() self._command.execute(self._fake_context) self._mock_api.start_job_update.assert_called_once_with( mock_config, self._mock_options.instance_spec.instance)
class TestStartUpdate(AuroraClientCommandTest): def setUp(self): self._command = StartUpdate() self._job_key = AuroraJobKey.from_thrift("cluster", UPDATE_KEY.job) self._mock_options = mock_verb_options(self._command) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, None) self._mock_options.wait = False self._fake_context = FakeAuroraCommandContext() self._fake_context.set_options(self._mock_options) self._mock_api = self._fake_context.get_api('UNUSED') @classmethod def create_mock_config(cls, is_cron=False): # TODO(wfarner): Consider using a real AuroraConfig object for this. mock_config = create_autospec(spec=AuroraConfig, spec_set=True, instance=True) raw_config = Job(cron_schedule='something' if is_cron else Empty) mock_config.raw = Mock(return_value=raw_config) mock_config.cluster = Mock(return_value=cls.TEST_CLUSTER) return mock_config def test_start_update_with_lock(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_api.start_job_update.return_value = AuroraClientCommandTest.create_blank_response( ResponseCode.LOCK_ERROR, "Error.") with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance) ] self.assert_lock_message(self._fake_context) def test_update_cron_job_fails(self): mock_config = self.create_mock_config(is_cron=True) self._fake_context.get_job_config = Mock(return_value=mock_config) with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) def test_update_no_active_instance_check(self): self._mock_options.instance_spec = TaskInstanceKey(self.TEST_JOBKEY, [1]) self._mock_options.strict = True mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_api.start_job_update.return_value = self.create_simple_success_response() self._command.execute(self._fake_context) assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance) ] def test_start_update_command_line_succeeds(self): resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey(role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, None) self._mock_options.message = 'hello' assert self._command.execute(self._fake_context) == EXIT_OK assert self._mock_api.start_job_update.mock_calls == [ call(ANY, 'hello', None) ] assert self._fake_context.get_out() == [ StartUpdate.UPDATE_MSG_TEMPLATE % ('http://something_or_other/scheduler/role/env/name/update/id') ] assert self._fake_context.get_err() == [] def test_start_update_and_wait_success(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.wait = True resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey(role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp self._mock_api.query_job_updates.side_effect = [ get_status_query_response(status=JobUpdateStatus.ROLLED_FORWARD) ] assert self._command.execute(self._fake_context) == EXIT_OK assert self._mock_api.start_job_update.mock_calls == [call(ANY, None, None)] assert self._mock_api.query_job_updates.mock_calls == [ call(update_key=resp.result.startJobUpdateResult.key) ] assert self._fake_context.get_out() == [ StartUpdate.UPDATE_MSG_TEMPLATE % ('http://something_or_other/scheduler/role/env/name/update/id'), 'Current state ROLLED_FORWARD' ] assert self._fake_context.get_err() == [] def test_start_update_and_wait_rollback(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.wait = True resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey(role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp self._mock_api.query_job_updates.side_effect = [ get_status_query_response(status=JobUpdateStatus.ROLLED_BACK) ] assert self._command.execute(self._fake_context) == EXIT_COMMAND_FAILURE def test_start_update_and_wait_error(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.wait = True resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey(role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp self._mock_api.query_job_updates.side_effect = [ get_status_query_response(status=JobUpdateStatus.ERROR) ] assert self._command.execute(self._fake_context) == EXIT_UNKNOWN_ERROR def test_start_update_command_line_succeeds_noop_update(self): resp = self.create_simple_success_response() resp.details = [ResponseDetail(message="Noop update.")] self._mock_api.start_job_update.return_value = resp mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) result = self._command.execute(self._fake_context) assert result == EXIT_OK assert self._mock_api.start_job_update.mock_calls == [call(ANY, None, None)] assert self._fake_context.get_out() == ["Noop update."] assert self._fake_context.get_err() == [] def test_update_pulse_interval_too_small(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) error = Context.CommandError(100, 'something failed') self._mock_api.start_job_update.side_effect = error with pytest.raises(Context.CommandError) as e: self._command.execute(self._fake_context) assert e.value == error assert self._mock_api.start_job_update.mock_calls == [call(ANY, None, None)]
class TestStartUpdate(AuroraClientCommandTest): def setUp(self): self._command = StartUpdate() self._job_key = AuroraJobKey.from_thrift("cluster", UPDATE_KEY.job) self._mock_options = mock_verb_options(self._command) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, None) self._mock_options.wait = False self._fake_context = FakeAuroraCommandContext() self._fake_context.set_options(self._mock_options) self._mock_api = self._fake_context.get_api('UNUSED') self._formatter = Mock(spec=DiffFormatter) @classmethod def create_mock_config(cls, is_cron=False): # TODO(wfarner): Consider using a real AuroraConfig object for this. mock_config = create_autospec(spec=AuroraConfig, spec_set=True, instance=True) raw_config = Job(cron_schedule='something' if is_cron else Empty) mock_config.raw = Mock(return_value=raw_config) mock_config.cluster = Mock(return_value=cls.TEST_CLUSTER) return mock_config def test_start_update_with_lock(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_api.start_job_update.return_value = AuroraClientCommandTest.create_blank_response( ResponseCode.LOCK_ERROR, "Error.") with patch('apache.aurora.client.cli.update.DiffFormatter'): with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance, ANY) ] self.assert_lock_message(self._fake_context) def test_start_update_invalid_request(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) err_msg = "Error." self._mock_api.start_job_update.return_value = AuroraClientCommandTest.create_blank_response( ResponseCode.INVALID_REQUEST, err_msg) with patch('apache.aurora.client.cli.update.DiffFormatter'): with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance, ANY) ] assert self._fake_context.get_err() == [ StartUpdate.FAILED_TO_START_UPDATE_ERROR_MSG, "\t%s" % err_msg ] def test_start_update_already_inprogress(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) update_id = 'some-mocked-uuid' err_msg = "Active updates exist for this job." return_value = AuroraClientCommandTest.create_start_job_update_result( ResponseCode.INVALID_REQUEST, err_msg, UPDATE_KEY, {Metadata(CLIENT_UPDATE_ID, update_id)}) self._mock_api.start_job_update.return_value = return_value with patch('apache.aurora.client.cli.update.DiffFormatter'): with patch('apache.aurora.client.cli.update.uuid') as mock_uuid: mock_uuid.uuid4.return_value = update_id self._command.execute(self._fake_context) assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance, {CLIENT_UPDATE_ID: update_id}) ] assert self._fake_context.get_out() == [ StartUpdate.UPDATE_MSG_TEMPLATE % ('http://something_or_other/scheduler/bozo/test/hello/update/update_id'), ] assert self._fake_context.get_err() == [] def test_start_update_different_update_inprogress(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) update_id = 'some-mocked-uuid' update_id_2 = 'some-other-mocked-uuid' err_msg = "Active updates exist for this job." return_value = AuroraClientCommandTest.create_start_job_update_result( ResponseCode.INVALID_REQUEST, err_msg, UPDATE_KEY, {Metadata(CLIENT_UPDATE_ID, update_id)}) self._mock_api.start_job_update.return_value = return_value with patch('apache.aurora.client.cli.update.DiffFormatter'): with pytest.raises(Context.CommandError): with patch('apache.aurora.client.cli.update.uuid') as mock_uuid: mock_uuid.uuid4.return_value = update_id_2 self._command.execute(self._fake_context) assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance, {CLIENT_UPDATE_ID: update_id_2}) ] assert self._fake_context.get_out() == [] assert self._fake_context.get_err() == [ StartUpdate.FAILED_TO_START_UPDATE_ERROR_MSG, "\t%s" % err_msg ] def test_update_cron_job_fails(self): mock_config = self.create_mock_config(is_cron=True) self._fake_context.get_job_config = Mock(return_value=mock_config) with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) def test_update_no_active_instance_check(self): self._mock_options.instance_spec = TaskInstanceKey(self.TEST_JOBKEY, [1]) self._mock_options.strict = True mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_api.start_job_update.return_value = self.create_simple_success_response() with patch('apache.aurora.client.cli.update.DiffFormatter') as formatter: formatter.return_value = self._formatter self._command.execute(self._fake_context) assert self._formatter.show_job_update_diff.mock_calls == [ call(self._mock_options.instance_spec.instance) ] assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance, ANY) ] def test_start_update_command_line_succeeds(self): resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey(role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, None) self._mock_options.message = 'hello' with patch('apache.aurora.client.cli.update.DiffFormatter') as formatter: formatter.return_value = self._formatter assert self._command.execute(self._fake_context) == EXIT_OK assert self._formatter.show_job_update_diff.mock_calls == [ call(self._mock_options.instance_spec.instance) ] assert self._mock_api.start_job_update.mock_calls == [ call(ANY, 'hello', None, ANY) ] assert self._fake_context.get_out() == [ StartUpdate.UPDATE_MSG_TEMPLATE % ('http://something_or_other/scheduler/role/env/name/update/id'), ] assert self._fake_context.get_err() == [] def test_start_update_and_wait_success(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.wait = True resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey(role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp self._mock_api.query_job_updates.side_effect = [ get_status_query_response(status=JobUpdateStatus.ROLLED_FORWARD) ] with patch('apache.aurora.client.cli.update.DiffFormatter') as formatter: formatter.return_value = self._formatter assert self._command.execute(self._fake_context) == EXIT_OK assert self._formatter.show_job_update_diff.mock_calls == [ call(self._mock_options.instance_spec.instance) ] assert self._mock_api.start_job_update.mock_calls == [call(ANY, None, None, ANY)] assert self._mock_api.query_job_updates.mock_calls == [ call(update_key=resp.result.startJobUpdateResult.key) ] assert self._fake_context.get_out() == [ StartUpdate.UPDATE_MSG_TEMPLATE % ('http://something_or_other/scheduler/role/env/name/update/id'), 'Current state ROLLED_FORWARD' ] assert self._fake_context.get_err() == [] def test_start_update_and_wait_rollback(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.wait = True resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey(role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp self._mock_api.query_job_updates.side_effect = [ get_status_query_response(status=JobUpdateStatus.ROLLED_BACK) ] with patch('apache.aurora.client.cli.update.DiffFormatter'): assert self._command.execute(self._fake_context) == EXIT_COMMAND_FAILURE def test_start_update_and_wait_error(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.wait = True resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey(role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp self._mock_api.query_job_updates.side_effect = [ get_status_query_response(status=JobUpdateStatus.ERROR) ] with patch('apache.aurora.client.cli.update.DiffFormatter'): assert self._command.execute(self._fake_context) == EXIT_UNKNOWN_ERROR def test_start_update_command_line_succeeds_noop_update(self): resp = self.create_simple_success_response() resp.details = [ResponseDetail(message="Noop update.")] self._mock_api.start_job_update.return_value = resp mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) with patch('apache.aurora.client.cli.update.DiffFormatter') as formatter: formatter.return_value = self._formatter assert self._command.execute(self._fake_context) == EXIT_OK assert self._formatter.show_job_update_diff.mock_calls == [ call(self._mock_options.instance_spec.instance) ] assert self._mock_api.start_job_update.mock_calls == [call(ANY, None, None, ANY)] assert self._fake_context.get_out() == [ "Noop update." ] assert self._fake_context.get_err() == [] def test_update_pulse_interval_too_small(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) error = Context.CommandError(100, 'something failed') self._mock_api.start_job_update.side_effect = error with patch('apache.aurora.client.cli.update.DiffFormatter'): with pytest.raises(Context.CommandError) as e: self._command.execute(self._fake_context) assert e.value == error assert self._mock_api.start_job_update.mock_calls == [call(ANY, None, None, ANY)]
class TestStartUpdate(AuroraClientCommandTest): def setUp(self): self._command = StartUpdate() self._job_key = AuroraJobKey.from_thrift("cluster", UPDATE_KEY.job) self._mock_options = mock_verb_options(self._command) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, None) self._mock_options.wait = False self._fake_context = FakeAuroraCommandContext() self._fake_context.set_options(self._mock_options) self._mock_api = self._fake_context.get_api('UNUSED') self._formatter = Mock(spec=DiffFormatter) @classmethod def create_mock_config(cls, is_cron=False): # TODO(wfarner): Consider using a real AuroraConfig object for this. mock_config = create_autospec(spec=AuroraConfig, spec_set=True, instance=True) raw_config = Job(cron_schedule='something' if is_cron else Empty) mock_config.raw = Mock(return_value=raw_config) mock_config.cluster = Mock(return_value=cls.TEST_CLUSTER) return mock_config def test_start_update_with_lock(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_api.start_job_update.return_value = AuroraClientCommandTest.create_blank_response( ResponseCode.LOCK_ERROR, "Error.") with patch('apache.aurora.client.cli.update.DiffFormatter'): with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance, ANY) ] self.assert_lock_message(self._fake_context) def test_start_update_invalid_request(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) err_msg = "Error." self._mock_api.start_job_update.return_value = AuroraClientCommandTest.create_blank_response( ResponseCode.INVALID_REQUEST, err_msg) with patch('apache.aurora.client.cli.update.DiffFormatter'): with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance, ANY) ] assert self._fake_context.get_err() == [ StartUpdate.FAILED_TO_START_UPDATE_ERROR_MSG, "\t%s" % err_msg ] def test_start_update_already_inprogress(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) update_id = 'some-mocked-uuid' err_msg = "Active updates exist for this job." return_value = AuroraClientCommandTest.create_start_job_update_result( ResponseCode.INVALID_REQUEST, err_msg, UPDATE_KEY, {Metadata(CLIENT_UPDATE_ID, update_id)}) self._mock_api.start_job_update.return_value = return_value with patch('apache.aurora.client.cli.update.DiffFormatter'): with patch('apache.aurora.client.cli.update.uuid') as mock_uuid: mock_uuid.uuid4.return_value = update_id self._command.execute(self._fake_context) assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance, {CLIENT_UPDATE_ID: update_id}) ] assert self._fake_context.get_out() == [ StartUpdate.UPDATE_MSG_TEMPLATE % ('http://something_or_other/scheduler/bozo/test/hello/update/update_id' ), ] assert self._fake_context.get_err() == [] def test_start_update_different_update_inprogress(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) update_id = 'some-mocked-uuid' update_id_2 = 'some-other-mocked-uuid' err_msg = "Active updates exist for this job." return_value = AuroraClientCommandTest.create_start_job_update_result( ResponseCode.INVALID_REQUEST, err_msg, UPDATE_KEY, {Metadata(CLIENT_UPDATE_ID, update_id)}) self._mock_api.start_job_update.return_value = return_value with patch('apache.aurora.client.cli.update.DiffFormatter'): with pytest.raises(Context.CommandError): with patch( 'apache.aurora.client.cli.update.uuid') as mock_uuid: mock_uuid.uuid4.return_value = update_id_2 self._command.execute(self._fake_context) assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance, {CLIENT_UPDATE_ID: update_id_2}) ] assert self._fake_context.get_out() == [] assert self._fake_context.get_err() == [ StartUpdate.FAILED_TO_START_UPDATE_ERROR_MSG, "\t%s" % err_msg ] def test_update_cron_job_fails(self): mock_config = self.create_mock_config(is_cron=True) self._fake_context.get_job_config = Mock(return_value=mock_config) with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) def test_update_no_active_instance_check(self): self._mock_options.instance_spec = TaskInstanceKey( self.TEST_JOBKEY, [1]) self._mock_options.strict = True mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_api.start_job_update.return_value = self.create_simple_success_response( ) with patch( 'apache.aurora.client.cli.update.DiffFormatter') as formatter: formatter.return_value = self._formatter self._command.execute(self._fake_context) assert self._formatter.show_job_update_diff.mock_calls == [ call(self._mock_options.instance_spec.instance) ] assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance, ANY) ] def test_start_update_command_line_succeeds(self): resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey( role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, None) self._mock_options.message = 'hello' with patch( 'apache.aurora.client.cli.update.DiffFormatter') as formatter: formatter.return_value = self._formatter assert self._command.execute(self._fake_context) == EXIT_OK assert self._formatter.show_job_update_diff.mock_calls == [ call(self._mock_options.instance_spec.instance) ] assert self._mock_api.start_job_update.mock_calls == [ call(ANY, 'hello', None, ANY) ] assert self._fake_context.get_out() == [ StartUpdate.UPDATE_MSG_TEMPLATE % ('http://something_or_other/scheduler/role/env/name/update/id'), ] assert self._fake_context.get_err() == [] def test_start_update_and_wait_success(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.wait = True resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey( role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp self._mock_api.query_job_updates.side_effect = [ get_status_query_response(status=JobUpdateStatus.ROLLED_FORWARD) ] with patch( 'apache.aurora.client.cli.update.DiffFormatter') as formatter: formatter.return_value = self._formatter assert self._command.execute(self._fake_context) == EXIT_OK assert self._formatter.show_job_update_diff.mock_calls == [ call(self._mock_options.instance_spec.instance) ] assert self._mock_api.start_job_update.mock_calls == [ call(ANY, None, None, ANY) ] assert self._mock_api.query_job_updates.mock_calls == [ call(update_key=resp.result.startJobUpdateResult.key) ] assert self._fake_context.get_out() == [ StartUpdate.UPDATE_MSG_TEMPLATE % ('http://something_or_other/scheduler/role/env/name/update/id'), 'Current state ROLLED_FORWARD' ] assert self._fake_context.get_err() == [] def test_start_update_and_wait_rollback(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.wait = True resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey( role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp self._mock_api.query_job_updates.side_effect = [ get_status_query_response(status=JobUpdateStatus.ROLLED_BACK) ] with patch('apache.aurora.client.cli.update.DiffFormatter'): assert self._command.execute( self._fake_context) == EXIT_COMMAND_FAILURE def test_start_update_and_wait_error(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.wait = True resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey( role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp self._mock_api.query_job_updates.side_effect = [ get_status_query_response(status=JobUpdateStatus.ERROR) ] with patch('apache.aurora.client.cli.update.DiffFormatter'): assert self._command.execute( self._fake_context) == EXIT_UNKNOWN_ERROR def test_start_update_command_line_succeeds_noop_update(self): resp = self.create_simple_success_response() resp.details = [ResponseDetail(message="Noop update.")] self._mock_api.start_job_update.return_value = resp mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) with patch( 'apache.aurora.client.cli.update.DiffFormatter') as formatter: formatter.return_value = self._formatter assert self._command.execute(self._fake_context) == EXIT_OK assert self._formatter.show_job_update_diff.mock_calls == [ call(self._mock_options.instance_spec.instance) ] assert self._mock_api.start_job_update.mock_calls == [ call(ANY, None, None, ANY) ] assert self._fake_context.get_out() == ["Noop update."] assert self._fake_context.get_err() == [] def test_update_pulse_interval_too_small(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) error = Context.CommandError(100, 'something failed') self._mock_api.start_job_update.side_effect = error with patch('apache.aurora.client.cli.update.DiffFormatter'): with pytest.raises(Context.CommandError) as e: self._command.execute(self._fake_context) assert e.value == error assert self._mock_api.start_job_update.mock_calls == [ call(ANY, None, None, ANY) ]
class TestStartUpdate(AuroraClientCommandTest): def setUp(self): self._command = StartUpdate() self._job_key = AuroraJobKey.from_thrift("cluster", UPDATE_KEY.job) self._mock_options = mock_verb_options(self._command) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, None) self._mock_options.wait = False self._fake_context = FakeAuroraCommandContext() self._fake_context.set_options(self._mock_options) self._mock_api = self._fake_context.get_api('UNUSED') @classmethod def create_mock_config(cls, is_cron=False): # TODO(wfarner): Consider using a real AuroraConfig object for this. mock_config = create_autospec(spec=AuroraConfig, spec_set=True, instance=True) raw_config = Job(cron_schedule='something' if is_cron else Empty) mock_config.raw = Mock(return_value=raw_config) mock_config.cluster = Mock(return_value=cls.TEST_CLUSTER) return mock_config def test_start_update_with_lock(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_api.start_job_update.return_value = AuroraClientCommandTest.create_blank_response( ResponseCode.LOCK_ERROR, "Error.") with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance) ] self.assert_lock_message(self._fake_context) def test_update_cron_job_fails(self): mock_config = self.create_mock_config(is_cron=True) self._fake_context.get_job_config = Mock(return_value=mock_config) with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) def test_update_no_active_instance_check(self): self._mock_options.instance_spec = TaskInstanceKey( self.TEST_JOBKEY, [1]) self._mock_options.strict = True mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_api.start_job_update.return_value = self.create_simple_success_response( ) self._command.execute(self._fake_context) assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance) ] def test_start_update_command_line_succeeds(self): resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey( role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, None) self._mock_options.message = 'hello' assert self._command.execute(self._fake_context) == EXIT_OK assert self._mock_api.start_job_update.mock_calls == [ call(ANY, 'hello', None) ] assert self._fake_context.get_out() == [ StartUpdate.UPDATE_MSG_TEMPLATE % ('http://something_or_other/scheduler/role/env/name/update/id') ] assert self._fake_context.get_err() == [] def test_start_update_and_wait_success(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.wait = True resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey( role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp self._mock_api.query_job_updates.side_effect = [ get_status_query_response(status=JobUpdateStatus.ROLLED_FORWARD) ] assert self._command.execute(self._fake_context) == EXIT_OK assert self._mock_api.start_job_update.mock_calls == [ call(ANY, None, None) ] assert self._mock_api.query_job_updates.mock_calls == [ call(update_key=resp.result.startJobUpdateResult.key) ] assert self._fake_context.get_out() == [ StartUpdate.UPDATE_MSG_TEMPLATE % ('http://something_or_other/scheduler/role/env/name/update/id'), 'Current state ROLLED_FORWARD' ] assert self._fake_context.get_err() == [] def test_start_update_and_wait_rollback(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.wait = True resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey( role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp self._mock_api.query_job_updates.side_effect = [ get_status_query_response(status=JobUpdateStatus.ROLLED_BACK) ] assert self._command.execute( self._fake_context) == EXIT_COMMAND_FAILURE def test_start_update_and_wait_error(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.wait = True resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey( role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp self._mock_api.query_job_updates.side_effect = [ get_status_query_response(status=JobUpdateStatus.ERROR) ] assert self._command.execute(self._fake_context) == EXIT_UNKNOWN_ERROR def test_start_update_command_line_succeeds_noop_update(self): resp = self.create_simple_success_response() resp.details = [ResponseDetail(message="Noop update.")] self._mock_api.start_job_update.return_value = resp mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) result = self._command.execute(self._fake_context) assert result == EXIT_OK assert self._mock_api.start_job_update.mock_calls == [ call(ANY, None, None) ] assert self._fake_context.get_out() == ["Noop update."] assert self._fake_context.get_err() == [] def test_update_pulse_interval_too_small(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) error = Context.CommandError(100, 'something failed') self._mock_api.start_job_update.side_effect = error with pytest.raises(Context.CommandError) as e: self._command.execute(self._fake_context) assert e.value == error assert self._mock_api.start_job_update.mock_calls == [ call(ANY, None, None) ]
class TestStartUpdate(AuroraClientCommandTest): def setUp(self): self._command = StartUpdate() self._job_key = AuroraJobKey.from_thrift("cluster", UPDATE_KEY.job) self._mock_options = mock_verb_options(self._command) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, None) self._fake_context = FakeAuroraCommandContext() self._fake_context.set_options(self._mock_options) self._mock_api = self._fake_context.get_api('UNUSED') @classmethod def create_mock_config(cls, is_cron=False): mock_config = create_autospec(spec=AuroraConfig, spec_set=True, instance=True) raw_config = Job(cron_schedule='something' if is_cron else Empty) mock_config.raw = Mock(return_value=raw_config) mock_config.cluster = Mock(return_value=cls.TEST_CLUSTER) return mock_config def test_start_update_with_lock(self): mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_api.start_job_update.return_value = AuroraClientCommandTest.create_blank_response( ResponseCode.LOCK_ERROR, "Error.") with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance) ] self.assert_lock_message(self._fake_context) def test_update_cron_job_fails(self): mock_config = self.create_mock_config(is_cron=True) self._fake_context.get_job_config = Mock(return_value=mock_config) with pytest.raises(Context.CommandError): self._command.execute(self._fake_context) def test_update_no_active_instance_check(self): self._mock_options.instance_spec = TaskInstanceKey( self.TEST_JOBKEY, [1]) self._mock_options.strict = True mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_api.start_job_update.return_value = self.create_simple_success_response( ) self._command.execute(self._fake_context) assert self._mock_api.start_job_update.mock_calls == [ call(mock_config, None, self._mock_options.instance_spec.instance) ] def test_start_update_command_line_succeeds(self): resp = self.create_simple_success_response() resp.result = Result(startJobUpdateResult=StartJobUpdateResult( key=JobUpdateKey(job=JobKey( role="role", environment="env", name="name"), id="id"))) self._mock_api.start_job_update.return_value = resp mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) self._mock_options.instance_spec = TaskInstanceKey(self._job_key, None) self._mock_options.message = 'hello' assert self._command.execute(self._fake_context) == EXIT_OK update_url_msg = StartUpdate.UPDATE_MSG_TEMPLATE % ( 'http://something_or_other/scheduler/role/env/name/id') assert self._mock_api.start_job_update.mock_calls == [ call(ANY, 'hello', None) ] assert self._fake_context.get_out() == [update_url_msg] assert self._fake_context.get_err() == [] def test_start_update_command_line_succeeds_noop_update(self): resp = self.create_simple_success_response() resp.details = [ResponseDetail(message="Noop update.")] self._mock_api.start_job_update.return_value = resp mock_config = self.create_mock_config() self._fake_context.get_job_config = Mock(return_value=mock_config) result = self._command.execute(self._fake_context) assert result == EXIT_OK assert self._mock_api.start_job_update.mock_calls == [ call(ANY, None, None) ] assert self._fake_context.get_out() == ["Noop update."] assert self._fake_context.get_err() == []