Skip to content

Commit

Permalink
[WIP] feat: Implemented building to directory (#11)
Browse files Browse the repository at this point in the history
* feat: Implemented building to directory

* feat: Updated tests

* feat: Updated README.md and args description

* fix: Added tests descriptors
  • Loading branch information
micmurawski authored Jun 10, 2024
1 parent 0a2b134 commit 414ce0f
Show file tree
Hide file tree
Showing 7 changed files with 282 additions and 100 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,17 +92,18 @@ Arguments:
docker_network_disabled Disable networking ex. docker_network_disabled=0
docker_network_mode Network_mode
docker_platform Platform in the format os[/arch[/variant]]. Only used if the method needs to pull the requested image.
package_artifact_path Output package path
package_install_dir Installation directory inside zip artifact for single zip package
function_artifact_path Output function package path
function_install_dir Installation directory inside zip artifact for function zip package
layer_artifact_path Output layer package path
layer_install_dir Installation directory inside zip artifact for layer zip package
package_artifact_path Output package path (default: package.zip). Set the '.zip' extension to wrap the artifact into a zip package otherwise, output will be created in the directory.
package_install_dir Installation directory inside artifact for single package
function_artifact_path Output function package path. Set the '.zip' extension to wrap the artifact into a zip package otherwise, output will be created in the directory.
function_install_dir Installation directory inside artifact for function package
layer_artifact_path Output layer package path. Set the '.zip' extension to wrap the artifact into a zip package otherwise, output will be created in the directory.
layer_install_dir Installation directory inside artifact for layer package
only The only dependency groups to include
without The dependency groups to ignore
with The optional dependency groups to include
zip_compresslevel None (default for the given compression type) or an integer specifying the level to pass to the compressor. When using ZIP_STORED or ZIP_LZMA this keyword has no effect. When using ZIP_DEFLATED integers 0 through 9 are accepted. When using ZIP_BZIP2 integers 1 through 9 are accepted.
zip_compression ZIP_STORED (no compression), ZIP_DEFLATED (requires zlib), ZIP_BZIP2 (requires bz2) or ZIP_LZMA (requires lzma)
pre_install_script The script that is executed before installation.
Options:
-h, --help Display help for the given command. When no command is given display help for the list command.
Expand Down
4 changes: 2 additions & 2 deletions poetry_plugin_lambda_build/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def get_docker_client() -> docker.DockerClient:
return docker.from_env()


def copy_to(src: str, dst: str):
def copy_to_container(src: str, dst: str):
name, dst = dst.split(":")
container = get_docker_client().containers.get(name)

Expand All @@ -53,7 +53,7 @@ def copy_to(src: str, dst: str):
container.put_archive(os.path.dirname(dst), data)


def copy_from(src: str, dst: str):
def copy_from_container(src: str, dst: str):
name, src = src.split(":")
container = get_docker_client().containers.get(name)
tar_path = dst + "_archive.tar"
Expand Down
12 changes: 6 additions & 6 deletions poetry_plugin_lambda_build/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ def comma_separated_collection(x): return x.split(",")
"docker_network_disabled": ("Disable networking ex. docker_network_disabled=0", True, False, None, str),
"docker_network_mode": ("Network_mode", True, False, None),
"docker_platform": ("Platform in the format os[/arch[/variant]]. Only used if the method needs to pull the requested image.", True, False, None, str),
"package_artifact_path": ("Output package path", True, False, None, str),
"package_install_dir": ("Installation directory inside zip artifact for single zip package", True, False, None, str),
"function_artifact_path": ("Output function package path", True, False, None, str),
"function_install_dir": ("Installation directory inside zip artifact for function zip package", True, False, None, str),
"layer_artifact_path": ("Output layer package path", True, False, None, str),
"layer_install_dir": ("Installation directory inside zip artifact for layer zip package", True, False, None, str),
"package_artifact_path": ("Output package path (default: package.zip). Set the '.zip' extension to wrap the artifact into a zip package otherwise, output will be created in the directory.", True, False, None, str),
"package_install_dir": ("Installation directory inside artifact for single package", True, False, None, str),
"function_artifact_path": ("Output function package path. Set the '.zip' extension to wrap the artifact into a zip package otherwise, output will be created in the directory." , True, False, None, str),
"function_install_dir": ("Installation directory inside artifact for function package", True, False, None, str),
"layer_artifact_path": ("Output layer package path. Set the '.zip' extension to wrap the artifact into a zip package otherwise, output will be created in the directory.", True, False, None, str),
"layer_install_dir": ("Installation directory inside artifact for layer package", True, False, None, str),
"only": ("The only dependency groups to include", True, False, None, comma_separated_collection),
"without": ("The dependency groups to ignore", True, False, None, comma_separated_collection),
"with": ("The optional dependency groups to include", True, False, None, comma_separated_collection),
Expand Down
73 changes: 49 additions & 24 deletions poetry_plugin_lambda_build/recipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,30 @@
from poetry.console.commands.command import Command

from poetry_plugin_lambda_build.commands import (
INSTALL_CMD_TMPL, INSTALL_DEPS_CMD_IN_CONTAINER_TMPL,
INSTALL_DEPS_CMD_TMPL, INSTALL_IN_CONTAINER_CMD_TMPL,
INSTALL_IN_CONTAINER_NO_DEPS_CMD_TMPL, INSTALL_NO_DEPS_CMD_TMPL)
from poetry_plugin_lambda_build.docker import (copy_from, copy_to,
exec_run_container,
run_container)
INSTALL_CMD_TMPL,
INSTALL_DEPS_CMD_IN_CONTAINER_TMPL,
INSTALL_DEPS_CMD_TMPL,
INSTALL_IN_CONTAINER_CMD_TMPL,
INSTALL_IN_CONTAINER_NO_DEPS_CMD_TMPL,
INSTALL_NO_DEPS_CMD_TMPL
)
from poetry_plugin_lambda_build.docker import (
copy_from_container,
copy_to_container,
exec_run_container,
run_container
)
from poetry_plugin_lambda_build.parameters import ParametersContainer
from poetry_plugin_lambda_build.requirements import RequirementsExporter
from poetry_plugin_lambda_build.utils import (format_str, join_cmds,
mask_string, remove_suffix,
run_python_cmd)
from poetry_plugin_lambda_build.utils import (
format_str,
join_cmds,
mask_string,
remove_suffix,
run_python_cmd
)
from poetry_plugin_lambda_build.zip import create_zip_package
import shutil

CONTAINER_CACHE_DIR = "/opt/lambda/cache"
CURRENT_WORK_DIR = os.getcwd()
Expand Down Expand Up @@ -93,7 +105,7 @@ def format_str(self, string: str, **kwargs) -> tuple[str, str]:
def _build_separate_layer_in_container(self, requirements_path: str, layer_output_dir: str):
self.cmd.info("Running docker container...")
with run_container(self.cmd, **self.parameters.get_section("docker")) as container:
copy_to(
copy_to_container(
src=requirements_path,
dst=f"{container.id}:/requirements.txt"
)
Expand Down Expand Up @@ -122,11 +134,27 @@ def _build_separate_layer_in_container(self, requirements_path: str, layer_outpu
)
self.cmd.info(
f"Coping output to {layer_output_dir}")
copy_from(
copy_from_container(
src=f"{container.id}:{CONTAINER_CACHE_DIR}/.",
dst=layer_output_dir
)

def _create_target(self, dir: str, target: str, exclude: None | list = None):
if target.endswith(".zip"):
create_zip_package(
dir=dir,
output=target,
exclude=exclude,
**self.parameters.get_section("zip")
)
else:
shutil.copytree(
dir,
target,
dirs_exist_ok=True,
ignore=shutil.ignore_patterns(*exclude) if exclude else None
)

def _build_separate_layer_on_local(self, requirements_path: str, layer_output_dir: str):
self.cmd.info("Installing requirements")
cmd, print_safe_cmd = self.format_str(
Expand Down Expand Up @@ -168,18 +196,17 @@ def build_separate_layer_package(self):

self.cmd.info(f"Building {target}...")
os.makedirs(os.path.dirname(target), exist_ok=True)
create_zip_package(
self._create_target(
dir=remove_suffix(layer_output_dir, install_dir),
output=target,
target=target,
exclude=[requirements_path],
**self.parameters.get_section("zip")
)
self.cmd.info(
f"target successfully built: {target}...")

def _build_separated_function_in_container(self, package_dir: str):
with run_container(self.cmd, **self.parameters.get_section("docker"), working_dir="/") as container:
copy_to(
copy_to_container(
src=f"{CURRENT_WORK_DIR}/.",
dst=f"{container.id}:/"
)
Expand All @@ -200,7 +227,7 @@ def _build_separated_function_in_container(self, package_dir: str):
f"Executing: {print_safe_cmd}")
exec_run_container(
self.cmd, container, self.parameters["docker_entrypoint"], cmd)
copy_from(
copy_from_container(
src=f"{container.id}:{CONTAINER_CACHE_DIR}/.",
dst=package_dir
)
Expand Down Expand Up @@ -241,10 +268,9 @@ def build_separated_function_package(self):

self.cmd.info(f"Building target: {target}")
os.makedirs(os.path.dirname(target), exist_ok=True)
create_zip_package(
self._create_target(
dir=remove_suffix(package_dir, install_dir),
output=target,
**self.parameters.get_section("zip")
target=target,
)
self.cmd.info(
f"Target successfully built: {target}...")
Expand All @@ -253,7 +279,7 @@ def _build_package_in_container(self, package_dir: str):
self.cmd.info("Running container...")
with run_container(self.cmd, **self.parameters.get_section("docker"), working_dir="/") as container:
self.cmd.info("Coping content")
copy_to(f"{CURRENT_WORK_DIR}/.", f"{container.id}:/")
copy_to_container(f"{CURRENT_WORK_DIR}/.", f"{container.id}:/")

if self.parameters.get("pre_install_script"):
install_in_container_cmd_tmpl = join_cmds(
Expand All @@ -276,7 +302,7 @@ def _build_package_in_container(self, package_dir: str):
entrypoint=self.parameters["docker_entrypoint"],
container_cmd=cmd
)
copy_from(
copy_from_container(
src=f"{container.id}:{CONTAINER_CACHE_DIR}/.",
dst=package_dir
)
Expand Down Expand Up @@ -317,10 +343,9 @@ def build_package(self):
self._build_package_on_local(package_dir)

os.makedirs(os.path.dirname(target), exist_ok=True)
create_zip_package(
self._create_target(
dir=remove_suffix(package_dir, install_dir),
output=target,
**self.parameters.get_section("zip")
target=target
)
self.cmd.info(
f"target successfully built: {target}...")
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "poetry-plugin-lambda-build"
version = "0.6.2"
version = "0.6.4"
description = "The plugin for poetry that allows you to build zip packages suited for serverless deployment like AWS Lambda, Google App Engine, Azure App Service, and more..."
authors = ["Michal Murawski <[email protected]>"]
readme = "README.md"
Expand Down
Loading

0 comments on commit 414ce0f

Please sign in to comment.