Skip to content

Commit

Permalink
cli: prioritize --use-lxd over SNAPCRAFT_BUILD_ENVIRONMENT (#4329)
Browse files Browse the repository at this point in the history
Prioritize the command line argument `--use-lxd` over the
environment variable `SNAPCRAFT_BUILD_ENVIRONMENT=host`.

Signed-off-by: Callahan Kovacs <callahan.kovacs@canonical.com>
  • Loading branch information
mr-cal committed Aug 22, 2023
1 parent 4f13298 commit 7f8d4cf
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 11 deletions.
2 changes: 1 addition & 1 deletion snapcraft/parts/lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ def _run_command(
permanent=True,
)

if (
if parsed_args.use_lxd or (
not managed_mode
and not parsed_args.destructive_mode
and not os.getenv("SNAPCRAFT_BUILD_ENVIRONMENT") == "host"
Expand Down
29 changes: 29 additions & 0 deletions tests/spread/providers/use-lxd/task.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
summary: Test --use-lxd takes priority over environment variables
systems:
- ubuntu-22.04*

prepare: |
snapcraft init
restore: |
rm -rf ./*.snap
execute: |
export SNAPCRAFT_BUILD_ENVIRONMENT="host"
snapcraft pull --use-lxd
if [[ -d parts ]]; then
echo "snapcraft did not run inside a lxd instance"
exit 1
fi
unset SNAPCRAFT_BUILD_ENVIRONMENT
export SNAPCRAFT_MANAGED_MODE=1
snapcraft pull --use-lxd
if [[ -d parts ]]; then
echo "snapcraft did not run inside a lxd instance"
exit 1
fi
152 changes: 142 additions & 10 deletions tests/unit/parts/test_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,11 +306,33 @@ def test_lifecycle_run_command_step(
assert run_mock.mock_calls == [call(step, **call_args)]


@pytest.mark.parametrize("managed_mode", [True, False])
@pytest.mark.parametrize("build_env", [None, "host", "multipass", "lxd", "other"])
@pytest.mark.parametrize("cmd", ["pack", "snap"])
def test_lifecycle_run_command_pack(cmd, snapcraft_yaml, project_vars, new_dir, mocker):
def test_lifecycle_run_local_destructive_mode(
managed_mode,
build_env,
cmd,
snapcraft_yaml,
project_vars,
new_dir,
mocker,
monkeypatch,
):
"""Run the lifecycle locally when destructive_mode is True."""
project = Project.unmarshal(snapcraft_yaml(base="core22"))
run_in_provider_mock = mocker.patch("snapcraft.parts.lifecycle._run_in_provider")
run_mock = mocker.patch("snapcraft.parts.PartsLifecycle.run")
pack_mock = mocker.patch("snapcraft.pack.pack_snap")
mocker.patch("snapcraft.utils.is_managed_mode", return_value=managed_mode)
mocker.patch(
"snapcraft.utils.get_managed_environment_home_path",
return_value=new_dir / "home",
)
if build_env:
monkeypatch.setenv("SNAPCRAFT_BUILD_ENVIRONMENT", build_env)
else:
monkeypatch.delenv("SNAPCRAFT_BUILD_ENVIRONMENT", raising=False)

parts_lifecycle._run_command(
cmd,
Expand All @@ -333,10 +355,11 @@ def test_lifecycle_run_command_pack(cmd, snapcraft_yaml, project_vars, new_dir,
),
)

assert run_in_provider_mock.mock_calls == []
assert run_mock.mock_calls == [call("prime", shell=False, shell_after=False)]
assert pack_mock.mock_calls[:1] == [
call(
new_dir / "prime",
new_dir / "home/prime" if managed_mode else new_dir / "prime",
output=None,
compression="xz",
name="mytest",
Expand All @@ -346,10 +369,20 @@ def test_lifecycle_run_command_pack(cmd, snapcraft_yaml, project_vars, new_dir,
]


@pytest.mark.parametrize("destructive_mode", [True, False])
@pytest.mark.parametrize("build_env", [None, "host", "multipass", "lxd", "other"])
@pytest.mark.parametrize("cmd", ["pack", "snap"])
def test_lifecycle_pack_destructive_mode(
cmd, snapcraft_yaml, project_vars, new_dir, mocker
def test_lifecycle_run_local_managed_mode(
destructive_mode,
build_env,
cmd,
snapcraft_yaml,
project_vars,
new_dir,
mocker,
monkeypatch,
):
"""Run the lifecycle locally when managed_mode is True."""
project = Project.unmarshal(snapcraft_yaml(base="core22"))
run_in_provider_mock = mocker.patch("snapcraft.parts.lifecycle._run_in_provider")
run_mock = mocker.patch("snapcraft.parts.PartsLifecycle.run")
Expand All @@ -359,6 +392,10 @@ def test_lifecycle_pack_destructive_mode(
"snapcraft.utils.get_managed_environment_home_path",
return_value=new_dir / "home",
)
if build_env:
monkeypatch.setenv("SNAPCRAFT_BUILD_ENVIRONMENT", build_env)
else:
monkeypatch.delenv("SNAPCRAFT_BUILD_ENVIRONMENT", raising=False)

parts_lifecycle._run_command(
cmd,
Expand All @@ -372,7 +409,7 @@ def test_lifecycle_pack_destructive_mode(
output=None,
debug=False,
enable_manifest=False,
destructive_mode=True,
destructive_mode=destructive_mode,
shell=False,
shell_after=False,
use_lxd=False,
Expand All @@ -395,17 +432,30 @@ def test_lifecycle_pack_destructive_mode(
]


@pytest.mark.parametrize("managed_mode", [True, False])
@pytest.mark.parametrize("destructive_mode", [True, False])
@pytest.mark.parametrize("cmd", ["pack", "snap"])
def test_lifecycle_pack_managed(cmd, snapcraft_yaml, project_vars, new_dir, mocker):
def test_lifecycle_run_local_build_env(
managed_mode,
destructive_mode,
cmd,
monkeypatch,
snapcraft_yaml,
project_vars,
new_dir,
mocker,
):
"""Run the lifecycle locally when the build environment is 'host'."""
project = Project.unmarshal(snapcraft_yaml(base="core22"))
run_in_provider_mock = mocker.patch("snapcraft.parts.lifecycle._run_in_provider")
run_mock = mocker.patch("snapcraft.parts.PartsLifecycle.run")
pack_mock = mocker.patch("snapcraft.pack.pack_snap")
mocker.patch("snapcraft.utils.is_managed_mode", return_value=True)
mocker.patch("snapcraft.utils.is_managed_mode", return_value=managed_mode)
mocker.patch(
"snapcraft.utils.get_managed_environment_home_path",
return_value=new_dir / "home",
)
monkeypatch.setenv("SNAPCRAFT_BUILD_ENVIRONMENT", "host")

parts_lifecycle._run_command(
cmd,
Expand All @@ -422,7 +472,7 @@ def test_lifecycle_pack_managed(cmd, snapcraft_yaml, project_vars, new_dir, mock
build_for=None,
enable_manifest=False,
manifest_image_information=None,
destructive_mode=False,
destructive_mode=destructive_mode,
shell=False,
shell_after=False,
use_lxd=False,
Expand All @@ -435,7 +485,7 @@ def test_lifecycle_pack_managed(cmd, snapcraft_yaml, project_vars, new_dir, mock
assert run_mock.mock_calls == [call("prime", shell=False, shell_after=False)]
assert pack_mock.mock_calls[:1] == [
call(
new_dir / "home/prime",
new_dir / "home/prime" if managed_mode else new_dir / "prime",
output=None,
compression="xz",
name="mytest",
Expand All @@ -445,12 +495,21 @@ def test_lifecycle_pack_managed(cmd, snapcraft_yaml, project_vars, new_dir, mock
]


@pytest.mark.parametrize("build_env", [None, "lxd", "multipass", "other"])
@pytest.mark.parametrize("cmd", ["pack", "snap"])
def test_lifecycle_pack_not_managed(cmd, snapcraft_yaml, new_dir, mocker):
def test_lifecycle_run_in_provider_by_default(
build_env, cmd, snapcraft_yaml, new_dir, mocker, monkeypatch
):
"""Run lifecycle in a provider when not in managed_mode, not in destructive_mode,
and the build environment is not 'host'."""
project = Project.unmarshal(snapcraft_yaml(base="core22"))
run_in_provider_mock = mocker.patch("snapcraft.parts.lifecycle._run_in_provider")
run_mock = mocker.patch("snapcraft.parts.PartsLifecycle.run")
mocker.patch("snapcraft.utils.is_managed_mode", return_value=False)
if build_env:
monkeypatch.setenv("SNAPCRAFT_BUILD_ENVIRONMENT", build_env)
else:
monkeypatch.delenv("SNAPCRAFT_BUILD_ENVIRONMENT", raising=False)

parts_lifecycle._run_command(
cmd,
Expand Down Expand Up @@ -484,6 +543,78 @@ def test_lifecycle_pack_not_managed(cmd, snapcraft_yaml, new_dir, mocker):
]


@pytest.mark.parametrize("managed_mode", [True, False])
@pytest.mark.parametrize("destructive_mode", [True, False])
@pytest.mark.parametrize("build_env", [None, "host", "lxd", "multipass", "other"])
@pytest.mark.parametrize("cmd", ["pack", "snap"])
def test_lifecycle_run_in_provider_use_lxd(
managed_mode,
destructive_mode,
build_env,
cmd,
mocker,
monkeypatch,
new_dir,
project_vars,
snapcraft_yaml,
):
"""Run the lifecycle in a provider when `use_lxd` is true."""
project = Project.unmarshal(snapcraft_yaml(base="core22"))
run_in_provider_mock = mocker.patch("snapcraft.parts.lifecycle._run_in_provider")
run_mock = mocker.patch("snapcraft.parts.PartsLifecycle.run")
mocker.patch("snapcraft.pack.pack_snap")
mocker.patch(
"snapcraft.utils.get_managed_environment_home_path",
return_value=new_dir / "home",
)
mocker.patch("snapcraft.utils.is_managed_mode", return_value=managed_mode)
if build_env:
monkeypatch.setenv("SNAPCRAFT_BUILD_ENVIRONMENT", build_env)
else:
monkeypatch.delenv("SNAPCRAFT_BUILD_ENVIRONMENT", raising=False)

parts_lifecycle._run_command(
cmd,
project=project,
parse_info={},
assets_dir=Path(),
start_time=datetime.now(),
parallel_build_count=8,
parsed_args=argparse.Namespace(
directory=None,
output=None,
debug=False,
enable_manifest=False,
destructive_mode=destructive_mode,
shell=False,
shell_after=False,
use_lxd=True,
ua_token=None,
parts=[],
),
)

assert run_mock.mock_calls == []
assert run_in_provider_mock.mock_calls == [
call(
project,
cmd,
argparse.Namespace(
directory=None,
output=None,
debug=False,
enable_manifest=False,
destructive_mode=destructive_mode,
shell=False,
shell_after=False,
use_lxd=True,
ua_token=None,
parts=[],
),
)
]


@pytest.mark.parametrize("cmd", ["pack", "snap"])
def test_lifecycle_pack_metadata_error(cmd, snapcraft_yaml, new_dir, mocker):
project = Project.unmarshal(snapcraft_yaml(base="core22"))
Expand Down Expand Up @@ -1703,6 +1834,7 @@ def test_lifecycle_write_metadata(
parsed_args = argparse.Namespace(
debug=False,
destructive_mode=True,
use_lxd=False,
enable_manifest=True,
ua_token=None,
parts=[],
Expand Down

0 comments on commit 7f8d4cf

Please sign in to comment.