Beispiel #1
0
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
Beispiel #2
0
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(),
    ]
Beispiel #3
0
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)
Beispiel #4
0
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,
        )
Beispiel #5
0
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")
Beispiel #6
0
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",
    }
Beispiel #7
0
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
Beispiel #8
0
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 == []
Beispiel #9
0
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",
    }
Beispiel #10
0
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
Beispiel #11
0
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
Beispiel #12
0
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(),
    ]
Beispiel #13
0
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,
        )
    ]
Beispiel #14
0
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
Beispiel #15
0
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()
Beispiel #16
0
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"),
    ]