-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(pebble): place pebble in a separate location (#528)
The context here is that starting from Ubuntu 24.04, the 'base-files' package (and related chisel slices) provides "bin" as a symlink to "usr/bin". This breaks the previous "phantom" pebble part because it created "bin" as a regular directory which then conflicts with the symlink. Moving forward, the pebble binary is now placed in ".rock/bin/". This way we won't get further collisions and this reflects the fact that the location of the binary is, and should be seen, as an implementation detail.
- Loading branch information
Showing
11 changed files
with
138 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- | ||
# | ||
# Copyright 2024 Canonical Ltd. | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License version 3 as | ||
# published by the Free Software Foundation. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
"""Project-wide constants.""" | ||
|
||
# Rock control data location | ||
ROCK_CONTROL_DIR = ".rock" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,7 @@ | |
|
||
from rockcraft import errors, layers | ||
from rockcraft.architectures import SUPPORTED_ARCHS | ||
from rockcraft.constants import ROCK_CONTROL_DIR | ||
from rockcraft.pebble import Pebble | ||
from rockcraft.utils import get_snap_command_path | ||
|
||
|
@@ -357,9 +358,7 @@ def set_entrypoint(self, entrypoint_service: str | None, build_base: str) -> Non | |
"""Set the OCI image entrypoint. It is always Pebble.""" | ||
emit.progress("Configuring entrypoint...") | ||
image_path = self.path / self.image_name | ||
entrypoint = [f"/{Pebble.PEBBLE_BINARY_PATH}", "enter"] | ||
if build_base in ["[email protected]", "[email protected]"]: | ||
entrypoint.append("--verbose") | ||
entrypoint = Pebble.get_entrypoint(build_base) | ||
if entrypoint_service: | ||
entrypoint.extend(["--args", entrypoint_service]) | ||
params = ["--clear=config.entrypoint"] | ||
|
@@ -463,7 +462,7 @@ def set_control_data(self, metadata: dict[str, Any]) -> None: | |
local_control_data_path = Path(tempfile.mkdtemp()) | ||
|
||
# the rock control data structure starts with the folder ".rock" | ||
control_data_rock_folder = local_control_data_path / ".rock" | ||
control_data_rock_folder = local_control_data_path / ROCK_CONTROL_DIR | ||
control_data_rock_folder.mkdir() | ||
|
||
rock_metadata_file = control_data_rock_folder / "metadata.yaml" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,8 @@ | |
from craft_application.errors import CraftValidationError | ||
from craft_cli import emit | ||
|
||
from rockcraft.constants import ROCK_CONTROL_DIR | ||
|
||
|
||
def _alias_generator(name: str) -> str: | ||
"""Convert underscores to dashes in aliases.""" | ||
|
@@ -166,18 +168,28 @@ class Pebble: | |
|
||
PEBBLE_PATH = "var/lib/pebble/default" | ||
PEBBLE_LAYERS_PATH = f"{PEBBLE_PATH}/layers" | ||
PEBBLE_BINARY_PATH = "bin/pebble" | ||
PEBBLE_PART_SPEC = { | ||
PEBBLE_BINARY_DIR = f"{ROCK_CONTROL_DIR}/bin" | ||
PEBBLE_BINARY_PATH = f"{PEBBLE_BINARY_DIR}/pebble" | ||
PEBBLE_BINARY_PATH_PREVIOUS = "bin/pebble" | ||
_BASE_PART_SPEC = { | ||
"plugin": "nil", | ||
"stage-snaps": ["pebble/latest/stable"], | ||
"stage": [PEBBLE_BINARY_PATH], | ||
# We need this because "services" is Optional, but the directory must exist | ||
"override-prime": str( | ||
"craftctl default\n" | ||
f"mkdir -p {PEBBLE_LAYERS_PATH}\n" | ||
f"chmod 777 {PEBBLE_PATH}" | ||
), | ||
} | ||
PEBBLE_PART_SPEC = { | ||
**_BASE_PART_SPEC, | ||
"organize": {"bin": PEBBLE_BINARY_DIR}, | ||
"stage": [PEBBLE_BINARY_PATH], | ||
} | ||
PEBBLE_PART_SPEC_PREVIOUS = { | ||
**_BASE_PART_SPEC, | ||
"stage": [PEBBLE_BINARY_PATH_PREVIOUS], | ||
} | ||
|
||
def define_pebble_layer( | ||
self, | ||
|
@@ -229,3 +241,34 @@ def define_pebble_layer( | |
) | ||
|
||
tmp_new_layer.chmod(0o777) | ||
|
||
@staticmethod | ||
def get_part_spec(build_base: str) -> dict[str, Any]: | ||
"""Get the part providing the pebble binary for a given build base.""" | ||
part_spec: dict[str, Any] = Pebble.PEBBLE_PART_SPEC | ||
|
||
if Pebble._is_focal_or_jammy(build_base): | ||
part_spec = Pebble.PEBBLE_PART_SPEC_PREVIOUS | ||
|
||
return part_spec | ||
|
||
@staticmethod | ||
def get_entrypoint(build_base: str) -> list[str]: | ||
"""Get the rock's entry point for a given build base.""" | ||
is_legacy = Pebble._is_focal_or_jammy(build_base) | ||
|
||
pebble_path = Pebble.PEBBLE_BINARY_PATH | ||
if is_legacy: | ||
# Previously pebble existed in /bin/pebble | ||
pebble_path = Pebble.PEBBLE_BINARY_PATH_PREVIOUS | ||
|
||
entrypoint = [f"/{pebble_path}", "enter"] | ||
|
||
if is_legacy: | ||
entrypoint += ["--verbose"] | ||
|
||
return entrypoint | ||
|
||
@staticmethod | ||
def _is_focal_or_jammy(build_base: str) -> bool: | ||
return build_base in ("[email protected]", "[email protected]") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,24 @@ | ||
name: chiseled-dotnet | ||
summary: A "bare" rock containing the .NET runtime | ||
description: A "bare" rock containing the .NET runtime | ||
name: chiseled-base-files | ||
summary: An Ubuntu 24.04 rock with chiseled base-files | ||
description: | | ||
Check that a simple rock containing base-files is able to build successfully | ||
with the part that provides the pebble binary. | ||
license: Apache-2.0 | ||
|
||
version: "0.0.1" | ||
|
||
base: bare | ||
build_base: [email protected] | ||
run-user: _daemon_ | ||
services: | ||
dotnet: | ||
override: replace | ||
command: /usr/lib/dotnet/dotnet [ --info ] | ||
startup: enabled | ||
build-base: devel | ||
|
||
platforms: | ||
amd64: | ||
|
||
parts: | ||
|
||
chisel-part: | ||
plugin: nil | ||
stage-packages: | ||
- dotnet-runtime-6.0_libs | ||
# This slice has "bin" as a symlink to "usr/bin" | ||
- base-files_base | ||
# This slice has "test" | ||
- coreutils_bins | ||
# This is needed to generate /etc/passwd | ||
- base-passwd_data |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,9 @@ | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
from pathlib import Path | ||
|
||
import pytest | ||
import yaml | ||
|
||
from rockcraft.pebble import Pebble | ||
|
||
ENVIRONMENT_YAML = """\ | ||
|
@@ -57,10 +60,28 @@ def test_application_expand_environment(new_dir, default_application): | |
} | ||
|
||
|
||
def test_application_pebble_part(new_dir, default_application): | ||
@pytest.mark.parametrize( | ||
("base", "build_base", "expected_spec"), | ||
[ | ||
# 24.04 and beyond: pebble exists in .rock/bin/ | ||
("bare", "devel", Pebble.PEBBLE_PART_SPEC), | ||
("[email protected]", "devel", Pebble.PEBBLE_PART_SPEC), | ||
# 20.04 and 22.04: pebble exists in bin/ | ||
("[email protected]", None, Pebble.PEBBLE_PART_SPEC_PREVIOUS), | ||
("[email protected]", None, Pebble.PEBBLE_PART_SPEC_PREVIOUS), | ||
("[email protected]", "[email protected]", Pebble.PEBBLE_PART_SPEC_PREVIOUS), | ||
("[email protected]", "[email protected]", Pebble.PEBBLE_PART_SPEC_PREVIOUS), | ||
], | ||
) | ||
def test_application_pebble_part( | ||
new_dir, default_application, base, build_base, expected_spec | ||
): | ||
"""Test that loading the project through the application adds the Pebble part.""" | ||
project_file = Path(new_dir) / "rockcraft.yaml" | ||
project_file.write_text(ENVIRONMENT_YAML) | ||
new_yaml = yaml.safe_load(ENVIRONMENT_YAML) | ||
new_yaml["base"] = base | ||
new_yaml["build-base"] = build_base | ||
project_file.write_text(yaml.safe_dump(new_yaml)) | ||
|
||
project = default_application.project | ||
assert project.parts["pebble"] == Pebble.PEBBLE_PART_SPEC | ||
assert project.parts["pebble"] == expected_spec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ | |
import tests | ||
from rockcraft import errors, oci | ||
from rockcraft.architectures import SUPPORTED_ARCHS | ||
from rockcraft.pebble import Pebble | ||
|
||
MOCK_NEW_USER = { | ||
"user": "foo", | ||
|
@@ -562,23 +563,26 @@ def test_set_default_user(self, mock_run): | |
] | ||
|
||
@pytest.mark.parametrize( | ||
("service", "build_base", "verbose", "service_config"), | ||
("service", "build_base", "pebble_binary", "verbose", "service_config"), | ||
[ | ||
( | ||
None, | ||
"[email protected]", | ||
Pebble.PEBBLE_BINARY_PATH_PREVIOUS, | ||
["--config.entrypoint", "--verbose"], | ||
[], | ||
), | ||
( | ||
None, | ||
"[email protected]", | ||
Pebble.PEBBLE_BINARY_PATH, | ||
[], | ||
[], | ||
), | ||
( | ||
"test-service", | ||
"[email protected]", | ||
Pebble.PEBBLE_BINARY_PATH_PREVIOUS, | ||
["--config.entrypoint", "--verbose"], | ||
[ | ||
"--config.entrypoint", | ||
|
@@ -590,6 +594,7 @@ def test_set_default_user(self, mock_run): | |
( | ||
"test-service", | ||
"[email protected]", | ||
Pebble.PEBBLE_BINARY_PATH, | ||
[], | ||
[ | ||
"--config.entrypoint", | ||
|
@@ -601,7 +606,7 @@ def test_set_default_user(self, mock_run): | |
], | ||
) | ||
def test_set_entrypoint_default( | ||
self, mock_run, service, build_base, verbose, service_config | ||
self, mock_run, service, build_base, pebble_binary, verbose, service_config | ||
): | ||
image = oci.Image("a:b", Path("/tmp")) | ||
|
||
|
@@ -614,7 +619,7 @@ def test_set_entrypoint_default( | |
"/tmp/a:b", | ||
"--clear=config.entrypoint", | ||
"--config.entrypoint", | ||
"/bin/pebble", | ||
f"/{pebble_binary}", | ||
"--config.entrypoint", | ||
"enter", | ||
] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters