Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions examples/build-package/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

Configuration in this directory creates deployment packages in a variety of combinations.

This example demonstrates various packaging scenarios including:
- Python packages with pip requirements
- Poetry-based Python packages
- Node.js packages with npm
- Docker-based builds
- **Quiet packaging** - suppressing Poetry/pip/npm output during builds using `quiet_archive_local_exec = true`

Look into [Runtimes Examples](https://github.com/terraform-aws-modules/terraform-aws-lambda/tree/master/examples/runtimes) for more ways to build and deploy AWS Lambda Functions using supported runtimes (Rust, Go, Java).

## Usage
Expand Down Expand Up @@ -44,6 +51,7 @@ Note that this example may create resources which cost money. Run `terraform des
| <a name="module_package_dir_pip_dir"></a> [package\_dir\_pip\_dir](#module\_package\_dir\_pip\_dir) | ../../ | n/a |
| <a name="module_package_dir_poetry"></a> [package\_dir\_poetry](#module\_package\_dir\_poetry) | ../../ | n/a |
| <a name="module_package_dir_poetry_no_docker"></a> [package\_dir\_poetry\_no\_docker](#module\_package\_dir\_poetry\_no\_docker) | ../../ | n/a |
| <a name="module_package_dir_poetry_quiet"></a> [package\_dir\_poetry\_quiet](#module\_package\_dir\_poetry\_quiet) | ../../ | n/a |
| <a name="module_package_dir_with_npm_install"></a> [package\_dir\_with\_npm\_install](#module\_package\_dir\_with\_npm\_install) | ../../ | n/a |
| <a name="module_package_dir_with_npm_install_lock_file"></a> [package\_dir\_with\_npm\_install\_lock\_file](#module\_package\_dir\_with\_npm\_install\_lock\_file) | ../../ | n/a |
| <a name="module_package_dir_without_npm_install"></a> [package\_dir\_without\_npm\_install](#module\_package\_dir\_without\_npm\_install) | ../../ | n/a |
Expand Down
18 changes: 18 additions & 0 deletions examples/build-package/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,24 @@ module "package_dir_poetry_no_docker" {
artifacts_dir = "${path.root}/builds/package_dir_poetry/"
}

# Create zip-archive with Poetry dependencies and demonstrate quiet packaging output
module "package_dir_poetry_quiet" {
source = "../../"

create_function = false

runtime = "python3.12"

source_path = [
{
path = "${path.module}/../fixtures/python-app-poetry"
poetry_install = true
}
]
artifacts_dir = "${path.root}/builds/package_dir_poetry_quiet/"
quiet_archive_local_exec = true # Suppress Poetry/pip output during packaging
}

# Create zip-archive of a single directory without running "pip install" (which is default for python runtime)
module "package_dir_without_pip_install" {
source = "../../"
Expand Down
53 changes: 42 additions & 11 deletions package.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,11 @@ def __init__(
compress_type=zipfile.ZIP_DEFLATED,
compresslevel=None,
timestamp=None,
quiet=False,
):
self.timestamp = timestamp
self.filename = zip_filename
self.quiet = quiet

if not (self.filename and isinstance(self.filename, str)):
raise ValueError("Zip file path must be provided")
Expand All @@ -312,7 +314,8 @@ def open(self):
raise zipfile.BadZipFile("ZipStream object can't be reused")
self._ensure_base_path(self.filename)
self._tmp_filename = "{}.tmp".format(self.filename)
self._log.info("creating '%s' archive", self.filename)
if not self.quiet:
self._log.info("creating '%s' archive", self.filename)
self._zip = zipfile.ZipFile(self._tmp_filename, "w", self._compress_type)
return self

Expand Down Expand Up @@ -356,7 +359,8 @@ def write_dirs(self, *base_dirs, prefix=None, timestamp=None):
"""
self._ensure_open()
for base_dir in base_dirs:
self._log.info("adding content of directory: %s", base_dir)
if not self.quiet:
self._log.info("adding content of directory: %s", base_dir)
for path in emit_dir_content(base_dir):
arcname = os.path.relpath(path, base_dir)
self._write_file(path, prefix, arcname, timestamp)
Expand All @@ -382,10 +386,11 @@ def _write_file(self, file_path, prefix=None, name=None, timestamp=None):
if prefix:
arcname = os.path.join(prefix, arcname)
zinfo = self._make_zinfo_from_file(file_path, arcname)
if zinfo.is_dir():
self._log.info("adding: %s/", arcname)
else:
self._log.info("adding: %s", arcname)
if not self.quiet:
if zinfo.is_dir():
self._log.info("adding: %s/", arcname)
else:
self._log.info("adding: %s", arcname)
if timestamp is None:
timestamp = self.timestamp
date_time = self._timestamp_to_date_time(timestamp)
Expand Down Expand Up @@ -1170,7 +1175,15 @@ def install_pip_requirements(query, requirements_file, tmp_dir):
cmd_log.info(shlex_join(pip_command))
log_handler and log_handler.flush()
try:
check_call(pip_command, env=subproc_env)
if query.quiet:
check_call(
pip_command,
env=subproc_env,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
else:
check_call(pip_command, env=subproc_env)
except FileNotFoundError as e:
raise RuntimeError(
"Python interpreter version equal "
Expand Down Expand Up @@ -1346,7 +1359,15 @@ def copy_file_to_target(file, temp_dir):
cmd_log.info(poetry_commands)
log_handler and log_handler.flush()
for poetry_command in poetry_commands:
check_call(poetry_command, env=subproc_env)
if query.quiet:
check_call(
poetry_command,
env=subproc_env,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
else:
check_call(poetry_command, env=subproc_env)

os.remove(pyproject_target_file)
if poetry_lock_target_file:
Expand Down Expand Up @@ -1443,7 +1464,15 @@ def install_npm_requirements(query, requirements_file, tmp_dir):
cmd_log.info(shlex_join(npm_command))
log_handler and log_handler.flush()
try:
check_call(npm_command, env=subproc_env)
if query.quiet:
check_call(
npm_command,
env=subproc_env,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
else:
check_call(npm_command, env=subproc_env)
except FileNotFoundError as e:
raise RuntimeError(
"Nodejs interpreter version equal "
Expand Down Expand Up @@ -1719,6 +1748,7 @@ def prepare_command(args):
"runtime": runtime,
"artifacts_dir": artifacts_dir,
"build_plan": build_plan,
"quiet": query.quiet,
}
if docker:
build_data["docker"] = docker
Expand Down Expand Up @@ -1778,12 +1808,13 @@ def build_command(args):

# Zip up the build plan and write it to the target filename.
# This will be used by the Lambda function as the source code package.
with ZipWriteStream(filename) as zs:
with ZipWriteStream(filename, quiet=getattr(query, "quiet", False)) as zs:
bpm = BuildPlanManager(args, log=log)
bpm.execute(build_plan, zs, query)

os.utime(filename, ns=(timestamp, timestamp))
log.info("Created: %s", shlex.quote(filename))
if not getattr(query, "quiet", False):
log.info("Created: %s", shlex.quote(filename))
if log.isEnabledFor(logging.DEBUG):
with open(filename, "rb") as f:
log.info("Base64sha256: %s", source_code_hash(f.read()))
Expand Down
1 change: 1 addition & 0 deletions package.tf
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ data "external" "archive_prepare" {
)

recreate_missing_package = var.recreate_missing_package
quiet = var.quiet_archive_local_exec
}
}

Expand Down