From b7ec47b6226836dacdac952a1d69c68fe44d504a Mon Sep 17 00:00:00 2001 From: David Calavera Date: Thu, 9 Feb 2023 15:26:37 -0800 Subject: [PATCH] feat: Rust cargo lambda workflow (#350) * feat: support rust via cargo * make black reformat * use os.path.join in path assertion tests to address windows paths * address pylint ci errors * fix reformatted list comprehensions * try passing rust-lld linker on windows * update rust cargo design doc. windows support was added and tested * add test for cargo workspaces project * reformat test sources * build with musl on linux because glibc may differ on lambda * update linux copy and bin paths * update make test again, use the version appveyor is complaining about * update integration tests for rust cargo with latest aws rust runtime interfaces * align TestCustomMakeWorkflow integ test assumptions with appveyor reality * make x86_64-unknown-linux-musl a const for the rust cargo workflow * add integ test for failing cargo rust build * Update Rust workflow to use cargo-lambda Cargo-lambda takes care of cross compiling using Zig as linker. This works on Windows, Linux, and MacOS natively. Signed-off-by: David Calavera * Fix deprecation warnings. Signed-off-by: David Calavera * Install Zig on Windows manually Signed-off-by: David Calavera * Print Zig version on Windows Signed-off-by: David Calavera * Update version of cargo-lambda Signed-off-by: David Calavera * Run windows tests in powershell Signed-off-by: David Calavera * Fix powershell env notation Signed-off-by: David Calavera * Print clang version on windows Signed-off-by: David Calavera * Fix env variable name Signed-off-by: David Calavera * Try new version of zigbuild that fixes some linker issues on Windows. Signed-off-by: David Calavera * Update releases URL. Signed-off-by: David Calavera * Upgrade LLVM and clang Signed-off-by: David Calavera * Update visual studio image To check if that makes any difference. Signed-off-by: David Calavera * Change the visual studio image everywhere. Signed-off-by: David Calavera * Revert upgrade changes They didn't fix the problem Signed-off-by: David Calavera * Print environment Signed-off-by: David Calavera * Update to Visual Studio 2022 Signed-off-by: David Calavera * Fix python variable Signed-off-by: David Calavera * Fix package urls Signed-off-by: David Calavera * Update missing vs 2019 reference. Signed-off-by: David Calavera * Change windows package suffix Signed-off-by: David Calavera * Update cargo-lambda to version 0.9.0 Signed-off-by: David Calavera * Go back to the original VS version. Signed-off-by: David Calavera * Cleanup options - Use architecture to setup the right build target. - Don't require `--bin` flag, the default behaviour should work for the majority of functions. - Add flags option to provide a list of additional flags for projects that need extra configuration, like projects within a workspace. Signed-off-by: David Calavera * Add integration test with cargo_lambda_flags Signed-off-by: David Calavera * Detect binaries when the project only includes one function. Signed-off-by: David Calavera * Bring back handler as an optional argument. It saves some duplicated flags for working with workspaces. Signed-off-by: David Calavera * Ignore errors if directory doesn't exist. Signed-off-by: David Calavera * Add debug logs Set RUST_LOG=debug when debug is enabled. Signed-off-by: David Calavera * Log the artifact destination path. Signed-off-by: David Calavera * Add missing comma Signed-off-by: David Calavera * Print out and err in the log when debug is enabled Signed-off-by: David Calavera * Only set RUST_LOG when it's not already set Log it's value, so users know what's set at. Signed-off-by: David Calavera * Add experimentalCargoLambda feature flag. Signed-off-by: David Calavera * Add integration test for multi-function projects. Signed-off-by: David Calavera * Remove type hints They're causing false positives in Python 3.9 with pylint. Signed-off-by: David Calavera * Add new CI steps for GHA Signed-off-by: David Calavera * Add build_in_source_support Signed-off-by: David Calavera * Test rust logger Signed-off-by: David Calavera * Fix assertion Signed-off-by: David Calavera * Don't fail fast Signed-off-by: David Calavera * fix: Fix failing esbuild integration tests (#423) * fix: Fix failing esbuild integration tests * Replace npm ci with npm install * Remove default shell Signed-off-by: David Calavera * Revert "Remove default shell" This reverts commit 478c3b6629e673e32fcfd2705c018f730b9b51a2. * Add check to ensure that Cargo Lambda is installed. Include a link to the gettings started guide that gives direct installation instructions based on the platform. Signed-off-by: David Calavera * feat: Add support for mjs files with esbuild (#427) * feat: Add support for mjs files with esbuild * Black reformat * Test Cargo Lambda check Signed-off-by: David Calavera * Don't redefine which Signed-off-by: David Calavera * Organize code in more modules This structure follows other workflows, and provides better testeability. Signed-off-by: David Calavera * Add more documentation Signed-off-by: David Calavera * Format code Signed-off-by: David Calavera * Capture exception Signed-off-by: David Calavera * chore: Remove type/bug label for Bug Issue Template (#425) Co-authored-by: Jacob Fuss Co-authored-by: Mehmet Nuri Deveci <5735811+mndeveci@users.noreply.github.com> * Clean design doc and tests Signed-off-by: David Calavera * chore: Version bump to 1.25.0 (#429) * refactor: assign each workflow a default build directory (#428) * fix: remove unused symlinking (#432) * chore: Move to ruff from pylint (#435) When we started the project we defaulted to use pylint. Pylint has served it's purpose but it pretty slow. Ruff is a newer linter in the python ecosystem but is written in Rust. This makes Ruff was faster than pylint. On my machine (while testing in SAM CLI), pylint took about 70s to lint the repo but with ruff it took .04s. Co-authored-by: Jacob Fuss * chore: Enable pylint within ruff (#436) Co-authored-by: Jacob Fuss * refactor: esbuild refactor for readability (#433) * feat: use build_dir in esbuild workflow to support building in source (#437) * Fix formatting Signed-off-by: David Calavera * Update build in source settings Signed-off-by: David Calavera * fix: remove python3.6 support (#434) * chore: bump version to 1.26.0 (#441) * Remove default value for subprocess_cargo_lambda Signed-off-by: David Calavera * feat: Pin ruff version, add dependabot config (#442) * feat: Pin ruff version, add dependabot config to keep our dependencies up to date * Exlude isort and flake8 from dependabot updates * feat: Add sources content flag to supported esbuild options (#439) * Better process management Signed-off-by: David Calavera * Make release mode the default Signed-off-by: David Calavera * Remove already default None Signed-off-by: David Calavera * Turn debug message into warning Signed-off-by: David Calavera * Update documentation format Signed-off-by: David Calavera * Fix formatting Signed-off-by: David Calavera * Preserve binary permissions Use copy2 instead of copyfile Signed-off-by: David Calavera --------- Signed-off-by: David Calavera Co-authored-by: softprops Co-authored-by: Daniel Mil <84205762+mildaniel@users.noreply.github.com> Co-authored-by: Jacob Fuss <32497805+jfuss@users.noreply.github.com> Co-authored-by: Jacob Fuss Co-authored-by: Mehmet Nuri Deveci <5735811+mndeveci@users.noreply.github.com> Co-authored-by: Ruperto Torres <86501267+torresxb1@users.noreply.github.com> --- .github/workflows/build.yml | 58 +- Makefile | 5 +- README.md | 1 + aws_lambda_builders/workflows/__init__.py | 1 + .../workflows/rust_cargo/DESIGN.md | 28 + .../workflows/rust_cargo/__init__.py | 5 + .../workflows/rust_cargo/actions.py | 146 ++++ .../workflows/rust_cargo/cargo_lambda.py | 131 ++++ .../workflows/rust_cargo/exceptions.py | 14 + .../workflows/rust_cargo/feature_flag.py | 12 + .../workflows/rust_cargo/utils.py | 20 + .../workflows/rust_cargo/workflow.py | 59 ++ .../workflows/rust_cargo/test_rust_cargo.py | 184 +++++ .../rust_cargo/testdata/fail/.gitignore | 1 + .../rust_cargo/testdata/fail/Cargo.lock | 727 +++++++++++++++++ .../rust_cargo/testdata/fail/Cargo.toml | 9 + .../rust_cargo/testdata/fail/src/main.rs | 10 + .../rust_cargo/testdata/hello/.gitignore | 1 + .../rust_cargo/testdata/hello/Cargo.lock | 727 +++++++++++++++++ .../rust_cargo/testdata/hello/Cargo.toml | 9 + .../rust_cargo/testdata/hello/src/main.rs | 44 ++ .../testdata/multi-binary/.gitignore | 1 + .../testdata/multi-binary/Cargo.lock | 581 ++++++++++++++ .../testdata/multi-binary/Cargo.toml | 31 + .../testdata/multi-binary/src/function_a.rs | 53 ++ .../testdata/multi-binary/src/function_b.rs | 53 ++ .../rust_cargo/testdata/workspaces/.gitignore | 1 + .../rust_cargo/testdata/workspaces/Cargo.lock | 736 ++++++++++++++++++ .../rust_cargo/testdata/workspaces/Cargo.toml | 2 + .../testdata/workspaces/bar/Cargo.toml | 9 + .../testdata/workspaces/bar/src/main.rs | 44 ++ .../testdata/workspaces/foo/Cargo.toml | 9 + .../testdata/workspaces/foo/src/main.rs | 44 ++ tests/unit/workflows/rust_cargo/__init__.py | 0 .../unit/workflows/rust_cargo/test_actions.py | 165 ++++ .../workflows/rust_cargo/test_cargo_lambda.py | 21 + tests/unit/workflows/rust_cargo/test_utils.py | 25 + .../workflows/rust_cargo/test_workflow.py | 48 ++ 38 files changed, 4013 insertions(+), 2 deletions(-) create mode 100644 aws_lambda_builders/workflows/rust_cargo/DESIGN.md create mode 100644 aws_lambda_builders/workflows/rust_cargo/__init__.py create mode 100644 aws_lambda_builders/workflows/rust_cargo/actions.py create mode 100644 aws_lambda_builders/workflows/rust_cargo/cargo_lambda.py create mode 100644 aws_lambda_builders/workflows/rust_cargo/exceptions.py create mode 100644 aws_lambda_builders/workflows/rust_cargo/feature_flag.py create mode 100644 aws_lambda_builders/workflows/rust_cargo/utils.py create mode 100644 aws_lambda_builders/workflows/rust_cargo/workflow.py create mode 100644 tests/integration/workflows/rust_cargo/test_rust_cargo.py create mode 100644 tests/integration/workflows/rust_cargo/testdata/fail/.gitignore create mode 100644 tests/integration/workflows/rust_cargo/testdata/fail/Cargo.lock create mode 100644 tests/integration/workflows/rust_cargo/testdata/fail/Cargo.toml create mode 100644 tests/integration/workflows/rust_cargo/testdata/fail/src/main.rs create mode 100644 tests/integration/workflows/rust_cargo/testdata/hello/.gitignore create mode 100644 tests/integration/workflows/rust_cargo/testdata/hello/Cargo.lock create mode 100644 tests/integration/workflows/rust_cargo/testdata/hello/Cargo.toml create mode 100644 tests/integration/workflows/rust_cargo/testdata/hello/src/main.rs create mode 100644 tests/integration/workflows/rust_cargo/testdata/multi-binary/.gitignore create mode 100644 tests/integration/workflows/rust_cargo/testdata/multi-binary/Cargo.lock create mode 100644 tests/integration/workflows/rust_cargo/testdata/multi-binary/Cargo.toml create mode 100644 tests/integration/workflows/rust_cargo/testdata/multi-binary/src/function_a.rs create mode 100644 tests/integration/workflows/rust_cargo/testdata/multi-binary/src/function_b.rs create mode 100644 tests/integration/workflows/rust_cargo/testdata/workspaces/.gitignore create mode 100644 tests/integration/workflows/rust_cargo/testdata/workspaces/Cargo.lock create mode 100644 tests/integration/workflows/rust_cargo/testdata/workspaces/Cargo.toml create mode 100644 tests/integration/workflows/rust_cargo/testdata/workspaces/bar/Cargo.toml create mode 100644 tests/integration/workflows/rust_cargo/testdata/workspaces/bar/src/main.rs create mode 100644 tests/integration/workflows/rust_cargo/testdata/workspaces/foo/Cargo.toml create mode 100644 tests/integration/workflows/rust_cargo/testdata/workspaces/foo/src/main.rs create mode 100644 tests/unit/workflows/rust_cargo/__init__.py create mode 100644 tests/unit/workflows/rust_cargo/test_actions.py create mode 100644 tests/unit/workflows/rust_cargo/test_cargo_lambda.py create mode 100644 tests/unit/workflows/rust_cargo/test_utils.py create mode 100644 tests/unit/workflows/rust_cargo/test_workflow.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5955909da..f4b321ffa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,6 +21,7 @@ jobs: - python-integration - ruby-integration - dotnet-integration + - rust-cargo-lambda-integration steps: - name: report-failure if: | @@ -33,7 +34,8 @@ jobs: needs.custom-make-integration.result != 'success' || needs.python-integration.result != 'success' || needs.ruby-integration.result != 'success' || - needs.dotnet-integration.result != 'success' + needs.dotnet-integration.result != 'success' || + needs.rust-cargo-lambda-integration.result != 'success' run: exit 1 - name: report-success run: exit 0 @@ -296,3 +298,57 @@ jobs: python-version: ${{ matrix.python }} - run: make init - run: pytest -vv tests/integration/workflows/dotnet_clipackage + + rust-cargo-lambda-integration: + name: ${{ matrix.os }} / ${{ matrix.python }} / rust-cargo-lambda + if: github.repository_owner == 'aws' + runs-on: ${{ matrix.os }} + env: + CARGO_LAMBDA_VERSION: 0.15.0 + defaults: + run: + shell: bash + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + - windows-latest + python: + - "3.9" + - "3.8" + - "3.7" + rust: + - stable + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python }} + + # Install and configure Rust + - name: Install rustup + run: | + : install rustup if needed + if ! command -v rustup &> /dev/null ; then + curl --proto '=https' --tlsv1.2 --retry 10 --retry-connrefused -fsSL "https://sh.rustup.rs" | sh -s -- --default-toolchain none -y + echo "${CARGO_HOME:-$HOME/.cargo}/bin" >> $GITHUB_PATH + fi + if: ${{ matrix.os }} == 'ubuntu-latest' + - name: rustup toolchain install ${{ matrix.rust }} + run: rustup toolchain install ${{ matrix.rust }} --profile minimal --no-self-update + - run: rustup default ${{ matrix.rust }} + - run: | + : disable incremental compilation + echo CARGO_INCREMENTAL=0 >> $GITHUB_ENV + - run: | + : enable colors in Cargo output + echo CARGO_TERM_COLOR=always >> $GITHUB_ENV + + # Install and configure Cargo Lambda + - name: Install Cargo Lambda + run: pip install cargo-lambda==$CARGO_LAMBDA_VERSION + - run: echo "$HOME/.local/bin" >> $GITHUB_PATH + + - run: make init + - run: pytest -vv tests/integration/workflows/rust_cargo diff --git a/Makefile b/Makefile index 7b4b49ec5..a4b44ad32 100644 --- a/Makefile +++ b/Makefile @@ -2,10 +2,13 @@ init: LAMBDA_BUILDERS_DEV=1 pip install -e '.[dev]' test: - # Run unit tests + # Run unit and functional tests # Fail if coverage falls below 94% LAMBDA_BUILDERS_DEV=1 pytest -vv --cov aws_lambda_builders --cov-report term-missing --cov-fail-under 94 tests/unit tests/functional +unit-test: + LAMBDA_BUILDERS_DEV=1 pytest tests/unit + func-test: LAMBDA_BUILDERS_DEV=1 pytest tests/functional diff --git a/README.md b/README.md index 5b8db24c5..c7528017c 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Lambda Builders currently contains the following workflows * Typescript with esbuild * Ruby with Bundler * Go with Mod +* Rust with Cargo In Addition to above workflows, AWS Lambda Builders also supports *Custom Workflows* through a Makefile. diff --git a/aws_lambda_builders/workflows/__init__.py b/aws_lambda_builders/workflows/__init__.py index 4f7402492..6966c0758 100644 --- a/aws_lambda_builders/workflows/__init__.py +++ b/aws_lambda_builders/workflows/__init__.py @@ -11,3 +11,4 @@ import aws_lambda_builders.workflows.dotnet_clipackage import aws_lambda_builders.workflows.custom_make import aws_lambda_builders.workflows.nodejs_npm_esbuild +import aws_lambda_builders.workflows.rust_cargo diff --git a/aws_lambda_builders/workflows/rust_cargo/DESIGN.md b/aws_lambda_builders/workflows/rust_cargo/DESIGN.md new file mode 100644 index 000000000..4b504503d --- /dev/null +++ b/aws_lambda_builders/workflows/rust_cargo/DESIGN.md @@ -0,0 +1,28 @@ +# Rust Cargo Builder + +## Scope + +This package enables the creation of a Lambda deployment package for Rust projects managed using the [cargo](https://doc.rust-lang.org/cargo/) build tool targeting Lambda's "provided" runtime. Rust support for the provided runtime is bundled as a compilation dependency of these projects, provided by the [lambda](https://github.com/awslabs/aws-lambda-rust-runtime) crate. + +## Implementation + +This package uses [Cargo Lambda](https://www.cargo-lambda.info) to do all the heavy lifting for cross compilation, target validation, and other executable optimizations. + +It supports X86-64 architectures with the target `x86_64-unknown-linux-gnu` by default. It also supports ARM architectures with the target option `aarch64-unknown-linux-gnu`. Those are the only two valid targets. The target is automatically configured based on the `architecture` option in the `RustCargoLambdaWorkflow`. + +The general algorithm for preparing a rust executable for use on AWS Lambda is as follows. + +### Build + +It builds a binary in the standard cargo target directory. The binary's name is always `bootstrap`, and it's always located under `target/lambda/HANDLER_NAME/bootstrap`. + +### Copy and Rename executable + +It then copies the executable to the target directory honoring the provided runtime's [expectation on executable names](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html). + +## Notes + +Like the go builders, the workflow argument `options.artifact_executable_name` +interface can used to provide a handler name that resolves to an executable. This +enables sam support for cargo workspaces allowing for one rust project to have multiple lambdas. Cargo workspaces have a notion of a `package` and `bin`. A `package` can have +multiple bins but typically `packages` have a 1-to-1 relationship with a default `bin`: `main.rs`. The handler names must be uniques across a Rust project, regardless of how many packages and binaries that project includes. diff --git a/aws_lambda_builders/workflows/rust_cargo/__init__.py b/aws_lambda_builders/workflows/rust_cargo/__init__.py new file mode 100644 index 000000000..149e66e07 --- /dev/null +++ b/aws_lambda_builders/workflows/rust_cargo/__init__.py @@ -0,0 +1,5 @@ +""" +Builds Rust Lambda functions using Cargo Lambda +""" + +from .workflow import RustCargoLambdaWorkflow diff --git a/aws_lambda_builders/workflows/rust_cargo/actions.py b/aws_lambda_builders/workflows/rust_cargo/actions.py new file mode 100644 index 000000000..c585594c8 --- /dev/null +++ b/aws_lambda_builders/workflows/rust_cargo/actions.py @@ -0,0 +1,146 @@ +""" +Rust Cargo build actions +""" + +import logging +import os + +from aws_lambda_builders.workflow import BuildMode +from aws_lambda_builders.actions import ActionFailedError, BaseAction, Purpose +from aws_lambda_builders.architecture import X86_64, ARM64 +from .exceptions import CargoLambdaExecutionException +from .utils import OSUtils + + +LOG = logging.getLogger(__name__) + + +class RustCargoLambdaBuildAction(BaseAction): + NAME = "CargoLambdaBuild" + DESCRIPTION = "Building the project using Cargo Lambda" + PURPOSE = Purpose.COMPILE_SOURCE + + def __init__( + self, + source_dir, + binaries, + mode, + subprocess_cargo_lambda, + architecture=X86_64, + handler=None, + flags=None, + ): + """ + Build the a Rust executable + + :type source_dir: str + :param source_dir: + Path to a folder containing the source code + + :type binaries: dict + :param binaries: + Resolved path dependencies + + :type mode: str + :param mode: + Mode the build should produce + + :type architecture: str, optional + :param architecture: + Target architecture to build the binary, either arm64 or x86_64 + + :type handler: str, optional + :param handler: + Handler name in `bin_name` format + + :type flags: list, optional + :param flags: + Extra list of flags to pass to `cargo lambda build` + + :type subprocess_cargo_lambda: aws_lambda_builders.workflows.rust_cargo.cargo_lambda.SubprocessCargoLambda + :param subprocess_cargo_lambda: An instance of the Cargo Lambda process wrapper + """ + + self._source_dir = source_dir + self._mode = mode + self._binaries = binaries + self._handler = handler + self._flags = flags + self._architecture = architecture + self._subprocess_cargo_lambda = subprocess_cargo_lambda + + def build_command(self): + cmd = [self._binaries["cargo"].binary_path, "lambda", "build"] + if self._mode != BuildMode.DEBUG: + cmd.append("--release") + if self._architecture == ARM64: + cmd.append("--arm64") + if self._handler: + cmd.extend(["--bin", self._handler]) + if self._flags: + cmd.extend(self._flags) + + return cmd + + def execute(self): + try: + return self._subprocess_cargo_lambda.run(command=self.build_command(), cwd=self._source_dir) + except CargoLambdaExecutionException as ex: + raise ActionFailedError(str(ex)) + + +class RustCopyAndRenameAction(BaseAction): + NAME = "RustCopyAndRename" + DESCRIPTION = "Copy Rust executable, renaming if needed" + PURPOSE = Purpose.COPY_SOURCE + + def __init__(self, source_dir, artifacts_dir, handler=None, osutils=OSUtils()): + """ + Copy and rename Rust executable + + Parameters + ---------- + source_dir : str + Path to a folder containing the source code + + artifacts_dir : str + Path to a folder containing the deployable artifacts + + handler : str, optional + Handler name in `package.bin_name` or `bin_name` format + + osutils : aws_lambda_builders.workflows.rust_cargo.utils.OSUtils, optional + Optional, External IO utils + """ + self._source_dir = source_dir + self._handler = handler + self._artifacts_dir = artifacts_dir + self._osutils = osutils + + def base_path(self): + return os.path.join(self._source_dir, "target", "lambda") + + def binary_path(self): + base = self.base_path() + if self._handler: + binary_path = os.path.join(base, self._handler, "bootstrap") + LOG.debug("copying function binary from %s", binary_path) + return binary_path + + output = os.listdir(base) + if len(output) == 1: + binary_path = os.path.join(base, output[0], "bootstrap") + LOG.debug("copying function binary from %s", binary_path) + return binary_path + + LOG.warning("unexpected list of binary directories: [%s]", ", ".join(output)) + raise CargoLambdaExecutionException( + message="unable to find function binary, use the option `artifact_executable_name` to specify the name" + ) + + def execute(self): + self._osutils.makedirs(self._artifacts_dir) + binary_path = self.binary_path() + destination_path = os.path.join(self._artifacts_dir, "bootstrap") + LOG.debug("copying function binary from %s to %s", binary_path, destination_path) + self._osutils.copyfile(binary_path, destination_path) diff --git a/aws_lambda_builders/workflows/rust_cargo/cargo_lambda.py b/aws_lambda_builders/workflows/rust_cargo/cargo_lambda.py new file mode 100644 index 000000000..0facf0286 --- /dev/null +++ b/aws_lambda_builders/workflows/rust_cargo/cargo_lambda.py @@ -0,0 +1,131 @@ +""" +Wrapper around calling Cargo Lambda through a subprocess. +""" +import io +import logging +import os +import subprocess +import shutil +import threading + +from .exceptions import CargoLambdaExecutionException +from .utils import OSUtils + + +LOG = logging.getLogger(__name__) + + +class SubprocessCargoLambda(object): + """ + Wrapper around the Cargo Lambda command line utility, making it + easy to consume execution results. + """ + + def __init__(self, which, executable_search_paths=None, osutils=OSUtils()): + """ + Parameters + ---------- + which : aws_lambda_builders.utils.which + Function to get paths which conform to the given mode on the PATH + with the prepended additional search paths + + executable_search_paths : list, optional + List of paths to the NPM package binary utilities. This will + be used to find embedded esbuild at runtime if present in the package + + osutils : aws_lambda_builders.workflows.rust_cargo.utils.OSUtils, optional + An instance of OS Utilities for file manipulation + """ + self._which = which + self._executable_search_paths = executable_search_paths + self._osutils = osutils + + def check_cargo_lambda_installation(self): + """ + Checks if Cargo Lambda is in the system + + Returns + ------- + str + Path to the cargo-lambda binary + + Raises + ------ + CargoLambdaExecutionException: + Raised when Cargo Lambda is not installed in the system to run the command. + """ + + LOG.debug("checking for cargo-lambda") + binaries = self._which("cargo-lambda", executable_search_paths=self._executable_search_paths) + LOG.debug("potential cargo-lambda binaries: %s", binaries) + + if binaries: + return binaries[0] + else: + raise CargoLambdaExecutionException( + message="Cannot find Cargo Lambda. " + "Cargo Lambda must be installed on the host machine to use this feature. " + "Follow the gettings started guide to learn how to install it: " + "https://www.cargo-lambda.info/guide/getting-started.html" + ) + + def run(self, command, cwd): + """ + Runs the build command. + + Parameters + ---------- + command : str + Cargo Lambda command to run + + cwd : str + Directory where to execute the command (defaults to current dir) + + Returns + ------- + str + Text of the standard output from the command + + Raises + ------ + CargoLambdaExecutionException: + Raised when the command executes with a non-zero return code. The exception will + contain the text of the standard error output from the command. + """ + + self.check_cargo_lambda_installation() + + LOG.debug("Executing cargo-lambda: %s", " ".join(command)) + if LOG.isEnabledFor(logging.DEBUG): + if "RUST_LOG" not in os.environ: + os.environ["RUST_LOG"] = "debug" + LOG.debug("RUST_LOG environment variable set to `%s`", os.environ.get("RUST_LOG")) + cargo_process = self._osutils.popen( + command, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + cwd=cwd, + ) + stdout = "" + # Create a buffer and use a thread to gather the stderr stream into the buffer + stderr_buf = io.BytesIO() + stderr_thread = threading.Thread( + target=shutil.copyfileobj, args=(cargo_process.stderr, stderr_buf), daemon=True + ) + stderr_thread.start() + + # Log every stdout line by iterating + for line in cargo_process.stdout: + decoded_line = line.decode("utf-8").strip() + LOG.info(decoded_line) + # Gather total stdout + stdout += decoded_line + + # Wait for the process to exit and stderr thread to end. + return_code = cargo_process.wait() + stderr_thread.join() + + if return_code != 0: + # Raise an Error with the appropriate value from the stderr buffer. + raise CargoLambdaExecutionException(message=stderr_buf.getvalue().decode("utf8").strip()) + return stdout diff --git a/aws_lambda_builders/workflows/rust_cargo/exceptions.py b/aws_lambda_builders/workflows/rust_cargo/exceptions.py new file mode 100644 index 000000000..39d6a02dd --- /dev/null +++ b/aws_lambda_builders/workflows/rust_cargo/exceptions.py @@ -0,0 +1,14 @@ +""" +Cargo Lambda specific exceptions +""" + +from aws_lambda_builders.exceptions import LambdaBuilderError + + +class CargoLambdaExecutionException(LambdaBuilderError): + """ + Exception raised in case Cargo Lambda execution fails. + It will pass on the standard error output from the Cargo Lambda console. + """ + + MESSAGE = "Cargo Lambda failed: {message}" diff --git a/aws_lambda_builders/workflows/rust_cargo/feature_flag.py b/aws_lambda_builders/workflows/rust_cargo/feature_flag.py new file mode 100644 index 000000000..fca068225 --- /dev/null +++ b/aws_lambda_builders/workflows/rust_cargo/feature_flag.py @@ -0,0 +1,12 @@ +""" +Cargo Lambda specific feature flag utilities +""" + +EXPERIMENTAL_FLAG_CARGO_LAMBDA = "experimentalCargoLambda" + + +def is_experimental_cargo_lambda_scope(experimental_flags): + """ + A function which will determine if experimental Cargo Lambda scope is active + """ + return bool(experimental_flags) and EXPERIMENTAL_FLAG_CARGO_LAMBDA in experimental_flags diff --git a/aws_lambda_builders/workflows/rust_cargo/utils.py b/aws_lambda_builders/workflows/rust_cargo/utils.py new file mode 100644 index 000000000..99aed66ab --- /dev/null +++ b/aws_lambda_builders/workflows/rust_cargo/utils.py @@ -0,0 +1,20 @@ +import os +import subprocess +import shutil + + +class OSUtils(object): + """ + Wrapper around file system functions, to make it easy to + unit test actions in memory + """ + + def popen(self, command, stdout=None, stderr=None, env=None, cwd=None): + return subprocess.Popen(command, stdout=stdout, stderr=stderr, env=env, cwd=cwd) + + def copyfile(self, source, destination): + shutil.copy2(source, destination) + + def makedirs(self, path): + if not os.path.exists(path): + os.makedirs(path) diff --git a/aws_lambda_builders/workflows/rust_cargo/workflow.py b/aws_lambda_builders/workflows/rust_cargo/workflow.py new file mode 100644 index 000000000..dcd971c65 --- /dev/null +++ b/aws_lambda_builders/workflows/rust_cargo/workflow.py @@ -0,0 +1,59 @@ +""" +Rust Cargo Workflow +""" + +from aws_lambda_builders.utils import which +from aws_lambda_builders.path_resolver import PathResolver +from aws_lambda_builders.workflow import BaseWorkflow, Capability, BuildInSourceSupport, BuildDirectory +from .actions import RustCargoLambdaBuildAction, RustCopyAndRenameAction +from .cargo_lambda import SubprocessCargoLambda +from .exceptions import CargoLambdaExecutionException +from .feature_flag import is_experimental_cargo_lambda_scope + + +class RustCargoLambdaWorkflow(BaseWorkflow): + NAME = "RustCargoLambdaBuilder" + + CAPABILITY = Capability(language="rust", dependency_manager="cargo", application_framework=None) + + DEFAULT_BUILD_DIR = BuildDirectory.SOURCE + BUILD_IN_SOURCE_SUPPORT = BuildInSourceSupport.EXCLUSIVELY_SUPPORTED + + SUPPORTED_MANIFESTS = ["Cargo.toml"] + + def __init__(self, source_dir, artifacts_dir, scratch_dir, manifest_path, runtime=None, mode=None, **kwargs): + super(RustCargoLambdaWorkflow, self).__init__( + source_dir, artifacts_dir, scratch_dir, manifest_path, runtime=runtime, **kwargs + ) + if not is_experimental_cargo_lambda_scope(self.experimental_flags): + raise CargoLambdaExecutionException( + message="Feature flag `experimentalCargoLambda` must be enabled to use this workflow" + ) + + # we utilize the handler identifier to + # select the binary to build + options = kwargs.get("options") or {} + handler = options.get("artifact_executable_name") + flags = options.get("cargo_lambda_flags") + subprocess_cargo_lambda = SubprocessCargoLambda(which=which) + self.actions = [ + RustCargoLambdaBuildAction( + source_dir, + self.binaries, + mode, + subprocess_cargo_lambda, + self.architecture, + handler, + flags, + ), + RustCopyAndRenameAction(source_dir, artifacts_dir, handler), + ] + + def get_resolvers(self): + """ + specialized path resolver that just returns the list of executable for the runtime on the path. + """ + return [ + PathResolver(runtime=self.runtime, binary="cargo"), + PathResolver(runtime=self.runtime, binary="cargo-lambda"), + ] diff --git a/tests/integration/workflows/rust_cargo/test_rust_cargo.py b/tests/integration/workflows/rust_cargo/test_rust_cargo.py new file mode 100644 index 000000000..2fb846718 --- /dev/null +++ b/tests/integration/workflows/rust_cargo/test_rust_cargo.py @@ -0,0 +1,184 @@ +import os +import shutil +import tempfile + +from unittest import TestCase + +from aws_lambda_builders.builder import LambdaBuilder +from aws_lambda_builders.exceptions import WorkflowFailedError +from aws_lambda_builders.workflows.rust_cargo.feature_flag import EXPERIMENTAL_FLAG_CARGO_LAMBDA + + +def rm_target_lambda(base): + shutil.rmtree(os.path.join(base, "target", "lambda"), ignore_errors=True) + + +class TestRustCargo(TestCase): + """ + Verifies that rust workflow works by building a Lambda using cargo + """ + + TEST_DATA_FOLDER = os.path.join(os.path.dirname(__file__), "testdata") + + def setUp(self): + self.artifacts_dir = tempfile.mkdtemp() + self.scratch_dir = tempfile.mkdtemp() + self.runtime = "provided" + # this inherently tests that rust was was wired up though + # the registry, a runtime error would be raised here if not + self.builder = LambdaBuilder(language="rust", dependency_manager="cargo", application_framework=None) + + def tearDown(self): + shutil.rmtree(self.artifacts_dir) + shutil.rmtree(self.scratch_dir) + + def test_failed_build_project(self): + source_dir = os.path.join(self.TEST_DATA_FOLDER, "fail") + + with self.assertRaises(WorkflowFailedError) as raised: + self.builder.build( + source_dir, + self.artifacts_dir, + self.scratch_dir, + os.path.join(source_dir, "Cargo.toml"), + runtime=self.runtime, + options={"artifact_executable_name": "fail"}, + experimental_flags=[EXPERIMENTAL_FLAG_CARGO_LAMBDA], + ) + self.assertTrue( + raised.exception.args[0].startswith("RustCargoLambdaBuilder:CargoLambdaBuild - Cargo Lambda failed"), + raised.exception.args[0], + ) + + def test_builds_hello_project(self): + source_dir = os.path.join(self.TEST_DATA_FOLDER, "hello") + rm_target_lambda(source_dir) + + self.builder.build( + source_dir, + self.artifacts_dir, + self.scratch_dir, + os.path.join(source_dir, "Cargo.toml"), + runtime=self.runtime, + experimental_flags=[EXPERIMENTAL_FLAG_CARGO_LAMBDA], + ) + + expected_files = {"bootstrap"} + output_files = set(os.listdir(self.artifacts_dir)) + + self.assertEqual(expected_files, output_files) + + def test_builds_hello_project_with_artifact_name(self): + source_dir = os.path.join(self.TEST_DATA_FOLDER, "hello") + rm_target_lambda(source_dir) + + self.builder.build( + source_dir, + self.artifacts_dir, + self.scratch_dir, + os.path.join(source_dir, "Cargo.toml"), + runtime=self.runtime, + options={"artifact_executable_name": "hello"}, + experimental_flags=[EXPERIMENTAL_FLAG_CARGO_LAMBDA], + ) + + expected_files = {"bootstrap"} + output_files = set(os.listdir(self.artifacts_dir)) + + self.assertEqual(expected_files, output_files) + + def test_builds_hello_project_for_arm64(self): + source_dir = os.path.join(self.TEST_DATA_FOLDER, "hello") + rm_target_lambda(source_dir) + + self.builder.build( + source_dir, + self.artifacts_dir, + self.scratch_dir, + os.path.join(source_dir, "Cargo.toml"), + architecture="arm64", + runtime=self.runtime, + options={"artifact_executable_name": "hello"}, + experimental_flags=[EXPERIMENTAL_FLAG_CARGO_LAMBDA], + ) + + expected_files = {"bootstrap"} + output_files = set(os.listdir(self.artifacts_dir)) + + self.assertEqual(expected_files, output_files) + + def test_builds_workspaces_project_with_bin_name(self): + source_dir = os.path.join(self.TEST_DATA_FOLDER, "workspaces") + rm_target_lambda(source_dir) + + self.builder.build( + source_dir, + self.artifacts_dir, + self.scratch_dir, + os.path.join(source_dir, "Cargo.toml"), + runtime=self.runtime, + options={"artifact_executable_name": "foo"}, + experimental_flags=[EXPERIMENTAL_FLAG_CARGO_LAMBDA], + ) + + expected_files = {"bootstrap"} + output_files = set(os.listdir(self.artifacts_dir)) + + self.assertEqual(expected_files, output_files) + + def test_builds_workspaces_project_with_package_option(self): + source_dir = os.path.join(self.TEST_DATA_FOLDER, "workspaces") + rm_target_lambda(source_dir) + + self.builder.build( + source_dir, + self.artifacts_dir, + self.scratch_dir, + os.path.join(source_dir, "Cargo.toml"), + runtime=self.runtime, + options={"cargo_lambda_flags": ["--package", "foo"]}, + experimental_flags=[EXPERIMENTAL_FLAG_CARGO_LAMBDA], + ) + + expected_files = {"bootstrap"} + output_files = set(os.listdir(self.artifacts_dir)) + + self.assertEqual(expected_files, output_files) + + def test_builds_multi_function_project_with_function_a(self): + source_dir = os.path.join(self.TEST_DATA_FOLDER, "multi-binary") + rm_target_lambda(source_dir) + + self.builder.build( + source_dir, + self.artifacts_dir, + self.scratch_dir, + os.path.join(source_dir, "Cargo.toml"), + runtime=self.runtime, + options={"artifact_executable_name": "function_a"}, + experimental_flags=[EXPERIMENTAL_FLAG_CARGO_LAMBDA], + ) + + expected_files = {"bootstrap"} + output_files = set(os.listdir(self.artifacts_dir)) + + self.assertEqual(expected_files, output_files) + + def test_builds_multi_function_project_with_function_b(self): + source_dir = os.path.join(self.TEST_DATA_FOLDER, "multi-binary") + rm_target_lambda(source_dir) + + self.builder.build( + source_dir, + self.artifacts_dir, + self.scratch_dir, + os.path.join(source_dir, "Cargo.toml"), + runtime=self.runtime, + options={"artifact_executable_name": "function_b"}, + experimental_flags=[EXPERIMENTAL_FLAG_CARGO_LAMBDA], + ) + + expected_files = {"bootstrap"} + output_files = set(os.listdir(self.artifacts_dir)) + + self.assertEqual(expected_files, output_files) diff --git a/tests/integration/workflows/rust_cargo/testdata/fail/.gitignore b/tests/integration/workflows/rust_cargo/testdata/fail/.gitignore new file mode 100644 index 000000000..1de565933 --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/fail/.gitignore @@ -0,0 +1 @@ +target \ No newline at end of file diff --git a/tests/integration/workflows/rust_cargo/testdata/fail/Cargo.lock b/tests/integration/workflows/rust_cargo/testdata/fail/Cargo.lock new file mode 100644 index 000000000..f15e92225 --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/fail/Cargo.lock @@ -0,0 +1,727 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "async-stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "fail" +version = "0.1.0" +dependencies = [ + "lambda_runtime", + "serde_json", + "tokio", +] + +[[package]] +name = "flate2" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "hdrhistogram" +version = "7.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31672b7011be2c4f7456c4ddbcb40e7e9a4a9fad8efe49a6ebaf5f307d0109c0" +dependencies = [ + "base64", + "byteorder", + "crossbeam-channel", + "flate2", + "nom", + "num-traits", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "http" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "indexmap" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "lambda_runtime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c73464e59463e91bf179195a308738477df90240173649d5dd2a1f3a2e4a2d2" +dependencies = [ + "async-stream", + "bytes", + "http", + "hyper", + "lambda_runtime_api_client", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", +] + +[[package]] +name = "lambda_runtime_api_client" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e921024b5eb4e2f0800a5d6e25c7ed554562aa62f02cf5f60a48c26c8a678974" +dependencies = [ + "http", + "hyper", + "tokio", + "tower-service", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" + +[[package]] +name = "log" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "mio" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "wasi 0.11.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "pin-project" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "syn" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "tokio" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e" +dependencies = [ + "futures-core", + "futures-util", + "hdrhistogram", + "indexmap", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tracing" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/tests/integration/workflows/rust_cargo/testdata/fail/Cargo.toml b/tests/integration/workflows/rust_cargo/testdata/fail/Cargo.toml new file mode 100644 index 000000000..97c36973f --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/fail/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "fail" +version = "0.1.0" +edition = "2018" + +[dependencies] +lambda_runtime = "0.5.1" +serde_json = "1" +tokio = { version = "1.17", features = ["macros", "rt"] } \ No newline at end of file diff --git a/tests/integration/workflows/rust_cargo/testdata/fail/src/main.rs b/tests/integration/workflows/rust_cargo/testdata/fail/src/main.rs new file mode 100644 index 000000000..a649502ef --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/fail/src/main.rs @@ -0,0 +1,10 @@ +use lambda::{lambda, Context}; +use serde_json::Value; + +// fails to compile because missing semi colon +type Error = Box + +#[tokio::main] +async fn main(event: Value, _: Context) -> Result { + Ok(event) +} \ No newline at end of file diff --git a/tests/integration/workflows/rust_cargo/testdata/hello/.gitignore b/tests/integration/workflows/rust_cargo/testdata/hello/.gitignore new file mode 100644 index 000000000..1de565933 --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/hello/.gitignore @@ -0,0 +1 @@ +target \ No newline at end of file diff --git a/tests/integration/workflows/rust_cargo/testdata/hello/Cargo.lock b/tests/integration/workflows/rust_cargo/testdata/hello/Cargo.lock new file mode 100644 index 000000000..22725e9be --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/hello/Cargo.lock @@ -0,0 +1,727 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "async-stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "flate2" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "hdrhistogram" +version = "7.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31672b7011be2c4f7456c4ddbcb40e7e9a4a9fad8efe49a6ebaf5f307d0109c0" +dependencies = [ + "base64", + "byteorder", + "crossbeam-channel", + "flate2", + "nom", + "num-traits", +] + +[[package]] +name = "hello" +version = "0.1.0" +dependencies = [ + "lambda_runtime", + "serde", + "tokio", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "http" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "indexmap" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "lambda_runtime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c73464e59463e91bf179195a308738477df90240173649d5dd2a1f3a2e4a2d2" +dependencies = [ + "async-stream", + "bytes", + "http", + "hyper", + "lambda_runtime_api_client", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", +] + +[[package]] +name = "lambda_runtime_api_client" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e921024b5eb4e2f0800a5d6e25c7ed554562aa62f02cf5f60a48c26c8a678974" +dependencies = [ + "http", + "hyper", + "tokio", + "tower-service", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" + +[[package]] +name = "log" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "mio" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "wasi 0.11.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "pin-project" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "syn" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "tokio" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e" +dependencies = [ + "futures-core", + "futures-util", + "hdrhistogram", + "indexmap", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tracing" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/tests/integration/workflows/rust_cargo/testdata/hello/Cargo.toml b/tests/integration/workflows/rust_cargo/testdata/hello/Cargo.toml new file mode 100644 index 000000000..cc282cc65 --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/hello/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "hello" +version = "0.1.0" +edition = "2018" + +[dependencies] +lambda_runtime = "0.5.1" +serde = "1" +tokio = { version = "1.17", features = ["macros", "rt"] } \ No newline at end of file diff --git a/tests/integration/workflows/rust_cargo/testdata/hello/src/main.rs b/tests/integration/workflows/rust_cargo/testdata/hello/src/main.rs new file mode 100644 index 000000000..aa2b6f93c --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/hello/src/main.rs @@ -0,0 +1,44 @@ +// This example requires the following input to succeed: +// { "command": "do something" } + +use lambda_runtime::{service_fn, Error, LambdaEvent}; +use serde::{Deserialize, Serialize}; + +/// This is also a made-up example. Requests come into the runtime as unicode +/// strings in json format, which can map to any structure that implements `serde::Deserialize` +/// The runtime pays no attention to the contents of the request payload. +#[derive(Deserialize)] +struct Request { + command: String, +} + +/// This is a made-up example of what a response structure may look like. +/// There is no restriction on what it can be. The runtime requires responses +/// to be serialized into json. The runtime pays no attention +/// to the contents of the response payload. +#[derive(Serialize)] +struct Response { + req_id: String, + msg: String, +} + +#[tokio::main] +async fn main() -> Result<(), Error> { + let func = service_fn(my_handler); + lambda_runtime::run(func).await?; + Ok(()) +} + +pub(crate) async fn my_handler(event: LambdaEvent) -> Result { + // extract some useful info from the request + let command = event.payload.command; + + // prepare the response + let resp = Response { + req_id: event.context.request_id, + msg: format!("Command {} executed at {:?}.", command, std::time::SystemTime::now()), + }; + + // return `Response` (it will be serialized to JSON automatically by the runtime) + Ok(resp) +} \ No newline at end of file diff --git a/tests/integration/workflows/rust_cargo/testdata/multi-binary/.gitignore b/tests/integration/workflows/rust_cargo/testdata/multi-binary/.gitignore new file mode 100644 index 000000000..1de565933 --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/multi-binary/.gitignore @@ -0,0 +1 @@ +target \ No newline at end of file diff --git a/tests/integration/workflows/rust_cargo/testdata/multi-binary/Cargo.lock b/tests/integration/workflows/rust_cargo/testdata/multi-binary/Cargo.lock new file mode 100644 index 000000000..0eabf8275 --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/multi-binary/Cargo.lock @@ -0,0 +1,581 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "async-stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bytes" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" + +[[package]] +name = "futures-task" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" + +[[package]] +name = "futures-util" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "itoa" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" + +[[package]] +name = "lambda_runtime" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cf2e2a435d327806e7c8d46d341d624a6a2e3b35b253eee44d1c89980451be" +dependencies = [ + "async-stream", + "bytes", + "http", + "hyper", + "lambda_runtime_api_client", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", +] + +[[package]] +name = "lambda_runtime_api_client" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b54698c666ffe503cb51fa66e4567e53e806128a10359de7095999d925a771ed" +dependencies = [ + "http", + "hyper", + "tokio", + "tower-service", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mio" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" + +[[package]] +name = "pin-project" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "proc-macro2" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "serde" +version = "1.0.144" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.144" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "syn" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "test-handler" +version = "0.1.0" +dependencies = [ + "lambda_runtime", + "serde", + "tokio", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tokio" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89797afd69d206ccd11fb0ea560a44bbb87731d020670e79416d442919257d42" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "pin-project-lite", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "unicode-ident" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/tests/integration/workflows/rust_cargo/testdata/multi-binary/Cargo.toml b/tests/integration/workflows/rust_cargo/testdata/multi-binary/Cargo.toml new file mode 100644 index 000000000..14063f523 --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/multi-binary/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "test-handler" +version = "0.1.0" +edition = "2021" + +# Starting in Rust 1.62 you can use `cargo add` to add dependencies +# to your project. +# +# If you're using an older Rust version, +# download cargo-edit(https://github.com/killercup/cargo-edit#installation) +# to install the `add` subcommand. +# +# Running `cargo add DEPENDENCY_NAME` will +# add the latest version of a dependency to the list, +# and it will keep the alphabetic ordering for you. + +[dependencies] + +lambda_runtime = "0.6.0" +serde = "1.0.136" +tokio = { version = "1", features = ["macros"] } +tracing = { version = "0.1", features = ["log"] } +tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt"] } + +[[bin]] +name = "function_a" +path = "src/function_a.rs" + +[[bin]] +name = "function_b" +path = "src/function_b.rs" diff --git a/tests/integration/workflows/rust_cargo/testdata/multi-binary/src/function_a.rs b/tests/integration/workflows/rust_cargo/testdata/multi-binary/src/function_a.rs new file mode 100644 index 000000000..be1f7c9ea --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/multi-binary/src/function_a.rs @@ -0,0 +1,53 @@ +use lambda_runtime::{run, service_fn, Error, LambdaEvent}; + +use serde::{Deserialize, Serialize}; + +/// This is a made-up example. Requests come into the runtime as unicode +/// strings in json format, which can map to any structure that implements `serde::Deserialize` +/// The runtime pays no attention to the contents of the request payload. +#[derive(Deserialize)] +struct Request { + command: String, +} + +/// This is a made-up example of what a response structure may look like. +/// There is no restriction on what it can be. The runtime requires responses +/// to be serialized into json. The runtime pays no attention +/// to the contents of the response payload. +#[derive(Serialize)] +struct Response { + req_id: String, + msg: String, +} + +/// This is the main body for the function. +/// Write your code inside it. +/// There are some code example in the following URLs: +/// - https://github.com/awslabs/aws-lambda-rust-runtime/tree/main/examples +/// - https://github.com/aws-samples/serverless-rust-demo/ +async fn function_handler(event: LambdaEvent) -> Result { + // Extract some useful info from the request + let command = event.payload.command; + + // Prepare the response + let resp = Response { + req_id: event.context.request_id, + msg: format!("Command {}.", command), + }; + + // Return `Response` (it will be serialized to JSON automatically by the runtime) + Ok(resp) +} + +#[tokio::main] +async fn main() -> Result<(), Error> { + tracing_subscriber::fmt() + .with_max_level(tracing::Level::INFO) + // disable printing the name of the module in every log line. + .with_target(false) + // disabling time is handy because CloudWatch will add the ingestion time. + .without_time() + .init(); + + run(service_fn(function_handler)).await +} diff --git a/tests/integration/workflows/rust_cargo/testdata/multi-binary/src/function_b.rs b/tests/integration/workflows/rust_cargo/testdata/multi-binary/src/function_b.rs new file mode 100644 index 000000000..be1f7c9ea --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/multi-binary/src/function_b.rs @@ -0,0 +1,53 @@ +use lambda_runtime::{run, service_fn, Error, LambdaEvent}; + +use serde::{Deserialize, Serialize}; + +/// This is a made-up example. Requests come into the runtime as unicode +/// strings in json format, which can map to any structure that implements `serde::Deserialize` +/// The runtime pays no attention to the contents of the request payload. +#[derive(Deserialize)] +struct Request { + command: String, +} + +/// This is a made-up example of what a response structure may look like. +/// There is no restriction on what it can be. The runtime requires responses +/// to be serialized into json. The runtime pays no attention +/// to the contents of the response payload. +#[derive(Serialize)] +struct Response { + req_id: String, + msg: String, +} + +/// This is the main body for the function. +/// Write your code inside it. +/// There are some code example in the following URLs: +/// - https://github.com/awslabs/aws-lambda-rust-runtime/tree/main/examples +/// - https://github.com/aws-samples/serverless-rust-demo/ +async fn function_handler(event: LambdaEvent) -> Result { + // Extract some useful info from the request + let command = event.payload.command; + + // Prepare the response + let resp = Response { + req_id: event.context.request_id, + msg: format!("Command {}.", command), + }; + + // Return `Response` (it will be serialized to JSON automatically by the runtime) + Ok(resp) +} + +#[tokio::main] +async fn main() -> Result<(), Error> { + tracing_subscriber::fmt() + .with_max_level(tracing::Level::INFO) + // disable printing the name of the module in every log line. + .with_target(false) + // disabling time is handy because CloudWatch will add the ingestion time. + .without_time() + .init(); + + run(service_fn(function_handler)).await +} diff --git a/tests/integration/workflows/rust_cargo/testdata/workspaces/.gitignore b/tests/integration/workflows/rust_cargo/testdata/workspaces/.gitignore new file mode 100644 index 000000000..1de565933 --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/workspaces/.gitignore @@ -0,0 +1 @@ +target \ No newline at end of file diff --git a/tests/integration/workflows/rust_cargo/testdata/workspaces/Cargo.lock b/tests/integration/workflows/rust_cargo/testdata/workspaces/Cargo.lock new file mode 100644 index 000000000..103c00784 --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/workspaces/Cargo.lock @@ -0,0 +1,736 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "async-stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bar" +version = "0.1.0" +dependencies = [ + "lambda_runtime", + "serde", + "tokio", +] + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "flate2" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foo" +version = "0.1.0" +dependencies = [ + "lambda_runtime", + "serde", + "tokio", +] + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "hdrhistogram" +version = "7.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31672b7011be2c4f7456c4ddbcb40e7e9a4a9fad8efe49a6ebaf5f307d0109c0" +dependencies = [ + "base64", + "byteorder", + "crossbeam-channel", + "flate2", + "nom", + "num-traits", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "http" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "indexmap" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "lambda_runtime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c73464e59463e91bf179195a308738477df90240173649d5dd2a1f3a2e4a2d2" +dependencies = [ + "async-stream", + "bytes", + "http", + "hyper", + "lambda_runtime_api_client", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", +] + +[[package]] +name = "lambda_runtime_api_client" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e921024b5eb4e2f0800a5d6e25c7ed554562aa62f02cf5f60a48c26c8a678974" +dependencies = [ + "http", + "hyper", + "tokio", + "tower-service", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" + +[[package]] +name = "log" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "mio" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "wasi 0.11.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "pin-project" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "syn" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "tokio" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e" +dependencies = [ + "futures-core", + "futures-util", + "hdrhistogram", + "indexmap", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tracing" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/tests/integration/workflows/rust_cargo/testdata/workspaces/Cargo.toml b/tests/integration/workflows/rust_cargo/testdata/workspaces/Cargo.toml new file mode 100644 index 000000000..7492eaa8e --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/workspaces/Cargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["foo", "bar"] \ No newline at end of file diff --git a/tests/integration/workflows/rust_cargo/testdata/workspaces/bar/Cargo.toml b/tests/integration/workflows/rust_cargo/testdata/workspaces/bar/Cargo.toml new file mode 100644 index 000000000..14b0e9377 --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/workspaces/bar/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "bar" +version = "0.1.0" +edition = "2018" + +[dependencies] +lambda_runtime = "0.5.1" +serde = "1" +tokio = { version = "1.17", features = ["macros", "rt"] } \ No newline at end of file diff --git a/tests/integration/workflows/rust_cargo/testdata/workspaces/bar/src/main.rs b/tests/integration/workflows/rust_cargo/testdata/workspaces/bar/src/main.rs new file mode 100644 index 000000000..aa2b6f93c --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/workspaces/bar/src/main.rs @@ -0,0 +1,44 @@ +// This example requires the following input to succeed: +// { "command": "do something" } + +use lambda_runtime::{service_fn, Error, LambdaEvent}; +use serde::{Deserialize, Serialize}; + +/// This is also a made-up example. Requests come into the runtime as unicode +/// strings in json format, which can map to any structure that implements `serde::Deserialize` +/// The runtime pays no attention to the contents of the request payload. +#[derive(Deserialize)] +struct Request { + command: String, +} + +/// This is a made-up example of what a response structure may look like. +/// There is no restriction on what it can be. The runtime requires responses +/// to be serialized into json. The runtime pays no attention +/// to the contents of the response payload. +#[derive(Serialize)] +struct Response { + req_id: String, + msg: String, +} + +#[tokio::main] +async fn main() -> Result<(), Error> { + let func = service_fn(my_handler); + lambda_runtime::run(func).await?; + Ok(()) +} + +pub(crate) async fn my_handler(event: LambdaEvent) -> Result { + // extract some useful info from the request + let command = event.payload.command; + + // prepare the response + let resp = Response { + req_id: event.context.request_id, + msg: format!("Command {} executed at {:?}.", command, std::time::SystemTime::now()), + }; + + // return `Response` (it will be serialized to JSON automatically by the runtime) + Ok(resp) +} \ No newline at end of file diff --git a/tests/integration/workflows/rust_cargo/testdata/workspaces/foo/Cargo.toml b/tests/integration/workflows/rust_cargo/testdata/workspaces/foo/Cargo.toml new file mode 100644 index 000000000..67b0af758 --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/workspaces/foo/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "foo" +version = "0.1.0" +edition = "2018" + +[dependencies] +lambda_runtime = "0.5.1" +serde = "1" +tokio = { version = "1.17", features = ["macros", "rt"] } \ No newline at end of file diff --git a/tests/integration/workflows/rust_cargo/testdata/workspaces/foo/src/main.rs b/tests/integration/workflows/rust_cargo/testdata/workspaces/foo/src/main.rs new file mode 100644 index 000000000..aa2b6f93c --- /dev/null +++ b/tests/integration/workflows/rust_cargo/testdata/workspaces/foo/src/main.rs @@ -0,0 +1,44 @@ +// This example requires the following input to succeed: +// { "command": "do something" } + +use lambda_runtime::{service_fn, Error, LambdaEvent}; +use serde::{Deserialize, Serialize}; + +/// This is also a made-up example. Requests come into the runtime as unicode +/// strings in json format, which can map to any structure that implements `serde::Deserialize` +/// The runtime pays no attention to the contents of the request payload. +#[derive(Deserialize)] +struct Request { + command: String, +} + +/// This is a made-up example of what a response structure may look like. +/// There is no restriction on what it can be. The runtime requires responses +/// to be serialized into json. The runtime pays no attention +/// to the contents of the response payload. +#[derive(Serialize)] +struct Response { + req_id: String, + msg: String, +} + +#[tokio::main] +async fn main() -> Result<(), Error> { + let func = service_fn(my_handler); + lambda_runtime::run(func).await?; + Ok(()) +} + +pub(crate) async fn my_handler(event: LambdaEvent) -> Result { + // extract some useful info from the request + let command = event.payload.command; + + // prepare the response + let resp = Response { + req_id: event.context.request_id, + msg: format!("Command {} executed at {:?}.", command, std::time::SystemTime::now()), + }; + + // return `Response` (it will be serialized to JSON automatically by the runtime) + Ok(resp) +} \ No newline at end of file diff --git a/tests/unit/workflows/rust_cargo/__init__.py b/tests/unit/workflows/rust_cargo/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/workflows/rust_cargo/test_actions.py b/tests/unit/workflows/rust_cargo/test_actions.py new file mode 100644 index 000000000..370fa0011 --- /dev/null +++ b/tests/unit/workflows/rust_cargo/test_actions.py @@ -0,0 +1,165 @@ +from unittest import TestCase +from mock import patch +import io +import logging +import os + +from aws_lambda_builders.actions import ActionFailedError +from aws_lambda_builders.binary_path import BinaryPath +from aws_lambda_builders.workflow import BuildMode +from aws_lambda_builders.workflows.rust_cargo.actions import ( + RustCargoLambdaBuildAction, + RustCopyAndRenameAction, +) +from aws_lambda_builders.workflows.rust_cargo.cargo_lambda import SubprocessCargoLambda + +LOG = logging.getLogger("aws_lambda_builders.workflows.rust_cargo.cargo_lambda") + + +class FakePopen: + def __init__(self, out=b"out", err=b"err", retcode=0): + self.out = out + self.err = err + self.stderr = io.BytesIO(err) + self.stdout = [out] + self.returncode = retcode + + def communicate(self): + return self.out, self.err + + def wait(self): + return self.returncode + + +class TestBuildAction(TestCase): + @patch("aws_lambda_builders.workflows.rust_cargo.actions.OSUtils") + def setUp(self, OSUtilMock): + self.osutils = OSUtilMock.return_value + self.osutils.popen.side_effect = [FakePopen()] + + def which(cmd, executable_search_paths): + return ["/bin/cargo-lambda"] + + proc = SubprocessCargoLambda(which=which, osutils=self.osutils) + self.subprocess_cargo_lambda = proc + + def test_release_build_cargo_command_without_release_mode(self): + cargo = BinaryPath(None, None, None, binary_path="path/to/cargo") + action = RustCargoLambdaBuildAction("source_dir", {"cargo": cargo}, None, self.subprocess_cargo_lambda) + self.assertEqual( + action.build_command(), + ["path/to/cargo", "lambda", "build", "--release"], + ) + + def test_release_build_cargo_command(self): + cargo = BinaryPath(None, None, None, binary_path="path/to/cargo") + action = RustCargoLambdaBuildAction( + "source_dir", {"cargo": cargo}, BuildMode.RELEASE, self.subprocess_cargo_lambda + ) + self.assertEqual( + action.build_command(), + ["path/to/cargo", "lambda", "build", "--release"], + ) + + def test_release_build_cargo_command_with_target(self): + cargo = BinaryPath(None, None, None, binary_path="path/to/cargo") + action = RustCargoLambdaBuildAction( + "source_dir", {"cargo": cargo}, BuildMode.RELEASE, self.subprocess_cargo_lambda, "arm64" + ) + self.assertEqual( + action.build_command(), + ["path/to/cargo", "lambda", "build", "--release", "--arm64"], + ) + + def test_debug_build_cargo_command(self): + cargo = BinaryPath(None, None, None, binary_path="path/to/cargo") + action = RustCargoLambdaBuildAction( + "source_dir", {"cargo": cargo}, BuildMode.DEBUG, self.subprocess_cargo_lambda + ) + self.assertEqual( + action.build_command(), + ["path/to/cargo", "lambda", "build"], + ) + + def test_debug_build_cargo_command_with_architecture(self): + cargo = BinaryPath(None, None, None, binary_path="path/to/cargo") + action = RustCargoLambdaBuildAction( + "source_dir", {"cargo": cargo}, BuildMode.DEBUG, self.subprocess_cargo_lambda, "arm64" + ) + self.assertEqual( + action.build_command(), + ["path/to/cargo", "lambda", "build", "--arm64"], + ) + + def test_debug_build_cargo_command_with_flags(self): + cargo = BinaryPath(None, None, None, binary_path="path/to/cargo") + flags = ["--package", "package-in-workspace"] + action = RustCargoLambdaBuildAction( + "source_dir", {"cargo": cargo}, BuildMode.DEBUG, self.subprocess_cargo_lambda, "arm64", flags=flags + ) + self.assertEqual( + action.build_command(), + ["path/to/cargo", "lambda", "build", "--arm64", "--package", "package-in-workspace"], + ) + + def test_debug_build_cargo_command_with_handler(self): + cargo = BinaryPath(None, None, None, binary_path="path/to/cargo") + action = RustCargoLambdaBuildAction( + "source_dir", {"cargo": cargo}, BuildMode.DEBUG, self.subprocess_cargo_lambda, "arm64", handler="foo" + ) + self.assertEqual( + action.build_command(), + ["path/to/cargo", "lambda", "build", "--arm64", "--bin", "foo"], + ) + + def test_execute_happy_path(self): + cargo = BinaryPath(None, None, None, binary_path="path/to/cargo") + action = RustCargoLambdaBuildAction( + "source_dir", {"cargo": cargo}, BuildMode.RELEASE, self.subprocess_cargo_lambda + ) + action.execute() + + def test_execute_cargo_build_fail(self): + popen = FakePopen(retcode=1, err=b"build failed") + self.subprocess_cargo_lambda._osutils.popen.side_effect = [popen] + + cargo = BinaryPath(None, None, None, binary_path="path/to/cargo") + action = RustCargoLambdaBuildAction( + "source_dir", {"cargo": cargo}, BuildMode.RELEASE, self.subprocess_cargo_lambda + ) + with self.assertRaises(ActionFailedError) as err_assert: + action.execute() + self.assertEqual(err_assert.exception.args[0], "Cargo Lambda failed: build failed") + + def test_execute_happy_with_logger(self): + LOG.setLevel(logging.DEBUG) + with patch.object(LOG, "debug") as mock_warning: + cargo = BinaryPath(None, None, None, binary_path="path/to/cargo") + action = RustCargoLambdaBuildAction( + "source_dir", {"cargo": cargo}, BuildMode.RELEASE, self.subprocess_cargo_lambda + ) + out = action.execute() + self.assertEqual(out, "out") + mock_warning.assert_called_with("RUST_LOG environment variable set to `%s`", "debug") + + +class TestCopyAndRenameAction(TestCase): + def test_debug_copy_path(self): + action = RustCopyAndRenameAction("source_dir", "output_dir", "foo") + self.assertEqual(action.binary_path(), os.path.join("source_dir", "target", "lambda", "foo", "bootstrap")) + + def test_release_copy_path(self): + action = RustCopyAndRenameAction("source_dir", "output_dir", "foo") + self.assertEqual(action.binary_path(), os.path.join("source_dir", "target", "lambda", "foo", "bootstrap")) + + def test_nonlinux_copy_path(self): + action = RustCopyAndRenameAction("source_dir", "output_dir", "foo") + self.assertEqual(action.binary_path(), os.path.join("source_dir", "target", "lambda", "foo", "bootstrap")) + + @patch("aws_lambda_builders.workflows.rust_cargo.actions.OSUtils") + def test_execute(self, OSUtilsMock): + osutils = OSUtilsMock.return_value + osutils.copyfile.return_value = "" + osutils.makedirs.return_value = "" + action = RustCopyAndRenameAction("source_dir", "foo", "output_dir", osutils=osutils) + action.execute() diff --git a/tests/unit/workflows/rust_cargo/test_cargo_lambda.py b/tests/unit/workflows/rust_cargo/test_cargo_lambda.py new file mode 100644 index 000000000..7fc86ecb7 --- /dev/null +++ b/tests/unit/workflows/rust_cargo/test_cargo_lambda.py @@ -0,0 +1,21 @@ +from unittest import TestCase + +from aws_lambda_builders.workflows.rust_cargo.actions import CargoLambdaExecutionException +from aws_lambda_builders.workflows.rust_cargo.cargo_lambda import SubprocessCargoLambda + + +class TestSubprocessCargoLambda(TestCase): + def test_raises_RustCargoLambdaBuilderError_if_which_returns_no_results(self): + def which(cmd, executable_search_paths): + return [] + + proc = SubprocessCargoLambda(which=which) + + with self.assertRaises(CargoLambdaExecutionException) as raised: + proc.run("cargo lambda build", "/source_dir") + + self.assertEqual( + raised.exception.args[0], + "Cargo Lambda failed: Cannot find Cargo Lambda. Cargo Lambda must be installed on the host machine to use this feature. " + "Follow the gettings started guide to learn how to install it: https://www.cargo-lambda.info/guide/getting-started.html", + ) diff --git a/tests/unit/workflows/rust_cargo/test_utils.py b/tests/unit/workflows/rust_cargo/test_utils.py new file mode 100644 index 000000000..6d1964fd7 --- /dev/null +++ b/tests/unit/workflows/rust_cargo/test_utils.py @@ -0,0 +1,25 @@ +import os +import sys +import subprocess + +from unittest import TestCase + +from aws_lambda_builders.workflows.rust_cargo.utils import OSUtils + + +class TestOSUtils(TestCase): + def test_popen_runs_a_process_and_returns_outcome(self): + cwd_py = os.path.join(os.path.dirname(__file__), "..", "..", "..", "functional", "testdata", "cwd.py") + p = OSUtils().popen([sys.executable, cwd_py], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + self.assertEqual(p.returncode, 0) + self.assertEqual(out.decode("utf8").strip(), os.getcwd()) + + def test_popen_can_accept_cwd(self): + testdata_dir = os.path.join(os.path.dirname(__file__), "..", "..", "..", "functional", "testdata") + p = OSUtils().popen( + [sys.executable, "cwd.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=testdata_dir + ) + out, err = p.communicate() + self.assertEqual(p.returncode, 0) + self.assertEqual(out.decode("utf8").strip(), os.path.abspath(testdata_dir)) diff --git a/tests/unit/workflows/rust_cargo/test_workflow.py b/tests/unit/workflows/rust_cargo/test_workflow.py new file mode 100644 index 000000000..ff34e03e4 --- /dev/null +++ b/tests/unit/workflows/rust_cargo/test_workflow.py @@ -0,0 +1,48 @@ +from unittest import TestCase + +from aws_lambda_builders.path_resolver import PathResolver +from aws_lambda_builders.workflows.rust_cargo.workflow import RustCargoLambdaWorkflow +from aws_lambda_builders.workflows.rust_cargo.actions import ( + RustCargoLambdaBuildAction, + RustCopyAndRenameAction, +) +from aws_lambda_builders.workflows.rust_cargo.feature_flag import EXPERIMENTAL_FLAG_CARGO_LAMBDA + + +class TestRustCargoLambdaWorkflow(TestCase): + """ + Validate workflow wiring + """ + + def test_workflow_sets_up_builder_actions(self): + workflow = RustCargoLambdaWorkflow( + "source", + "artifacts", + "scratch_dir", + "manifest", + runtime="provided", + experimental_flags=[EXPERIMENTAL_FLAG_CARGO_LAMBDA], + ) + self.assertEqual(len(workflow.actions), 2) + self.assertIsInstance(workflow.actions[0], RustCargoLambdaBuildAction) + self.assertIsInstance(workflow.actions[1], RustCopyAndRenameAction) + + def test_workflow_configures_path_resolver_for_cargo(self): + workflow = RustCargoLambdaWorkflow( + "source", + "artifacts", + "scratch_dir", + "manifest", + runtime="provided", + experimental_flags=[EXPERIMENTAL_FLAG_CARGO_LAMBDA], + ) + resolvers = workflow.get_resolvers() + self.assertEqual(len(resolvers), 2) + resolver = resolvers[0] + self.assertIsInstance(resolver, PathResolver) + self.assertEqual(resolver.binary, "cargo") + self.assertEqual(resolver.runtime, "provided") + resolver = resolvers[1] + self.assertIsInstance(resolver, PathResolver) + self.assertEqual(resolver.binary, "cargo-lambda") + self.assertEqual(resolver.runtime, "provided")