def test_already_attached(self, _m_getuid, FakeConfig): """Check that an attached machine raises AlreadyAttachedError.""" account_name = "test_account" cfg = FakeConfig.for_attached_machine(account_name=account_name) with pytest.raises(AlreadyAttachedError): action_auto_attach(mock.MagicMock(), cfg)
def test_non_root_users_are_rejected(getuid, FakeConfig): """Check that a UID != 0 will receive a message and exit non-zero""" getuid.return_value = 1 cfg = FakeConfig() with pytest.raises(NonRootUserError): action_auto_attach(mock.MagicMock(), cfg=cfg)
def test_delta_in_instance_id_forces_detach( self, _m_cloud_instance_factory, m_get_instance_id, _m_auto_attach, _m_post_cli_attach, _m_getuid, iid_response, calls_detach, FakeConfig, ): """When instance-id changes since last attach, call detach.""" m_get_instance_id.return_value = iid_response cfg = FakeConfig.for_attached_machine() # persist old instance-id value cfg.write_cache("instance-id", "old-iid") if calls_detach: with mock.patch(M_PATH + "_detach") as m_detach: m_detach.return_value = 0 action_auto_attach(mock.MagicMock(), cfg=cfg) assert [mock.call(cfg, assume_yes=True)] == m_detach.call_args_list else: with pytest.raises(AlreadyAttachedOnPROError): action_auto_attach(mock.MagicMock(), cfg=cfg)
def test_lock_file_exists(self, m_subp, _getuid, FakeConfig): """Check inability to auto-attach if operation holds lock file.""" cfg = FakeConfig() cfg.write_cache("lock", "123:ua disable") with pytest.raises(LockHeldError) as err: action_auto_attach(mock.MagicMock(), cfg=cfg) assert [mock.call(["ps", "123"])] == m_subp.call_args_list assert ("Unable to perform: ua auto-attach.\n" "Operation in progress: ua disable (pid:123)") == err.value.msg
def test_already_attached_on_non_ubuntu_pro(self, m_cloud_instance_factory, _m_getuid, FakeConfig): """An attached machine raises AlreadyAttachedError on non-PRO.""" # Non-PRO raises UserFacingError on non-PRO image m_cloud_instance_factory.side_effect = UserFacingError("Not-a-PRO") account_name = "test_account" cfg = FakeConfig.for_attached_machine(account_name=account_name) with pytest.raises(AlreadyAttachedError): action_auto_attach(mock.MagicMock(), cfg)
def test_happy_path_on_aws_non_auto_attach( self, get_contract_token_from_cloud_identity, request_updated_contract, _m_getuid, ): """Noop when _get_contract_token_from_cloud_identity finds no token""" exc = NonAutoAttachImageError("msg") get_contract_token_from_cloud_identity.side_effect = exc with pytest.raises(NonAutoAttachImageError): action_auto_attach(mock.MagicMock(), FakeConfig()) assert 0 == request_updated_contract.call_count
def test_disable_auto_attach_config( self, m_get_instance_id, m_cloud_instance_factory, m_auto_attach, m_post_cli_attach, _m_getuid, features_override, FakeConfig, ): cfg = FakeConfig() if features_override: cfg.override_features(features_override) ret = action_auto_attach(mock.MagicMock(), cfg=cfg) assert 0 == ret if features_override: assert [] == m_cloud_instance_factory.call_args_list assert [] == m_get_instance_id.call_args_list assert [] == m_auto_attach.call_args_list assert [] == m_post_cli_attach.call_args_list else: assert [mock.call()] == m_cloud_instance_factory.call_args_list assert [mock.call()] == m_get_instance_id.call_args_list assert [mock.call(mock.ANY, mock.ANY)] == m_auto_attach.call_args_list assert [mock.call(mock.ANY)] == m_post_cli_attach.call_args_list
def test_happy_path_on_aws_auto_attach( self, action_status, get_contract_token_from_cloud_identity, request_updated_contract, _m_getuid, features_override, FakeConfig, ): """A mock-heavy test for the happy path on auto attach AWS""" # TODO: Improve this test with less general mocking and more # post-conditions cfg = FakeConfig() if features_override: cfg.override_features(features_override) expected_calls = [] else: expected_calls = [ mock.call(cfg, "myPKCS7-token", allow_enable=True) ] get_contract_token_from_cloud_identity.return_value = "myPKCS7-token" def fake_request_updated_contract(cfg, contract_token, allow_enable): cfg.write_cache("machine-token", BASIC_MACHINE_TOKEN) return BASIC_MACHINE_TOKEN request_updated_contract.side_effect = fake_request_updated_contract ret = action_auto_attach(mock.MagicMock(), cfg) assert 0 == ret assert expected_calls == request_updated_contract.call_args_list
def test_failed_detach_on_changed_instance_id_raises_errors( self, _m_cloud_instance_factory, m_get_instance_id, m_detach, _m_getuid, FakeConfig, ): """When instance-id changes since last attach, call detach.""" m_get_instance_id.return_value = "new-iid" m_detach.return_value = 1 # Failure to auto-detach cfg = FakeConfig.for_attached_machine() # persist old instance-id value cfg.write_cache("instance-id", "old-iid") with pytest.raises(UserFacingError) as err: action_auto_attach(mock.MagicMock(), cfg=cfg) assert messages.DETACH_AUTOMATION_FAILURE == str(err.value)
def test_numeric_iid_does_not_trigger_auto_attach( self, _m_cloud_instance_factory, m_get_instance_id, _m_getuid, iid_curr, iid_old, FakeConfig, ): """Treat numeric and string values for instance ID as the same.""" m_get_instance_id.return_value = iid_curr cfg = FakeConfig.for_attached_machine() # persist old instance-id value cfg.write_cache("instance-id", iid_old) with pytest.raises(AlreadyAttachedOnPROError): action_auto_attach(mock.MagicMock(), cfg=cfg) assert str(iid_curr) == str(cfg.read_cache("instance-id"))
def test_handle_cloud_factory_errors( self, m_cloud_instance_factory, _m_getuid, cloud_factory_error, is_attached, expected_error_cls, expected_error_msg, FakeConfig, ): """Non-supported clouds will error.""" m_cloud_instance_factory.side_effect = cloud_factory_error if is_attached: cfg = FakeConfig.for_attached_machine() else: cfg = FakeConfig() with pytest.raises(expected_error_cls) as excinfo: action_auto_attach(mock.MagicMock(), cfg=cfg) if expected_error_msg: assert expected_error_msg == str(excinfo.value)