def test_ensure_provider_is_available_errors_when_lxd_install_fails( mock_confirm_with_user, mock_lxd_is_installed, mock_lxd_install): error = LXDInstallationError("foo") mock_confirm_with_user.return_value = True mock_lxd_is_installed.return_value = False mock_lxd_install.side_effect = error provider = providers.LXDProvider() with pytest.raises( CraftError, match=re.escape( "Failed to install LXD. Visit https://snapcraft.io/lxd for " "instructions on how to install the LXD snap for your distribution" ), ) as exc_info: provider.ensure_provider_is_available() assert mock_confirm_with_user.mock_calls == [ mock.call( "LXD is required, but not installed. " "Do you wish to install LXD and configure it with the defaults?", default=False, ) ] assert exc_info.value.__cause__ is error
def test_launched_environment( channel, alias, mock_buildd_base_configuration, mock_configure_buildd_image_remote, mock_lxd_launch, monkeypatch, tmp_path, mock_path, ): expected_environment = { "CHARMCRAFT_MANAGED_MODE": "1", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin", } base = Base(name="ubuntu", channel=channel, architectures=["host-arch"]) provider = providers.LXDProvider() with provider.launched_environment( charm_name="test-charm", project_path=mock_path, base=base, bases_index=1, build_on_index=2, ) as instance: assert instance is not None assert mock_configure_buildd_image_remote.mock_calls == [mock.call()] assert mock_lxd_launch.mock_calls == [ mock.call( name="charmcraft-test-charm-445566-1-2-host-arch", base_configuration=mock_buildd_base_configuration.return_value, image_name=channel, image_remote="buildd-remote", auto_clean=True, auto_create_project=True, map_user_uid=True, use_snapshots=True, project="charmcraft", remote="local", ), mock.call().mount(host_source=mock_path, target=pathlib.Path("/root/project")), ] assert mock_buildd_base_configuration.mock_calls == [ call( alias=alias, environment=expected_environment, hostname="charmcraft-test-charm-445566-1-2-host-arch", ) ] mock_lxd_launch.reset_mock() assert mock_lxd_launch.mock_calls == [ mock.call().unmount_all(), mock.call().stop(), ]
def test_is_base_available(mock_get_host_architecture, name, channel, architectures, expected_valid, expected_reason): base = Base(name=name, channel=channel, architectures=architectures) provider = providers.LXDProvider() valid, reason = provider.is_base_available(base) assert (valid, reason) == (expected_valid, expected_reason)
def test_clean_project_environments_list_failure(mock_lxc, mock_path): mock_lxc.list_names.side_effect = LXDError(brief="fail") provider = providers.LXDProvider(lxc=mock_lxc) with pytest.raises(CraftError, match="fail"): provider.clean_project_environments( charm_name="charm", project_path=mock_path, )
def test_get_instance_name(bases_index, build_on_index, project_name, target_arch, expected, mock_path): provider = providers.LXDProvider() assert provider.get_instance_name( bases_index=bases_index, build_on_index=build_on_index, project_name=project_name, project_path=mock_path, target_arch=target_arch, ) == expected.format(inode="445566")
def test_get_command_environment_minimal(monkeypatch): monkeypatch.setenv("IGNORE_ME", "or-im-failing") monkeypatch.setenv("PATH", "not-using-host-path") provider = providers.LXDProvider() env = provider.get_command_environment() assert env == { "CHARMCRAFT_MANAGED_MODE": "1", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin", }
def test_clean_project_environments_delete_failure(mock_lxc, mock_path): error = LXDError("fail") mock_lxc.list_names.return_value = ["charmcraft-testcharm-445566-b-c-d"] mock_lxc.delete.side_effect = error provider = providers.LXDProvider(lxc=mock_lxc) with pytest.raises(CraftError, match="fail") as exc_info: provider.clean_project_environments( charm_name="testcharm", project_path=mock_path, ) assert exc_info.value.__cause__ is error
def test_clean_project_environments_without_lxd(mock_lxc, mock_lxd_is_installed, mock_path): mock_lxd_is_installed.return_value = False provider = providers.LXDProvider(lxc=mock_lxc, lxd_project="test-project", lxd_remote="test-remote") assert (provider.clean_project_environments( charm_name="my-charm", project_path=mock_path, ) == []) assert mock_lxd_is_installed.mock_calls == [mock.call()] assert mock_lxc.mock_calls == []
def test_get_command_environment_all_opts(monkeypatch): monkeypatch.setenv("IGNORE_ME", "or-im-failing") monkeypatch.setenv("PATH", "not-using-host-path") monkeypatch.setenv("http_proxy", "test-http-proxy") monkeypatch.setenv("https_proxy", "test-https-proxy") monkeypatch.setenv("no_proxy", "test-no-proxy") provider = providers.LXDProvider() env = provider.get_command_environment() assert env == { "CHARMCRAFT_MANAGED_MODE": "1", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin", "http_proxy": "test-http-proxy", "https_proxy": "test-https-proxy", "no_proxy": "test-no-proxy", }
def test_ensure_provider_is_available_errors_when_lxd_not_ready( mock_confirm_with_user, mock_lxd_is_installed, mock_lxd_install, mock_lxd_ensure_lxd_is_ready): error = LXDError(brief="some error", details="some details", resolution="some resolution") mock_confirm_with_user.return_value = True mock_lxd_is_installed.return_value = True mock_lxd_ensure_lxd_is_ready.side_effect = error provider = providers.LXDProvider() with pytest.raises( CraftError, match=re.escape("some error\nsome details\nsome resolution"), ) as exc_info: provider.ensure_provider_is_available() assert exc_info.value.__cause__ is error
def test_launched_environment_stop_error(mock_buildd_base_configuration, mock_configure_buildd_image_remote, mock_lxd_launch, tmp_path): error = LXDError(brief="fail") mock_lxd_launch.return_value.stop.side_effect = error base = Base(name="ubuntu", channel="20.04", architectures=["host-arch"]) provider = providers.LXDProvider() with pytest.raises(CraftError, match="fail") as exc_info: with provider.launched_environment( charm_name="test-charm", project_path=tmp_path, base=base, bases_index=1, build_on_index=2, ): pass assert exc_info.value.__cause__ is error
def test_launched_environment_unmounts_and_stops_after_error( mock_buildd_base_configuration, mock_configure_buildd_image_remote, mock_lxd_launch, tmp_path): base = Base(name="ubuntu", channel="20.04", architectures=["host-arch"]) provider = providers.LXDProvider() with pytest.raises(RuntimeError): with provider.launched_environment( charm_name="test-charm", project_path=tmp_path, base=base, bases_index=1, build_on_index=2, ): mock_lxd_launch.reset_mock() raise RuntimeError("this is a test") assert mock_lxd_launch.mock_calls == [ mock.call().unmount_all(), mock.call().stop(), ]
def test_ensure_provider_is_available_errors_when_user_declines( mock_confirm_with_user, mock_lxd_is_installed): mock_confirm_with_user.return_value = False mock_lxd_is_installed.return_value = False provider = providers.LXDProvider() with pytest.raises( CraftError, match=re.escape( "LXD is required, but not installed. Visit https://snapcraft.io/lxd for " "instructions on how to install the LXD snap for your distribution" ), ): provider.ensure_provider_is_available() assert mock_confirm_with_user.mock_calls == [ mock.call( "LXD is required, but not installed. " "Do you wish to install LXD and configure it with the defaults?", default=False, ) ]
def test_is_provider_available(is_installed, mock_lxd_is_installed): mock_lxd_is_installed.return_value = is_installed provider = providers.LXDProvider() assert provider.is_provider_available() == is_installed
def test_ensure_provider_is_available_ok_when_installed(mock_lxd_is_installed): mock_lxd_is_installed.return_value = True provider = providers.LXDProvider() provider.ensure_provider_is_available()
def test_clean_project_environments(mock_lxc, mock_path): mock_lxc.list_names.return_value = [ "do-not-delete-me-please", "charmcraft-testcharm-445566-b-c-d", "charmcraft-my-charm---", "charmcraft-my-charm-445566---", "charmcraft-my-charm-project-445566-0-0-amd99", "charmcraft-my-charm-project-445566-999-444-arm64", "charmcraft_445566_a_b_c_d", ] provider = providers.LXDProvider(lxc=mock_lxc, lxd_project="test-project", lxd_remote="test-remote") assert provider.clean_project_environments( charm_name="my-charm-project", project_path=mock_path, ) == [ "charmcraft-my-charm-project-445566-0-0-amd99", "charmcraft-my-charm-project-445566-999-444-arm64", ] assert mock_lxc.mock_calls == [ mock.call.list_names(project="test-project", remote="test-remote"), mock.call.delete( instance_name="charmcraft-my-charm-project-445566-0-0-amd99", force=True, project="test-project", remote="test-remote", ), mock.call.delete( instance_name="charmcraft-my-charm-project-445566-999-444-arm64", force=True, project="test-project", remote="test-remote", ), ] mock_lxc.reset_mock() assert provider.clean_project_environments( charm_name="testcharm", project_path=mock_path, ) == [ "charmcraft-testcharm-445566-b-c-d", ] assert mock_lxc.mock_calls == [ mock.call.list_names(project="test-project", remote="test-remote"), mock.call.delete( instance_name="charmcraft-testcharm-445566-b-c-d", force=True, project="test-project", remote="test-remote", ), ] mock_lxc.reset_mock() assert (provider.clean_project_environments( charm_name="unknown-charm", project_path=mock_path, ) == []) assert mock_lxc.mock_calls == [ mock.call.list_names(project="test-project", remote="test-remote"), ]