def test_no_bases_defaults_to_ubuntu_20_04_with_dn03(caplog, create_config, tmp_path): caplog.set_level(logging.WARNING, logger="charmcraft") create_config(""" type: charm """) config = load(tmp_path) assert config.bases == [ BasesConfiguration( **{ "build-on": [Base(name="ubuntu", channel="20.04")], "run-on": [Base(name="ubuntu", channel="20.04")], }) ] assert "DEPRECATED: Bases configuration is now required." in [ rec.message for rec in caplog.records ]
def test_launched_environment( channel, alias, mock_buildd_base_configuration, mock_multipass_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.MultipassProvider() 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_multipass_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, cpus=2, disk_gb=64, mem_gb=2, auto_clean=True, ), 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_multipass_launch.reset_mock() assert mock_multipass_launch.mock_calls == [ mock.call().unmount_all(), mock.call().stop(), ]
def test_check_if_bases_matches_host_arch_mismatch(mock_get_os_platform, mock_get_host_architecture): base = Base( name="host-os", channel="host-CHANNEL", architectures=["other-ARCH", "other-ARCH2"], ) assert check_if_base_matches_host(base) == ( False, "host architecture 'host-ARCH' not in base architectures ['other-ARCH', 'other-ARCH2']", )
def get_host_as_base() -> Base: """Get host OS represented as Base. The host OS name is translated to lower-case for consistency. :returns: Base configuration matching host. """ os_platform = get_os_platform() host_arch = get_host_architecture() name = os_platform.system.lower() channel = os_platform.release return Base(name=name, channel=channel, architectures=[host_arch])
def test_launched_environment_stop_error(mock_buildd_base_configuration, mock_multipass_launch, tmp_path): error = MultipassError(brief="fail") mock_multipass_launch.return_value.stop.side_effect = error base = Base(name="ubuntu", channel="20.04", architectures=["host-arch"]) provider = providers.MultipassProvider() with pytest.raises(CommandError, 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_unmount_all_error( mock_buildd_base_configuration, mock_configure_buildd_image_remote, mock_lxd_launch, tmp_path): error = LXDError(brief="fail") mock_lxd_launch.return_value.unmount_all.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_multipass_launch, tmp_path): base = Base(name="ubuntu", channel="20.04", architectures=["host-arch"]) provider = providers.MultipassProvider() 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_multipass_launch.reset_mock() raise RuntimeError("this is a test") assert mock_multipass_launch.mock_calls == [ mock.call().unmount_all(), mock.call().stop(), ]
def test_complex_long_form_bases(create_config): tmp_path = create_config(""" type: charm bases: - build-on: - name: test-build-name-1 channel: test-build-channel-1 - name: test-build-name-2 channel: test-build-channel-2 - name: test-build-name-3 channel: test-build-channel-3 architectures: [riscVI] run-on: - name: test-run-name-1 channel: test-run-channel-1 architectures: [amd64] - name: test-run-name-2 channel: test-run-channel-2 architectures: [amd64, arm64] - name: test-run-name-3 channel: test-run-channel-3 architectures: [amd64, arm64, riscVI] """) config = load(tmp_path) assert config.bases == [ BasesConfiguration( **{ "build-on": [ Base( name="test-build-name-1", channel="test-build-channel-1", architectures=[get_host_architecture()], ), Base( name="test-build-name-2", channel="test-build-channel-2", architectures=[get_host_architecture()], ), Base( name="test-build-name-3", channel="test-build-channel-3", architectures=["riscVI"], ), ], "run-on": [ Base( name="test-run-name-1", channel="test-run-channel-1", architectures=["amd64"], ), Base( name="test-run-name-2", channel="test-run-channel-2", architectures=["amd64", "arm64"], ), Base( name="test-run-name-3", channel="test-run-channel-3", architectures=["amd64", "arm64", "riscVI"], ), ], }) ]
def test_launched_environment( channel, alias, mock_configure_buildd_image_remote, mock_lxd, 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", } monkeypatch.setattr(providers, "get_host_architecture", lambda: "host-arch") base = Base(name="ubuntu", channel=channel, architectures=["host-arch"]) with mock.patch("charmcraft.providers.CharmcraftBuilddBaseConfiguration" ) as mock_base_config: with providers.launched_environment( charm_name="test-charm", project_path=mock_path, base=base, bases_index=1, build_on_index=2, lxd_project="charmcraft", lxd_remote="local", ) as instance: assert instance is not None assert mock_configure_buildd_image_remote.mock_calls == [ mock.call() ] assert mock_lxd.mock_calls == [ mock.call.launch( name="charmcraft-test-charm-445566-1-2-host-arch", base_configuration=mock_base_config.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.launch().mount(host_source=mock_path, target=pathlib.Path("/root/project")), ] assert mock_base_config.mock_calls == [ call( alias=alias, environment=expected_environment, hostname="charmcraft-test-charm-445566-1-2-host-arch", ) ] mock_lxd.reset_mock() assert mock_lxd.mock_calls == [ mock.call.launch().unmount_all(), mock.call.launch().stop(), ]
def test_get_host_as_base(mock_get_os_platform, mock_get_host_architecture): assert get_host_as_base() == Base( name="host-os", channel="host-CHANNEL", architectures=["host-ARCH"], )