From 84c4a2083580a9a79142d1585dbca858e9f1d26b Mon Sep 17 00:00:00 2001 From: Sudeep Pillai Date: Sat, 21 Oct 2023 13:57:36 -0700 Subject: [PATCH] Fix `add` validation with tests and path check (#6) --- agipack/config.py | 29 +++++++++++++++------ agipack/templates/Dockerfile.j2 | 2 +- agipack/version.py | 2 +- tests/test_config.py | 1 + tests/test_data/agibuild-malformed-add.yaml | 11 ++++++++ 5 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 tests/test_data/agibuild-malformed-add.yaml diff --git a/agipack/config.py b/agipack/config.py index 5f27175..0df56f7 100644 --- a/agipack/config.py +++ b/agipack/config.py @@ -1,7 +1,7 @@ import logging from dataclasses import asdict, field from pathlib import Path -from typing import Dict, List, Optional, Union +from typing import Dict, List, Optional, Tuple, Union import yaml from pydantic import validator @@ -82,7 +82,7 @@ class ImageConfig: """List of Python requirements files to install (via `pip install -r`).""" add: Optional[List[str]] = field(default_factory=list) - """List of files to copy into the image.""" + """List of files to add into the image (`./entrypoint.sh:/app/entrytpoint.sh`).""" workdir: Optional[str] = field(default=None) """Working directory for the image (defaults to /app/${AGIPACK_ENV} if not set).""" @@ -114,15 +114,28 @@ def is_base_image(self) -> bool: return ":" in self.base @validator("python", pre=True) - def validate_python_version(cls, python): + def validate_python_version(cls, python) -> str: """Validate the python version.""" python = str(python) if not python.startswith("3."): raise ValueError(f"Python version must be >= 3.6 (found {python})") return python + @validator("add", pre=True) + def validate_add(cls, items) -> Tuple[str, str]: + """Validate the add command.""" + for item in items: + if ":" not in item: + raise ValueError( + f"`add` must have a colon to separate from and to paths `from_path:to_path`, provided {item}" + ) + from_path, to_path = item.split(":") + if not Path(from_path).exists(): + raise ValueError(f"`add` {from_path} does not exist") + return items + @validator("command", pre=True) - def validate_command_version(cls, cmd): + def validate_command_version(cls, cmd) -> List[str]: """Validate the command.""" if isinstance(cmd, str): cmd = cmd.split(" ") @@ -178,14 +191,14 @@ def is_prod(self) -> bool: @validator("images") def validate_python_dependencies_for_nonbase_images(cls, images): """Validate that all images have the same python dependency as the base image.""" - version = None + py_version = None for target, config in images.items(): if config.is_base_image(): - version = config.python + py_version = config.python else: - if config.python != version: + if config.python != py_version: logger.debug(f"Ignoring python version for non-base image [{target}]") - config.python = version + config.python = py_version return images @classmethod diff --git a/agipack/templates/Dockerfile.j2 b/agipack/templates/Dockerfile.j2 index 81f6b3d..467d7c6 100644 --- a/agipack/templates/Dockerfile.j2 +++ b/agipack/templates/Dockerfile.j2 @@ -151,7 +151,7 @@ WORKDIR /app/$AGIPACK_PYENV # Add project files {%- for item in add %} -ADD {{ item }} {{ item }} +ADD {{ item.split(":")[0] }} {{ item.split(":")[1] }} {%- endfor %} {%- endif %} diff --git a/agipack/version.py b/agipack/version.py index 74acd0e..3cb7d95 100644 --- a/agipack/version.py +++ b/agipack/version.py @@ -1 +1 @@ -__version__ = "0.1.12" +__version__ = "0.1.13" diff --git a/tests/test_config.py b/tests/test_config.py index e4b1f88..e410269 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -27,6 +27,7 @@ def test_configs(test_data_dir): def test_poorly_formatted_configs(test_data_dir): poorly_formatted_configs = [ test_data_dir / "agibuild-no-base.yaml", + test_data_dir / "agibuild-malformed-add.yaml", ] for filename in poorly_formatted_configs: with pytest.raises(ValueError): diff --git a/tests/test_data/agibuild-malformed-add.yaml b/tests/test_data/agibuild-malformed-add.yaml new file mode 100644 index 0000000..5de0bd4 --- /dev/null +++ b/tests/test_data/agibuild-malformed-add.yaml @@ -0,0 +1,11 @@ +images: + base-cpu: + system: + - wget + python: 3.8.10 + pip: + - scikit-learn + add: + - "path_without_colon.txt" + run: + - echo "Hello, world!" \ No newline at end of file