diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml new file mode 100644 index 0000000..f0757d1 --- /dev/null +++ b/.github/workflows/integration-tests.yml @@ -0,0 +1,139 @@ +name: integration-tests + +permissions: + contents: read + +on: + push: + branches: [main] + pull_request: + branches: ['*'] + workflow_dispatch: + +jobs: + integration-test: + runs-on: ${{ matrix.arch.runner }} + strategy: + fail-fast: false + matrix: + arch: + - runner: ubuntu-latest + rie: aws-lambda-rie + label: x64 + - runner: ubuntu-24.04-arm + rie: aws-lambda-rie-arm64 + label: arm64 + distro_config: + # al2023 + - distro: al2023 + distro_version: "al2023" + runtime_version: "3.4" + executable: /usr/local/bin/aws_lambda_ric + - distro: al2023 + distro_version: "al2023" + runtime_version: "3.3" + executable: /usr/local/bin/aws_lambda_ric + # Alpine + - distro: alpine + distro_version: "3.23" + runtime_version: "3.4" + executable: /usr/local/bundle/bin/aws_lambda_ric + - distro: alpine + distro_version: "3.23" + runtime_version: "3.3" + executable: /usr/local/bundle/bin/aws_lambda_ric + # Debian + - distro: debian + distro_version: bookworm + runtime_version: "3.4" + executable: /usr/local/bundle/bin/aws_lambda_ric + - distro: debian + distro_version: bookworm + runtime_version: "3.3" + executable: /usr/local/bundle/bin/aws_lambda_ric + # Ubuntu + - distro: ubuntu + distro_version: "24.04" + runtime_version: "3.4" + executable: /usr/local/bin/aws_lambda_ric + - distro: ubuntu + distro_version: "24.04" + runtime_version: "3.3" + executable: /usr/local/bin/aws_lambda_ric + + name: "${{ matrix.distro_config.distro }} ${{ matrix.distro_config.distro_version }} / ruby ${{ matrix.distro_config.runtime_version }} (${{ matrix.arch.label }})" + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Download RIE + run: | + mkdir -p .scratch + RIE_NAME="${{ matrix.arch.rie }}" + curl -sSL "https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/${RIE_NAME}" -o ".scratch/${RIE_NAME}" + chmod +x ".scratch/${RIE_NAME}" + echo "RIE_NAME=${RIE_NAME}" >> "$GITHUB_ENV" + + - name: Build Docker image + run: | + DOCKERFILE="test/integration/docker/Dockerfile.echo.${{ matrix.distro_config.distro }}" + TMPFILE=".scratch/Dockerfile.tmp" + cp "$DOCKERFILE" "$TMPFILE" + echo "COPY .scratch/${{ env.RIE_NAME }} /usr/bin/${{ env.RIE_NAME }}" >> "$TMPFILE" + docker build . \ + -f "$TMPFILE" \ + -t ric-test \ + --build-arg RUNTIME_VERSION=${{ matrix.distro_config.runtime_version }} \ + --build-arg DISTRO_VERSION=${{ matrix.distro_config.distro_version }} + + - name: Run integration test + run: | + TEST_NAME="ric-integ-test" + docker network create "${TEST_NAME}-net" + + # Start the Lambda function container with RIE + docker run \ + --detach \ + --name "${TEST_NAME}-app" \ + --network "${TEST_NAME}-net" \ + --entrypoint="" \ + ric-test \ + sh -c "/usr/bin/${{ env.RIE_NAME }} ${{ matrix.distro_config.executable }} app.App::Handler.process" + + # Wait for RIE to be ready + sleep 2 + + # Invoke the function + docker run \ + --name "${TEST_NAME}-tester" \ + --env "TARGET=${TEST_NAME}-app" \ + --network "${TEST_NAME}-net" \ + --entrypoint="" \ + ric-test \ + sh -c 'curl -sS -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' + + # Assert response + ACTUAL="$(docker logs --tail 1 "${TEST_NAME}-tester" | xargs)" + EXPECTED="success" + echo "Response: ${ACTUAL}" + if [ "$ACTUAL" != "$EXPECTED" ]; then + echo "FAIL: ${{ matrix.distro_config.distro }}-${{ matrix.distro_config.distro_version }}:${{ matrix.distro_config.runtime_version }} — expected '${EXPECTED}', got '${ACTUAL}'" + exit 1 + fi + echo "PASS" + + - name: Dump container logs + if: always() + run: | + TEST_NAME="ric-integ-test" + echo "=== App container logs ===" + docker logs "${TEST_NAME}-app" 2>&1 || true + echo "=== Tester container logs ===" + docker logs "${TEST_NAME}-tester" 2>&1 || true + + - name: Cleanup + if: always() + run: | + TEST_NAME="ric-integ-test" + docker rm -f "${TEST_NAME}-app" "${TEST_NAME}-tester" 2>/dev/null || true + docker network rm "${TEST_NAME}-net" 2>/dev/null || true diff --git a/.gitignore b/.gitignore index bdd8bdf..f29279b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,5 @@ Gemfile.lock # containerized test runner clone .test-runner/ -.vscode/ \ No newline at end of file +.vscode/ +.scratch \ No newline at end of file diff --git a/Makefile b/Makefile index cd58f54..2b5ac26 100644 --- a/Makefile +++ b/Makefile @@ -7,21 +7,19 @@ target: init: bundle install -.PHONY: setup-codebuild-agent -setup-codebuild-agent: - docker build -t codebuild-agent - < test/integration/codebuild-local/Dockerfile.agent - -.PHONY: test-smoke -test-smoke: setup-codebuild-agent - CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.alpine.1.yml alpine 3.16 3.1 - .PHONY: test-unit test-unit: ruby test/run_tests.rb unit .PHONY: test-integ -test-integ: setup-codebuild-agent - CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_all.sh test/integration/codebuild +test-integ: + @echo "Integration tests run via GitHub Actions (see .github/workflows/integration-tests.yml)" + @echo "To run a single combo locally:" + @echo " make test-integ-local DISTRO=alpine DISTRO_VERSION=3.19 RUNTIME_VERSION=3.3" + +.PHONY: test-integ-local +test-integ-local: + test/integration/run-local.sh $(DISTRO) $(DISTRO_VERSION) $(RUNTIME_VERSION) .PHONY: build build: @@ -62,7 +60,7 @@ test-dockerized: /suites/*.json .PHONY: pr -pr: init test-unit test-smoke +pr: init test-unit define HELP_MESSAGE @@ -73,9 +71,9 @@ TARGETS build Builds the package. clean Cleans the working directory by removing built artifacts. init Initialize and install the dependencies and dev-dependencies for this project. - test-integ Run Integration tests. + test-integ Show instructions for running integration tests. + test-integ-local Run a single integration test locally (requires DISTRO, DISTRO_VERSION, RUNTIME_VERSION). test-unit Run Unit Tests. - test-smoke Run Sanity/Smoke tests. test-dockerized Run dockerized tests locally (requires RUBY_VERSION=X.X). run-local-ric Run local RIC changes with Runtime Interface Emulator. pr Perform all checks before submitting a Pull Request. diff --git a/test/integration/codebuild-local/Dockerfile.agent b/test/integration/codebuild-local/Dockerfile.agent deleted file mode 100644 index de9eada..0000000 --- a/test/integration/codebuild-local/Dockerfile.agent +++ /dev/null @@ -1,5 +0,0 @@ -FROM amazonlinux:2 - -RUN amazon-linux-extras enable docker && \ - yum clean metadata && \ - yum install -y docker tar \ No newline at end of file diff --git a/test/integration/codebuild-local/codebuild_build.sh b/test/integration/codebuild-local/codebuild_build.sh deleted file mode 100755 index 049a304..0000000 --- a/test/integration/codebuild-local/codebuild_build.sh +++ /dev/null @@ -1,194 +0,0 @@ -#!/bin/bash -# This file is copied from https://github.com/aws/aws-codebuild-docker-images/blob/f0912e4b16e427da35351fc102f0f56f4ceb938a/local_builds/codebuild_build.sh - -function allOSRealPath() { - if isOSWindows - then - path="" - case $1 in - .* ) path="$PWD/${1#./}" ;; - /* ) path="$1" ;; - * ) path="/$1" ;; - esac - - echo "/$path" | sed -e 's/\\/\//g' -e 's/://' -e 's/./\U&/3' - else - case $1 in - /* ) echo "$1"; exit;; - * ) echo "$PWD/${1#./}"; exit;; - esac - fi -} - -function isOSWindows() { - if [ $OSTYPE == "msys" ] - then - return 0 - else - return 1 - fi -} - -function usage { - echo "usage: codebuild_build.sh [-i image_name] [-a artifact_output_directory] [options]" - echo "Required:" - echo " -i Used to specify the customer build container image." - echo " -a Used to specify an artifact output directory." - echo "Options:" - echo " -l IMAGE Used to override the default local agent image." - echo " -s Used to specify source information. Defaults to the current working directory for primary source." - echo " * First (-s) is for primary source" - echo " * Use additional (-s) in : format for secondary source" - echo " * For sourceIdentifier, use a value that is fewer than 128 characters and contains only alphanumeric characters and underscores" - echo " -c Use the AWS configuration and credentials from your local host. This includes ~/.aws and any AWS_* environment variables." - echo " -p Used to specify the AWS CLI Profile." - echo " -b FILE Used to specify a buildspec override file. Defaults to buildspec.yml in the source directory." - echo " -m Used to mount the source directory to the customer build container directly." - echo " -d Used to run the build container in docker privileged mode." - echo " -e FILE Used to specify a file containing environment variables." - echo " (-e) File format expectations:" - echo " * Each line is in VAR=VAL format" - echo " * Lines beginning with # are processed as comments and ignored" - echo " * Blank lines are ignored" - echo " * File can be of type .env or .txt" - echo " * There is no special handling of quotation marks, meaning they will be part of the VAL" - exit 1 -} - -image_flag=false -artifact_flag=false -awsconfig_flag=false -mount_src_dir_flag=false -docker_privileged_mode_flag=false - -while getopts "cmdi:a:s:b:e:l:p:h" opt; do - case $opt in - i ) image_flag=true; image_name=$OPTARG;; - a ) artifact_flag=true; artifact_dir=$OPTARG;; - b ) buildspec=$OPTARG;; - c ) awsconfig_flag=true;; - m ) mount_src_dir_flag=true;; - d ) docker_privileged_mode_flag=true;; - s ) source_dirs+=("$OPTARG");; - e ) environment_variable_file=$OPTARG;; - l ) local_agent_image=$OPTARG;; - p ) aws_profile=$OPTARG;; - h ) usage; exit;; - \? ) echo "Unknown option: -$OPTARG" >&2; exit 1;; - : ) echo "Missing option argument for -$OPTARG" >&2; exit 1;; - * ) echo "Invalid option: -$OPTARG" >&2; exit 1;; - esac -done - -if ! $image_flag -then - echo "The image name flag (-i) must be included for a build to run" >&2 -fi - -if ! $artifact_flag -then - echo "The artifact directory (-a) must be included for a build to run" >&2 -fi - -if ! $image_flag || ! $artifact_flag -then - exit 1 -fi - -docker_command="docker run " -if isOSWindows -then - docker_command+="-v //var/run/docker.sock:/var/run/docker.sock -e " -else - docker_command+="-v /var/run/docker.sock:/var/run/docker.sock -e " -fi - -docker_command+="\"IMAGE_NAME=$image_name\" -e \ - \"ARTIFACTS=$(allOSRealPath "$artifact_dir")\"" - -if [ -z "$source_dirs" ] -then - docker_command+=" -e \"SOURCE=$(allOSRealPath "$PWD")\"" -else - for index in "${!source_dirs[@]}"; do - if [ $index -eq 0 ] - then - docker_command+=" -e \"SOURCE=$(allOSRealPath "${source_dirs[$index]}")\"" - else - identifier=${source_dirs[$index]%%:*} - src_dir=$(allOSRealPath "${source_dirs[$index]#*:}") - - docker_command+=" -e \"SECONDARY_SOURCE_$index=$identifier:$src_dir\"" - fi - done -fi - -if [ -n "$buildspec" ] -then - docker_command+=" -e \"BUILDSPEC=$(allOSRealPath "$buildspec")\"" -fi - -if [ -n "$environment_variable_file" ] -then - environment_variable_file_path=$(allOSRealPath "$environment_variable_file") - environment_variable_file_dir=$(dirname "$environment_variable_file_path") - environment_variable_file_basename=$(basename "$environment_variable_file") - docker_command+=" -v \"$environment_variable_file_dir:/LocalBuild/envFile/\" -e \"ENV_VAR_FILE=$environment_variable_file_basename\"" -fi - -if [ -n "$local_agent_image" ] -then - docker_command+=" -e \"LOCAL_AGENT_IMAGE_NAME=$local_agent_image\"" -fi - -if $awsconfig_flag -then - if [ -d "$HOME/.aws" ] - then - configuration_file_path=$(allOSRealPath "$HOME/.aws") - docker_command+=" -e \"AWS_CONFIGURATION=$configuration_file_path\"" - else - docker_command+=" -e \"AWS_CONFIGURATION=NONE\"" - fi - - if [ -n "$aws_profile" ] - then - docker_command+=" -e \"AWS_PROFILE=$aws_profile\"" - fi - - docker_command+="$(env | grep ^AWS_ | while read -r line; do echo " -e \"$line\""; done )" -fi - -if $mount_src_dir_flag -then - docker_command+=" -e \"MOUNT_SOURCE_DIRECTORY=TRUE\"" -fi - -if $docker_privileged_mode_flag -then - docker_command+=" -e \"DOCKER_PRIVILEGED_MODE=TRUE\"" -fi - -if isOSWindows -then - docker_command+=" -e \"INITIATOR=$USERNAME\"" -else - docker_command+=" -e \"INITIATOR=$USER\"" -fi - -docker_command+=" amazon/aws-codebuild-local:latest" - -# Note we do not expose the AWS_SECRET_ACCESS_KEY or the AWS_SESSION_TOKEN -exposed_command=$docker_command -secure_variables=( "AWS_SECRET_ACCESS_KEY=" "AWS_SESSION_TOKEN=") -for variable in "${secure_variables[@]}" -do - exposed_command="$(echo $exposed_command | sed "s/\($variable\)[^ ]*/\1********\"/")" -done - -echo "Build Command:" -echo "" -echo $exposed_command -echo "" - -eval $docker_command \ No newline at end of file diff --git a/test/integration/codebuild-local/test_all.sh b/test/integration/codebuild-local/test_all.sh deleted file mode 100755 index b184186..0000000 --- a/test/integration/codebuild-local/test_all.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -CODEBUILD_IMAGE_TAG="${CODEBUILD_IMAGE_TAG:-al2/x86_64/standard/3.0}" -DRYRUN="${DRYRUN-0}" - -function usage { - echo "usage: test_all.sh buildspec_yml_dir" - echo "Runs all buildspec build-matrix combinations via test_one.sh." - echo "Required:" - echo " buildspec_yml_dir Used to specify the CodeBuild buildspec template file." -} - -do_one_yaml() { - local -r YML="$1" - - OS_DISTRIBUTION=$(grep -oE 'OS_DISTRIBUTION:\s*(\S+)' "$YML" | cut -d' ' -f2) - DISTRO_VERSIONS=$(sed '1,/DISTRO_VERSION/d;/RUNTIME_VERSION/,$d' "$YML" | tr -d '\-" ') - RUNTIME_VERSIONS=$(sed '1,/RUNTIME_VERSION/d;/phases/,$d' "$YML" | sed '/#.*$/d' | tr -d '\-" ') - - for DISTRO_VERSION in $DISTRO_VERSIONS ; do - for RUNTIME_VERSION in $RUNTIME_VERSIONS ; do - if (( DRYRUN == 1 )) ; then - echo DRYRUN test_one_combination "$YML" "$OS_DISTRIBUTION" "$DISTRO_VERSION" "$RUNTIME_VERSION" - else - test_one_combination "$YML" "$OS_DISTRIBUTION" "$DISTRO_VERSION" "$RUNTIME_VERSION" - fi - done - done -} - -test_one_combination() { - local -r YML="$1" - local -r OS_DISTRIBUTION="$2" - local -r DISTRO_VERSION="$3" - local -r RUNTIME_VERSION="$4" - - echo Testing: - echo " BUILDSPEC" "$YML" - echo " with" "$OS_DISTRIBUTION"-"$DISTRO_VERSION" "$RUNTIME_VERSION" - - "$(dirname "$0")"/test_one.sh "$YML" "$OS_DISTRIBUTION" "$DISTRO_VERSION" "$RUNTIME_VERSION" \ - > >(sed "s/^/$OS_DISTRIBUTION$DISTRO_VERSION-$RUNTIME_VERSION: /") 2> >(sed "s/^/$OS_DISTRIBUTION-$DISTRO_VERSION:$RUNTIME_VERSION: /" >&2) -} - -main() { - if (( $# != 1 && $# != 2)); then - >&2 echo "Invalid number of parameters." - usage - exit 1 - fi - - BUILDSPEC_YML_DIR="$1" - HAS_YML=0 - for f in "$BUILDSPEC_YML_DIR"/*.yml ; do - [ -f "$f" ] || continue; - do_one_yaml "$f" - HAS_YML=1 - done - - if (( HAS_YML == 0 )); then - >&2 echo At least one buildspec is required. - exit 2 - fi -} - -main "$@" \ No newline at end of file diff --git a/test/integration/codebuild-local/test_one.sh b/test/integration/codebuild-local/test_one.sh deleted file mode 100755 index 14acaaf..0000000 --- a/test/integration/codebuild-local/test_one.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -CODEBUILD_IMAGE_TAG="${CODEBUILD_IMAGE_TAG:-al2/x86_64/standard/3.0}" - -function usage { - >&2 echo "usage: test_one.sh buildspec_yml os_distribution distro_version runtime_version [env]" - >&2 echo "Runs one buildspec version combination from a build-matrix buildspec." - >&2 echo "Required:" - >&2 echo " buildspec_yml Used to specify the CodeBuild buildspec template file." - >&2 echo " os_distribution Used to specify the OS distribution to build." - >&2 echo " distro_version Used to specify the distro version of ." - >&2 echo " runtime_version Used to specify the runtime version to test on the selected ." - >&2 echo "Optional:" - >&2 echo " env Additional environment variables file." -} - -main() { - if (( $# != 3 && $# != 4)); then - >&2 echo "Invalid number of parameters." - usage - exit 1 - fi - - BUILDSPEC_YML="$1" - OS_DISTRIBUTION="$2" - DISTRO_VERSION="$3" - RUNTIME_VERSION="$4" - EXTRA_ENV="${5-}" - - CODEBUILD_TEMP_DIR=$(mktemp -d codebuild."$OS_DISTRIBUTION"-"$DISTRO_VERSION"-"$RUNTIME_VERSION".XXXXXXXXXX ) - trap 'rm -rf $CODEBUILD_TEMP_DIR' EXIT - - # Create an env file for codebuild_build. - ENVFILE="$CODEBUILD_TEMP_DIR/.env" - if [ -f "$EXTRA_ENV" ]; then - cat "$EXTRA_ENV" > "$ENVFILE" - fi - { - echo "" - echo "OS_DISTRIBUTION=$OS_DISTRIBUTION" - echo "DISTRO_VERSION=$DISTRO_VERSION" - echo "RUNTIME_VERSION=$RUNTIME_VERSION" - } >> "$ENVFILE" - - ARTIFACTS_DIR="$CODEBUILD_TEMP_DIR/artifacts" - mkdir -p "$ARTIFACTS_DIR" - - # Run CodeBuild local agent. - "$(dirname "$0")"/codebuild_build.sh \ - -i "$CODEBUILD_IMAGE_TAG" \ - -a "$ARTIFACTS_DIR" \ - -e "$ENVFILE" \ - -b "$BUILDSPEC_YML" -} - -main "$@" \ No newline at end of file diff --git a/test/integration/codebuild/buildspec.os.alpine.1.yml b/test/integration/codebuild/buildspec.os.alpine.1.yml deleted file mode 100644 index 0b4686e..0000000 --- a/test/integration/codebuild/buildspec.os.alpine.1.yml +++ /dev/null @@ -1,110 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: alpine - EXECUTABLE: "/usr/local/bundle/bin/aws_lambda_ric" - TEST_NAME: "aws-lambda-ruby-ric-alpine-test" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "3.16" - RUNTIME_VERSION: - - "3.1" -phases: - pre_build: - commands: - - export IMAGE_TAG="ruby-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "RUN apk add curl" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${TEST_NAME}-network" - - > - docker run \ - --detach \ - --name "${TEST_NAME}-app" \ - --network "${TEST_NAME}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} "${EXECUTABLE}" "app.App::Handler.process"" - - sleep 2 - - > - docker run \ - --name "${TEST_NAME}-tester" \ - --env "TARGET=${TEST_NAME}-app" \ - --network "${TEST_NAME}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${TEST_NAME}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: ${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION} - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${TEST_NAME}-app----------" - echo - docker logs "${TEST_NAME}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${TEST_NAME}-tester--------" - echo - docker logs "${TEST_NAME}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${TEST_NAME}-app" || true - - docker rm --force "${TEST_NAME}-app" || true - - docker stop "${TEST_NAME}-tester" || true - - docker rm --force "${TEST_NAME}-tester" || true - - docker network rm "${TEST_NAME}-network" || true \ No newline at end of file diff --git a/test/integration/codebuild/buildspec.os.alpine.2.yml b/test/integration/codebuild/buildspec.os.alpine.2.yml deleted file mode 100644 index 0b4686e..0000000 --- a/test/integration/codebuild/buildspec.os.alpine.2.yml +++ /dev/null @@ -1,110 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: alpine - EXECUTABLE: "/usr/local/bundle/bin/aws_lambda_ric" - TEST_NAME: "aws-lambda-ruby-ric-alpine-test" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "3.16" - RUNTIME_VERSION: - - "3.1" -phases: - pre_build: - commands: - - export IMAGE_TAG="ruby-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "RUN apk add curl" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${TEST_NAME}-network" - - > - docker run \ - --detach \ - --name "${TEST_NAME}-app" \ - --network "${TEST_NAME}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} "${EXECUTABLE}" "app.App::Handler.process"" - - sleep 2 - - > - docker run \ - --name "${TEST_NAME}-tester" \ - --env "TARGET=${TEST_NAME}-app" \ - --network "${TEST_NAME}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${TEST_NAME}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: ${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION} - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${TEST_NAME}-app----------" - echo - docker logs "${TEST_NAME}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${TEST_NAME}-tester--------" - echo - docker logs "${TEST_NAME}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${TEST_NAME}-app" || true - - docker rm --force "${TEST_NAME}-app" || true - - docker stop "${TEST_NAME}-tester" || true - - docker rm --force "${TEST_NAME}-tester" || true - - docker network rm "${TEST_NAME}-network" || true \ No newline at end of file diff --git a/test/integration/codebuild/buildspec.os.amazonlinux.yml b/test/integration/codebuild/buildspec.os.amazonlinux.yml deleted file mode 100644 index 12f5248..0000000 --- a/test/integration/codebuild/buildspec.os.amazonlinux.yml +++ /dev/null @@ -1,107 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: amazonlinux - EXECUTABLE: "/usr/local/bin/aws_lambda_ric" - TEST_NAME: "aws-lambda-ruby-ric-amazonlinux-test" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "2" - RUNTIME_VERSION: - - "3.1" -phases: - pre_build: - commands: - - export IMAGE_TAG="ruby-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${TEST_NAME}-network" - - > - docker run \ - --detach \ - --name "${TEST_NAME}-app" \ - --network "${TEST_NAME}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} "${EXECUTABLE}" "app.App::Handler.process"" - - sleep 2 - - > - docker run \ - --name "${TEST_NAME}-tester" \ - --env "TARGET=${TEST_NAME}-app" \ - --network "${TEST_NAME}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${TEST_NAME}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: ${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION} - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${TEST_NAME}-app----------" - echo - docker logs "${TEST_NAME}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${TEST_NAME}-tester--------" - echo - docker logs "${TEST_NAME}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${TEST_NAME}-app" || true - - docker rm --force "${TEST_NAME}-app" || true - - docker stop "${TEST_NAME}-tester" || true - - docker rm --force "${TEST_NAME}-tester" || true - - docker network rm "${TEST_NAME}-network" || true \ No newline at end of file diff --git a/test/integration/codebuild/buildspec.os.debian.yml b/test/integration/codebuild/buildspec.os.debian.yml deleted file mode 100644 index 27fb149..0000000 --- a/test/integration/codebuild/buildspec.os.debian.yml +++ /dev/null @@ -1,108 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: debian - EXECUTABLE: "/usr/local/bundle/bin/aws_lambda_ric" - TEST_NAME: "aws-lambda-ruby-ric-debian-test" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "buster" - - "bullseye" - RUNTIME_VERSION: - - "3.1" -phases: - pre_build: - commands: - - export IMAGE_TAG="ruby-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${TEST_NAME}-network" - - > - docker run \ - --detach \ - --name "${TEST_NAME}-app" \ - --network "${TEST_NAME}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} "${EXECUTABLE}" "app.App::Handler.process"" - - sleep 2 - - > - docker run \ - --name "${TEST_NAME}-tester" \ - --env "TARGET=${TEST_NAME}-app" \ - --network "${TEST_NAME}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${TEST_NAME}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: ${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION} - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${TEST_NAME}-app----------" - echo - docker logs "${TEST_NAME}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${TEST_NAME}-tester--------" - echo - docker logs "${TEST_NAME}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${TEST_NAME}-app" || true - - docker rm --force "${TEST_NAME}-app" || true - - docker stop "${TEST_NAME}-tester" || true - - docker rm --force "${TEST_NAME}-tester" || true - - docker network rm "${TEST_NAME}-network" || true \ No newline at end of file diff --git a/test/integration/codebuild/buildspec.os.ubuntu.yml b/test/integration/codebuild/buildspec.os.ubuntu.yml deleted file mode 100644 index 650652b..0000000 --- a/test/integration/codebuild/buildspec.os.ubuntu.yml +++ /dev/null @@ -1,110 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: ubuntu - EXECUTABLE: "/usr/local/bin/aws_lambda_ric" - TEST_NAME: "aws-lambda-ruby-ric-ubuntu-test" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "22.04" - RUNTIME_VERSION: - - "3.1" -phases: - pre_build: - commands: - - export IMAGE_TAG="ruby-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "RUN apt-get install -y curl" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${TEST_NAME}-network" - - > - docker run \ - --detach \ - --name "${TEST_NAME}-app" \ - --network "${TEST_NAME}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} "${EXECUTABLE}" "app.App::Handler.process"" - - sleep 2 - - > - docker run \ - --name "${TEST_NAME}-tester" \ - --env "TARGET=${TEST_NAME}-app" \ - --network "${TEST_NAME}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${TEST_NAME}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: ${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION} - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${TEST_NAME}-app----------" - echo - docker logs "${TEST_NAME}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${TEST_NAME}-tester--------" - echo - docker logs "${TEST_NAME}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${TEST_NAME}-app" || true - - docker rm --force "${TEST_NAME}-app" || true - - docker stop "${TEST_NAME}-tester" || true - - docker rm --force "${TEST_NAME}-tester" || true - - docker network rm "${TEST_NAME}-network" || true \ No newline at end of file diff --git a/test/integration/docker/Dockerfile.echo.amazonlinux b/test/integration/docker/Dockerfile.echo.al2023 similarity index 64% rename from test/integration/docker/Dockerfile.echo.amazonlinux rename to test/integration/docker/Dockerfile.echo.al2023 index 8ee0c4a..2cef033 100644 --- a/test/integration/docker/Dockerfile.echo.amazonlinux +++ b/test/integration/docker/Dockerfile.echo.al2023 @@ -1,21 +1,20 @@ # Define global args -ARG DISTRO_VERSION +ARG RUNTIME_VERSION -# Grab a fresh copy of the image and install ruby and build the runtime interface client gem -FROM amazonlinux:${DISTRO_VERSION} AS build-image +# Build stage: compile Ruby and build the RIC gem +FROM public.ecr.aws/lambda/provided:al2023 AS build-image ARG RUNTIME_VERSION -RUN yum update -y && \ - yum install -y git-core zlib zlib-devel gcc-c++ patch readline readline-devel libffi-devel openssl-devel make bzip2 autoconf automake libtool bison curl sqlite-devel +RUN dnf update -y && \ + dnf install -y git gcc gcc-c++ make openssl-devel readline-devel zlib-devel \ + libffi-devel libyaml-devel bzip2 autoconf automake libtool bison tar gzip RUN rm -rf /root/.rbenv/ RUN git clone https://github.com/rbenv/rbenv.git /root/.rbenv ENV PATH="/root/.rbenv/bin:$PATH" -RUN echo 'eval "$(rbenv init -)"' >> /root/.bashrc RUN git clone https://github.com/rbenv/ruby-build.git /root/.rbenv/plugins/ruby-build -RUN source /root/.bashrc -RUN RUNTIME_VERSIONS=($(rbenv install -L | grep -oE $(echo "^${RUNTIME_VERSION}\.[0-9]+"))) && \ +RUN RUNTIME_VERSIONS=($(rbenv install -L | grep -oE $(echo "^${RUNTIME_VERSION}\.[0-9]+"))) && \ RUNTIME_LATEST_VERSION=${RUNTIME_VERSIONS[-1]} && \ rbenv install -v ${RUNTIME_LATEST_VERSION} && \ rbenv global ${RUNTIME_LATEST_VERSION} && \ @@ -24,39 +23,35 @@ RUN RUNTIME_VERSIONS=($(rbenv install -L | grep -oE $(echo "^${RUNTIME_VERSION} gem install bundler ARG RIC_BUILD_DIR="/build" -# Create directory to build the Runtime Interface Client gem RUN mkdir -p ${RIC_BUILD_DIR} - WORKDIR ${RIC_BUILD_DIR} COPY . . RUN rake build -# Grab a fresh copy of the Ruby image -FROM amazonlinux:${DISTRO_VERSION} +# Runtime stage +FROM public.ecr.aws/lambda/provided:al2023 ARG RUNTIME_VERSION +RUN dnf install -y libyaml libxcrypt + # Copy ruby from the build-image COPY --from=build-image /root/.rbenv /root/.rbenv - ENV PATH="/root/.rbenv/bin:$PATH" # Copy the Runtime Interface Client gem and install it ARG RIC_BUILD_DIR="/build" COPY --from=build-image ${RIC_BUILD_DIR}/pkg/aws_lambda_ric*.gem aws_lambda_ric.gem -RUN RUNTIME_VERSIONS=($(rbenv install -L | grep -oE $(echo "^${RUNTIME_VERSION}\.[0-9]+"))) && \ +RUN RUNTIME_VERSIONS=($(rbenv install -L | grep -oE $(echo "^${RUNTIME_VERSION}\.[0-9]+"))) && \ RUNTIME_LATEST_VERSION=${RUNTIME_VERSIONS[-1]} && \ cp /root/.rbenv/versions/${RUNTIME_LATEST_VERSION}/bin/gem /usr/local/bin/gem && \ gem install aws_lambda_ric.gem && \ cp /root/.rbenv/versions/${RUNTIME_LATEST_VERSION}/bin/aws_lambda_ric /usr/local/bin/aws_lambda_ric ARG FUNCTION_DIR="/function" - RUN mkdir -p ${FUNCTION_DIR} -# Copy function code COPY test/integration/test-handlers/echo/* ${FUNCTION_DIR} -# Set working directory to function root directory WORKDIR ${FUNCTION_DIR} ENTRYPOINT ["aws_lambda_ric"] diff --git a/test/integration/docker/Dockerfile.echo.alpine b/test/integration/docker/Dockerfile.echo.alpine index cb4ebab..defb882 100644 --- a/test/integration/docker/Dockerfile.echo.alpine +++ b/test/integration/docker/Dockerfile.echo.alpine @@ -24,6 +24,7 @@ FROM ruby:${RUNTIME_VERSION}-alpine${DISTRO_VERSION} # Copy the Runtime Interface Client gem and install it ARG RIC_BUILD_DIR="/build" COPY --from=build-image ${RIC_BUILD_DIR}/pkg/aws_lambda_ric*.gem aws_lambda_ric.gem +RUN apk add --no-cache curl RUN gem install aws_lambda_ric.gem ARG FUNCTION_DIR="/function" diff --git a/test/integration/docker/Dockerfile.echo.debian b/test/integration/docker/Dockerfile.echo.debian index ffdadba..f1a74e9 100644 --- a/test/integration/docker/Dockerfile.echo.debian +++ b/test/integration/docker/Dockerfile.echo.debian @@ -25,6 +25,7 @@ FROM ruby:${RUNTIME_VERSION}-${DISTRO_VERSION} # Copy the Runtime Interface Client gem and install it ARG RIC_BUILD_DIR="/build" COPY --from=build-image ${RIC_BUILD_DIR}/pkg/aws_lambda_ric*.gem aws_lambda_ric.gem +RUN apt-get update -y && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/* RUN gem install aws_lambda_ric.gem ARG FUNCTION_DIR="/function" diff --git a/test/integration/docker/Dockerfile.echo.ubuntu b/test/integration/docker/Dockerfile.echo.ubuntu index 6bce61b..11db56b 100644 --- a/test/integration/docker/Dockerfile.echo.ubuntu +++ b/test/integration/docker/Dockerfile.echo.ubuntu @@ -42,7 +42,7 @@ FROM ubuntu:${DISTRO_VERSION} # Get dependencies for the Runtime Interface Client RUN apt-get update -y && \ - apt-get install -y libyaml-dev libssl-dev + apt-get install -y libyaml-dev libssl-dev curl ARG RUNTIME_VERSION diff --git a/test/integration/resources/aws-lambda-rie-arm64.tar.gz b/test/integration/resources/aws-lambda-rie-arm64.tar.gz deleted file mode 100644 index f62577f..0000000 Binary files a/test/integration/resources/aws-lambda-rie-arm64.tar.gz and /dev/null differ diff --git a/test/integration/resources/aws-lambda-rie.tar.gz b/test/integration/resources/aws-lambda-rie.tar.gz deleted file mode 100644 index feda16d..0000000 Binary files a/test/integration/resources/aws-lambda-rie.tar.gz and /dev/null differ diff --git a/test/integration/run-local.sh b/test/integration/run-local.sh new file mode 100755 index 0000000..614a084 --- /dev/null +++ b/test/integration/run-local.sh @@ -0,0 +1,100 @@ +#!/bin/bash +# Run a single integration test locally. +# Usage: ./test/integration/run-local.sh +# Example: ./test/integration/run-local.sh alpine 3.19 3.3 + +set -euo pipefail + +DISTRO="${1:?Usage: $0 }" +DISTRO_VERSION="${2:?Usage: $0 }" +RUNTIME_VERSION="${3:?Usage: $0 }" + +TEST_NAME="ric-local-test" +SCRATCH_DIR=".scratch" + +# Determine executable path based on distro +case "$DISTRO" in + alpine|debian) + EXECUTABLE="/usr/local/bundle/bin/aws_lambda_ric" + ;; + al2023|amazonlinux|ubuntu) + EXECUTABLE="/usr/local/bin/aws_lambda_ric" + ;; + *) + echo "Unknown distro: $DISTRO" >&2 + exit 1 + ;; +esac + +cleanup() { + echo "Cleaning up..." + docker rm -f "${TEST_NAME}-app" "${TEST_NAME}-tester" 2>/dev/null || true + docker network rm "${TEST_NAME}-net" 2>/dev/null || true + rm -rf "$SCRATCH_DIR" +} +trap cleanup EXIT + +# Download RIE +mkdir -p "$SCRATCH_DIR" +ARCH=$(uname -m) +if [ "$ARCH" = "x86_64" ]; then + RIE="aws-lambda-rie" +elif [ "$ARCH" = "aarch64" ]; then + RIE="aws-lambda-rie-arm64" +else + echo "Unsupported architecture: $ARCH" >&2 + exit 1 +fi +echo "Downloading ${RIE} from GitHub..." +curl -sSL "https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/${RIE}" -o "${SCRATCH_DIR}/${RIE}" +chmod +x "${SCRATCH_DIR}/${RIE}" + +# Build image +DOCKERFILE="test/integration/docker/Dockerfile.echo.${DISTRO}" +TMPFILE="${SCRATCH_DIR}/Dockerfile.tmp" +cp "$DOCKERFILE" "$TMPFILE" +echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> "$TMPFILE" + +IMAGE_TAG="ric-test-${DISTRO}-${DISTRO_VERSION}:${RUNTIME_VERSION}" +echo "Building ${IMAGE_TAG}..." +docker build . \ + -f "$TMPFILE" \ + -t "$IMAGE_TAG" \ + --build-arg RUNTIME_VERSION="$RUNTIME_VERSION" \ + --build-arg DISTRO_VERSION="$DISTRO_VERSION" + +# Run test +docker network create "${TEST_NAME}-net" + +docker run \ + --detach \ + --name "${TEST_NAME}-app" \ + --network "${TEST_NAME}-net" \ + --entrypoint="" \ + "$IMAGE_TAG" \ + sh -c "/usr/bin/${RIE} ${EXECUTABLE} app.App::Handler.process" + +sleep 2 + +docker run \ + --name "${TEST_NAME}-tester" \ + --env "TARGET=${TEST_NAME}-app" \ + --network "${TEST_NAME}-net" \ + --entrypoint="" \ + "$IMAGE_TAG" \ + sh -c 'curl -sS -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' + +ACTUAL="$(docker logs --tail 1 "${TEST_NAME}-tester" | xargs)" +EXPECTED="success" + +echo "" +echo "=== App logs ===" +docker logs "${TEST_NAME}-app" 2>&1 || true +echo "" + +if [ "$ACTUAL" != "$EXPECTED" ]; then + echo "FAIL: ${DISTRO}-${DISTRO_VERSION}:${RUNTIME_VERSION} — expected '${EXPECTED}', got '${ACTUAL}'" + exit 1 +fi + +echo "PASS: ${DISTRO}-${DISTRO_VERSION}:${RUNTIME_VERSION}"