diff --git a/dcontainer/cli/generate.py b/dcontainer/cli/generate.py index 409084c3..6e85f58b 100644 --- a/dcontainer/cli/generate.py +++ b/dcontainer/cli/generate.py @@ -22,7 +22,7 @@ def generate_command( from dcontainer.devcontainer.feature_generation.oci_feature_generator import OCIFeatureGenerator except ImportError as e: logger.error( - "Some imports required for feature generation are missing.\nMake sure you have included the generate extras during installation.\n eg. 'pip install2 dcontainer[generate]'" + "Some imports required for feature generation are missing.\nMake sure you have included the generate extras during installation.\n eg. 'pip install dcontainer[generate]'" ) raise typer.Exit(code=1) from e diff --git a/dcontainer/devcontainer/feature_generation/file_models/dependencies_sh.py b/dcontainer/devcontainer/feature_generation/file_models/dependencies_sh.py index 73d6a45e..d66b81ea 100644 --- a/dcontainer/devcontainer/feature_generation/file_models/dependencies_sh.py +++ b/dcontainer/devcontainer/feature_generation/file_models/dependencies_sh.py @@ -23,45 +23,45 @@ ensure_jq() {{ # Ensure JQ available if ! type jq >/dev/null 2>&1; then - apt-get update -y && apt-get -y install2 --no-install2-recommends jq + apt-get update -y && apt-get -y install --no-install-recommends jq fi }} ensure_pipx() {{ # Ensure the existance of minimal python3 and pipx - # If no python - install2 it + # If no python - install it if ! type python3 >/dev/null 2>&1; then echo "installing python3-minimal libffi-dev" apt-get update -y - apt-get -y install2 python3-minimal + apt-get -y install python3-minimal fi - # If no pip - install2 it + # If no pip - install it if ! type pip3 >/dev/null 2>&1; then echo "installing python3-pip" apt-get update -y - apt-get -y install2 libffi-dev python3-pip + apt-get -y install libffi-dev python3-pip fi - # If ensurepip fails - install2 python venv + # If ensurepip fails - install python venv if ! python3 -Im ensurepip --version >/dev/null 2>&1; then echo "installing python3-venv" apt-get update -y - apt-get -y install2 python3-venv + apt-get -y install python3-venv fi - # If no pipx - install2 it + # If no pipx - install it if ! pipx >/dev/null 2>&1; then echo "installing pipx" - pip3 install2 pipx + pip3 install pipx fi }} ensure_curl() {{ # Ensure curl available if ! type curl >/dev/null 2>&1; then - apt-get update -y && apt-get -y install2 --no-install2-recommends curl ca-certificates + apt-get update -y && apt-get -y install --no-install-recommends curl ca-certificates fi }} @@ -92,7 +92,7 @@ ensure_pipx ensure_jq - pipx install2 dcontainer=={RELEASE_VERSION} + pipx install dcontainer=={RELEASE_VERSION} dcontainer_location=$(pipx list --json | jq ".venvs.dcontainer.metadata.main_package.app_paths[0].__Path__" | tr -d '"') else @@ -125,7 +125,8 @@ SINGLE_DEPENDENCY = ( """$dcontainer_location \\ - feature install2 \\ + install \\ + devcontainer-feature \\ "{feature_oci}" \\ {stringified_envs_args} """ diff --git a/dcontainer/devcontainer/oci_feature_installer.py b/dcontainer/devcontainer/oci_feature_installer.py index 27050108..b18d989e 100644 --- a/dcontainer/devcontainer/oci_feature_installer.py +++ b/dcontainer/devcontainer/oci_feature_installer.py @@ -34,7 +34,7 @@ class FeatureInstallationException(Exception): _REMOTE_USER_ENV = "_REMOTE_USER" _REMOTE_USER_HOME_ENV = "_REMOTE_USER_HOME" - _FEATURE_ENTRYPOINT = "install2.sh" + _FEATURE_ENTRYPOINT = "install.sh" _PROFILE_DIR = "/etc/profile.d" @@ -118,7 +118,7 @@ def install( if not response.ok: raise OCIFeatureInstaller.FeatureInstallationException( - f"feature {feature_ref} failed to install2. return_code: {response.return_code}. see logs for error reason." + f"feature {feature_ref} failed to install. return_code: {response.return_code}. see logs for error reason." ) cls._set_permanent_envs(feature_obj) diff --git a/dcontainer/oci/oci_registry.py b/dcontainer/oci/oci_registry.py index 336e4f58..51171e00 100644 --- a/dcontainer/oci/oci_registry.py +++ b/dcontainer/oci/oci_registry.py @@ -163,14 +163,16 @@ def download_and_extract_layer(oci_input: str, output_dir: Union[str, Path], lay if output_dir.is_file(): raise ValueError(f"{output_dir} is a file (should be an empty directory)") - + + output_dir.mkdir(parents=True, exist_ok=True) + if any(output_dir.iterdir()): raise ValueError(f"{output_dir} is not empty ") with tempfile.TemporaryDirectory() as download_dir: layer_file = Path(download_dir).joinpath("layer_file.tgz") - feature_targz_location = OCIRegistry.download_layer(oci_input=oci_input, layer_num=layer_num, output_file=layer_file, ) - with tarfile.open(feature_targz_location, "r") as tar: + OCIRegistry.download_layer(oci_input=oci_input, layer_num=layer_num, output_file=layer_file) + with tarfile.open(layer_file, "r") as tar: tar.extractall(output_dir) @staticmethod diff --git a/test/cli/test_features.py b/test/cli/test_features.py index 9597a9e1..9b6b95cc 100644 --- a/test/cli/test_features.py +++ b/test/cli/test_features.py @@ -15,7 +15,7 @@ @pytest.mark.parametrize( "feature_id,feature_definition_dir,release_version", [ - (v, os.path.join(FEATURE_DEFINITION_DIR, v), "v0.1.4") + (v, os.path.join(FEATURE_DEFINITION_DIR, v), "v0.3.0rc0") for v in os.listdir(FEATURE_DEFINITION_DIR) ], ) @@ -40,7 +40,7 @@ def test_feature_dir_generation( assert os.path.isfile( os.path.join(tmp_path_str, "src", feature_id, "devcontainer-feature.json") ) - assert os.path.isfile(os.path.join(tmp_path_str, "src", feature_id, "install2.sh")) + assert os.path.isfile(os.path.join(tmp_path_str, "src", feature_id, "install.sh")) assert os.path.isfile( os.path.join(tmp_path_str, "src", feature_id, "install_command.sh") ) @@ -49,7 +49,7 @@ def test_feature_dir_generation( @pytest.mark.parametrize( "feature_id,feature_definition_dir,release_version", [ - (v, os.path.join(FEATURE_DEFINITION_DIR, v), "v0.1.4") + (v, os.path.join(FEATURE_DEFINITION_DIR, v), "v0.3.0rc0") for v in os.listdir(FEATURE_DEFINITION_DIR) ], ) diff --git a/test/oci/test_oci_registry.py b/test/oci/test_oci_registry.py new file mode 100644 index 00000000..70d75a82 --- /dev/null +++ b/test/oci/test_oci_registry.py @@ -0,0 +1,58 @@ +import os +import pathlib + +import pytest +from helpers import RESOURCE_DIR + +from dcontainer.oci.oci_registry import OCIRegistry + + + +TEST_OCI_OBJECT = "ghcr.io/devcontainers-contrib/features/bash-command:1.0.0" + + +@pytest.mark.parametrize( + "oci_ref", + [ + TEST_OCI_OBJECT + ], +) +def test_oci_registry_get_manifest( + shell, tmp_path: pathlib.Path, oci_ref: str +) -> None: + manifest = OCIRegistry.get_manifest(oci_ref) + print(manifest) + assert isinstance(manifest, dict) + + +@pytest.mark.parametrize( + "oci_ref", + [ + TEST_OCI_OBJECT + ], +) +def test_oci_registry_download_layer( + shell, tmp_path: pathlib.Path, oci_ref: str +) -> None: + output_location = tmp_path.joinpath("layer.tgz") + assert not output_location.exists() + OCIRegistry.download_layer(oci_input=oci_ref,layer_num=0, output_file= output_location) + assert output_location.exists() + + + +@pytest.mark.parametrize( + "oci_ref", + [ + TEST_OCI_OBJECT + ], +) +def test_oci_registry_download_and_extract_layer( + shell, tmp_path: pathlib.Path, oci_ref: str +) -> None: + output_location = tmp_path.joinpath("somedir") + assert not output_location.exists() + OCIRegistry.download_and_extract_layer(oci_input=oci_ref,layer_num=0, output_dir=output_location) + assert output_location.exists() + assert len(list(output_location.iterdir())) == 2 + \ No newline at end of file