diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ab40d21d7..d9fdc8b1d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,5 +2,7 @@ *Description of changes:* +*Target (OCI, Managed Runtime, both):* + By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. diff --git a/.github/actions/configure-maven-mirror/action.yml b/.github/actions/configure-maven-mirror/action.yml new file mode 100644 index 000000000..ce309a8f7 --- /dev/null +++ b/.github/actions/configure-maven-mirror/action.yml @@ -0,0 +1,42 @@ +name: Configure Maven CodeArtifact mirror +description: Configure Maven to resolve dependencies through the release CodeArtifact repository. + +runs: + using: composite + steps: + - shell: bash + run: | + CA_DOMAIN=aws-lambda + CA_REPO=maven-central-store + + # Uses the ambient region and caller account. + TOKEN=$(aws codeartifact get-authorization-token \ + --domain "$CA_DOMAIN" --query authorizationToken --output text) + echo "::add-mask::$TOKEN" + + CA_URL=$(aws codeartifact get-repository-endpoint \ + --domain "$CA_DOMAIN" --repository "$CA_REPO" --format maven \ + --query repositoryEndpoint --output text) + + # * routes all resolution through the mirror; + # deployment uses distributionManagement and is unaffected. + mkdir -p "$HOME/.m2" + cat > "$HOME/.m2/settings.xml" < + + + codeartifact-mirror + aws + ${TOKEN} + + + + + codeartifact-mirror + release CodeArtifact Maven Central proxy + ${CA_URL} + * + + + + EOF diff --git a/.github/actions/configure-release-aws-credentials/action.yml b/.github/actions/configure-release-aws-credentials/action.yml new file mode 100644 index 000000000..6a34f6480 --- /dev/null +++ b/.github/actions/configure-release-aws-credentials/action.yml @@ -0,0 +1,28 @@ +name: "Configure AWS credentials for release (OIDC)" +description: > + Assumes the release OIDC role via aws-actions/configure-aws-credentials so the + job can read the signing key and Sonatype token from Secrets Manager. Pinning + of the underlying action lives here so it is updated in one place. + +inputs: + aws-region: + description: "AWS region to operate in." + required: true + role-to-assume: + description: "ARN of the OIDC role to assume." + required: true + role-session-name: + description: "Session name for the assumed role (helps distinguish callers in CloudTrail)." + required: true + +runs: + using: composite + steps: + - uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4 + with: + aws-region: ${{ inputs.aws-region }} + role-to-assume: ${{ inputs.role-to-assume }} + role-session-name: ${{ inputs.role-session-name }} + # Kept short: the job only needs the role briefly to read two secrets. + # 900s is STS's minimum for assume-role; anything lower is rejected. + role-duration-seconds: 900 diff --git a/.github/actions/resolve-release-version/action.yml b/.github/actions/resolve-release-version/action.yml new file mode 100644 index 000000000..06d3f4f1e --- /dev/null +++ b/.github/actions/resolve-release-version/action.yml @@ -0,0 +1,54 @@ +name: "Resolve and validate release version" +description: > + Reads the module POM version (the source of truth), verifies it is a + -SNAPSHOT, and derives the effective release version (the optional override, + or the POM version with -SNAPSHOT stripped). Exports CURRENT_VERSION and + EFFECTIVE_RELEASE_VERSION to the job environment for subsequent steps. + +inputs: + module: + description: "Module directory containing the pom.xml to release." + required: true + release-version-override: + description: "Optional release version; defaults to the POM version without -SNAPSHOT." + required: false + default: "" + validate-module-dir: + description: "Fail if the module directory or its pom.xml is missing (use for the choice-driven workflow)." + required: false + default: "false" + +runs: + using: composite + steps: + - name: Resolve and validate release version + shell: bash + env: + MODULE: ${{ inputs.module }} + RELEASE_VERSION_OVERRIDE: ${{ inputs.release-version-override }} + VALIDATE_MODULE_DIR: ${{ inputs.validate-module-dir }} + run: | + if [[ "$VALIDATE_MODULE_DIR" == "true" ]]; then + if [[ ! -d "$MODULE" ]]; then + echo "::error::Module directory '$MODULE' does not exist" + exit 1 + fi + if [[ ! -f "$MODULE/pom.xml" ]]; then + echo "::error::No pom.xml found in '$MODULE'" + exit 1 + fi + fi + + # The POM version is the source of truth and must be a SNAPSHOT. + CURRENT_VERSION=$(mvn -q -DforceStdout help:evaluate -Dexpression=project.version --file "$MODULE/pom.xml") + CURRENT_VERSION="${CURRENT_VERSION//[$'\r\n']/}" + if [[ "$CURRENT_VERSION" != *-SNAPSHOT ]]; then + echo "::error::POM version '$CURRENT_VERSION' is not a SNAPSHOT" + exit 1 + fi + + # Optional override; default strips -SNAPSHOT. + EFFECTIVE_RELEASE_VERSION="${RELEASE_VERSION_OVERRIDE:-${CURRENT_VERSION%-SNAPSHOT}}" + + echo "CURRENT_VERSION=$CURRENT_VERSION" >> "$GITHUB_ENV" + echo "EFFECTIVE_RELEASE_VERSION=$EFFECTIVE_RELEASE_VERSION" >> "$GITHUB_ENV" diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..88f18ea29 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "maven" + directory: "/aws-lambda-java-runtime-interface" + schedule: + interval: "weekly" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" \ No newline at end of file diff --git a/.github/test-matrix.json b/.github/test-matrix.json new file mode 100644 index 000000000..7e6539cb6 --- /dev/null +++ b/.github/test-matrix.json @@ -0,0 +1,16 @@ +{ + "arch": [ + { + "runner": "ubuntu-latest", + "label": "x64", + "sam_arch": "x86_64", + "java_suffix": "X64" + }, + { + "runner": "ubuntu-24.04-arm", + "label": "arm64", + "sam_arch": "arm64", + "java_suffix": "ARM64" + } + ] +} diff --git a/.github/workflows/aws-lambda-java-core.yml b/.github/workflows/aws-lambda-java-core.yml new file mode 100644 index 000000000..3e4364672 --- /dev/null +++ b/.github/workflows/aws-lambda-java-core.yml @@ -0,0 +1,36 @@ +# This workflow will be triggered if there will be changes to aws-lambda-java-core +# package and it builds the package. + +name: Java CI aws-lambda-java-core + +on: + workflow_dispatch: + push: + branches: [ main ] + paths: + - 'aws-lambda-java-core/**' + pull_request: + branches: [ '*' ] + paths: + - 'aws-lambda-java-core/**' + - '.github/workflows/aws-lambda-java-core.yml' + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + - name: Set up JDK 1.8 + uses: actions/setup-java@v5 + with: + java-version: 8 + distribution: corretto + cache: maven + + - name: Install core with Maven + run: mvn -B install --file aws-lambda-java-core/pom.xml diff --git a/.github/workflows/aws-lambda-java-events-sdk-transformer.yml b/.github/workflows/aws-lambda-java-events-sdk-transformer.yml new file mode 100644 index 000000000..144d52f86 --- /dev/null +++ b/.github/workflows/aws-lambda-java-events-sdk-transformer.yml @@ -0,0 +1,43 @@ +# This workflow will be triggered if there will be changes to +# aws-lambda-java-events-sdk-transformer package or its dependency (events), +# and it builds the package. + +name: Java CI aws-lambda-java-events-sdk-transformer + +on: + workflow_dispatch: + push: + branches: [ main ] + paths: + - 'aws-lambda-java-events-sdk-transformer/**' + - 'aws-lambda-java-events/**' + pull_request: + branches: [ '*' ] + paths: + - 'aws-lambda-java-events-sdk-transformer/**' + - 'aws-lambda-java-events/**' + - '.github/workflows/aws-lambda-java-events-sdk-transformer.yml' + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + - name: Set up JDK 1.8 + uses: actions/setup-java@v5 + with: + java-version: 8 + distribution: corretto + cache: maven + + # Install dependency + - name: Install events with Maven + run: mvn -B install --file aws-lambda-java-events/pom.xml + # Package target module + - name: Package events-sdk-transformer with Maven + run: mvn -B package --file aws-lambda-java-events-sdk-transformer/pom.xml diff --git a/.github/workflows/aws-lambda-java-events.yml b/.github/workflows/aws-lambda-java-events.yml new file mode 100644 index 000000000..18be63cf9 --- /dev/null +++ b/.github/workflows/aws-lambda-java-events.yml @@ -0,0 +1,36 @@ +# This workflow will be triggered if there will be changes to aws-lambda-java-events +# package and it builds the package. + +name: Java CI aws-lambda-java-events + +on: + workflow_dispatch: + push: + branches: [ main ] + paths: + - 'aws-lambda-java-events/**' + pull_request: + branches: [ '*' ] + paths: + - 'aws-lambda-java-events/**' + - '.github/workflows/aws-lambda-java-events.yml' + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + - name: Set up JDK 1.8 + uses: actions/setup-java@v5 + with: + java-version: 8 + distribution: corretto + cache: maven + + - name: Install events with Maven + run: mvn -B install --file aws-lambda-java-events/pom.xml diff --git a/.github/workflows/aws-lambda-java-log4j2.yml b/.github/workflows/aws-lambda-java-log4j2.yml new file mode 100644 index 000000000..945a1cb30 --- /dev/null +++ b/.github/workflows/aws-lambda-java-log4j2.yml @@ -0,0 +1,42 @@ +# This workflow will be triggered if there will be changes to +# aws-lambda-java-log4j2 package or its dependency (core), and it builds the package. + +name: Java CI aws-lambda-java-log4j2 + +on: + push: + workflow_dispatch: + branches: [ main ] + paths: + - 'aws-lambda-java-log4j2/**' + - 'aws-lambda-java-core/**' + pull_request: + branches: [ '*' ] + paths: + - 'aws-lambda-java-log4j2/**' + - 'aws-lambda-java-core/**' + - '.github/workflows/aws-lambda-java-log4j2.yml' + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + - name: Set up JDK 1.8 + uses: actions/setup-java@v5 + with: + java-version: 8 + distribution: corretto + cache: maven + + # Install dependency + - name: Install core with Maven + run: mvn -B install --file aws-lambda-java-core/pom.xml + # Package target module + - name: Package log4j2 with Maven + run: mvn -B package --file aws-lambda-java-log4j2/pom.xml diff --git a/.github/workflows/aws-lambda-java-profiler.yml b/.github/workflows/aws-lambda-java-profiler.yml new file mode 100644 index 000000000..a098bfd14 --- /dev/null +++ b/.github/workflows/aws-lambda-java-profiler.yml @@ -0,0 +1,79 @@ +name: Run integration tests for aws-lambda-java-profiler + +on: + pull_request: + branches: [ '*' ] + paths: + - 'experimental/aws-lambda-java-profiler/**' + - '.github/workflows/aws-lambda-java-profiler.yml' + push: + branches: ['*'] + paths: + - 'experimental/aws-lambda-java-profiler/**' + - '.github/workflows/aws-lambda-java-profiler.yml' + +jobs: + + build: + runs-on: ubuntu-latest + + permissions: + id-token: write + contents: read + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Set up JDK + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: 21 + distribution: corretto + cache: maven + + - name: Issue AWS credentials + uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4 + with: + aws-region: ${{ secrets.AWS_REGION_PROFILER_EXTENSION_INTEGRATION_TEST }} + role-to-assume: ${{ secrets.AWS_ROLE_PROFILER_EXTENSION_INTEGRATION_TEST }} + role-session-name: GitHubActionsRunIntegrationTests + role-duration-seconds: 900 + + - name: Build layer + working-directory: ./experimental/aws-lambda-java-profiler/extension + run: ./build_layer.sh + + - name: Publish layer + working-directory: ./experimental/aws-lambda-java-profiler + run: ./integration_tests/publish_layer.sh + + - name: Create the bucket layer + working-directory: ./experimental/aws-lambda-java-profiler + run: ./integration_tests/create_bucket.sh + + - name: Create Java function + working-directory: ./experimental/aws-lambda-java-profiler + run: ./integration_tests/create_function.sh + + - name: Invoke Java function + working-directory: ./experimental/aws-lambda-java-profiler + run: ./integration_tests/invoke_function.sh + + - name: Invoke Java Custom Options function + working-directory: ./experimental/aws-lambda-java-profiler + run: ./integration_tests/invoke_function_custom_options.sh + + - name: Download from s3 + working-directory: ./experimental/aws-lambda-java-profiler + run: ./integration_tests/download_from_s3.sh + + - name: Upload profiles + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: profiles + path: /tmp/s3-artifacts + + - name: cleanup + if: always() + working-directory: ./experimental/aws-lambda-java-profiler + run: ./integration_tests/cleanup.sh \ No newline at end of file diff --git a/.github/workflows/aws-lambda-java-serialization.yml b/.github/workflows/aws-lambda-java-serialization.yml new file mode 100644 index 000000000..f52c96fed --- /dev/null +++ b/.github/workflows/aws-lambda-java-serialization.yml @@ -0,0 +1,47 @@ +# This workflow will be triggered if there will be changes to aws-lambda-java-serialization +# package or its dependency (events), and it builds the package. + +name: Java CI aws-lambda-java-serialization + +on: + workflow_dispatch: + push: + branches: [ main ] + paths: + - 'aws-lambda-java-serialization/**' + - 'aws-lambda-java-events/**' + pull_request: + branches: [ '*' ] + paths: + - 'aws-lambda-java-serialization/**' + - 'aws-lambda-java-events/**' + - '.github/workflows/aws-lambda-java-serialization.yml' + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + - name: Set up JDK 1.8 + uses: actions/setup-java@v5 + with: + java-version: 8 + distribution: corretto + cache: maven + + # Install dependency + - name: Install events with Maven + run: mvn -B install --file aws-lambda-java-events/pom.xml + + # Package and install target module + - name: Package serialization with Maven + run: mvn -B install --file aws-lambda-java-serialization/pom.xml + + # Run tests + - name: Run tests from aws-lambda-java-tests + run: mvn test --file aws-lambda-java-tests/pom.xml diff --git a/.github/workflows/aws-lambda-java-tests.yml b/.github/workflows/aws-lambda-java-tests.yml new file mode 100644 index 000000000..324c44514 --- /dev/null +++ b/.github/workflows/aws-lambda-java-tests.yml @@ -0,0 +1,47 @@ +# This workflow will be triggered if there will be changes to aws-lambda-java-tests +# package or its dependencies (events, serialization), and it builds the package. + +name: Java CI aws-lambda-java-tests + +on: + workflow_dispatch: + push: + branches: [ main ] + paths: + - 'aws-lambda-java-tests/**' + - 'aws-lambda-java-events/**' + - 'aws-lambda-java-serialization/**' + pull_request: + branches: [ '*' ] + paths: + - 'aws-lambda-java-tests/**' + - 'aws-lambda-java-events/**' + - 'aws-lambda-java-serialization/**' + - '.github/workflows/aws-lambda-java-tests.yml' + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + - name: Set up JDK 1.8 + uses: actions/setup-java@v5 + with: + java-version: 8 + distribution: corretto + cache: maven + + # Install dependencies + - name: Install events with Maven + run: mvn -B install --file aws-lambda-java-events/pom.xml + - name: Install serialization with Maven + run: mvn -B install --file aws-lambda-java-serialization/pom.xml + + # Package target module + - name: Package tests with Maven + run: mvn -B package --file aws-lambda-java-tests/pom.xml diff --git a/.github/workflows/build-integration-test.yml b/.github/workflows/build-integration-test.yml new file mode 100644 index 000000000..2a6bb30c5 --- /dev/null +++ b/.github/workflows/build-integration-test.yml @@ -0,0 +1,86 @@ +# this workflow verifies that the integration test Lambda function builds successfully. +# it does NOT deploy or run the tests (that requires AWS credentials and is done in +# run-integration-test.yml). + +name: Build integration tests + +on: + push: + branches: [ main ] + paths: + - 'aws-lambda-java-log4j2/**' + - 'aws-lambda-java-core/**' + - 'lambda-integration-tests/**' + pull_request: + branches: [ '*' ] + paths: + - 'aws-lambda-java-log4j2/**' + - 'aws-lambda-java-core/**' + - 'lambda-integration-tests/**' + - '.github/workflows/build-integration-test.yml' + +permissions: + contents: read + +jobs: + load-matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set.outputs.matrix }} + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Load test matrix + id: set + run: | + MATRIX=$(jq -c '.' .github/test-matrix.json) + echo "matrix=${MATRIX}" >> "$GITHUB_OUTPUT" + + build-arch: + needs: load-matrix + runs-on: ${{ matrix.arch.runner }} + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.load-matrix.outputs.matrix) }} + name: "build (${{ matrix.arch.label }})" + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Set up JDK + uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + with: + java-version: | + 8 + 21 + distribution: corretto + cache: maven + + - name: Install core with Maven + run: | + export JAVA_HOME=$JAVA_HOME_8_${{ matrix.arch.java_suffix }} + mvn -B install --file aws-lambda-java-core/pom.xml + + - name: Install log4j2 with Maven + run: | + export JAVA_HOME=$JAVA_HOME_8_${{ matrix.arch.java_suffix }} + mvn -B install --file aws-lambda-java-log4j2/pom.xml + + # build the integration test function + # this verifies that the function compiles and packages correctly. + # the tests will run in run-integration-test.yml which deploys to AWS. + - name: Package integration test function + run: | + export JAVA_HOME=$JAVA_HOME_21_${{ matrix.arch.java_suffix }} + mvn -B package --file lambda-integration-tests/log4j2-test-function/pom.xml + + build: + needs: build-arch + if: always() + runs-on: ubuntu-latest + steps: + - name: Check build results + run: | + if [ "${{ needs.build-arch.result }}" != "success" ]; then + echo "Build failed on one or more architectures" + exit 1 + fi diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml new file mode 100644 index 000000000..e41dcfc61 --- /dev/null +++ b/.github/workflows/release-runtime-interface-client.yml @@ -0,0 +1,361 @@ +name: Release RIC to Maven Central + +# RIC ships a native JNI lib for 4 targets + a main JAR (5 artifacts). Each +# native lib is built on its own architecture (x86_64 and aarch64 CodeBuild +# runners) instead of emulating with QEMU. A build matrix produces the +# classifier JARs, then one job assembles and publishes them. + +on: + workflow_dispatch: + inputs: + releaseVersion: + description: 'Release version override (optional; defaults to the POM version without -SNAPSHOT)' + required: false + type: string + developmentVersion: + description: 'Next development version override (optional, must end with -SNAPSHOT)' + required: false + type: string + skip_publish: + description: 'Skip publish (dry-run validation)' + required: false + type: boolean + default: false + +permissions: + contents: write # push release commit and tag + id-token: write # assume the OIDC role for secret retrieval + +# Share the repo-wide "release" group with release.yml so RIC and the pure-Java +# modules can never publish concurrently. Never cancel in-flight: it could leave +# a half-published state. +concurrency: + group: release + cancel-in-progress: false + +env: + MODULE: aws-lambda-java-runtime-interface-client + RELEASE_VERSION_INPUT: ${{ github.event.inputs.releaseVersion }} + DEVELOPMENT_VERSION_INPUT: ${{ github.event.inputs.developmentVersion }} + MAVEN_ARGS: "-B --no-transfer-progress" + AWS_REGION: ${{ vars.AWS_REGION_MAVEN_RELEASE }} + OIDC_ROLE_ARN: ${{ secrets.AWS_ROLE_MAVEN_RELEASE }} + # ECR pull-through cache used for the native JNI base images. ECR_REGISTRY is + # the login target; BASE_REGISTRY (with the /ecr-public prefix) is passed to + # the Dockerfiles as a build-arg. + ECR_REGISTRY: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ vars.AWS_REGION_MAVEN_RELEASE }}.amazonaws.com + BASE_REGISTRY: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ vars.AWS_REGION_MAVEN_RELEASE }}.amazonaws.com/ecr-public + +jobs: + # Build each architecture's native libs (glibc + musl) on a native runner. + build-natives: + strategy: + fail-fast: true + matrix: + include: + - arch: x86_64 + runner: codebuild-aws-lambda-java-libs-test-trigger-x86-${{ github.run_id }}-${{ github.run_attempt }} + profiles: linux-x86_64 linux_musl-x86_64 + - arch: aarch64 + runner: codebuild-aws-lambda-java-libs-test-trigger-arm64-${{ github.run_id }}-${{ github.run_attempt }} + profiles: linux-aarch64 linux_musl-aarch64 + runs-on: ${{ matrix.runner }} + timeout-minutes: 45 + steps: + # Manual (workflow_dispatch) releases must only run from main, never from + # an arbitrary branch that could carry unreviewed release logic. Guarding + # the first job blocks the whole pipeline (release needs build-natives). + - name: Verify release branch + run: | + if [[ "$GITHUB_REF_NAME" != "main" ]]; then + echo "::error::Releases must run from the main branch, got '$GITHUB_REF_NAME'" + exit 1 + fi + + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + # Use the CodeBuild image's preinstalled Corretto 8. The image ships it at + # $JAVA_8_HOME but defaults JAVA_HOME to Java 25, so point JAVA_HOME/PATH at + # 8. Avoids actions/setup-java, which fetches from corretto.github.io + + # corretto.aws, both blocked by the runner egress lock. $JAVA_8_HOME + # resolves per-arch (x86_64/aarch64). + - name: Use the runner image's preinstalled Corretto 8 + run: | + echo "JAVA_HOME=$JAVA_8_HOME" >> "$GITHUB_ENV" + echo "$JAVA_8_HOME/bin" >> "$GITHUB_PATH" + "$JAVA_8_HOME/bin/java" -version + mkdir -p "$HOME/.m2" + cat > "$HOME/.m2/toolchains.xml" < + + + jdk + 8 + $JAVA_8_HOME + + + EOF + + # Route all mvn resolution through the CodeArtifact mirror. Must precede + # resolve-release-version, which invokes `mvn help:evaluate`. Ambient + # CodeBuild runner-role creds supply the token; no OIDC step in this job. + - name: Configure Maven CodeArtifact mirror + uses: ./.github/actions/configure-maven-mirror + + - name: Resolve and validate release version + uses: ./.github/actions/resolve-release-version + with: + module: ${{ env.MODULE }} + release-version-override: ${{ env.RELEASE_VERSION_INPUT }} + + # The native JNI build shells out to `docker build` against the ECR + # pull-through cache (see src/main/jni/Dockerfile.*). Authenticate first so + # the base-image pulls don't hit public.ecr.aws. Uses ambient runner creds. + - name: Log in to Amazon ECR (pull-through cache) + run: | + aws ecr get-login-password --region "$AWS_REGION" \ + | docker login --username AWS --password-stdin "$ECR_REGISTRY" + + # -DskipTests: only installed so the module compiles, not released here. + - name: Install intra-repo dependencies + run: | + for dep in aws-lambda-java-core aws-lambda-java-serialization; do + mvn install -DskipTests --file "$dep/pom.xml" + done + + # Build at the release version (matches the JAR names the release job + # attaches). + - name: Build native classifier JARs (${{ matrix.arch }}) + env: + IS_JAVA_8: true + run: | + mvn versions:set -DnewVersion="$EFFECTIVE_RELEASE_VERSION" -DgenerateBackupPoms=false --file "$MODULE/pom.xml" + for profile in ${{ matrix.profiles }}; do + echo "::group::Building $profile" + mvn package -P "$profile" -DmultiArch=false -DskipTests --file "$MODULE/pom.xml" + echo "::endgroup::" + done + + # JARs to attach + .so files to assemble the fat main JAR. + - name: Upload native artifacts + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: ric-natives-${{ matrix.arch }} + if-no-files-found: error + path: | + ${{ env.MODULE }}/target/*-linux*.jar + ${{ env.MODULE }}/target/classes/jni/*.so + + # Remove the user settings holding the CodeArtifact mirror token once the + # build is done. Ephemeral runner, so defence-in-depth, not load-bearing. + - name: Scrub Maven settings + if: always() + run: rm -f "$HOME/.m2/settings.xml" + + # Assemble all native builds and publish. + release: + needs: build-natives + runs-on: codebuild-aws-lambda-java-libs-test-trigger-x86-${{ github.run_id }}-${{ github.run_attempt }} + environment: Release + timeout-minutes: 30 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + fetch-depth: 0 # full history for tagging/pushing + + # Use the CodeBuild image's preinstalled Corretto 8. The image ships it at + # $JAVA_8_HOME but defaults JAVA_HOME to Java 25, so point JAVA_HOME/PATH at + # 8. Avoids actions/setup-java, which fetches from corretto.github.io + + # corretto.aws, both blocked by the runner egress lock. $JAVA_8_HOME + # resolves per-arch (x86_64/aarch64). + - name: Use the runner image's preinstalled Corretto 8 + run: | + echo "JAVA_HOME=$JAVA_8_HOME" >> "$GITHUB_ENV" + echo "$JAVA_8_HOME/bin" >> "$GITHUB_PATH" + "$JAVA_8_HOME/bin/java" -version + mkdir -p "$HOME/.m2" + cat > "$HOME/.m2/toolchains.xml" < + + + jdk + 8 + $JAVA_8_HOME + + + EOF + + # Route all mvn resolution through the CodeArtifact mirror. Must precede + # resolve-release-version (which invokes `mvn help:evaluate`) and the OIDC + # step (which would shadow the runner-role creds this needs). Runs on every + # path, since dependency resolution happens on dry-runs too. + - name: Configure Maven CodeArtifact mirror + uses: ./.github/actions/configure-maven-mirror + + - name: Resolve and validate release version + uses: ./.github/actions/resolve-release-version + with: + module: ${{ env.MODULE }} + release-version-override: ${{ env.RELEASE_VERSION_INPUT }} + + # The native JNI build shells out to `docker build` against the ECR + # pull-through cache (see src/main/jni/Dockerfile.*). Authenticate first so + # the base-image pulls don't hit public.ecr.aws. Uses ambient runner creds. + - name: Log in to Amazon ECR (pull-through cache) + run: | + aws ecr get-login-password --region "$AWS_REGION" \ + | docker login --username AWS --password-stdin "$ECR_REGISTRY" + + - name: Resolve next development version and tag + run: | + # Next development version: use the override, or bump the patch. + if [[ -n "$DEVELOPMENT_VERSION_INPUT" ]]; then + if [[ "$DEVELOPMENT_VERSION_INPUT" != *-SNAPSHOT ]]; then + echo "::error::developmentVersion '$DEVELOPMENT_VERSION_INPUT' must end with -SNAPSHOT" + exit 1 + fi + NEXT_DEV_VERSION="$DEVELOPMENT_VERSION_INPUT" + else + IFS='.' read -r MA MI PA <<< "$EFFECTIVE_RELEASE_VERSION" + NEXT_DEV_VERSION="${MA}.${MI}.$((PA + 1))-SNAPSHOT" + fi + + echo "NEXT_DEV_VERSION=$NEXT_DEV_VERSION" >> "$GITHUB_ENV" + echo "TAG_NAME=${MODULE}-${EFFECTIVE_RELEASE_VERSION}" >> "$GITHUB_ENV" + echo "::notice::Releasing $MODULE $EFFECTIVE_RELEASE_VERSION (next dev $NEXT_DEV_VERSION)" + + - name: Configure git user + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + # -DskipTests: only installed so the module compiles, not released here. + - name: Install intra-repo dependencies + run: | + for dep in aws-lambda-java-core aws-lambda-java-serialization; do + mvn install -DskipTests --file "$dep/pom.xml" + done + + - name: Set release version + run: mvn versions:set -DnewVersion="$EFFECTIVE_RELEASE_VERSION" -DgenerateBackupPoms=false --file "$MODULE/pom.xml" + + # Test gate before publish. + - name: Run tests + env: + IS_JAVA_8: true + run: mvn test -DargLineForReflectionTestOnly="" --file "$MODULE/pom.xml" + + # JARs to attach + .so files for the fat main JAR. + - name: Download native artifacts + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + with: + pattern: ric-natives-* + path: ric-natives + + - name: Stage native artifacts + run: | + mkdir -p "$MODULE/target/classes/jni" + find ric-natives -name '*.jar' -exec cp {} "$MODULE/target/" \; + find ric-natives -name '*.so' -exec cp {} "$MODULE/target/classes/jni/" \; + echo "Staged native artifacts:" + ls -1 "$MODULE/target/"*-linux*.jar "$MODULE/target/classes/jni/"*.so + + - name: Configure AWS credentials (OIDC) + if: ${{ github.event.inputs.skip_publish != 'true' }} + uses: ./.github/actions/configure-release-aws-credentials + with: + aws-region: ${{ env.AWS_REGION }} + role-to-assume: ${{ env.OIDC_ROLE_ARN }} + role-session-name: GitHubActionsRicMavenCentralRelease + + # Fetch signing material and publish in a single step so the GPG passphrase + # and Sonatype token stay in this shell and never cross a $GITHUB_ENV + # boundary, where a later (possibly compromised) step could read them. + # -DmultiArch=false builds only the host .so; the aarch_64 .so is already + # staged, so the main JAR still bundles all four. build-helper attaches + # the staged classifier JARs. Gate already ran, so -DskipTests. + - name: Publish to Maven Central + if: ${{ github.event.inputs.skip_publish != 'true' }} + env: + IS_JAVA_8: true + run: | + # Scrub the settings.xml (contains the Sonatype token) and the keyring + # on exit, so no sensitive file is left on the runner even on failure. + MAVEN_SETTINGS="$RUNNER_TEMP/settings.xml" + export GNUPGHOME=$(mktemp -d) + trap 'rm -rf "$MAVEN_SETTINGS" "$GNUPGHOME"' EXIT + + # --- Signing key + Sonatype token (shared secrets from LambdaMavenDeploy) --- + GPG_JSON=$(aws secretsmanager get-secret-value --secret-id lambda-runtimes/java/gpg-signing-key --query SecretString --output text) + CREDS_JSON=$(aws secretsmanager get-secret-value --secret-id lambda-runtimes/java/maven-sonatype-creds --query SecretString --output text) + GPG_PRIVATE_KEY=$(jq -r '.private' <<< "$GPG_JSON") + GPG_PASSPHRASE=$(jq -r '.passphrase' <<< "$GPG_JSON") + SONATYPE_USERNAME=$(jq -r '."maven-central-login"' <<< "$CREDS_JSON") + SONATYPE_PASSWORD=$(jq -r '."maven-central-password"' <<< "$CREDS_JSON") + echo "::add-mask::$GPG_PASSPHRASE" + echo "::add-mask::$SONATYPE_USERNAME" + echo "::add-mask::$SONATYPE_PASSWORD" + + # Import the key with loopback pinentry so Maven can sign non-interactively. + chmod 700 "$GNUPGHOME" + echo "allow-loopback-pinentry" > "$GNUPGHOME/gpg-agent.conf" + echo "pinentry-mode loopback" > "$GNUPGHOME/gpg.conf" + gpgconf --kill gpg-agent || true + gpg --batch --import <<< "$GPG_PRIVATE_KEY" + GPG_KEYNAME=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/ {print $5; exit}') + + # Global settings holding only the Sonatype "central" server for upload. + # Passed to Maven as -gs (global) so it MERGES with the CodeArtifact + # mirror in ~/.m2/settings.xml (user) that the mirror step wrote: deps + # resolve through the mirror, upload goes to central, and the mirror + # token stays in that user file instead of being re-passed here. + { + echo '' + echo "central" + echo "${SONATYPE_USERNAME}" + echo "${SONATYPE_PASSWORD}" + echo '' + } > "$MAVEN_SETTINGS" + + # --- Publish --- (-gs: merge Sonatype creds with the ~/.m2 mirror) + mvn deploy -Prelease -DskipTests -DmultiArch=false \ + -gs "$MAVEN_SETTINGS" \ + -Dgpg.keyname="$GPG_KEYNAME" -Dgpg.passphrase="$GPG_PASSPHRASE" \ + --file "$MODULE/pom.xml" + + - name: Tag and push (only after publish succeeds) + if: ${{ github.event.inputs.skip_publish != 'true' }} + run: | + git commit -am "chore(ric): release ${EFFECTIVE_RELEASE_VERSION}" + git tag "$TAG_NAME" + mvn versions:set -DnewVersion="$NEXT_DEV_VERSION" -DgenerateBackupPoms=false --file "$MODULE/pom.xml" + git commit -am "chore(ric): prepare next development ${NEXT_DEV_VERSION}" + git push --atomic origin "HEAD:${GITHUB_REF_NAME}" "refs/tags/${TAG_NAME}" + + # Dry-run: validate assembly, no publish/push. + - name: Dry-run assemble (no publish) + if: ${{ github.event.inputs.skip_publish == 'true' }} + env: + IS_JAVA_8: true + run: mvn package -DskipTests -DmultiArch=false --file "$MODULE/pom.xml" + + # Nothing was pushed, so this only cleans the runner. + - name: Roll back local tag on failure + if: ${{ failure() && github.event.inputs.skip_publish != 'true' }} + run: | + git tag -d "$TAG_NAME" 2>/dev/null || true + echo "::warning::Release failed. The remote was not modified; safe to retry." + + - name: Summary + if: ${{ github.event.inputs.skip_publish != 'true' }} + run: | + echo "## Release Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY + echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY + echo "| Module | \`$MODULE\` |" >> $GITHUB_STEP_SUMMARY + echo "| Version | \`$EFFECTIVE_RELEASE_VERSION\` |" >> $GITHUB_STEP_SUMMARY + echo "| Tag | \`$TAG_NAME\` |" >> $GITHUB_STEP_SUMMARY + echo "| Artifacts | main JAR + linux/linux_musl x x86_64/aarch_64 classifier JARs |" >> $GITHUB_STEP_SUMMARY + echo "| Built natively | x86_64 and aarch_64 on CodeBuild runners (no QEMU) |" >> $GITHUB_STEP_SUMMARY + echo "| Maven Central | [com.amazonaws:$MODULE:$EFFECTIVE_RELEASE_VERSION](https://central.sonatype.com/artifact/com.amazonaws/$MODULE/$EFFECTIVE_RELEASE_VERSION) |" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..7ff834e56 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,297 @@ +name: Release to Maven Central + +# Builds, tests, and publishes a module to Maven Central in one environment. + +on: + workflow_dispatch: + inputs: + module: + description: 'Module to release (directory name, e.g. aws-lambda-java-log4j2)' + required: true + type: choice + # aws-lambda-java-runtime-interface-client is intentionally excluded: it + # ships a cross-compiled JNI native library and has its own dedicated + # pipeline, .github/workflows/release-runtime-interface-client.yml. + options: + - aws-lambda-java-core + - aws-lambda-java-events + - aws-lambda-java-events-sdk-transformer + - aws-lambda-java-log4j2 + - aws-lambda-java-serialization + - aws-lambda-java-tests + releaseVersion: + description: 'Release version override (optional; defaults to the POM version without -SNAPSHOT)' + required: false + type: string + developmentVersion: + description: 'Next development version override (optional, must end with -SNAPSHOT)' + required: false + type: string + skip_publish: + description: 'Skip publish (dry-run validation)' + required: false + type: boolean + default: false + +permissions: + contents: write + id-token: write + +# Serialize all releases repo-wide to avoid concurrent pushes racing on the +# default branch. Never cancel in-flight: it could leave a half-published state. +concurrency: + group: release + cancel-in-progress: false + +env: + MODULE: ${{ github.event.inputs.module }} + RELEASE_VERSION_INPUT: ${{ github.event.inputs.releaseVersion }} + DEVELOPMENT_VERSION_INPUT: ${{ github.event.inputs.developmentVersion }} + # Batch mode + no transfer-progress spam for every Maven call (Maven 3.9+). + MAVEN_ARGS: "-B --no-transfer-progress" + AWS_REGION: ${{ vars.AWS_REGION_MAVEN_RELEASE }} + OIDC_ROLE_ARN: ${{ secrets.AWS_ROLE_MAVEN_RELEASE }} + +jobs: + # Pre-publish gate for log4j2: deploy a real Lambda, invoke it, + # and assert the log line reaches CloudWatch. Binds the end-to-end validation + # to the publish event itself. Skipped for every other module, which are + # covered by their own tests (or the cross-module gate below). + integration-test: + if: ${{ github.event.inputs.module == 'aws-lambda-java-log4j2' }} + uses: ./.github/workflows/run-integration-test.yml + secrets: inherit + + release: + needs: [integration-test] + # Publish when the gate passed, or when it was skipped for a non-log4j2 + # module. A failed or cancelled gate blocks the release. + if: ${{ always() && (needs.integration-test.result == 'success' || needs.integration-test.result == 'skipped') }} + runs-on: codebuild-aws-lambda-java-libs-test-trigger-x86-${{ github.run_id }}-${{ github.run_attempt }} + environment: Release + timeout-minutes: 30 + + steps: + # Manual (workflow_dispatch) releases must only run from main, never from + # an arbitrary branch that could carry unreviewed release logic. + - name: Verify release branch + run: | + if [[ "$GITHUB_REF_NAME" != "main" ]]; then + echo "::error::Releases must run from the main branch, got '$GITHUB_REF_NAME'" + exit 1 + fi + + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + fetch-depth: 0 # full history for tagging/pushing + + # Use the CodeBuild image's preinstalled Corretto 8. The image ships it at + # $JAVA_8_HOME but defaults JAVA_HOME to Java 25, so point JAVA_HOME/PATH at + # 8. Avoids actions/setup-java, which fetches from corretto.github.io + + # corretto.aws, both blocked by the runner egress lock. $JAVA_8_HOME + # resolves per-arch (x86_64/aarch64). + - name: Use the runner image's preinstalled Corretto 8 + run: | + echo "JAVA_HOME=$JAVA_8_HOME" >> "$GITHUB_ENV" + echo "$JAVA_8_HOME/bin" >> "$GITHUB_PATH" + "$JAVA_8_HOME/bin/java" -version + mkdir -p "$HOME/.m2" + cat > "$HOME/.m2/toolchains.xml" < + + + jdk + 8 + $JAVA_8_HOME + + + EOF + + # Route all mvn resolution through the CodeArtifact mirror. Runs before the + # OIDC step (which would shadow the runner-role creds this needs) and on + # every path, since dependency resolution happens on dry-runs too. + - name: Configure Maven CodeArtifact mirror + uses: ./.github/actions/configure-maven-mirror + + - name: Resolve and validate release version + uses: ./.github/actions/resolve-release-version + with: + module: ${{ env.MODULE }} + release-version-override: ${{ env.RELEASE_VERSION_INPUT }} + validate-module-dir: "true" + + - name: Validate development version override + run: | + if [[ -n "$DEVELOPMENT_VERSION_INPUT" && "$DEVELOPMENT_VERSION_INPUT" != *-SNAPSHOT ]]; then + echo "::error::developmentVersion '$DEVELOPMENT_VERSION_INPUT' must end with -SNAPSHOT" + exit 1 + fi + echo "::notice::Releasing $MODULE $EFFECTIVE_RELEASE_VERSION (POM currently $CURRENT_VERSION)" + + - name: Configure git user + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Install intra-repo dependencies + run: | + # Installed so the target compiles. -DskipTests: not released here, + # only the target module gets the full verify gate below. + declare -A DEPS + DEPS[aws-lambda-java-core]="" + DEPS[aws-lambda-java-events]="" + DEPS[aws-lambda-java-serialization]="" + DEPS[aws-lambda-java-log4j2]="aws-lambda-java-core" + DEPS[aws-lambda-java-events-sdk-transformer]="aws-lambda-java-events" + DEPS[aws-lambda-java-tests]="aws-lambda-java-core aws-lambda-java-serialization aws-lambda-java-events" + + DEP_LIST="${DEPS[$MODULE]}" + if [[ -n "$DEP_LIST" ]]; then + for dep in $DEP_LIST; do + echo "::group::Installing dependency: $dep" + mvn install -DskipTests --file "$dep/pom.xml" + echo "::endgroup::" + done + else + echo "::notice::No intra-repo dependencies for $MODULE" + fi + + - name: Run tests + run: mvn verify --file "$MODULE/pom.xml" + + # Cross-module gate: serialization has no tests in its own build, so the + # `mvn verify` above exercises nothing. Its behavioral coverage lives in + # aws-lambda-java-tests, which depends on serialization via a version + # property. Install the just-built serialization and run that suite + # against it, so we never publish serialization the suite hasn't exercised. + - name: Run cross-module test gate + run: | + case "$MODULE" in + aws-lambda-java-serialization) + MOD_VER=$(mvn -q -DforceStdout help:evaluate -Dexpression=project.version --file "$MODULE/pom.xml") + MOD_VER="${MOD_VER//[$'\r\n']/}" + echo "::group::Installing $MODULE $MOD_VER for the gate" + mvn install -DskipTests --file "$MODULE/pom.xml" + echo "::endgroup::" + echo "::notice::Gating $MODULE on aws-lambda-java-tests (aws-lambda-java-serialization.version=$MOD_VER)" + mvn verify -Daws-lambda-java-serialization.version="$MOD_VER" --file aws-lambda-java-tests/pom.xml + ;; + *) + echo "::notice::No cross-module test gate for $MODULE" + ;; + esac + + - name: Configure AWS credentials (OIDC) + if: ${{ github.event.inputs.skip_publish != 'true' }} + uses: ./.github/actions/configure-release-aws-credentials + with: + aws-region: ${{ env.AWS_REGION }} + role-to-assume: ${{ env.OIDC_ROLE_ARN }} + role-session-name: GitHubActionsMavenCentralRelease + + # Fetch signing material and publish in a single step so the GPG passphrase + # and Sonatype token stay in this shell and never cross a $GITHUB_ENV + # boundary, where a later (possibly compromised) step could read them. + # prepare/perform aren't atomic: prepare locally, publish, push only after. + - name: Release (prepare locally, publish, then push) + if: ${{ github.event.inputs.skip_publish != 'true' }} + run: | + # Scrub the settings.xml (contains the Sonatype token) and the keyring + # on exit, so no sensitive file is left on the runner even on failure. + MAVEN_SETTINGS="$RUNNER_TEMP/settings.xml" + export GNUPGHOME=$(mktemp -d) + trap 'rm -rf "$MAVEN_SETTINGS" "$GNUPGHOME"' EXIT + + # --- Signing key + Sonatype token (shared secrets from LambdaMavenDeploy) --- + GPG_JSON=$(aws secretsmanager get-secret-value --secret-id lambda-runtimes/java/gpg-signing-key --query SecretString --output text) + CREDS_JSON=$(aws secretsmanager get-secret-value --secret-id lambda-runtimes/java/maven-sonatype-creds --query SecretString --output text) + GPG_PRIVATE_KEY=$(jq -r '.private' <<< "$GPG_JSON") + GPG_PASSPHRASE=$(jq -r '.passphrase' <<< "$GPG_JSON") + SONATYPE_USERNAME=$(jq -r '."maven-central-login"' <<< "$CREDS_JSON") + SONATYPE_PASSWORD=$(jq -r '."maven-central-password"' <<< "$CREDS_JSON") + echo "::add-mask::$GPG_PASSPHRASE" + echo "::add-mask::$SONATYPE_USERNAME" + echo "::add-mask::$SONATYPE_PASSWORD" + + # Import the key with loopback pinentry so Maven can sign non-interactively. + chmod 700 "$GNUPGHOME" + echo "allow-loopback-pinentry" > "$GNUPGHOME/gpg-agent.conf" + echo "pinentry-mode loopback" > "$GNUPGHOME/gpg.conf" + gpgconf --kill gpg-agent || true + gpg --batch --import <<< "$GPG_PRIVATE_KEY" + GPG_KEYNAME=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/ {print $5; exit}') + + # Global settings holding only the Sonatype "central" server for upload. + # Passed to Maven as -gs (global) so it MERGES with the CodeArtifact + # mirror in ~/.m2/settings.xml (user) that the mirror step wrote: deps + # resolve through the mirror, upload goes to central, and the mirror + # token stays in that user file instead of being re-passed here. + { + echo '' + echo "central" + echo "${SONATYPE_USERNAME}" + echo "${SONATYPE_PASSWORD}" + echo '' + } > "$MAVEN_SETTINGS" + + # --- Release: build args as an array so each value is a single, + # properly quoted argument (no word-splitting of untrusted input). --- + RELEASE_ARGS=(-DreleaseVersion="$EFFECTIVE_RELEASE_VERSION") + if [[ -n "$DEVELOPMENT_VERSION_INPUT" ]]; then + RELEASE_ARGS+=(-DdevelopmentVersion="$DEVELOPMENT_VERSION_INPUT") + fi + + # Prepare locally (no push): release commits + tag. + mvn release:prepare -DpushChanges=false "${RELEASE_ARGS[@]}" --file "$MODULE/pom.xml" + + # perform forks a fresh build. Pass the Sonatype creds as GLOBAL + # settings (-gs) so the fork still auto-reads ~/.m2/settings.xml (the + # mirror) and merges the two. + mvn release:perform -DlocalCheckout=true \ + -Darguments="-gs $MAVEN_SETTINGS -Prelease -Dgpg.keyname=$GPG_KEYNAME -Dgpg.passphrase=$GPG_PASSPHRASE" \ + --file "$MODULE/pom.xml" + + # Push commits + tag atomically, only after publish succeeded. + git push --atomic origin \ + "HEAD:${GITHUB_REF_NAME}" \ + "refs/tags/${MODULE}-${EFFECTIVE_RELEASE_VERSION}" + + - name: Dry-run release (prepare only, no publish) + if: ${{ github.event.inputs.skip_publish == 'true' }} + run: | + RELEASE_ARGS=(-DreleaseVersion="$EFFECTIVE_RELEASE_VERSION") + if [[ -n "$DEVELOPMENT_VERSION_INPUT" ]]; then + RELEASE_ARGS+=(-DdevelopmentVersion="$DEVELOPMENT_VERSION_INPUT") + fi + mvn release:prepare -DdryRun=true "${RELEASE_ARGS[@]}" --file "$MODULE/pom.xml" + mvn release:clean --file "$MODULE/pom.xml" || true + + # Nothing was pushed, so this only cleans the runner for a retry. + - name: Roll back release on failure + if: ${{ failure() && github.event.inputs.skip_publish != 'true' }} + run: | + mvn release:rollback --file "$MODULE/pom.xml" || true + mvn release:clean --file "$MODULE/pom.xml" || true + git tag -d "${MODULE}-${EFFECTIVE_RELEASE_VERSION}" 2>/dev/null || true + echo "::warning::Release failed before publish completed. The remote was not modified; the runner state has been rolled back. Safe to retry." + + - name: Summary + if: ${{ github.event.inputs.skip_publish != 'true' }} + run: | + TAG_NAME="${MODULE}-${EFFECTIVE_RELEASE_VERSION}" + echo "## Release Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY + echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY + echo "| Module | \`$MODULE\` |" >> $GITHUB_STEP_SUMMARY + echo "| Version | \`$EFFECTIVE_RELEASE_VERSION\` |" >> $GITHUB_STEP_SUMMARY + echo "| Tag | \`$TAG_NAME\` |" >> $GITHUB_STEP_SUMMARY + echo "| Maven Central | [com.amazonaws:$MODULE:$EFFECTIVE_RELEASE_VERSION](https://central.sonatype.com/artifact/com.amazonaws/$MODULE/$EFFECTIVE_RELEASE_VERSION) |" >> $GITHUB_STEP_SUMMARY + + # Symmetry with the publish step's in-shell scrub: remove the user settings + # holding the CodeArtifact mirror token. Last step, after the mvn-using + # rollback path, so nothing still needs it. The runner is ephemeral, so + # this is defence-in-depth, not load-bearing. + - name: Scrub Maven settings + if: always() + run: rm -f "$HOME/.m2/settings.xml" diff --git a/.github/workflows/repo-sync.yml b/.github/workflows/repo-sync.yml new file mode 100644 index 000000000..4934754d8 --- /dev/null +++ b/.github/workflows/repo-sync.yml @@ -0,0 +1,39 @@ +name: Repo Sync + +on: + schedule: + - cron: "0 8 * * 1-5" # At 08:00 on every day-of-week from Monday through Friday + pull_request: + branches: [ '*' ] + paths: + - '.github/workflows/repo-sync.yml' + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + repo-sync: + name: Repo Sync + runs-on: ubuntu-latest + env: + IS_CONFIGURED: ${{ secrets.SOURCE_REPO != '' }} + steps: + - uses: actions/checkout@v6 + if: ${{ env.IS_CONFIGURED == 'true' }} + - uses: repo-sync/github-sync@3832fe8e2be32372e1b3970bbae8e7079edeec88 # v2.3.0 + name: Sync repo to branch + if: ${{ env.IS_CONFIGURED == 'true' }} + with: + source_repo: ${{ secrets.SOURCE_REPO }} + source_branch: main + destination_branch: ${{ secrets.INTERMEDIATE_BRANCH }} + github_token: ${{ secrets.GITHUB_TOKEN }} + - uses: repo-sync/pull-request@7e79a9f5dc3ad0ce53138f01df2fad14a04831c5 # v2.12.1 + name: Create pull request + if: ${{ env.IS_CONFIGURED == 'true' }} + with: + source_branch: ${{ secrets.INTERMEDIATE_BRANCH }} + destination_branch: main + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/run-integration-test.yml b/.github/workflows/run-integration-test.yml new file mode 100644 index 000000000..35456a7c5 --- /dev/null +++ b/.github/workflows/run-integration-test.yml @@ -0,0 +1,139 @@ +# this workflow deploys a Lambda function that uses aws-lambda-java-log4j2, +# invokes it, and verifies that logs arrive in CloudWatch. + +name: Run integration tests + +permissions: + id-token: write + contents: read + +on: + workflow_dispatch: + workflow_call: + push: + branches: [ main ] + paths: + - 'aws-lambda-java-log4j2/**' + - 'aws-lambda-java-core/**' + - 'lambda-integration-tests/**' + +jobs: + load-matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set.outputs.matrix }} + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Load test matrix + id: set + run: | + MATRIX=$(jq -c '.' .github/test-matrix.json) + echo "matrix=${MATRIX}" >> "$GITHUB_OUTPUT" + + run-integration-tests: + needs: load-matrix + # Only run on the main repo, not forks + if: ${{ github.repository_owner == 'aws' }} + runs-on: ${{ matrix.arch.runner }} + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.load-matrix.outputs.matrix) }} + name: "integration-test (${{ matrix.arch.label }})" + concurrency: + group: integration-test-${{ matrix.arch.label }} + cancel-in-progress: false + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Set up JDK + uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + with: + java-version: | + 8 + 21 + distribution: corretto + cache: maven + + - name: Install SAM CLI + uses: aws-actions/setup-sam@f84ec7d548307efafe33230528756de3c5841a17 # v2 + with: + use-installer: true + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0 + with: + role-to-assume: ${{ secrets.AWS_ROLE_LOG4J2_INTEG_TEST }} + role-session-name: GitHubActionsLog4j2IntegTest + aws-region: ${{ secrets.AWS_REGION_LOG4J2_INTEG_TEST }} + + - name: Install core with Maven + run: | + export JAVA_HOME=$JAVA_HOME_8_${{ matrix.arch.java_suffix }} + mvn -B install --file aws-lambda-java-core/pom.xml + + - name: Install log4j2 with Maven + run: | + export JAVA_HOME=$JAVA_HOME_8_${{ matrix.arch.java_suffix }} + mvn -B install --file aws-lambda-java-log4j2/pom.xml + + - name: Build SAM stack + run: | + export JAVA_HOME=$JAVA_HOME_21_${{ matrix.arch.java_suffix }} + cd lambda-integration-tests && sam build + + - name: Validate SAM stack + run: cd lambda-integration-tests && sam validate --lint + + - name: Deploy stack + id: deploy_stack + env: + AWS_REGION: ${{ secrets.AWS_REGION_LOG4J2_INTEG_TEST }} + run: | + cd lambda-integration-tests + stackName="aws-lambda-java-log4j2-integ-test-${{ matrix.arch.label }}-$GITHUB_RUN_ID" + echo "STACK_NAME=$stackName" >> "$GITHUB_OUTPUT" + echo "Stack name = $stackName" + sam deploy \ + --stack-name "${stackName}" \ + --parameter-overrides "ParameterKey=LambdaRole,ParameterValue=${{ secrets.AWS_LAMBDA_ROLE_LOG4J2_INTEG_TEST }} ParameterKey=Architecture,ParameterValue=${{ matrix.arch.sam_arch }}" \ + --no-confirm-changeset \ + --no-progressbar \ + --s3-bucket "${{ secrets.S3_BUCKET_LOG4J2_INTEG_TEST }}" \ + --capabilities CAPABILITY_IAM \ + 2>&1 | tee /tmp/sam-deploy.log | tail -n 20 + + # Verify stack is in a healthy state + STACK_STATUS=$(aws cloudformation describe-stacks \ + --stack-name "${stackName}" \ + --region "${AWS_REGION}" \ + --query 'Stacks[0].StackStatus' \ + --output text 2>&1) + echo "Stack status: $STACK_STATUS" + if [ "$STACK_STATUS" != "CREATE_COMPLETE" ] && [ "$STACK_STATUS" != "UPDATE_COMPLETE" ]; then + echo "FAIL: Stack is not in a healthy state (status: $STACK_STATUS)" + aws cloudformation describe-stack-events \ + --stack-name "${stackName}" \ + --region "${AWS_REGION}" \ + --query 'StackEvents[?ResourceStatus==`CREATE_FAILED` || ResourceStatus==`UPDATE_FAILED`].[LogicalResourceId,ResourceStatusReason]' \ + --output table 2>&1 || true + exit 1 + fi + + LOG4J2_TEST_FUNCTION=$(sam list stack-outputs --stack-name "${stackName}" --output json | jq -r '.[] | select(.OutputKey=="Log4j2TestFunction") | .OutputValue') + echo "LOG4J2_TEST_FUNCTION=$LOG4J2_TEST_FUNCTION" >> "$GITHUB_OUTPUT" + echo "Function name: $LOG4J2_TEST_FUNCTION" + + - name: Run integration test + env: + LOG4J2_TEST_FUNCTION: ${{ steps.deploy_stack.outputs.LOG4J2_TEST_FUNCTION }} + AWS_REGION: ${{ secrets.AWS_REGION_LOG4J2_INTEG_TEST }} + run: ./lambda-integration-tests/run-tests.sh + + - name: Cleanup + if: always() && steps.deploy_stack.outputs.STACK_NAME + env: + AWS_REGION: ${{ secrets.AWS_REGION_LOG4J2_INTEG_TEST }} + STACK_NAME: ${{ steps.deploy_stack.outputs.STACK_NAME }} + run: | + sam delete --stack-name "${STACK_NAME}" --no-prompts --region "${AWS_REGION}" diff --git a/.github/workflows/runtime-interface-client_merge_to_main.yml b/.github/workflows/runtime-interface-client_merge_to_main.yml new file mode 100644 index 000000000..d0d479111 --- /dev/null +++ b/.github/workflows/runtime-interface-client_merge_to_main.yml @@ -0,0 +1,96 @@ +# This workflow will be triggered on merge to the main branch if +# aws-lambda-java-runtime-interface-client package was changed +# +# It will publish artifacts to CodeArtifact repository, specified by properties defined in GitHub repo secrets: +# CODE_ARTIFACT_REPO_ACCOUNT, AWS_REGION, CODE_ARTIFACT_REPO_NAME, CODE_ARTIFACT_DOMAIN +# and will assume role specified by AWS_ROLE +# +# Prerequisite setup: +# https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services + +name: Publish artifact for aws-lambda-java-runtime-interface-client + +on: + workflow_dispatch: + push: + branches: [ main ] + paths: + - 'aws-lambda-java-runtime-interface-client/**' + - '.github/workflows/runtime-interface-client_*.yml' + +jobs: + + publish: + runs-on: ubuntu-latest + + permissions: + id-token: write + contents: read + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Set up JDK 1.8 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: 8 + distribution: corretto + cache: maven + + - name: Set up QEMU + uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 + with: + install: true + + - name: Available buildx platforms + run: echo ${{ steps.buildx.outputs.platforms }} + + - name: Build and install serialization dependency locally + working-directory: ./aws-lambda-java-serialization + run: mvn clean install + + - name: Test Runtime Interface Client xplatform build - Run 'build' target + working-directory: ./aws-lambda-java-runtime-interface-client + run: make build + env: + IS_JAVA_8: true + + - name: Issue AWS credentials + if: env.ENABLE_SNAPSHOT != null + env: + ENABLE_SNAPSHOT: ${{ secrets.ENABLE_SNAPSHOT }} + uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4 + with: + aws-region: ${{ secrets.AWS_REGION }} + role-to-assume: ${{ secrets.AWS_ROLE }} + role-session-name: GitHubActionsPublishPackage + role-duration-seconds: 900 + + - name: Prepare codeartifact properties + if: env.ENABLE_SNAPSHOT != null + env: + ENABLE_SNAPSHOT: ${{ secrets.ENABLE_SNAPSHOT }} + working-directory: ./aws-lambda-java-runtime-interface-client/ric-dev-environment + run: | + cat < codeartifact-properties.mk + CODE_ARTIFACT_REPO_ACCOUNT=${{ secrets.AWS_ACCOUNT }} + CODE_ARTIFACT_REPO_REGION=${{ env.AWS_REGION }} + CODE_ARTIFACT_REPO_NAME=${{ secrets.CODE_ARTIFACT_REPO_NAME }} + CODE_ARTIFACT_DOMAIN=${{ secrets.AWS_CODEARTIFACT_DOMAIN }} + EOF + + - name: Publish + if: env.ENABLE_SNAPSHOT != null + working-directory: ./aws-lambda-java-runtime-interface-client + env: + ENABLE_SNAPSHOT: ${{ secrets.ENABLE_SNAPSHOT }} + run: make publish + + - name: Upload coverage to Codecov + if: env.CODECOV_TOKEN != null + uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/runtime-interface-client_pr.yml b/.github/workflows/runtime-interface-client_pr.yml new file mode 100644 index 000000000..bc9e3f3eb --- /dev/null +++ b/.github/workflows/runtime-interface-client_pr.yml @@ -0,0 +1,186 @@ +# This workflow will be triggered if there will be changes to +# aws-lambda-java-runtime-interface-client package or its dependencies (core, serialization), +# and it builds the package. + +name: PR to runtime-interface-client + +on: + workflow_dispatch: + pull_request: + branches: [ '*' ] + paths: + - 'aws-lambda-java-runtime-interface-client/**' + - 'aws-lambda-java-core/**' + - 'aws-lambda-java-serialization/**' + - '.github/workflows/runtime-interface-client_*.yml' + +permissions: + contents: read + +jobs: + + smoke-test-arch: + strategy: + fail-fast: true + matrix: + include: + - arch: x86_64 + runner: ubuntu-latest + - arch: aarch64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + name: "smoke-test (${{ matrix.arch }})" + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Set up JDK 1.8 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: 8 + distribution: corretto + cache: maven + + - name: Build and install core dependency locally + working-directory: ./aws-lambda-java-core + run: mvn clean install + + - name: Build and install serialization dependency locally + working-directory: ./aws-lambda-java-serialization + run: mvn clean install + + - name: Runtime Interface Client smoke tests - Run 'pr-${{ matrix.arch }}' target + working-directory: ./aws-lambda-java-runtime-interface-client + run: make pr-${{ matrix.arch }} + env: + IS_JAVA_8: true + + build-arch: + strategy: + fail-fast: true + matrix: + include: + - arch: x86_64 + runner: ubuntu-latest + - arch: aarch64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + name: "build (${{ matrix.arch }})" + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Set up JDK 1.8 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: 8 + distribution: corretto + cache: maven + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 + with: + install: true + + - name: Build and install core dependency locally + working-directory: ./aws-lambda-java-core + run: mvn clean install + + - name: Build and install serialization dependency locally + working-directory: ./aws-lambda-java-serialization + run: mvn clean install + + - name: Test Runtime Interface Client build - Run 'build-${{ matrix.arch }}' target + working-directory: ./aws-lambda-java-runtime-interface-client + run: make build-${{ matrix.arch }} + env: + IS_JAVA_8: true + + - name: Save the built jar + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: aws-lambda-java-runtime-interface-client-${{ matrix.arch }} + path: ./aws-lambda-java-runtime-interface-client/target/aws-lambda-java-runtime-interface-client-*.jar + + - name: Upload coverage to Codecov + if: env.CODECOV_TOKEN != null + uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + integration-test-matrix: + runs-on: ${{ matrix.arch.runner }} + strategy: + # Run every OS/arch combination to completion so one failure doesn't mask the others. + fail-fast: false + matrix: + buildspec: + - buildspec.os.alpine.yml + - buildspec.os.amazoncorretto.yml + - buildspec.os.amazonlinux.1.yml + - buildspec.os.amazonlinux.2.yml + - buildspec.os.debian.yml + - buildspec.os.ubuntu.yml + arch: + - label: x64 + runner: ubuntu-latest + platform: linux/amd64 + - label: arm64 + runner: ubuntu-24.04-arm + platform: linux/arm64/v8 + exclude: + # Amazon Linux 1 was never published for ARM64 (x86_64 only), so + # public.ecr.aws/amazonlinux/amazonlinux:1 has no arm64 manifest. + - buildspec: buildspec.os.amazonlinux.1.yml + arch: + label: arm64 + runner: ubuntu-24.04-arm + platform: linux/arm64/v8 + name: "integration-test (${{ matrix.buildspec }} / ${{ matrix.arch.label }})" + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 + with: + install: true + + - name: Run OS integration test - 'test-integ' target + working-directory: ./aws-lambda-java-runtime-interface-client + run: make test-integ BUILDSPEC=test/integration/codebuild/${{ matrix.buildspec }} + env: + PLATFORM_FILTER: ${{ matrix.arch.platform }} + + integration-test: + needs: integration-test-matrix + if: always() + runs-on: ubuntu-latest + steps: + - name: Check integration-test results + run: | + if [ "${{ needs.integration-test-matrix.result }}" != "success" ]; then + echo "Integration tests failed on one or more OS/arch combinations" + exit 1 + fi + + smoke-test: + needs: smoke-test-arch + if: always() + runs-on: ubuntu-latest + steps: + - name: Check smoke-test results + run: | + if [ "${{ needs.smoke-test-arch.result }}" != "success" ]; then + echo "Smoke tests failed on one or more architectures" + exit 1 + fi + + build: + needs: build-arch + if: always() + runs-on: ubuntu-latest + steps: + - name: Check build results + run: | + if [ "${{ needs.build-arch.result }}" != "success" ]; then + echo "Build failed on one or more architectures" + exit 1 + fi diff --git a/.github/workflows/samples.yml b/.github/workflows/samples.yml new file mode 100644 index 000000000..68e25827d --- /dev/null +++ b/.github/workflows/samples.yml @@ -0,0 +1,86 @@ +# This workflow will be triggered if there will be changes to samples +# or their dependencies (events, serialization, tests). + +name: Java CI samples + +on: + workflow_dispatch: + push: + branches: [ main ] + paths: + - 'samples/**' + - 'aws-lambda-java-events/**' + - 'aws-lambda-java-serialization/**' + - 'aws-lambda-java-tests/**' + pull_request: + branches: [ '*' ] + paths: + - 'samples/**' + - 'aws-lambda-java-events/**' + - 'aws-lambda-java-serialization/**' + - 'aws-lambda-java-tests/**' + - '.github/workflows/samples.yml' + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Set up JDK 1.8 + uses: actions/setup-java@v5 + with: + java-version: 8 + distribution: corretto + cache: maven + + # Install dependencies + - name: Install events with Maven + run: mvn -B install --file aws-lambda-java-events/pom.xml + - name: Install serialization with Maven + run: mvn -B install --file aws-lambda-java-serialization/pom.xml + - name: Install tests with Maven + run: mvn -B install --file aws-lambda-java-tests/pom.xml + + # Install samples + - name: Install Kinesis Firehose Sample with Maven + run: mvn -B install --file samples/kinesis-firehose-event-handler/pom.xml + + custom-serialization: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + # Set up both Java 8 and 21 + - name: Set up Java 8 and 21 + uses: actions/setup-java@v5 + with: + java-version: | + 8 + 21 + distribution: corretto + cache: maven + + # Install events module using Java 8 + - name: Install events with Maven + run: | + export JAVA_HOME=$JAVA_HOME_8_X64 + mvn -B clean install \ + -Dmaven.compiler.source=1.8 \ + -Dmaven.compiler.target=1.8 \ + --file aws-lambda-java-events/pom.xml + + # Build custom-serialization samples + - name: install sam + uses: aws-actions/setup-sam@d78e1a4a9656d3b223e59b80676a797f20093133 # v2 + - name: test fastJson + run: cd samples/custom-serialization/fastJson && sam build && sam local invoke -e events/event.json | grep 200 + - name: test gson + run: cd samples/custom-serialization/gson && sam build && sam local invoke -e events/event.json | grep 200 + - name: test jackson-jr + run: cd samples/custom-serialization/jackson-jr && sam build && sam local invoke -e events/event.json | grep 200 + - name: test moshi + run: cd samples/custom-serialization/moshi && sam build && sam local invoke -e events/event.json | grep 200 + - name: test request-stream-handler + run: cd samples/custom-serialization/request-stream-handler && sam build && sam local invoke -e events/event.json | grep 200 diff --git a/.gitignore b/.gitignore index e7133935b..5a277e5d6 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,29 @@ hs_err_pid* # Maven build target/ +dependency-reduced-pom.xml # IDEA internal *.iml .idea +.gradle +.settings +.classpath +.project + +# OSX +.DS_Store + +# snapshot process +aws-lambda-java-runtime-interface-client/pom.xml.versionsBackup + +# profiler +experimental/aws-lambda-java-profiler/integration_tests/helloworld/build +experimental/aws-lambda-java-profiler/extension/build/ +experimental/aws-lambda-java-profiler/integration_tests/helloworld/bin +!experimental/aws-lambda-java-profiler/extension/gradle/wrapper/*.jar +/scratch/ +.vscode +.kiro +build +mise.toml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a1241783c..7e8164689 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,6 +36,25 @@ To send us a pull request, please: 5. Send us a pull request, answering any default questions in the pull request interface. 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. + +## Build Prerequisites + +This project uses the Maven Toolchains Plugin to pin compilation to JDK 8. If you don't have a `~/.m2/toolchains.xml` configured, builds will fail with: + +``` +No toolchain found for type jdk [ version='[1.8,9)' ] +``` + +To fix this, copy the example file to your Maven config directory and update the path: + +```bash +cp toolchains.xml.example ~/.m2/toolchains.xml +``` + +Then edit `~/.m2/toolchains.xml` and set `` to your local JDK 8 installation path. + +Note: if you use `actions/setup-java` in CI (as our GitHub Actions workflows do), this file is generated automatically. + GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). diff --git a/README.md b/README.md index 610cf82dd..580e14e41 100644 --- a/README.md +++ b/README.md @@ -1,93 +1,190 @@ # AWS Lambda Java Support Libraries -Interface definitions for Java code running on the AWS Lambda platform. +Key libraries for running Java on the AWS Lambda platform. -For issues and questions, you can start with our [FAQ](https://aws.amazon.com/lambda/faqs/) and the [AWS forums](https://forums.aws.amazon.com/forum.jspa?forumID=186) +For issues and questions, you can start with our [FAQ](https://aws.amazon.com/lambda/faqs/) +and the AWS questions and answer site [re:Post](https://repost.aws/tags/TA5uNafDy2TpGNjidWLMSxDw/aws-lambda) -To get started writing AWS Lambda functions in Java, check out the [official documentation] (http://docs.aws.amazon.com/lambda/latest/dg/java-gs.html). +To get started writing Lambda functions in Java, check out the official [developer guide](https://docs.aws.amazon.com/lambda/latest/dg/lambda-java.html). -# Disclaimer of use +For information on how to optimize your functions watch the re:Invent talk [Optimize your Java application on AWS Lambda](https://www.youtube.com/watch?v=sVJOJUD0fhQ). -Each of the supplied packages should be used without modification. Removing -dependencies, adding conflicting dependencies, or selectively including classes -from the packages can result in unexpected behavior. +## Core Java Lambda interfaces - aws-lambda-java-core + +[![Maven](https://img.shields.io/maven-central/v/com.amazonaws/aws-lambda-java-core.svg?label=Maven)](https://central.sonatype.com/artifact/com.amazonaws/aws-lambda-java-core) + +This package defines the Lambda [Context](http://docs.aws.amazon.com/lambda/latest/dg/java-context-object.html) object +as well as [interfaces](http://docs.aws.amazon.com/lambda/latest/dg/java-handler-using-predefined-interfaces.html) that Lambda accepts. + +- [Release Notes](aws-lambda-java-core/RELEASE.CHANGELOG.md) + +Example request handler + +```java +public class Handler implements RequestHandler, String>{ + @Override + public String handleRequest(Map event, Context context) { -# Recent Updates! + } +} +``` -* ### [SQS Support](https://github.com/aws/aws-lambda-java-libs/commit/9a74fdc9d92b5d7f73ae05660090e65cbd098360) -* ### [Kinesis Analytics Support](https://github.com/aws/aws-lambda-java-libs/commit/943352c7f0256afe82773e664e887e1593303508) -* ### [2017 Java Events Update](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-events) -* ### [Log4j2 Support](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-log4j2) +Example request stream handler -# Where to get packages -___ +```java +public class HandlerStream implements RequestStreamHandler { + @Override + public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { -[Maven](https://maven.apache.org) + } +} +``` ```xml - com.amazonaws - aws-lambda-java-core - 1.2.0 + com.amazonaws + aws-lambda-java-core + 1.3.0 +``` + +## Java objects of Lambda event sources - aws-lambda-java-events + +[![Maven](https://img.shields.io/maven-central/v/com.amazonaws/aws-lambda-java-events.svg?label=Maven)](https://central.sonatype.com/artifact/com.amazonaws/aws-lambda-java-events) + +This package defines [event sources](http://docs.aws.amazon.com/lambda/latest/dg/intro-invocation-modes.html) that Lambda natively accepts. +See the [documentation](aws-lambda-java-events/README.md) for a list of currently supported event sources. +Using this library you can have Java objects which represent event sources. + +For example an SQS event: + +```java +import com.amazonaws.services.lambda.runtime.events.SQSEvent; + +public class SqsHandler implements RequestHandler { + + @Override + public String handleRequest(SQSEvent event, Context context) { + + } +} +``` + +- [Release Notes](aws-lambda-java-events/RELEASE.CHANGELOG.md) + +```xml - com.amazonaws - aws-lambda-java-events - 2.2.6 + com.amazonaws + aws-lambda-java-events + 3.16.0 +``` + +## Java Lambda JUnit Support - aws-lambda-java-tests + +[![Maven](https://img.shields.io/maven-central/v/com.amazonaws/aws-lambda-java-tests.svg?label=Maven)](https://central.sonatype.com/artifact/com.amazonaws/aws-lambda-java-tests) + +This package provides utils to ease Lambda Java testing. It uses the same Lambda serialisation logic and `aws-lambda-java-events` to inject events in your JUnit tests. + +- [Release Notes](aws-lambda-java-tests/RELEASE.CHANGELOG.md) + +```java +@ParameterizedTest +@Event(value = "sqs/sqs_event.json", type = SQSEvent.class) +public void testInjectSQSEvent(SQSEvent event) { + ... +} +``` + +```xml com.amazonaws - aws-lambda-java-log4j - 1.0.0 + aws-lambda-java-tests + 1.1.1 + test +``` + +## aws-lambda-java-events-sdk-transformer + +[![Maven](https://img.shields.io/maven-central/v/com.amazonaws/aws-lambda-java-events-sdk-transformer.svg?label=Maven)](https://central.sonatype.com/artifact/com.amazonaws/aws-lambda-java-events-sdk-transformer) + +This package provides helper classes/methods to use alongside `aws-lambda-java-events` in order to transform +Lambda input event model objects into SDK-compatible output model objects. +See the [documentation](aws-lambda-java-events-sdk-transformer/README.md) for more information. + +- [Release Notes](aws-lambda-java-events-sdk-transformer/RELEASE.CHANGELOG.md) + +```xml - com.amazonaws - aws-lambda-java-log4j2 - 1.0.0 + com.amazonaws + aws-lambda-java-events-sdk-transformer + 3.1.0 ``` -[Gradle](https://gradle.org) +## Java Lambda Log4J2 support - aws-lambda-java-log4j2 -```groovy -'com.amazonaws:aws-lambda-java-core:1.2.0' -'com.amazonaws:aws-lambda-java-events:2.2.6' -'com.amazonaws:aws-lambda-java-log4j:1.0.0' -'com.amazonaws:aws-lambda-java-log4j2:1.0.0' -``` +[![Maven](https://img.shields.io/maven-central/v/com.amazonaws/aws-lambda-java-log4j2.svg?label=Maven)](https://central.sonatype.com/artifact/com.amazonaws/aws-lambda-java-log4j2) + +This package defines the Lambda adapter to use with Log4J version 2. +See the [README](aws-lambda-java-log4j2/README.md) or the [official documentation](http://docs.aws.amazon.com/lambda/latest/dg/java-logging.html#java-wt-logging-using-log4j) for information on how to use the adapter. -[Leiningen](http://leiningen.org) and [Boot](http://boot-clj.com) +- [Release Notes](aws-lambda-java-log4j2/RELEASE.CHANGELOG.md) -```clojure -[com.amazonaws/aws-lambda-java-core "1.2.0"] -[com.amazonaws/aws-lambda-java-events "2.2.6"] -[com.amazonaws/aws-lambda-java-log4j "1.0.0"] -[com.amazonaws/aws-lambda-java-log4j2 "1.0.0"] +```xml + + com.amazonaws + aws-lambda-java-log4j2 + 1.6.0 + ``` -[sbt](http://www.scala-sbt.org) +## Lambda Profiler Extension for Java - aws-lambda-java-profiler -```scala -"com.amazonaws" % "aws-lambda-java-core" % "1.2.0" -"com.amazonaws" % "aws-lambda-java-events" % "2.2.6" -"com.amazonaws" % "aws-lambda-java-log4j" % "1.0.0" -"com.amazonaws" % "aws-lambda-java-log4j2" % "1.0.0" -``` +

+ A flame graph of a Java Lambda function +

-# Using aws-lambda-java-core +This project allows you to profile your Java functions invoke by invoke, with high fidelity, and no code changes. It +uses the [async-profiler](https://github.com/async-profiler/async-profiler) project to produce profiling data and +automatically uploads the data as flame graphs to S3. -This package defines the Lambda [Context](http://docs.aws.amazon.com/lambda/latest/dg/java-context-object.html) -object as well as [interfaces](http://docs.aws.amazon.com/lambda/latest/dg/java-handler-using-predefined-interfaces.html) that Lambda accepts. +Follow our [Quick Start](experimental/aws-lambda-java-profiler#quick-start) to profile your functions. -# Using aws-lambda-java-events +## Java implementation of the Runtime Interface Client API - aws-lambda-java-runtime-interface-client +[![Maven](https://img.shields.io/maven-central/v/com.amazonaws/aws-lambda-java-runtime-interface-client.svg?label=Maven)](https://central.sonatype.com/artifact/com.amazonaws/aws-lambda-java-runtime-interface-client) -This package defines [event sources](http://docs.aws.amazon.com/lambda/latest/dg/intro-invocation-modes.html) that AWS Lambda natively accepts. See the [documentation](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-events) for more information. +This package defines the Lambda Java Runtime Interface Client package, a Lambda Runtime component that starts the runtime and interacts with the Runtime API - i.e., it calls the API for invocation events, starts the function code, calls the API to return the response. +The purpose of this package is to allow developers to deploy their applications in Lambda under the form of Container Images. See the [README](aws-lambda-java-runtime-interface-client/README.md) for information on how to use the library. -# Using aws-lambda-java-log4j2 +- [Release Notes](aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md) -This package defines the Lambda adapter to use with log4j version 2. See -[documentation](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-log4j2) for how to use the adapter. +```xml + + com.amazonaws + aws-lambda-java-runtime-interface-client + 2.10.1 + +``` + +## Java Lambda provided serialization support - aws-lambda-java-serialization + +[![Maven](https://img.shields.io/maven-central/v/com.amazonaws/aws-lambda-java-serialization.svg?label=Maven)](https://central.sonatype.com/artifact/com.amazonaws/aws-lambda-java-serialization) + +This package defines the Lambda serialization logic using in the `aws-lambda-java-runtime-client` library. It has no current standalone usage. + +- [Release Notes](aws-lambda-java-serialization/RELEASE.CHANGELOG.md) -# Using aws-lambda-java-log4j (Not recommended) +```xml + + com.amazonaws + aws-lambda-java-serialization + 1.1.5 + +``` -This package defines the Lambda adapter to use with log4j version 1. See -the [official documentation](http://docs.aws.amazon.com/lambda/latest/dg/java-logging.html#java-wt-logging-using-log4j) for how to use this adapter. +## Disclaimer of use + +Each of the supplied packages should be used without modification. Removing +dependencies, adding conflicting dependencies, or selectively including classes +from the packages can result in unexpected behavior. diff --git a/aws-lambda-java-core/RELEASE.CHANGELOG.md b/aws-lambda-java-core/RELEASE.CHANGELOG.md new file mode 100644 index 000000000..aebc8ecd9 --- /dev/null +++ b/aws-lambda-java-core/RELEASE.CHANGELOG.md @@ -0,0 +1,35 @@ +### September 3, 2025 +`1.4.0` +- Getter support for x-ray trace ID through the Context object + +### May 26, 2025 +`1.3.0` +- Adding support for multi tenancy ([#545](https://github.com/aws/aws-lambda-java-libs/pull/545)) + +### August 17, 2023 +`1.2.3`: +- Extended logger interface with level-aware logging backend functions + +### November 09, 2022 +`1.2.2`: +- Added new `CustomPojoSerializer` interface +- Removed unnecessary usage of public on interface methods (aws#172) + +### April 28, 2020 +`1.2.1`: +- Added missing XML namespace declarations to `pom.xml` file ([#97](https://github.com/aws/aws-lambda-java-libs/issues/97)) +- Updated `nexusUrl` in `pom.xml` file ([#108](https://github.com/aws/aws-lambda-java-libs/issues/108)) + +### November 21, 2017 +`1.2.0`: +- Added method to log byte array to `LambdaLogger` + +### October 07, 2015 +`1.1.0`: +- Added `LambdaRuntime` and `LambdaRuntimeInternal` +- Added `getInstallationId()` to `Client` +- Added `getFunctionVersion()` and `getInvokedFunctionArn()` to `Context` + +### June 15, 2015 +`1.0.0`: +- Initial support for java in AWS Lambda diff --git a/aws-lambda-java-core/pom.xml b/aws-lambda-java-core/pom.xml index 7fc787bce..f45b32fb6 100644 --- a/aws-lambda-java-core/pom.xml +++ b/aws-lambda-java-core/pom.xml @@ -1,9 +1,11 @@ - + 4.0.0 com.amazonaws aws-lambda-java-core - 1.2.0 + 1.4.0-SNAPSHOT jar AWS Lambda Java Core Library @@ -20,6 +22,9 @@ https://github.com/aws/aws-lambda-java-libs.git + scm:git:https://github.com/aws/aws-lambda-java-libs.git + scm:git:https://github.com/aws/aws-lambda-java-libs.git + HEAD @@ -29,12 +34,47 @@ - - - sonatype-nexus-staging - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - + + 1.8 + 1.8 + + + + + + org.apache.maven.plugins + maven-release-plugin + 3.1.1 + + aws-lambda-java-core-@{project.version} + true + release + deploy + + + + org.apache.maven.plugins + maven-toolchains-plugin + 3.2.0 + + + + + [1.8,9) + + + + + + + toolchain + + + + + + @@ -108,14 +148,13 @@ - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.3 + org.sonatype.central + central-publishing-maven-plugin + 0.8.0 true - sonatype-nexus-staging - https://oss.sonatype.org/ - false + central + false diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Client.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Client.java index 6acdd38cc..be8856871 100644 --- a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Client.java +++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Client.java @@ -11,28 +11,28 @@ public interface Client { /** * Gets the application's installation id */ - public String getInstallationId(); + String getInstallationId(); /** * Gets the application's title * */ - public String getAppTitle(); + String getAppTitle(); /** * Gets the application's version * */ - public String getAppVersionName(); + String getAppVersionName(); /** * Gets the application's version code * */ - public String getAppVersionCode(); + String getAppVersionCode(); /** * Gets the application's package name */ - public String getAppPackageName(); + String getAppPackageName(); } diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/ClientContext.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/ClientContext.java index 2815396d0..71f442e49 100644 --- a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/ClientContext.java +++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/ClientContext.java @@ -14,7 +14,7 @@ public interface ClientContext { * Gets the client information provided by the AWS Mobile SDK * */ - public Client getClient(); + Client getClient(); /** * Gets custom values set by the client application @@ -22,12 +22,12 @@ public interface ClientContext { * This map is mutable (and not thread-safe if mutated) *

*/ - public Map getCustom(); + Map getCustom(); /** * Gets environment information provided by mobile SDK, immutable. * */ - public Map getEnvironment(); + Map getEnvironment(); } diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/CognitoIdentity.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/CognitoIdentity.java index 25f3b3dd3..a65887632 100644 --- a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/CognitoIdentity.java +++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/CognitoIdentity.java @@ -11,11 +11,11 @@ public interface CognitoIdentity { * Gets the Amazon Cognito identity ID * */ - public String getIdentityId(); + String getIdentityId(); /** * Gets the Amazon Cognito identity pool ID * */ - public String getIdentityPoolId(); + String getIdentityPoolId(); } diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Context.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Context.java index a0850e78c..ed9311a11 100644 --- a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Context.java +++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Context.java @@ -100,4 +100,23 @@ public interface Context { */ LambdaLogger getLogger(); + /** + * + * Returns the tenant ID associated with the request. + * + * @return null by default + */ + default String getTenantId() { + return null; + } + + /** + * + * Returns the X-Ray trace ID associated with the request. + * + * @return null by default + */ + default String getXrayTraceId() { + return null; + } } diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/CustomPojoSerializer.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/CustomPojoSerializer.java new file mode 100644 index 000000000..0d7cc27d4 --- /dev/null +++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/CustomPojoSerializer.java @@ -0,0 +1,38 @@ +/* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. */ + +package com.amazonaws.services.lambda.runtime; + +import java.io.InputStream; +import java.io.OutputStream; + +import java.lang.reflect.Type; + +/** + * Interface required to implement a custom plain old java objects serializer + */ +public interface CustomPojoSerializer { + + /** + * Deserializes from input stream to plain old java object + * @param input input stream + * @param type plain old java object type + * @return deserialized plain old java object of type T + */ + T fromJson(InputStream input, Type type); + + /** + * Deserializes from String to plain old java object + * @param input input string + * @param type plain old java object type + * @return deserialized plain old java object of type T + */ + T fromJson(String input, Type type); + + /** + * Serializes plain old java object to output stream + * @param value instance of type T to be serialized + * @param output OutputStream to serialize plain old java object to + * @param type plain old java object type + */ + void toJson(T value, OutputStream output, Type type); +} diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/LambdaLogger.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/LambdaLogger.java index 8ff064589..e068abe8a 100644 --- a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/LambdaLogger.java +++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/LambdaLogger.java @@ -2,6 +2,8 @@ package com.amazonaws.services.lambda.runtime; +import com.amazonaws.services.lambda.runtime.logging.LogLevel; + /** * A low level Lambda runtime logger * @@ -10,7 +12,7 @@ public interface LambdaLogger { /** * Logs a string to AWS CloudWatch Logs - * + * *

* Logging will not be done: *

    @@ -22,15 +24,37 @@ public interface LambdaLogger { * *
*

- * + * * @param message A string containing the event to log. */ - public void log(String message); + void log(String message); /** * Logs a byte array to AWS CloudWatch Logs * @param message byte array containing logs */ - public void log(byte[] message); + void log(byte[] message); + + /** + * LogLevel aware logging backend function. + * + * @param message in String format + * @param logLevel + */ + default void log(String message, LogLevel logLevel) { + log(message); + } + + /** + * LogLevel aware logging backend function. + * + * @param message in byte[] format + * @param logLevel + */ + default void log(byte[] message, LogLevel logLevel) { + log(message); + } + + } diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java index 406f2be3b..834683f26 100644 --- a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java +++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java @@ -17,5 +17,5 @@ public interface RequestHandler { * @param context The Lambda execution environment context object. * @return The Lambda Function output */ - public O handleRequest(I input, Context context); + O handleRequest(I input, Context context); } diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java index d8ccf5a6b..3a34adc9b 100644 --- a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java +++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java @@ -18,5 +18,5 @@ public interface RequestStreamHandler { * @param context The Lambda execution environment context object. * @throws IOException */ - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException; + void handleRequest(InputStream input, OutputStream output, Context context) throws IOException; } diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/logging/LogFormat.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/logging/LogFormat.java new file mode 100644 index 000000000..0d65860d7 --- /dev/null +++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/logging/LogFormat.java @@ -0,0 +1,17 @@ +/* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. */ + +package com.amazonaws.services.lambda.runtime.logging; + + +public enum LogFormat { + JSON, + TEXT; + + public static LogFormat fromString(String logFormat) { + try { + return LogFormat.valueOf(logFormat.toUpperCase()); + } catch (Exception e) { + throw new IllegalArgumentException("Invalid log format: '" + logFormat + "' expected one of [JSON, TEXT]"); + } + } +} diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/logging/LogLevel.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/logging/LogLevel.java new file mode 100644 index 000000000..4f48a3e41 --- /dev/null +++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/logging/LogLevel.java @@ -0,0 +1,25 @@ +/* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. */ + +package com.amazonaws.services.lambda.runtime.logging; + + +public enum LogLevel { + // UNDEFINED log level is used when the legacy LambdaLogger::log(String) function is called + // where the loglevel is not defined. In this case we're not filtering the message in the runtime + UNDEFINED, + TRACE, + DEBUG, + INFO, + WARN, + ERROR, + FATAL; + + public static LogLevel fromString(String logLevel) { + try { + return LogLevel.valueOf(logLevel.toUpperCase()); + } catch (Exception e) { + throw new IllegalArgumentException( + "Invalid log level: '" + logLevel + "' expected one of [TRACE, DEBUG, INFO, WARN, ERROR, FATAL]"); + } + } +} diff --git a/aws-lambda-java-events-sdk-transformer/README.md b/aws-lambda-java-events-sdk-transformer/README.md new file mode 100644 index 000000000..02f2dc11f --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/README.md @@ -0,0 +1,214 @@ +# AWS Lambda Java Events SDK Transformer Library + +### About + +Provides helper classes/methods to use alongside `aws-lambda-java-events` in order to transform Lambda input event model + objects into SDK-compatible output model objects + (eg. DynamodbEvent to a List of records writable back to DynamoDB through the AWS DynamoDB SDK for Java v1 or v2). + + +### Getting started + +Add the following Apache Maven dependencies to your `pom.xml` file: + +```xml + + + com.amazonaws + aws-lambda-java-events-sdk-transformer + 3.1.0 + + + com.amazonaws + aws-lambda-java-events + 3.11.2 + + +``` + +To use this library as a transformer to the AWS DynamoDB Java SDK v2, also add the following dependency to your `pom.xml` file: + +```xml + + + software.amazon.awssdk + dynamodb + 2.15.40 + + +``` + +To use this library as a transformer to the AWS DynamoDB Java SDK v1, add the following dependency to your `pom.xml` file instead: + +```xml + + + com.amazonaws + aws-java-sdk-dynamodb + 1.11.914 + + +``` + + +### Example Usage + +#### SDK v2 + +To convert a full `DynamodbEvent` object to an SDK v2 compatible `List`: + +```java +import com.amazonaws.services.lambda.runtime.events.transformers.v2.DynamodbEventTransformer; + +public class DDBEventProcessor implements RequestHandler { + + public String handleRequest(DynamodbEvent ddbEvent, Context context) { + // Process input event + List convertedRecords = DynamodbEventTransformer.toRecordsV2(ddbEvent); + // Modify records as needed and write back to DynamoDB using the DynamoDB AWS SDK for Java 2.0 + } +} +``` + +To convert a single `DynamodbEvent.DynamodbStreamRecord` object to an SDK v2 compatible `Record`: + +```java +import com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbRecordTransformer; + +public class MyClass { + + public void myMethod(DynamodbEvent.DynamodbStreamRecord record) { + // ... + Record convertedRecord = DynamodbRecordTransformer.toRecordV2(record); + // ... + } +} +``` + +To convert a `StreamRecord` object originating from a `DynamodbEvent` to an SDK v2 compatible `StreamRecord`: + +```java +import com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbStreamRecordTransformer; + +public class MyClass { + + public void myMethod(StreamRecord streamRecord) { + // ... + software.amazon.awssdk.services.dynamodb.model.StreamRecord convertedStreamRecord = + DynamodbStreamRecordTransformer.toStreamRecordV2(streamRecord); + // ... + } +} +``` + +To convert an `AttributeValue` object originating from a `DynamodbEvent` to an SDK v2 compatible `AttributeValue`: + +```java +import com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformer; + +public class MyClass { + + public void myMethod(AttributeValue attributeValue) { + // ... + software.amazon.awssdk.services.dynamodb.model.AttributeValue convertedAttributeValue = + DynamodbAttributeValueTransformer.toAttributeValueV2(attributeValue); + // ... + } +} +``` + +To convert an `Identity` object originating from a `DynamodbEvent` to an SDK v2 compatible `Identity`: + +```java +import com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbIdentityTransformer; + +public class MyClass { + + public void myMethod(Identity identity) { + // ... + software.amazon.awssdk.services.dynamodb.model.Identity convertedIdentity = + DynamodbIdentityTransformer.toIdentityV2(identity); + // ... + } +} +``` + +#### SDK v1 + +To convert a full `DynamodbEvent` object to an SDK v1 compatible `List`: + +```java +import com.amazonaws.services.lambda.runtime.events.transformers.v1.DynamodbEventTransformer; + +public class DDBEventProcessor implements RequestHandler { + + public String handleRequest(DynamodbEvent ddbEvent, Context context) { + // Process input event + List convertedRecords = DynamodbEventTransformer.toRecordsV1(ddbEvent); + // Modify records as needed and write back to DynamoDB using the DynamoDB AWS SDK for Java 2.0 + } +} +``` + +To convert a single `DynamodbEvent.DynamodbStreamRecord` object to an SDK v1 compatible `Record`: + +```java +import com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbRecordTransformer; + +public class MyClass { + + public void myMethod(DynamodbEvent.DynamodbStreamRecord record) { + // ... + Record convertedRecord = DynamodbRecordTransformer.toRecordV1(record); + // ... + } +} +``` + +To convert a `StreamRecord` object originating from a `DynamodbEvent` to an SDK v1 compatible `StreamRecord`: + +```java +import com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbStreamRecordTransformer; + +public class MyClass { + + public void myMethod(StreamRecord streamRecord) { + // ... + com.amazonaws.services.dynamodbv2.model.StreamRecord convertedStreamRecord = + DynamodbStreamRecordTransformer.toStreamRecordV1(streamRecord); + // ... + } +} +``` + +To convert an `AttributeValue` object originating from a `DynamodbEvent` to an SDK v1 compatible `AttributeValue`: + +```java +import com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformer; + +public class MyClass { + + public void myMethod(AttributeValue attributeValue) { + // ... + com.amazonaws.services.dynamodbv2.model.AttributeValue convertedAttributeValue = + DynamodbAttributeValueTransformer.toAttributeValueV1(attributeValue); + // ... + } +} +``` + +To convert an `Identity` object originating from a `DynamodbEvent` to an SDK v1 compatible `Identity`: + +```java +import com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbIdentityTransformer; + +public class MyClass { + + public void myMethod(Identity identity) { + // ... + com.amazonaws.services.dynamodbv2.model.Identity convertedIdentity = + DynamodbIdentityTransformer.toIdentityV1(identity); + // ... + } +} +``` \ No newline at end of file diff --git a/aws-lambda-java-events-sdk-transformer/RELEASE.CHANGELOG.md b/aws-lambda-java-events-sdk-transformer/RELEASE.CHANGELOG.md new file mode 100644 index 000000000..791348208 --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/RELEASE.CHANGELOG.md @@ -0,0 +1,80 @@ +### February 03, 2022 +`3.1.0`: +- Make DynamodbAttributeValueTransformer v1 and v2 return empty list instead of null for empty list attribute ([#309](https://github.com/aws/aws-lambda-java-libs/pull/309)) + +### November 24, 2021 +`3.0.7`: +- Bumped `aws-lambda-java-events` to version `3.11.0` + +### September 02, 2021 +`3.0.6`: +- Fixed NPE when UserIdentity, OldImage, or NewImage is null ([#264](https://github.com/aws/aws-lambda-java-libs/pull/264)) + +### August 26, 2021 +`3.0.5`: +- Bumped `aws-lambda-java-events` to version `3.10.0` + +### June 2, 2021 +`3.0.4`: +- Bumped `aws-lambda-java-events` to version `3.9.0` + +### March 24, 2021 +`3.0.3`: +- Bumped `aws-lambda-java-events` to version `3.8.0` + +### December 16, 2020 +`3.0.2`: +- Bumped `aws-lambda-java-events` to version `3.7.0` + +### December 10, 2020 +`3.0.1`: +- Change visibility scope of `Map toAttributeValueMapVx(Map)` to `public` + +### December 09, 2020 +`3.0.0`: +- Added AWS SDK V1 transformers for `DynamodbEvent` in `aws-lambda-java-events` versions `3.0.0` and up +- Moved existing SDK v2 transformers into `v2` package (from `com.amazonaws.services.lambda.runtime.events.transformers` to `com.amazonaws.services.lambda.runtime.events.transformers.v2`) +- Bumped `software.amazon.awssdk:dynamodb` to version `2.15.40` + +### November 06, 2020 +`2.0.8`: +- Bumped `aws-lambda-java-events` to version `3.6.0` +- Bumped `junit-jupiter-engine` to version `5.7.0` + +### October 28, 2020 +`2.0.7`: +- Bumped `aws-lambda-java-events` to version `3.5.0` + +### October 07, 2020 +`2.0.6`: +- Fixed NPE when UserIdentity is null ([#169](https://github.com/aws/aws-lambda-java-libs/pull/169)) +- Bumped `aws-lambda-java-events` to version `3.4.0` + +### September 23, 2020 +`2.0.5`: +- Bumped `aws-lambda-java-events` to version `3.3.1` + +### September 14, 2020 +`2.0.4`: +- Bumped `aws-lambda-java-events` to version `3.3.0` + +### August 11, 2020 +`2.0.3`: +- Bumped `aws-lambda-java-events` to version `3.2.0` + +### July 31, 2020 +`2.0.2`: +- Bumped `aws-lambda-java-events` to version `3.1.1` + +### June 15, 2020 +`2.0.1`: +- Fixed NPE when mapping insert/delete events ([#143](https://github.com/aws/aws-lambda-java-libs/pull/143)) + +### May 20, 2020 +`2.0.0`: +- Updated AWS SDK V2 transformers for `DynamodbEvent` to work with `aws-lambda-java-events` versions `3.0.0` and up +- Bumped `software.amazon.awssdk:dynamodb` to version `2.13.18` + +### April 29, 2020 +`1.0.0`: +- Added AWS SDK V2 transformers for `DynamodbEvent` in `aws-lambda-java-events` versions up to and including `2.x` diff --git a/aws-lambda-java-events-sdk-transformer/pom.xml b/aws-lambda-java-events-sdk-transformer/pom.xml new file mode 100644 index 000000000..f66020068 --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/pom.xml @@ -0,0 +1,216 @@ + + 4.0.0 + + com.amazonaws + aws-lambda-java-events-sdk-transformer + 3.1.1-SNAPSHOT + jar + + AWS Lambda Java Events SDK Transformer Library + + Provides helper classes/methods to use alongside aws-lambda-java-events in order to transform Lambda input event model + objects into SDK-compatible output model objects (eg. DynamodbEvent to a List of records writable back to DynamoDB + through the AWS DynamoDB SDK for Java v1 or v2) + + https://aws.amazon.com/lambda/ + + + Apache License, Version 2.0 + https://aws.amazon.com/apache2.0 + repo + + + + https://github.com/aws/aws-lambda-java-libs.git + scm:git:https://github.com/aws/aws-lambda-java-libs.git + scm:git:https://github.com/aws/aws-lambda-java-libs.git + HEAD + + + + AWS Lambda team + Amazon Web Services + https://aws.amazon.com/ + + + + + 1.8 + 1.8 + 1.11.914 + 2.15.40 + 5.12.2 + 3.5.4 + + + + + sonatype-nexus-staging + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + software.amazon.awssdk + dynamodb + ${sdk.v2.version} + provided + + + com.amazonaws + aws-java-sdk-dynamodb + ${sdk.v1.version} + provided + + + com.amazonaws + aws-lambda-java-events + 3.16.1 + provided + + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter.version} + test + + + + + + + org.apache.maven.plugins + maven-release-plugin + 3.1.1 + + aws-lambda-java-events-sdk-transformer-@{project.version} + true + release + deploy + + + + org.apache.maven.plugins + maven-toolchains-plugin + 3.2.0 + + + + + [1.8,9) + + + + + + + toolchain + + + + + + maven-surefire-plugin + ${maven-surefire-plugin.version} + + true + + + + maven-failsafe-plugin + ${maven-surefire-plugin.version} + + + + + + + dev + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + -Xdoclint:none + + + + attach-javadocs + + jar + + + + + + + + + release + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + -Xdoclint:none + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + org.sonatype.central + central-publishing-maven-plugin + 0.8.0 + true + + central + false + + + + + + + \ No newline at end of file diff --git a/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/DynamodbEventTransformer.java b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/DynamodbEventTransformer.java new file mode 100644 index 000000000..c9686d103 --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/DynamodbEventTransformer.java @@ -0,0 +1,21 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v1; + +import com.amazonaws.services.dynamodbv2.model.Record; +import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; +import com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbRecordTransformer; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class DynamodbEventTransformer { + + public static List toRecordsV1(final DynamodbEvent dynamodbEvent) { + return dynamodbEvent + .getRecords() + .stream() + .filter(record -> !Objects.isNull(record)) + .map(DynamodbRecordTransformer::toRecordV1) + .collect(Collectors.toList()); + } +} diff --git a/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbAttributeValueTransformer.java b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbAttributeValueTransformer.java new file mode 100644 index 000000000..61f311f5b --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbAttributeValueTransformer.java @@ -0,0 +1,74 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb; + +import com.amazonaws.services.dynamodbv2.model.AttributeValue; + +import java.util.Collections; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +public class DynamodbAttributeValueTransformer { + + public static AttributeValue toAttributeValueV1(final com.amazonaws.services.lambda.runtime.events.models.dynamodb.AttributeValue value) { + if (Objects.nonNull(value.getS())) { + return new AttributeValue() + .withS(value.getS()); + + } else if (Objects.nonNull(value.getSS())) { + return new AttributeValue() + .withSS(value.getSS().isEmpty() ? null : value.getSS()); + + } else if (Objects.nonNull(value.getN())) { + return new AttributeValue() + .withN(value.getN()); + + } else if (Objects.nonNull(value.getNS())) { + return new AttributeValue() + .withNS(value.getNS().isEmpty() ? null : value.getNS()); + + } else if (Objects.nonNull(value.getB())) { + return new AttributeValue() + .withB(value.getB()); + + } else if (Objects.nonNull(value.getBS())) { + return new AttributeValue() + .withBS(value.getBS().isEmpty() ? null : value.getBS()); + + } else if (Objects.nonNull(value.getBOOL())) { + return new AttributeValue() + .withBOOL(value.getBOOL()); + + } else if (Objects.nonNull(value.getL())) { + return new AttributeValue() + .withL(value.getL().isEmpty() + ? Collections.emptyList() + : value.getL().stream() + .map(DynamodbAttributeValueTransformer::toAttributeValueV1) + .collect(Collectors.toList())); + + } else if (Objects.nonNull(value.getM())) { + return new AttributeValue() + .withM(toAttributeValueMapV1(value.getM())); + + } else if (Objects.nonNull(value.getNULL())) { + return new AttributeValue() + .withNULL(value.getNULL()); + + } else { + throw new IllegalArgumentException( + String.format("Unsupported attributeValue type: %s", value)); + } + } + + public static Map toAttributeValueMapV1( + final Map attributeValueMap + ) { + return attributeValueMap + .entrySet() + .stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> toAttributeValueV1(entry.getValue()) + )); + } +} diff --git a/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbIdentityTransformer.java b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbIdentityTransformer.java new file mode 100644 index 000000000..32f7aaff9 --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbIdentityTransformer.java @@ -0,0 +1,12 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb; + +import com.amazonaws.services.dynamodbv2.model.Identity; + +public class DynamodbIdentityTransformer { + + public static Identity toIdentityV1(final com.amazonaws.services.lambda.runtime.events.models.dynamodb.Identity identity) { + return new Identity() + .withPrincipalId(identity.getPrincipalId()) + .withType(identity.getType()); + } +} diff --git a/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbRecordTransformer.java b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbRecordTransformer.java new file mode 100644 index 000000000..7527cd91b --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbRecordTransformer.java @@ -0,0 +1,24 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb; + +import com.amazonaws.services.dynamodbv2.model.Record; +import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; + +public class DynamodbRecordTransformer { + + public static Record toRecordV1(final DynamodbEvent.DynamodbStreamRecord record) { + return new Record() + .withAwsRegion(record.getAwsRegion()) + .withDynamodb( + DynamodbStreamRecordTransformer.toStreamRecordV1(record.getDynamodb()) + ) + .withEventID(record.getEventID()) + .withEventName(record.getEventName()) + .withEventSource(record.getEventSource()) + .withEventVersion(record.getEventVersion()) + .withUserIdentity( + record.getUserIdentity() != null + ? DynamodbIdentityTransformer.toIdentityV1(record.getUserIdentity()) + : null + ); + } +} diff --git a/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbStreamRecordTransformer.java b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbStreamRecordTransformer.java new file mode 100644 index 000000000..f7ca2c6d3 --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbStreamRecordTransformer.java @@ -0,0 +1,29 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb; + +import com.amazonaws.services.dynamodbv2.model.StreamRecord; + +public class DynamodbStreamRecordTransformer { + + public static StreamRecord toStreamRecordV1(final com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord streamRecord) { + return new StreamRecord() + .withApproximateCreationDateTime( + streamRecord.getApproximateCreationDateTime() + ) + .withKeys( + DynamodbAttributeValueTransformer.toAttributeValueMapV1(streamRecord.getKeys()) + ) + .withNewImage( + streamRecord.getNewImage() != null + ? DynamodbAttributeValueTransformer.toAttributeValueMapV1(streamRecord.getNewImage()) + : null + ) + .withOldImage( + streamRecord.getOldImage() != null + ? DynamodbAttributeValueTransformer.toAttributeValueMapV1(streamRecord.getOldImage()) + : null + ) + .withSequenceNumber(streamRecord.getSequenceNumber()) + .withSizeBytes(streamRecord.getSizeBytes()) + .withStreamViewType(streamRecord.getStreamViewType()); + } +} diff --git a/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/DynamodbEventTransformer.java b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/DynamodbEventTransformer.java new file mode 100644 index 000000000..43e57564c --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/DynamodbEventTransformer.java @@ -0,0 +1,21 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v2; + +import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; +import com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbRecordTransformer; +import software.amazon.awssdk.services.dynamodb.model.Record; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class DynamodbEventTransformer { + + public static List toRecordsV2(final DynamodbEvent dynamodbEvent) { + return dynamodbEvent + .getRecords() + .stream() + .filter(record -> !Objects.isNull(record)) + .map(DynamodbRecordTransformer::toRecordV2) + .collect(Collectors.toList()); + } +} diff --git a/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbAttributeValueTransformer.java b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbAttributeValueTransformer.java new file mode 100644 index 000000000..ee810c501 --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbAttributeValueTransformer.java @@ -0,0 +1,89 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb; + +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; + +import java.util.Collections; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +public class DynamodbAttributeValueTransformer { + + public static AttributeValue toAttributeValueV2(final com.amazonaws.services.lambda.runtime.events.models.dynamodb.AttributeValue value) { + if (Objects.nonNull(value.getS())) { + return AttributeValue.builder() + .s(value.getS()) + .build(); + + } else if (Objects.nonNull(value.getSS())) { + return AttributeValue.builder() + .ss(value.getSS().isEmpty() ? null : value.getSS()) + .build(); + + } else if (Objects.nonNull(value.getN())) { + return AttributeValue.builder() + .n(value.getN()) + .build(); + + } else if (Objects.nonNull(value.getNS())) { + return AttributeValue.builder() + .ns(value.getNS().isEmpty() ? null : value.getNS()) + .build(); + + } else if (Objects.nonNull(value.getB())) { + return AttributeValue.builder() + .b(SdkBytes.fromByteBuffer(value.getB())) + .build(); + + } else if (Objects.nonNull(value.getBS())) { + return AttributeValue.builder() + .bs(value.getBS().isEmpty() + ? null + : value.getBS().stream() + .map(SdkBytes::fromByteBuffer) + .collect(Collectors.toList())) + .build(); + + } else if (Objects.nonNull(value.getBOOL())) { + return AttributeValue.builder() + .bool(value.getBOOL()) + .build(); + + } else if (Objects.nonNull(value.getL())) { + return AttributeValue.builder() + .l(value.getL().isEmpty() + ? Collections.emptyList() + : value.getL().stream() + .map(DynamodbAttributeValueTransformer::toAttributeValueV2) + .collect(Collectors.toList())) + .build(); + + } else if (Objects.nonNull(value.getM())) { + return AttributeValue.builder() + .m(toAttributeValueMapV2(value.getM())) + .build(); + + } else if (Objects.nonNull(value.getNULL())) { + return AttributeValue.builder() + .nul(value.getNULL()) + .build(); + + } else { + throw new IllegalArgumentException( + String.format("Unsupported attributeValue type: %s", value)); + } + } + + public static Map toAttributeValueMapV2( + final Map attributeValueMap + ) { + return attributeValueMap + .entrySet() + .stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> toAttributeValueV2(entry.getValue()) + )); + } +} diff --git a/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbIdentityTransformer.java b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbIdentityTransformer.java new file mode 100644 index 000000000..34c5fe69f --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbIdentityTransformer.java @@ -0,0 +1,13 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb; + +import software.amazon.awssdk.services.dynamodb.model.Identity; + +public class DynamodbIdentityTransformer { + + public static Identity toIdentityV2(final com.amazonaws.services.lambda.runtime.events.models.dynamodb.Identity identity) { + return Identity.builder() + .principalId(identity.getPrincipalId()) + .type(identity.getType()) + .build(); + } +} diff --git a/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbRecordTransformer.java b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbRecordTransformer.java new file mode 100644 index 000000000..0d035d192 --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbRecordTransformer.java @@ -0,0 +1,25 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb; + +import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; +import software.amazon.awssdk.services.dynamodb.model.Record; + +public class DynamodbRecordTransformer { + + public static Record toRecordV2(final DynamodbEvent.DynamodbStreamRecord record) { + return Record.builder() + .awsRegion(record.getAwsRegion()) + .dynamodb( + DynamodbStreamRecordTransformer.toStreamRecordV2(record.getDynamodb()) + ) + .eventID(record.getEventID()) + .eventName(record.getEventName()) + .eventSource(record.getEventSource()) + .eventVersion(record.getEventVersion()) + .userIdentity( + record.getUserIdentity() != null + ? DynamodbIdentityTransformer.toIdentityV2(record.getUserIdentity()) + : null + ) + .build(); + } +} diff --git a/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbStreamRecordTransformer.java b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbStreamRecordTransformer.java new file mode 100644 index 000000000..6cb1102dd --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/main/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbStreamRecordTransformer.java @@ -0,0 +1,31 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb; + +import software.amazon.awssdk.services.dynamodb.model.StreamRecord; + +public class DynamodbStreamRecordTransformer { + + public static StreamRecord toStreamRecordV2(final com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord streamRecord) { + + return StreamRecord.builder() + .approximateCreationDateTime( + streamRecord.getApproximateCreationDateTime().toInstant() + ) + .keys( + DynamodbAttributeValueTransformer.toAttributeValueMapV2(streamRecord.getKeys()) + ) + .newImage( + streamRecord.getNewImage() != null + ? DynamodbAttributeValueTransformer.toAttributeValueMapV2(streamRecord.getNewImage()) + : null + ) + .oldImage( + streamRecord.getOldImage() != null + ? DynamodbAttributeValueTransformer.toAttributeValueMapV2(streamRecord.getOldImage()) + : null + ) + .sequenceNumber(streamRecord.getSequenceNumber()) + .sizeBytes(streamRecord.getSizeBytes()) + .streamViewType(streamRecord.getStreamViewType()) + .build(); + } +} diff --git a/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/DynamodbEventTransformerTest.java b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/DynamodbEventTransformerTest.java new file mode 100644 index 000000000..234b97aea --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/DynamodbEventTransformerTest.java @@ -0,0 +1,43 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v1; + +import com.amazonaws.services.dynamodbv2.model.Record; +import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbRecordTransformerTest.record_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbRecordTransformerTest.record_v1; + +public class DynamodbEventTransformerTest { + + private final DynamodbEvent dynamodbEvent; + + { + record_event.setEventSourceARN("arn:aws:dynamodb:us-west-2:account-id:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899"); + dynamodbEvent = new DynamodbEvent(); + dynamodbEvent.setRecords(Collections.singletonList(record_event)); + } + + private final List expectedRecordsV2 = Collections.singletonList(record_v1); + + @Test + public void testDynamodbEventToRecordsV2() { + List convertedRecords = DynamodbEventTransformer.toRecordsV1(dynamodbEvent); + Assertions.assertEquals(expectedRecordsV2, convertedRecords); + } + + @Test + public void testDynamodbEventToRecordsV2_FiltersNullRecords() { + DynamodbEvent event = dynamodbEvent.clone(); + event.setRecords(Arrays.asList(record_event, null)); + Assertions.assertEquals(2, event.getRecords().size()); + + List convertedRecords = DynamodbEventTransformer.toRecordsV1(event); + Assertions.assertEquals(expectedRecordsV2, convertedRecords); + Assertions.assertEquals(1, convertedRecords.size()); + } +} \ No newline at end of file diff --git a/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbAttributeValueTransformerTest.java b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbAttributeValueTransformerTest.java new file mode 100644 index 000000000..14534fae5 --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbAttributeValueTransformerTest.java @@ -0,0 +1,316 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb; + +import com.amazonaws.services.lambda.runtime.events.models.dynamodb.AttributeValue; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +class DynamodbAttributeValueTransformerTest { + + private static final String valueN = "101"; + private static final List valueNS = Arrays.asList("1", "2", "3"); + private static final String valueS = "SVal"; + private static final List valueSS = Arrays.asList("first", "second", "third"); + private static final ByteBuffer valueB = ByteBuffer.wrap("BVal".getBytes()); + private static final List valueBS = Arrays.asList( + ByteBuffer.wrap("first".getBytes()), + ByteBuffer.wrap("second".getBytes()), + ByteBuffer.wrap("third".getBytes())); + private static final boolean valueBOOL = true; + private static final boolean valueNUL = true; + + private static final String keyM1 = "NestedMapKey1"; + private static final String keyM2 = "NestedMapKey2"; + + //region AttributeValue_event + public static final AttributeValue attributeValueN_event = new AttributeValue().withN(valueN); + public static final AttributeValue attributeValueNS_event = new AttributeValue().withNS(valueNS); + public static final AttributeValue attributeValueS_event = new AttributeValue().withS(valueS); + public static final AttributeValue attributeValueSS_event = new AttributeValue().withSS(valueSS); + public static final AttributeValue attributeValueB_event = new AttributeValue().withB(valueB); + public static final AttributeValue attributeValueBS_event = new AttributeValue().withBS(valueBS); + public static final AttributeValue attributeValueBOOL_event = new AttributeValue().withBOOL(valueBOOL); + public static final AttributeValue attributeValueNUL_event = new AttributeValue().withNULL(valueNUL); + public static final AttributeValue attributeValueM_event = new AttributeValue().withM(new HashMap() {{ + put(keyM1, attributeValueN_event); + put(keyM2, attributeValueS_event); + }}); + public static final AttributeValue attributeValueL_event = new AttributeValue().withL(Arrays.asList( + attributeValueN_event, + attributeValueNS_event, + attributeValueS_event, + attributeValueSS_event, + attributeValueB_event, + attributeValueBS_event, + attributeValueBOOL_event, + attributeValueNUL_event, + attributeValueM_event, + new AttributeValue().withL(Arrays.asList( + attributeValueN_event, + attributeValueNS_event, + attributeValueS_event, + attributeValueSS_event, + attributeValueB_event, + attributeValueBS_event, + attributeValueBOOL_event, + attributeValueNUL_event, + attributeValueM_event + )) + )); + //endregion + + //region AttributeValue_v1 + public static final com.amazonaws.services.dynamodbv2.model.AttributeValue attributeValueN_v1 = + new com.amazonaws.services.dynamodbv2.model.AttributeValue().withN(valueN); + public static final com.amazonaws.services.dynamodbv2.model.AttributeValue attributeValueNS_v1 = + new com.amazonaws.services.dynamodbv2.model.AttributeValue().withNS(valueNS); + public static final com.amazonaws.services.dynamodbv2.model.AttributeValue attributeValueS_v1 = + new com.amazonaws.services.dynamodbv2.model.AttributeValue().withS(valueS); + public static final com.amazonaws.services.dynamodbv2.model.AttributeValue attributeValueSS_v1 = + new com.amazonaws.services.dynamodbv2.model.AttributeValue().withSS(valueSS); + public static final com.amazonaws.services.dynamodbv2.model.AttributeValue attributeValueB_v1 = + new com.amazonaws.services.dynamodbv2.model.AttributeValue().withB(valueB); + public static final com.amazonaws.services.dynamodbv2.model.AttributeValue attributeValueBS_v1 = + new com.amazonaws.services.dynamodbv2.model.AttributeValue().withBS(valueBS); + public static final com.amazonaws.services.dynamodbv2.model.AttributeValue attributeValueBOOL_v1 = + new com.amazonaws.services.dynamodbv2.model.AttributeValue().withBOOL(valueBOOL); + public static final com.amazonaws.services.dynamodbv2.model.AttributeValue attributeValueNUL_v1 = + new com.amazonaws.services.dynamodbv2.model.AttributeValue().withNULL(valueNUL); + public static final com.amazonaws.services.dynamodbv2.model.AttributeValue attributeValueM_v1 = + new com.amazonaws.services.dynamodbv2.model.AttributeValue().withM(new HashMap() {{ + put(keyM1, attributeValueN_v1); + put(keyM2, attributeValueS_v1); + }}); + public static final com.amazonaws.services.dynamodbv2.model.AttributeValue attributeValueL_v1 = + new com.amazonaws.services.dynamodbv2.model.AttributeValue().withL(Arrays.asList( + attributeValueN_v1, + attributeValueNS_v1, + attributeValueS_v1, + attributeValueSS_v1, + attributeValueB_v1, + attributeValueBS_v1, + attributeValueBOOL_v1, + attributeValueNUL_v1, + attributeValueM_v1, + new com.amazonaws.services.dynamodbv2.model.AttributeValue().withL(Arrays.asList( + attributeValueN_v1, + attributeValueNS_v1, + attributeValueS_v1, + attributeValueSS_v1, + attributeValueB_v1, + attributeValueBS_v1, + attributeValueBOOL_v1, + attributeValueNUL_v1, + attributeValueM_v1 + )) + )); + //endregion + + @Test + public void testToAttributeValueV1_N() { + com.amazonaws.services.dynamodbv2.model.AttributeValue convertedAttributeValueN = + DynamodbAttributeValueTransformer.toAttributeValueV1(attributeValueN_event); + Assertions.assertEquals(attributeValueN_v1, convertedAttributeValueN); + } + + @Test + public void testToAttributeValueV1_NS() { + com.amazonaws.services.dynamodbv2.model.AttributeValue convertedAttributeValueNS = + DynamodbAttributeValueTransformer.toAttributeValueV1(attributeValueNS_event); + Assertions.assertEquals(attributeValueNS_v1, convertedAttributeValueNS); + } + + @Test + public void testToAttributeValueV1_S() { + com.amazonaws.services.dynamodbv2.model.AttributeValue convertedAttributeValueS = + DynamodbAttributeValueTransformer.toAttributeValueV1(attributeValueS_event); + Assertions.assertEquals(attributeValueS_v1, convertedAttributeValueS); + } + + @Test + public void testToAttributeValueV1_SS() { + com.amazonaws.services.dynamodbv2.model.AttributeValue convertedAttributeValueSS = + DynamodbAttributeValueTransformer.toAttributeValueV1(attributeValueSS_event); + Assertions.assertEquals(attributeValueSS_v1, convertedAttributeValueSS); + } + + @Test + public void testToAttributeValueV1_B() { + com.amazonaws.services.dynamodbv2.model.AttributeValue convertedAttributeValueB = + DynamodbAttributeValueTransformer.toAttributeValueV1(attributeValueB_event); + Assertions.assertEquals(attributeValueB_v1, convertedAttributeValueB); + } + + @Test + public void testToAttributeValueV1_BS() { + com.amazonaws.services.dynamodbv2.model.AttributeValue convertedAttributeValueBS = + DynamodbAttributeValueTransformer.toAttributeValueV1(attributeValueBS_event); + Assertions.assertEquals(attributeValueBS_v1, convertedAttributeValueBS); + } + + @Test + public void testToAttributeValueV1_BOOL() { + com.amazonaws.services.dynamodbv2.model.AttributeValue convertedAttributeValueBOOL = + DynamodbAttributeValueTransformer.toAttributeValueV1(attributeValueBOOL_event); + Assertions.assertEquals(attributeValueBOOL_v1, convertedAttributeValueBOOL); + } + + @Test + public void testToAttributeValueV1_NUL() { + com.amazonaws.services.dynamodbv2.model.AttributeValue convertedAttributeValueNUL = + DynamodbAttributeValueTransformer.toAttributeValueV1(attributeValueNUL_event); + Assertions.assertEquals(attributeValueNUL_v1, convertedAttributeValueNUL); + } + + @Test + public void testToAttributeValueV1_M() { + com.amazonaws.services.dynamodbv2.model.AttributeValue convertedAttributeValueM = + DynamodbAttributeValueTransformer.toAttributeValueV1(attributeValueM_event); + Assertions.assertEquals(attributeValueM_v1, convertedAttributeValueM); + } + + @Test + public void testToAttributeValueV1_L() { + com.amazonaws.services.dynamodbv2.model.AttributeValue convertedAttributeValueL = + DynamodbAttributeValueTransformer.toAttributeValueV1(attributeValueL_event); + Assertions.assertEquals(attributeValueL_v1, convertedAttributeValueL); + Assertions.assertEquals("ArrayList", convertedAttributeValueL.getL().getClass().getSimpleName(), "List is mutable"); + } + + @Test + public void testToAttributeValueV1_IllegalArgumentWhenNull() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue()) + ); + } + + @Test + public void testToAttributeValueV1_IllegalArgumentWhenNull_N() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withN(null)) + ); + } + + @Test + public void testToAttributeValueV1_IllegalArgumentWhenNull_S() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withS(null)) + ); + } + + @Test + public void testToAttributeValueV1_IllegalArgumentWhenNull_B() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withB(null)) + ); + } + + @Test + public void testToAttributeValueV1_IllegalArgumentWhenNull_BOOL() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withBOOL(null)) + ); + } + + @Test + public void testToAttributeValueV1_IllegalArgumentWhenNull_NUL() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withNULL(null)) + ); + } + + @Test + public void testToAttributeValueV1_IllegalArgumentWhenNull_M() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withM(null)) + ); + } + + @Test + public void testToAttributeValueV1_DoesNotThrowWhenEmpty_NS() { + Assertions.assertDoesNotThrow(() -> + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withNS()) + ); + Assertions.assertDoesNotThrow(() -> + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withNS(Collections.emptyList())) + ); + } + + @Test + public void testToAttributeValueV1_DoesNotThrowWhenEmpty_SS() { + Assertions.assertDoesNotThrow(() -> + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withSS()) + ); + Assertions.assertDoesNotThrow(() -> + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withSS(Collections.emptyList())) + ); + } + + @Test + public void testToAttributeValueV1_DoesNotThrowWhenEmpty_BS() { + Assertions.assertDoesNotThrow(() -> + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withBS()) + ); + Assertions.assertDoesNotThrow(() -> + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withBS(Collections.emptyList())) + ); + } + + @Test + public void testToAttributeValueV1_DoesNotThrowWhenEmpty_L() { + Assertions.assertDoesNotThrow(() -> { + com.amazonaws.services.dynamodbv2.model.AttributeValue attributeValue = DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withL()); + Assertions.assertEquals("ArrayList", attributeValue.getL().getClass().getSimpleName(), "List is mutable"); + }); + Assertions.assertDoesNotThrow(() -> { + com.amazonaws.services.dynamodbv2.model.AttributeValue attributeValue = DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withL(Collections.emptyList())); + Assertions.assertEquals("ArrayList", attributeValue.getL().getClass().getSimpleName(), "List is mutable"); + }); + } + + @Test + public void testToAttributeValueV1_EmptyV1ObjectWhenEmpty_NS() { + com.amazonaws.services.dynamodbv2.model.AttributeValue expectedAttributeValue_v1 = + new com.amazonaws.services.dynamodbv2.model.AttributeValue(); + Assertions.assertEquals(expectedAttributeValue_v1, + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withNS())); + Assertions.assertEquals(expectedAttributeValue_v1, + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withNS(Collections.emptyList()))); + } + + @Test + public void testToAttributeValueV1_EmptyV1ObjectWhenEmpty_SS() { + com.amazonaws.services.dynamodbv2.model.AttributeValue expectedAttributeValue_v1 = + new com.amazonaws.services.dynamodbv2.model.AttributeValue(); + Assertions.assertEquals(expectedAttributeValue_v1, + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withSS())); + Assertions.assertEquals(expectedAttributeValue_v1, + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withSS(Collections.emptyList()))); + } + + @Test + public void testToAttributeValueV1_EmptyV1ObjectWhenEmpty_BS() { + com.amazonaws.services.dynamodbv2.model.AttributeValue expectedAttributeValue_v1 = + new com.amazonaws.services.dynamodbv2.model.AttributeValue(); + Assertions.assertEquals(expectedAttributeValue_v1, + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withBS())); + Assertions.assertEquals(expectedAttributeValue_v1, + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withBS(Collections.emptyList()))); + } + + @Test + public void testToAttributeValueV1_EmptyV1ObjectWhenEmpty_L() { + com.amazonaws.services.dynamodbv2.model.AttributeValue expectedAttributeValue_v1 = + new com.amazonaws.services.dynamodbv2.model.AttributeValue().withL(Collections.emptyList()); + Assertions.assertEquals(expectedAttributeValue_v1, + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withL())); + Assertions.assertEquals(expectedAttributeValue_v1, + DynamodbAttributeValueTransformer.toAttributeValueV1(new AttributeValue().withL(Collections.emptyList()))); + } + +} \ No newline at end of file diff --git a/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbIdentityTransformerTest.java b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbIdentityTransformerTest.java new file mode 100644 index 000000000..5da2f319b --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbIdentityTransformerTest.java @@ -0,0 +1,30 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb; + +import com.amazonaws.services.dynamodbv2.model.Identity; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class DynamodbIdentityTransformerTest { + + private static final String principalId = "1234567890"; + private static final String identityType = "type"; + + //region Identity_event + public static final com.amazonaws.services.lambda.runtime.events.models.dynamodb.Identity identity_event = new com.amazonaws.services.lambda.runtime.events.models.dynamodb.Identity() + .withPrincipalId(principalId) + .withType(identityType); + //endregion + + //region Identity_v1 + public static final Identity identity_v1 = new Identity() + .withPrincipalId(principalId) + .withType(identityType); + //endregion + + @Test + public void testToIdentityV1() { + Identity convertedIdentity = DynamodbIdentityTransformer.toIdentityV1(identity_event); + Assertions.assertEquals(identity_v1, convertedIdentity); + } + +} \ No newline at end of file diff --git a/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbRecordTransformerTest.java b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbRecordTransformerTest.java new file mode 100644 index 000000000..4504da1db --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbRecordTransformerTest.java @@ -0,0 +1,63 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb; + +import com.amazonaws.services.dynamodbv2.model.OperationType; +import com.amazonaws.services.dynamodbv2.model.Record; +import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; +import com.amazonaws.services.lambda.runtime.events.transformers.v1.DynamodbEventTransformer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbIdentityTransformerTest.identity_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbIdentityTransformerTest.identity_v1; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbStreamRecordTransformerTest.streamRecord_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbStreamRecordTransformerTest.streamRecord_v1; + +public class DynamodbRecordTransformerTest { + + private static final String eventId = "2"; + private static final String eventName = OperationType.MODIFY.toString(); + private static final String eventVersion = "1.0"; + private static final String eventSource = "aws:dynamodb"; + private static final String awsRegion = "us-west-2"; + + //region Record_event + public static final DynamodbEvent.DynamodbStreamRecord record_event = (DynamodbEvent.DynamodbStreamRecord) + new DynamodbEvent.DynamodbStreamRecord() + .withEventID(eventId) + .withEventName(eventName) + .withEventVersion(eventVersion) + .withEventSource(eventSource) + .withAwsRegion(awsRegion) + .withDynamodb(streamRecord_event) + .withUserIdentity(identity_event); + //endregion + + //region Record_v1 + public static final Record record_v1 = + new Record() + .withEventID(eventId) + .withEventName(eventName) + .withEventVersion(eventVersion) + .withEventSource(eventSource) + .withAwsRegion(awsRegion) + .withDynamodb(streamRecord_v1) + .withUserIdentity(identity_v1); + //endregion + + @Test + public void testToRecordV1() { + Record convertedRecord = DynamodbRecordTransformer.toRecordV1(record_event); + Assertions.assertEquals(record_v1, convertedRecord); + } + + @Test + public void testToRecordV1WhenUserIdentityIsNull() { + DynamodbEvent.DynamodbStreamRecord record = record_event.clone(); + record.setUserIdentity(null); + + Assertions.assertDoesNotThrow(() -> { + com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbRecordTransformer.toRecordV1(record); + }); + } + +} \ No newline at end of file diff --git a/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbStreamRecordTransformerTest.java b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbStreamRecordTransformerTest.java new file mode 100644 index 000000000..594d2a1dc --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v1/dynamodb/DynamodbStreamRecordTransformerTest.java @@ -0,0 +1,150 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb; + +import com.amazonaws.services.dynamodbv2.model.StreamRecord; +import com.amazonaws.services.dynamodbv2.model.StreamViewType; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Date; +import java.util.HashMap; + +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueBOOL_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueBOOL_v1; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueBS_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueBS_v1; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueB_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueB_v1; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueL_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueL_v1; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueM_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueM_v1; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueNS_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueNS_v1; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueNUL_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueNUL_v1; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueN_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueN_v1; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueSS_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueSS_v1; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueS_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueS_v1; + +class DynamodbStreamRecordTransformerTest { + + private static final String keyNK = "Id"; + private static final String keyNSK = "KeyNS"; + + private static final String keySK = "SKey"; + private static final String keySSK = "KeySS"; + + private static final String keyBK = "BKey"; + private static final String keyBSK = "KeyBS"; + + private static final String keyBOOLK = "IsBool"; + private static final String keyNULK = "nil"; + + private static final String keyMK = "MapKey"; + + private static final String keyLK = "LongNum"; + + private static final String oldImageSK = "Message"; + private static final String newImageSK = "Message"; + private static final String streamViewType = StreamViewType.NEW_AND_OLD_IMAGES.toString(); + private static final String sequenceNumber = "222"; + private static final Long sizeBytes = 59L; + private static final Date approximateCreationDateTime = new Date(); + + //region StreamRecord_event + public static final com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord streamRecord_event = new com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord() + .withKeys(new HashMap() { + { + put(keyNK, attributeValueN_event); + put(keyNSK, attributeValueNS_event); + put(keySK, attributeValueS_event); + put(keySSK, attributeValueSS_event); + put(keyBK, attributeValueB_event); + put(keyBSK, attributeValueBS_event); + put(keyBOOLK, attributeValueBOOL_event); + put(keyNULK, attributeValueNUL_event); + put(keyMK, attributeValueM_event); + put(keyLK, attributeValueL_event); + } + }) + .withOldImage(new HashMap() { + { + put(oldImageSK, attributeValueS_event); + put(keyNK, attributeValueN_event); + } + }) + .withNewImage(new HashMap() { + { + put(newImageSK, attributeValueS_event); + put(keyNK, attributeValueN_event); + } + }) + .withStreamViewType(com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamViewType.fromValue(streamViewType)) + .withSequenceNumber(sequenceNumber) + .withSizeBytes(sizeBytes) + .withApproximateCreationDateTime(approximateCreationDateTime); + //endregion + + //region StreamRecord_v1 + public static final StreamRecord streamRecord_v1 = new StreamRecord() + .withApproximateCreationDateTime(approximateCreationDateTime) + .withKeys(new HashMap() { + { + put(keyNK, attributeValueN_v1); + put(keyNSK, attributeValueNS_v1); + put(keySK, attributeValueS_v1); + put(keySSK, attributeValueSS_v1); + put(keyBK, attributeValueB_v1); + put(keyBSK, attributeValueBS_v1); + put(keyBOOLK, attributeValueBOOL_v1); + put(keyNULK, attributeValueNUL_v1); + put(keyMK, attributeValueM_v1); + put(keyLK, attributeValueL_v1); + } + }) + .withOldImage(new HashMap() { + { + put(oldImageSK, attributeValueS_v1); + put(keyNK, attributeValueN_v1); + } + }) + .withNewImage(new HashMap() { + { + put(newImageSK, attributeValueS_v1); + put(keyNK, attributeValueN_v1); + } + }) + .withSequenceNumber(sequenceNumber) + .withSizeBytes(sizeBytes) + .withStreamViewType(streamViewType); + //endregion + + @Test + public void testToStreamRecordV1() { + StreamRecord convertedStreamRecord = DynamodbStreamRecordTransformer.toStreamRecordV1(streamRecord_event); + Assertions.assertEquals(streamRecord_v1, convertedStreamRecord); + } + + @Test + public void testToStreamRecordV1WhenOldImageIsNull() { + com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord streamRecord = streamRecord_event.clone(); + streamRecord.setOldImage(null); + + Assertions.assertDoesNotThrow(() -> { + com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbStreamRecordTransformer.toStreamRecordV1(streamRecord); + }); + } + + @Test + public void testToStreamRecordV1WhenNewImageIsNull() { + com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord streamRecord = streamRecord_event.clone(); + streamRecord.setNewImage(null); + + Assertions.assertDoesNotThrow(() -> { + com.amazonaws.services.lambda.runtime.events.transformers.v1.dynamodb.DynamodbStreamRecordTransformer.toStreamRecordV1(streamRecord); + }); + } +} \ No newline at end of file diff --git a/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/DynamodbEventTransformerTest.java b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/DynamodbEventTransformerTest.java new file mode 100644 index 000000000..e9e385480 --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/DynamodbEventTransformerTest.java @@ -0,0 +1,43 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v2; + +import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.dynamodb.model.Record; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbRecordTransformerTest.record_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbRecordTransformerTest.record_v2; + +public class DynamodbEventTransformerTest { + + private final DynamodbEvent dynamodbEvent; + + { + record_event.setEventSourceARN("arn:aws:dynamodb:us-west-2:account-id:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899"); + dynamodbEvent = new DynamodbEvent(); + dynamodbEvent.setRecords(Collections.singletonList(record_event)); + } + + private final List expectedRecordsV2 = Collections.singletonList(record_v2); + + @Test + public void testDynamodbEventToRecordsV2() { + List convertedRecords = DynamodbEventTransformer.toRecordsV2(dynamodbEvent); + Assertions.assertEquals(expectedRecordsV2, convertedRecords); + } + + @Test + public void testDynamodbEventToRecordsV2_FiltersNullRecords() { + DynamodbEvent event = dynamodbEvent.clone(); + event.setRecords(Arrays.asList(record_event, null)); + Assertions.assertEquals(2, event.getRecords().size()); + + List convertedRecords = DynamodbEventTransformer.toRecordsV2(event); + Assertions.assertEquals(expectedRecordsV2, convertedRecords); + Assertions.assertEquals(1, convertedRecords.size()); + } +} \ No newline at end of file diff --git a/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbAttributeValueTransformerTest.java b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbAttributeValueTransformerTest.java new file mode 100644 index 000000000..1c7f05f7d --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbAttributeValueTransformerTest.java @@ -0,0 +1,320 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb; + +import com.amazonaws.services.lambda.runtime.events.models.dynamodb.AttributeValue; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.utils.ImmutableMap; + +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +class DynamodbAttributeValueTransformerTest { + + private static final String valueN = "101"; + private static final List valueNS = Arrays.asList("1", "2", "3"); + private static final String valueS = "SVal"; + private static final List valueSS = Arrays.asList("first", "second", "third"); + private static final ByteBuffer valueB = ByteBuffer.wrap("BVal".getBytes()); + private static final List valueBS = Arrays.asList( + ByteBuffer.wrap("first".getBytes()), + ByteBuffer.wrap("second".getBytes()), + ByteBuffer.wrap("third".getBytes())); + private static final boolean valueBOOL = true; + private static final boolean valueNUL = true; + + private static final String keyM1 = "NestedMapKey1"; + private static final String keyM2 = "NestedMapKey2"; + + //region AttributeValue_event + public static final AttributeValue attributeValueN_event = new AttributeValue().withN(valueN); + public static final AttributeValue attributeValueNS_event = new AttributeValue().withNS(valueNS); + public static final AttributeValue attributeValueS_event = new AttributeValue().withS(valueS); + public static final AttributeValue attributeValueSS_event = new AttributeValue().withSS(valueSS); + public static final AttributeValue attributeValueB_event = new AttributeValue().withB(valueB); + public static final AttributeValue attributeValueBS_event = new AttributeValue().withBS(valueBS); + public static final AttributeValue attributeValueBOOL_event = new AttributeValue().withBOOL(valueBOOL); + public static final AttributeValue attributeValueNUL_event = new AttributeValue().withNULL(valueNUL); + public static final AttributeValue attributeValueM_event = new AttributeValue().withM(ImmutableMap.of( + keyM1, attributeValueN_event, + keyM2, attributeValueS_event + )); + public static final AttributeValue attributeValueL_event = new AttributeValue().withL(Arrays.asList( + attributeValueN_event, + attributeValueNS_event, + attributeValueS_event, + attributeValueSS_event, + attributeValueB_event, + attributeValueBS_event, + attributeValueBOOL_event, + attributeValueNUL_event, + attributeValueM_event, + new AttributeValue().withL(Arrays.asList( + attributeValueN_event, + attributeValueNS_event, + attributeValueS_event, + attributeValueSS_event, + attributeValueB_event, + attributeValueBS_event, + attributeValueBOOL_event, + attributeValueNUL_event, + attributeValueM_event + )) + )); + //endregion + + //region AttributeValue_v2 + public static final software.amazon.awssdk.services.dynamodb.model.AttributeValue attributeValueN_v2 = + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().n(valueN).build(); + public static final software.amazon.awssdk.services.dynamodb.model.AttributeValue attributeValueNS_v2 = + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().ns(valueNS).build(); + public static final software.amazon.awssdk.services.dynamodb.model.AttributeValue attributeValueS_v2 = + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().s(valueS).build(); + public static final software.amazon.awssdk.services.dynamodb.model.AttributeValue attributeValueSS_v2 = + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().ss(valueSS).build(); + public static final software.amazon.awssdk.services.dynamodb.model.AttributeValue attributeValueB_v2 = + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().b(SdkBytes.fromByteBuffer(valueB)).build(); + public static final software.amazon.awssdk.services.dynamodb.model.AttributeValue attributeValueBS_v2 = + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().bs(valueBS.stream() + .map(SdkBytes::fromByteBuffer) + .collect(Collectors.toList())).build(); + public static final software.amazon.awssdk.services.dynamodb.model.AttributeValue attributeValueBOOL_v2 = + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().bool(valueBOOL).build(); + public static final software.amazon.awssdk.services.dynamodb.model.AttributeValue attributeValueNUL_v2 = + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().nul(valueNUL).build(); + public static final software.amazon.awssdk.services.dynamodb.model.AttributeValue attributeValueM_v2 = + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().m(ImmutableMap.of( + keyM1, attributeValueN_v2, + keyM2, attributeValueS_v2 + )).build(); + public static final software.amazon.awssdk.services.dynamodb.model.AttributeValue attributeValueL_v2 = + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().l(Arrays.asList( + attributeValueN_v2, + attributeValueNS_v2, + attributeValueS_v2, + attributeValueSS_v2, + attributeValueB_v2, + attributeValueBS_v2, + attributeValueBOOL_v2, + attributeValueNUL_v2, + attributeValueM_v2, + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().l(Arrays.asList( + attributeValueN_v2, + attributeValueNS_v2, + attributeValueS_v2, + attributeValueSS_v2, + attributeValueB_v2, + attributeValueBS_v2, + attributeValueBOOL_v2, + attributeValueNUL_v2, + attributeValueM_v2 + )).build() + )).build(); + //endregion + + @Test + public void testToAttributeValueV2_N() { + software.amazon.awssdk.services.dynamodb.model.AttributeValue convertedAttributeValueN = + DynamodbAttributeValueTransformer.toAttributeValueV2(attributeValueN_event); + Assertions.assertEquals(attributeValueN_v2, convertedAttributeValueN); + } + + @Test + public void testToAttributeValueV2_NS() { + software.amazon.awssdk.services.dynamodb.model.AttributeValue convertedAttributeValueNS = + DynamodbAttributeValueTransformer.toAttributeValueV2(attributeValueNS_event); + Assertions.assertEquals(attributeValueNS_v2, convertedAttributeValueNS); + } + + @Test + public void testToAttributeValueV2_S() { + software.amazon.awssdk.services.dynamodb.model.AttributeValue convertedAttributeValueS = + DynamodbAttributeValueTransformer.toAttributeValueV2(attributeValueS_event); + Assertions.assertEquals(attributeValueS_v2, convertedAttributeValueS); + } + + @Test + public void testToAttributeValueV2_SS() { + software.amazon.awssdk.services.dynamodb.model.AttributeValue convertedAttributeValueSS = + DynamodbAttributeValueTransformer.toAttributeValueV2(attributeValueSS_event); + Assertions.assertEquals(attributeValueSS_v2, convertedAttributeValueSS); + } + + @Test + public void testToAttributeValueV2_B() { + software.amazon.awssdk.services.dynamodb.model.AttributeValue convertedAttributeValueB = + DynamodbAttributeValueTransformer.toAttributeValueV2(attributeValueB_event); + Assertions.assertEquals(attributeValueB_v2, convertedAttributeValueB); + } + + @Test + public void testToAttributeValueV2_BS() { + software.amazon.awssdk.services.dynamodb.model.AttributeValue convertedAttributeValueBS = + DynamodbAttributeValueTransformer.toAttributeValueV2(attributeValueBS_event); + Assertions.assertEquals(attributeValueBS_v2, convertedAttributeValueBS); + } + + @Test + public void testToAttributeValueV2_BOOL() { + software.amazon.awssdk.services.dynamodb.model.AttributeValue convertedAttributeValueBOOL = + DynamodbAttributeValueTransformer.toAttributeValueV2(attributeValueBOOL_event); + Assertions.assertEquals(attributeValueBOOL_v2, convertedAttributeValueBOOL); + } + + @Test + public void testToAttributeValueV2_NUL() { + software.amazon.awssdk.services.dynamodb.model.AttributeValue convertedAttributeValueNUL = + DynamodbAttributeValueTransformer.toAttributeValueV2(attributeValueNUL_event); + Assertions.assertEquals(attributeValueNUL_v2, convertedAttributeValueNUL); + } + + @Test + public void testToAttributeValueV2_M() { + software.amazon.awssdk.services.dynamodb.model.AttributeValue convertedAttributeValueM = + DynamodbAttributeValueTransformer.toAttributeValueV2(attributeValueM_event); + Assertions.assertEquals(attributeValueM_v2, convertedAttributeValueM); + } + + @Test + public void testToAttributeValueV2_L() { + software.amazon.awssdk.services.dynamodb.model.AttributeValue convertedAttributeValueL = + DynamodbAttributeValueTransformer.toAttributeValueV2(attributeValueL_event); + Assertions.assertEquals(attributeValueL_v2, convertedAttributeValueL); + Assertions.assertEquals("UnmodifiableRandomAccessList", convertedAttributeValueL.l().getClass().getSimpleName(), "List is immutable"); + } + + @Test + public void testToAttributeValueV2_IllegalArgumentWhenNull() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue()) + ); + } + + @Test + public void testToAttributeValueV2_IllegalArgumentWhenNull_N() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withN(null)) + ); + } + + @Test + public void testToAttributeValueV2_IllegalArgumentWhenNull_S() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withS(null)) + ); + } + + @Test + public void testToAttributeValueV2_IllegalArgumentWhenNull_B() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withB(null)) + ); + } + + @Test + public void testToAttributeValueV2_IllegalArgumentWhenNull_BOOL() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withBOOL(null)) + ); + } + + @Test + public void testToAttributeValueV2_IllegalArgumentWhenNull_NUL() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withNULL(null)) + ); + } + + @Test + public void testToAttributeValueV2_IllegalArgumentWhenNull_M() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withM(null)) + ); + } + + @Test + public void testToAttributeValueV2_DoesNotThrowWhenEmpty_NS() { + Assertions.assertDoesNotThrow(() -> + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withNS()) + ); + Assertions.assertDoesNotThrow(() -> + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withNS(Collections.emptyList())) + ); + } + + @Test + public void testToAttributeValueV2_DoesNotThrowWhenEmpty_SS() { + Assertions.assertDoesNotThrow(() -> + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withSS()) + ); + Assertions.assertDoesNotThrow(() -> + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withSS(Collections.emptyList())) + ); + } + + @Test + public void testToAttributeValueV2_DoesNotThrowWhenEmpty_BS() { + Assertions.assertDoesNotThrow(() -> + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withBS()) + ); + Assertions.assertDoesNotThrow(() -> + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withBS(Collections.emptyList())) + ); + } + + @Test + public void testToAttributeValueV2_DoesNotThrowWhenEmpty_L() { + Assertions.assertDoesNotThrow(() -> { + software.amazon.awssdk.services.dynamodb.model.AttributeValue attributeValue = DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withL()); + Assertions.assertEquals("UnmodifiableRandomAccessList", attributeValue.l().getClass().getSimpleName(), "List is immutable"); + }); + Assertions.assertDoesNotThrow(() -> { + software.amazon.awssdk.services.dynamodb.model.AttributeValue attributeValue = DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withL(Collections.emptyList())); + Assertions.assertEquals("UnmodifiableRandomAccessList", attributeValue.l().getClass().getSimpleName(), "List is immutable"); + }); + } + + @Test + public void testToAttributeValueV2_EmptyV2ObjectWhenEmpty_NS() { + software.amazon.awssdk.services.dynamodb.model.AttributeValue expectedAttributeValue_v2 = + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().build(); + Assertions.assertEquals(expectedAttributeValue_v2, + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withNS())); + Assertions.assertEquals(expectedAttributeValue_v2, + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withNS(Collections.emptyList()))); + } + + @Test + public void testToAttributeValueV2_EmptyV2ObjectWhenEmpty_SS() { + software.amazon.awssdk.services.dynamodb.model.AttributeValue expectedAttributeValue_v2 = + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().build(); + Assertions.assertEquals(expectedAttributeValue_v2, + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withSS())); + Assertions.assertEquals(expectedAttributeValue_v2, + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withSS(Collections.emptyList()))); + } + + @Test + public void testToAttributeValueV2_EmptyV2ObjectWhenEmpty_BS() { + software.amazon.awssdk.services.dynamodb.model.AttributeValue expectedAttributeValue_v2 = + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().build(); + Assertions.assertEquals(expectedAttributeValue_v2, + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withBS())); + Assertions.assertEquals(expectedAttributeValue_v2, + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withBS(Collections.emptyList()))); + } + + @Test + public void testToAttributeValueV2_EmptyV2ObjectWhenEmpty_L() { + software.amazon.awssdk.services.dynamodb.model.AttributeValue expectedAttributeValue_v2 = + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().l(Collections.emptyList()).build(); + Assertions.assertEquals(expectedAttributeValue_v2, + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withL())); + Assertions.assertEquals(expectedAttributeValue_v2, + DynamodbAttributeValueTransformer.toAttributeValueV2(new AttributeValue().withL(Collections.emptyList()))); + } + +} \ No newline at end of file diff --git a/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbIdentityTransformerTest.java b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbIdentityTransformerTest.java new file mode 100644 index 000000000..f4ec64be8 --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbIdentityTransformerTest.java @@ -0,0 +1,32 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.dynamodb.model.Identity; + +class DynamodbIdentityTransformerTest { + + private static final String principalId = "1234567890"; + private static final String identityType = "type"; + + //region Identity_event + public static final com.amazonaws.services.lambda.runtime.events.models.dynamodb.Identity identity_event = + new com.amazonaws.services.lambda.runtime.events.models.dynamodb.Identity() + .withPrincipalId(principalId) + .withType(identityType); + //endregion + + //region Identity_v2 + public static final Identity identity_v2 = Identity.builder() + .principalId(principalId) + .type(identityType) + .build(); + //endregion + + @Test + public void testToIdentityV2() { + Identity convertedIdentity = DynamodbIdentityTransformer.toIdentityV2(identity_event); + Assertions.assertEquals(identity_v2, convertedIdentity); + } + +} \ No newline at end of file diff --git a/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbRecordTransformerTest.java b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbRecordTransformerTest.java new file mode 100644 index 000000000..cd8bbdc88 --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbRecordTransformerTest.java @@ -0,0 +1,63 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb; + +import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.dynamodb.model.OperationType; +import software.amazon.awssdk.services.dynamodb.model.Record; + +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbIdentityTransformerTest.identity_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbIdentityTransformerTest.identity_v2; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbStreamRecordTransformerTest.streamRecord_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbStreamRecordTransformerTest.streamRecord_v2; + +public class DynamodbRecordTransformerTest { + + private static final String eventId = "2"; + private static final String eventName = OperationType.MODIFY.toString(); + private static final String eventVersion = "1.0"; + private static final String eventSource = "aws:dynamodb"; + private static final String awsRegion = "us-west-2"; + + //region Record_event + public static final DynamodbEvent.DynamodbStreamRecord record_event = (DynamodbEvent.DynamodbStreamRecord) + new DynamodbEvent.DynamodbStreamRecord() + .withEventID(eventId) + .withEventName(eventName) + .withEventVersion(eventVersion) + .withEventSource(eventSource) + .withAwsRegion(awsRegion) + .withDynamodb(streamRecord_event) + .withUserIdentity(identity_event); + //endregion + + //region Record_v2 + public static final Record record_v2 = + Record.builder() + .eventID(eventId) + .eventName(eventName) + .eventVersion(eventVersion) + .eventSource(eventSource) + .awsRegion(awsRegion) + .dynamodb(streamRecord_v2) + .userIdentity(identity_v2) + .build(); + //endregion + + @Test + public void testToRecordV2() { + Record convertedRecord = DynamodbRecordTransformer.toRecordV2(record_event); + Assertions.assertEquals(record_v2, convertedRecord); + } + + @Test + public void testToRecordV2WhenUserIdentityIsNull() { + DynamodbEvent.DynamodbStreamRecord record = record_event.clone(); + record.setUserIdentity(null); + + Assertions.assertDoesNotThrow(() -> { + DynamodbRecordTransformer.toRecordV2(record); + }); + } + +} \ No newline at end of file diff --git a/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbStreamRecordTransformerTest.java b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbStreamRecordTransformerTest.java new file mode 100644 index 000000000..d663d1dbf --- /dev/null +++ b/aws-lambda-java-events-sdk-transformer/src/test/java/com/amazonaws/services/lambda/runtime/events/transformers/v2/dynamodb/DynamodbStreamRecordTransformerTest.java @@ -0,0 +1,143 @@ +package com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb; + +import com.amazonaws.services.lambda.runtime.events.models.dynamodb.AttributeValue; +import com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamViewType; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.dynamodb.model.StreamRecord; +import software.amazon.awssdk.utils.ImmutableMap; + +import java.util.Date; + +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueBOOL_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueBOOL_v2; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueBS_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueBS_v2; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueB_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueB_v2; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueL_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueL_v2; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueM_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueM_v2; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueNS_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueNS_v2; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueNUL_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueNUL_v2; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueN_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueN_v2; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueSS_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueSS_v2; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueS_event; +import static com.amazonaws.services.lambda.runtime.events.transformers.v2.dynamodb.DynamodbAttributeValueTransformerTest.attributeValueS_v2; + +class DynamodbStreamRecordTransformerTest { + + private static final String keyNK = "Id"; + private static final String keyNSK = "KeyNS"; + + private static final String keySK = "SKey"; + private static final String keySSK = "KeySS"; + + private static final String keyBK = "BKey"; + private static final String keyBSK = "KeyBS"; + + private static final String keyBOOLK = "IsBool"; + private static final String keyNULK = "nil"; + + private static final String keyMK = "MapKey"; + + private static final String keyLK = "LongNum"; + + private static final String oldImageSK = "Message"; + private static final String newImageSK = "Message"; + private static final String streamViewType = StreamViewType.NEW_AND_OLD_IMAGES.toString(); + private static final String sequenceNumber = "222"; + private static final Long sizeBytes = 59L; + private static final Date approximateCreationDateTime = new Date(); + + //region StreamRecord_event + public static final com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord streamRecord_event = + new com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord() + .withKeys(ImmutableMap.builder() + .put(keyNK, attributeValueN_event) + .put(keyNSK, attributeValueNS_event) + .put(keySK, attributeValueS_event) + .put(keySSK, attributeValueSS_event) + .put(keyBK, attributeValueB_event) + .put(keyBSK, attributeValueBS_event) + .put(keyBOOLK, attributeValueBOOL_event) + .put(keyNULK, attributeValueNUL_event) + .put(keyMK, attributeValueM_event) + .put(keyLK, attributeValueL_event) + .build() + ) + .withOldImage(ImmutableMap.of( + oldImageSK, attributeValueS_event, + keyNK, attributeValueN_event + )) + .withNewImage(ImmutableMap.of( + newImageSK, attributeValueS_event, + keyNK, attributeValueN_event + )) + .withStreamViewType(StreamViewType.fromValue(streamViewType)) + .withSequenceNumber(sequenceNumber) + .withSizeBytes(sizeBytes) + .withApproximateCreationDateTime(approximateCreationDateTime); + //endregion + + //region StreamRecord_v2 + public static final StreamRecord streamRecord_v2 = StreamRecord.builder() + .approximateCreationDateTime(approximateCreationDateTime.toInstant()) + .keys(ImmutableMap.builder() + .put(keyNK, attributeValueN_v2) + .put(keyNSK, attributeValueNS_v2) + .put(keySK, attributeValueS_v2) + .put(keySSK, attributeValueSS_v2) + .put(keyBK, attributeValueB_v2) + .put(keyBSK, attributeValueBS_v2) + .put(keyBOOLK, attributeValueBOOL_v2) + .put(keyNULK, attributeValueNUL_v2) + .put(keyMK, attributeValueM_v2) + .put(keyLK, attributeValueL_v2) + .build() + ) + .oldImage(ImmutableMap.of( + oldImageSK, attributeValueS_v2, + keyNK, attributeValueN_v2 + )) + .newImage(ImmutableMap.of( + newImageSK, attributeValueS_v2, + keyNK, attributeValueN_v2 + )) + .sequenceNumber(sequenceNumber) + .sizeBytes(sizeBytes) + .streamViewType(streamViewType) + .build(); + //endregion + + @Test + public void testToStreamRecordV2() { + StreamRecord convertedStreamRecord = DynamodbStreamRecordTransformer.toStreamRecordV2(streamRecord_event); + Assertions.assertEquals(streamRecord_v2, convertedStreamRecord); + } + + @Test + public void testToStreamRecordV2WhenOldImageIsNull() { + com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord streamRecord = streamRecord_event.clone(); + streamRecord.setOldImage(null); + + Assertions.assertDoesNotThrow(() -> { + DynamodbStreamRecordTransformer.toStreamRecordV2(streamRecord); + }); + } + + @Test + public void testToStreamRecordV2WhenNewImageIsNull() { + com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord streamRecord = streamRecord_event.clone(); + streamRecord.setNewImage(null); + + Assertions.assertDoesNotThrow(() -> { + DynamodbStreamRecordTransformer.toStreamRecordV2(streamRecord); + }); + } +} \ No newline at end of file diff --git a/aws-lambda-java-events/README.md b/aws-lambda-java-events/README.md index 25b584476..43c25d76a 100644 --- a/aws-lambda-java-events/README.md +++ b/aws-lambda-java-events/README.md @@ -1,110 +1,67 @@ -# AWS Lambda Java Events v2.0 +# AWS Lambda Java Events v3 -### New Event Models Supported -* APIGatewayProxyRequestEvent -* APIGatewayProxyResponseEvent -* CloudFrontEvent -* CloudWatchLogsEvent -* CodeCommitEvent -* IoTButtonEvent -* KinesisFirehoseEvent -* LexEvent -* ScheduledEvent +### Event Models Supported +* `ActiveMQEvent` +* `APIGatewayCustomAuthorizerEvent` +* `APIGatewayProxyRequestEvent` +* `APIGatewayProxyResponseEvent` +* `APIGatewayV2CustomAuthorizerEvent` +* `APIGatewayV2HTTPEvent` +* `APIGatewayV2HTTPResponse` +* `APIGatewayV2WebSocketEvent` +* `APIGatewayV2WebSocketResponse` +* `ApplicationLoadBalancerRequestEvent` +* `ApplicationLoadBalancerResponseEvent` +* `AppSyncLambdaAuthorizerEvent` +* `AppSyncLambdaAuthorizerResponse` +* `CloudFormationCustomResourceEvent` +* `CloudFrontEvent` +* `CloudWatchCompositeAlarmEvent` +* `CloudWatchLogsEvent` +* `CloudWatchMetricAlarmEvent` +* `CodeCommitEvent` +* `CognitoEvent` +* `CognitoUserPoolCreateAuthChallengeEvent` +* `CognitoUserPoolCustomMessageEvent` +* `CognitoUserPoolDefineAuthChallengeEvent` +* `CognitoUserPoolEvent` +* `CognitoUserPoolMigrateUserEvent` +* `CognitoUserPoolPostAuthenticationEvent` +* `CognitoUserPoolPostConfirmationEvent` +* `CognitoUserPoolPreAuthenticationEvent` +* `CognitoUserPoolPreSignUpEvent` +* `CognitoUserPoolPreTokenGenerationEvent` +* `CognitoUserPoolPreTokenGenerationEventV2` +* `CognitoUserPoolVerifyAuthChallengeResponseEvent` +* `ConfigEvent` +* `ConnectEvent` +* `DynamodbEvent` +* `IoTButtonEvent` +* `KafkaEvent` +* `KinesisAnalyticsFirehoseInputPreprocessingEvent` +* `KinesisAnalyticsInputPreprocessingResponse` +* `KinesisAnalyticsOutputDeliveryEvent` +* `KinesisAnalyticsOutputDeliveryResponse` +* `KinesisAnalyticsStreamsInputPreprocessingEvent` +* `KinesisEvent` +* `KinesisFirehoseEvent` +* `LambdaDestinationEvent` +* `LexEvent` +* `MSKFirehoseEvent` +* `MSKFirehoseResponse` +* `RabbitMQEvent` +* `S3BatchEvent` +* `S3BatchResponse` +* `S3Event` +* `ScheduledEvent` +* `SecretsManagerRotationEvent` +* `SimpleIAMPolicyResponse` +* `SNSEvent` +* `SQSBatchResponse` +* `SQSEvent` -### New package inclusion model -The old package inclusion model required users to pull unused dependencies into -their package. We have removed this inclusion so that users' jars will be -smaller, which will results in reduced latency times. Customers using older -versions do not need to make any changes to their existing code. -The following event models do not require any SDK dependencies -* APIGatewayProxyRequestEvent -* APIGatewayProxyResponseEvent -* CloudFrontEvent -* CloudWatchLogsEvent -* CodeCommitEvent -* CognitoEvent -* ConfigEvent -* IoTButtonEvent -* KinesisFirehoseEvent -* LexEvent -* ScheduledEvent -* SNSEvent - -so the dependencies section in the pom.xml file would like this - -```xml - - ... - - com.amazonaws - aws-lambda-java-core - 1.1.0 - - - com.amazonaws - aws-lambda-java-events - 2.2.6 - - ... - -``` - -#### S3 Event - -For the S3 event the pom would look like this: - -```xml - - ... - - com.amazonaws - aws-lambda-java-core - 1.1.0 - - - com.amazonaws - aws-lambda-java-events - 2.2.6 - - - com.amazonaws - aws-java-sdk-s3 - 1.11.163 - - ... - -``` - -#### Kinesis Event - -For the Kinesis event - -```xml - - .... - - com.amazonaws - aws-lambda-java-core - 1.1.0 - - - com.amazonaws - aws-lambda-java-events - 2.2.6 - - - com.amazonaws - aws-java-sdk-kinesis - 1.11.163 - - ... - -``` - -#### Dynamodb Event - -For the Dynamodb event +### Usage ```xml @@ -112,17 +69,12 @@ For the Dynamodb event com.amazonaws aws-lambda-java-core - 1.1.0 + 1.2.3 com.amazonaws aws-lambda-java-events - 2.2.6 - - - com.amazonaws - aws-java-sdk-dynamodb - 1.11.163 + 3.16.0 ... diff --git a/aws-lambda-java-events/RELEASE.CHANGELOG.md b/aws-lambda-java-events/RELEASE.CHANGELOG.md new file mode 100644 index 000000000..a4bcd10a0 --- /dev/null +++ b/aws-lambda-java-events/RELEASE.CHANGELOG.md @@ -0,0 +1,278 @@ +### June 17, 2025 +`3.16.0`: +- Add Schema metadata related attributes in KafkaEvent ([#548](https://github.com/aws/aws-lambda-java-libs/pull/548)) + +### January 31, 2025 +`3.15.0`: +- Fix `CognitoUserPoolPreTokenGenerationEventV2` model ([#519](https://github.com/aws/aws-lambda-java-libs/pull/519)) +- Add RotationToken to SecretsManagerRotationEvent ([#520](https://github.com/aws/aws-lambda-java-libs/pull/520)) + + +### September 13, 2024 +`3.14.0`: +- Fix name of s3Bucket field of Task class in S3BatchEventV2 ([#506](https://github.com/aws/aws-lambda-java-libs/pull/506)) + +### July 29, 2024 +`3.13.0`: +- Add S3BatchEventV2 ([#496](https://github.com/aws/aws-lambda-java-libs/pull/496)) + +### July 11, 2024 +`3.12.0`: +- Added the object representations of the CloudWatch alarms([#493](https://github.com/aws/aws-lambda-java-libs/pull/493)) +- Added event class MskFirehoseEvent.java for Firehose Lambda transformation when MSK is the source([#490](https://github.com/aws/aws-lambda-java-libs/pull/490)) + +### June 11, 2024 +`3.11.6`: +- Add the V2 version of the pre token generation event([#465](https://github.com/aws/aws-lambda-java-libs/pull/465)) + +### April 12, 2024 +`3.11.5`: +- Add requestHeaders field for Appsync lambda authorizer event([#473](https://github.com/aws/aws-lambda-java-libs/pull/473)) + +### December 1, 2023 +`3.11.4`: +- Improve `toString` in Cognito events by calling `super` +- Added missing `version` field to ScheduledEvent from CloudWatch + +### September 1, 2023 +`3.11.3`: +- Update challengeAnswer field format in CognitoUserPoolEvent + +### May 18, 2023 +`3.11.2`: +- Add missing fields to API Gateway request context + +### March 10, 2023 +`3.11.1`: +- Extended ActiveMQEvent with custom properties ([#408](https://github.com/aws/aws-lambda-java-libs/pull/408)) +- Updated dependencies([#410](https://github.com/aws/aws-lambda-java-libs/pull/410)): + - `joda-time` from 2.6 to 2.10.8 + - `jackson-databind` from 2.13.4.1 to 2.14.2 + - `junit-jupiter-engine` from 5.7.0 to 5.9.2 + - `json-unit-assertj` from 2.22.0 to 2.36.1 + +### November 24, 2021 +`3.11.0`: +- Added support for SQSaaES Partial Batch Feature ([#279](https://github.com/aws/aws-lambda-java-libs/pull/279)) + - `SQSBatchResponse` + +### August 26, 2021 +`3.10.0`: +- Added headers in `KafkaEventRecord` ([#260](https://github.com/aws/aws-lambda-java-libs/pull/260)) +- Added support for AppSync Lambda Authorizer ([#263](https://github.com/aws/aws-lambda-java-libs/pull/263)) + - `AppSyncLambdaAuthorizerEvent` + - `AppSyncLambdaAuthorizerResponse` +- Added support for RabbitMQ Event ([#256](https://github.com/aws/aws-lambda-java-libs/pull/256)) + - `RabbitMQEvent` +- Added missing `version` field to `APIGatewayProxyRequestEvent` ([#258](https://github.com/aws/aws-lambda-java-libs/pull/258)) + +### June 2, 2021 +`3.9.0`: +- Added support for Cognito User Pool events ([#175](https://github.com/aws/aws-lambda-java-libs/pull/175)) + - `CognitoUserPoolCreateAuthChallengeEvent` + - `CognitoUserPoolCustomMessageEvent` + - `CognitoUserPoolDefineAuthChallengeEvent` + - `CognitoUserPoolEvent` + - `CognitoUserPoolMigrateUserEvent` + - `CognitoUserPoolPostAuthenticationEvent` + - `CognitoUserPoolPostConfirmationEvent` + - `CognitoUserPoolPreAuthenticationEvent` + - `CognitoUserPoolPreSignUpEvent` + - `CognitoUserPoolPreTokenGenerationEvent` + - `CognitoUserPoolVerifyAuthChallengeResponseEvent` +- Added support for IAM Policy Responses for API Gateway REST APIs ([#213](https://github.com/aws/aws-lambda-java-libs/pull/213)) + - `IamPolicyResponseV1` +- Added default IntelliJ equals, hashCode and toString methods to `APIGatewayV2WebSocketEvent` ([#248](https://github.com/aws/aws-lambda-java-libs/pull/248)) +- Fixed toString method in `KinesisEvent` ([#245](https://github.com/aws/aws-lambda-java-libs/pull/245)) +- Changed `body` field to lowercase in `APIGatewayV2HTTPEvent` ([#236](https://github.com/aws/aws-lambda-java-libs/pull/236)) +- Added `principalOrgId` field to `APIGatewayProxyRequestEvent` ([#247](https://github.com/aws/aws-lambda-java-libs/pull/247)) + +### March 24, 2021 +`3.8.0`: +- Added support for S3 Object Lambda event ([#229](https://github.com/aws/aws-lambda-java-libs/pull/229)) + - `S3ObjectLambdaEvent` +- Added support for IAM Policy response ([#213](https://github.com/aws/aws-lambda-java-libs/pull/213)) + - `IamPolicyResponse` +- Added `bootstrapServers` to `KafkaEvent` ([#216](https://github.com/aws/aws-lambda-java-libs/pull/216)) +- Added `requestId` to `APIGatewayV2HTTPEvent` ([#230](https://github.com/aws/aws-lambda-java-libs/pull/230)) +- Added `multiValueHeaders` to `APIGatewayProxyResponseEvent` ([#228](https://github.com/aws/aws-lambda-java-libs/pull/228)) +- Bumped `jackson-databind` from `2.10.4` to `2.10.5.1` ([#231](https://github.com/aws/aws-lambda-java-libs/pull/231)) + +### December 16, 2020 +`3.7.0`: +- Added support for StreamAnalytics and CustomCheckpointing ([#202](https://github.com/aws/aws-lambda-java-libs/pull/202)) + - `DynamodbTimeWindowEvent` + - `KinesisTimeWindowEvent` + - `StreamsEventResponse` + - `TimeWindowEventResponse` + +### November 06, 2020 +`3.6.0`: +- Added support for Amazon `ActiveMQ` event: ([#185](https://github.com/aws/aws-lambda-java-libs/pull/185)) +- Bumped `junit-jupiter-engine` to version `5.7.0` +- Bumped `lombok` to version `1.18.16` + +### October 28, 2020 +`3.5.0`: +- Added support for S3 Batch events: ([#179](https://github.com/aws/aws-lambda-java-libs/pull/179)) + - `S3BatchEvent` + - `S3BatchResponse` + +### October 07, 2020 +`3.4.0`: +- Added Lambda and IAM authorizers to `APIGatewayV2HTTPEvent` request context ([#167](https://github.com/aws/aws-lambda-java-libs/pull/167)) +- Added support for API Gateway custom authorizer: ([#166](https://github.com/aws/aws-lambda-java-libs/pull/166)) + - `APIGatewayCustomAuthorizerEvent` + - `APIGatewayV2CustomAuthorizerEvent` + - `SimpleIAMPolicyResponse` + +### September 23, 2020 +`3.3.1`: +- Added `multiValueQueryStringParameters` to `ApplicationLoadBalancerRequestEvent` ([#163](https://github.com/aws/aws-lambda-java-libs/pull/163)) + +### September 14, 2020 +`3.3.0`: +- Added support for Secrets Manager Rotation Event ([#130](https://github.com/aws/aws-lambda-java-libs/pull/130)) +- Added support for CloudFormation Custom Resource Event ([#138](https://github.com/aws/aws-lambda-java-libs/pull/138)) +- Added support for Lambda Destination Event ([#139](https://github.com/aws/aws-lambda-java-libs/pull/139)) +- Added support for Amazon Connect Event ([#140](https://github.com/aws/aws-lambda-java-libs/pull/140)) + +### August 11, 2020 +`3.2.0`: +- Added support for Kafka Events ([#154](https://github.com/aws/aws-lambda-java-libs/pull/154)) + +### July 31, 2020 +`3.1.1`: +- Fixed Base64 encoding for ALB and API Gateway HTTP events ([#150](https://github.com/aws/aws-lambda-java-libs/pull/131)) + +### May 20, 2020 +`3.1.0`: +- Added support for Application Load Balancer Target Events ([#131](https://github.com/aws/aws-lambda-java-libs/pull/131)) + - `ApplicationLoadBalancerRequestEvent` + - `ApplicationLoadBalancerResponseEvent` +- Added support for API Gateway HTTP API Events ([#123](https://github.com/aws/aws-lambda-java-libs/pull/123)) + - `APIGatewayV2HTTPEvent` + - `APIGatewayV2HTTPResponse` +- Aliased the existing APIGatewayV2Proxy classes as `APIGatewayV2WebSocketEvent`/`APIGatewayV2WebSocketResponse` ([#125](https://github.com/aws/aws-lambda-java-libs/pull/125)) + +### May 18, 2020 +`3.0.0`: +- Removed AWS SDK v1 dependencies ([#74](https://github.com/aws/aws-lambda-java-libs/issues/74)) + - Copied relevant S3, Kinesis and DynamoDB model classes under namespace `com.amazonaws.services.lambda.runtime.events.models` + - S3: + - `S3EventNotification` + - Kinesis: + - `EncryptionType` + - `Record` + - DynamoDB: + - `AttributeValue` + - `Identity` + - `OperationType` + - `Record` + - `StreamRecord` + - `StreamViewType` + +### May 13, 2020 +`2.2.9`: +- Added field `operationName` to `APIGatewayProxyRequestEvent` ([#126](https://github.com/aws/aws-lambda-java-libs/pull/126)) + +### April 28, 2020 +`2.2.8`: +- Added missing XML namespace declarations to `pom.xml` file ([#97](https://github.com/aws/aws-lambda-java-libs/issues/97)) +- Updated `nexusUrl` in `pom.xml` file ([#108](https://github.com/aws/aws-lambda-java-libs/issues/108)) + +### August 13, 2019 +`2.2.7`: +- Added support for APIGatewayV2 (Web Sockets) ([#92](https://github.com/aws/aws-lambda-java-libs/issues/92)) + - `APIGatewayV2ProxyRequestEvent` + - `APIGatewayV2ProxyResponseEvent` +- Fixed typo in `CognitoEvent` javadoc ([#87](https://github.com/aws/aws-lambda-java-libs/issues/87)) + +### March 11, 2019 +`2.2.6`: +- Added field `customData` to `CommitEvent.Record` ([#79](https://github.com/aws/aws-lambda-java-libs/issues/79)) +- Added field `isBase64Encoded` to `APIGatewayProxyResponseEvent` ([#48](https://github.com/aws/aws-lambda-java-libs/issues/48)) +- Added field `authorizer` to `APIGatewayProxyRequestEvent` ([#77](https://github.com/aws/aws-lambda-java-libs/issues/77)) + +### January 03, 2019 +`2.2.5`: +- Fixed "Paramters" typo in `APIGatewayProxyRequestEvent` and `ConfigEvent` ([#65](https://github.com/aws/aws-lambda-java-libs/issues/65)) + +### November 14, 2018 +`2.2.4`: +- Added default constructor for `S3Event` for easier deserialization + +### November 05, 2018 +`2.2.3`: +- Added support for Multi-Value Headers and Query String Parameters to `APIGatewayProxyRequestEvent` ([#60](https://github.com/aws/aws-lambda-java-libs/issues/60)) + +### July 02, 2018 +`2.2.2`: +- Made `SQSEvent.SQSMessage` default constructor public ([#51](https://github.com/aws/aws-lambda-java-libs/issues/51)) + +### June 29, 2018 +`2.2.1`: +- Made `SQSEvent.SQSMessage` public ([#51](https://github.com/aws/aws-lambda-java-libs/issues/51)) + +### June 28, 2018 +`2.2.0`: +- Added `SQSEvent` + +### March 09, 2018 +`2.1.0`: +- Added Kinesis Analytics events + - `KinesisAnalyticsFirehoseInputPreprocessingEvent` + - `KinesisAnalyticsInputPreprocessingResponse` + - `KinesisAnalyticsOutputDeliveryEvent` + - `KinesisAnalyticsOutputDeliveryResponse` + - `KinesisAnalyticsStreamsInputPreprocessingEvent` + +### November 21, 2017 +`2.0.2`: +- Added missing fields to `APIGatewayProxyRequestEvent` ([#46](https://github.com/aws/aws-lambda-java-libs/issues/46)) + +### October 07, 2017 +`2.0.1`: +- Updated KinesisFirehose event schema. + - `approximateArrivalTimestamp` is now represented as a millisecond epoch instead of an `org.joda.time.DateTime` object. + +### September 20, 2017 +`2.0`: +- Added the following events: + - `APIGatewayProxyRequestEvent` + - `APIGatewayProxyResponseEvent` + - `CloudFrontEvent` + - `CloudWatchLogsEvent` + - `CodeCommitEvent` + - `IoTButtonEvent` + - `KinesisFirehoseEvent` + - `LexEvent` + - `ScheduledEvent` +- Changed dependency management; Users must now supply the SDK package if they are using an event that is connected to an SDK library. + - These events are `S3Event`, `KinesisEvemt`, and `DynamodbEvent`. +- Bumped AWS SDK versions to `1.11.163` + + +### May 16, 2016 +`1.3.0`: +- Bumped AWS SDK versions to `1.11.0` + +### May 16, 2016 +`1.2.1`: +- Bumped AWS SDK versions to `1.10.77` + +### April 22, 2016 +`1.2.0`: +- Added `ConfigEvent` + +### August 21, 2015 +`1.1.0`: +- Added `DynamodbEvent` + +### June 15, 2015 +`1.0.0`: +- Initial support for java in AWS Lambda, includes the following events: + - `CognitoEvent` + - `KinesisEvent` + - `S3Event` + - `SNSEvent` diff --git a/aws-lambda-java-events/pom.xml b/aws-lambda-java-events/pom.xml index 93105bea5..0b69b03e6 100644 --- a/aws-lambda-java-events/pom.xml +++ b/aws-lambda-java-events/pom.xml @@ -1,151 +1,234 @@ - - 4.0.0 - - com.amazonaws - aws-lambda-java-events - 2.2.6 - jar + + 4.0.0 - AWS Lambda Java Events Library - - Event interface definitions AWS services supported by AWS Lambda. - - https://aws.amazon.com/lambda/ - - - Apache License, Version 2.0 - https://aws.amazon.com/apache2.0 - repo - - - - https://github.com/aws/aws-lambda-java-libs.git - - - - AWS Lambda team - Amazon Web Services - https://aws.amazon.com/ - - + com.amazonaws + aws-lambda-java-events + 3.16.1-SNAPSHOT + jar - - - sonatype-nexus-staging - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - + AWS Lambda Java Events Library + + Event interface definitions AWS services supported by AWS Lambda. + + https://aws.amazon.com/lambda/ + + + Apache License, Version 2.0 + https://aws.amazon.com/apache2.0 + repo + + + + https://github.com/aws/aws-lambda-java-libs.git + scm:git:https://github.com/aws/aws-lambda-java-libs.git + scm:git:https://github.com/aws/aws-lambda-java-libs.git + HEAD + + + + AWS Lambda team + Amazon Web Services + https://aws.amazon.com/ + + - - - joda-time - joda-time - 2.6 - - - com.amazonaws - aws-java-sdk-s3 - 1.11.163 - provided - - - com.amazonaws - aws-java-sdk-kinesis - 1.11.163 - provided - - - com.amazonaws - aws-java-sdk-dynamodb - 1.11.163 - provided - - - - - - dev - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - -Xdoclint:none - - - - attach-javadocs - - jar - - - - - - - - - release - + + 1.8 + 1.8 + 1.18.22 + UTF-8 + UTF-8 + 2.20.1 + 2.40.1 + 5.12.2 + + + - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - -Xdoclint:none - - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - sign-artifacts - verify - - sign - - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.3 - true - - sonatype-nexus-staging - https://oss.sonatype.org/ - false - - + + org.apache.maven.plugins + maven-toolchains-plugin + 3.2.0 + + + + + [1.8,9) + + + + + + + toolchain + + + + + + org.apache.maven.plugins + maven-release-plugin + 3.1.1 + + aws-lambda-java-events-@{project.version} + true + release + deploy + + - - - - + + + + + sonatype-nexus-staging + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + joda-time + joda-time + 2.10.8 + + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter.version} + test + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + test + + + net.javacrumbs.json-unit + json-unit-assertj + ${json.unit} + test + + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + + dev + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + -Xdoclint:none + + + + attach-javadocs + + jar + + + + + + + + + release + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + -Xdoclint:none + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + org.sonatype.central + central-publishing-maven-plugin + 0.8.0 + true + + central + false + + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.1 + + UTF-8 + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + + + org.projectlombok + lombok + ${lombok.version} + + + UTF-8 + + + + + + + \ No newline at end of file diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayCustomAuthorizerEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayCustomAuthorizerEvent.java new file mode 100644 index 000000000..728833195 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayCustomAuthorizerEvent.java @@ -0,0 +1,59 @@ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Map; + +/** + * The API Gateway customer authorizer event object as described - https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html + * + */ + +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class APIGatewayCustomAuthorizerEvent { + + private String version; + private String type; + private String methodArn; + private String identitySource; + private String authorizationToken; + private String resource; + private String path; + private String httpMethod; + private Map headers; + private Map queryStringParameters; + private Map pathParameters; + private Map stageVariables; + private RequestContext requestContext; + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class RequestContext { + private String path; + private String accountId; + private String resourceId; + private String stage; + private String requestId; + private Identity identity; + private String resourcePath; + private String httpMethod; + private String apiId; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Identity { + private String apiKey; + private String sourceIp; + } +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayProxyRequestEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayProxyRequestEvent.java index 68ca91da1..8ff8ccb8b 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayProxyRequestEvent.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayProxyRequestEvent.java @@ -11,6 +11,8 @@ public class APIGatewayProxyRequestEvent implements Serializable, Cloneable { private static final long serialVersionUID = 4189228800688527467L; + private String version; + private String resource; private String path; @@ -50,6 +52,8 @@ public static class ProxyRequestContext implements Serializable, Cloneable { private String requestId; + private String operationName; + private RequestIdentity identity; private String resourcePath; @@ -62,6 +66,18 @@ public static class ProxyRequestContext implements Serializable, Cloneable { private Map authorizer; + private String extendedRequestId; + + private String requestTime; + + private Long requestTimeEpoch; + + private String domainName; + + private String domainPrefix; + + private String protocol; + /** * default constructor */ @@ -282,6 +298,164 @@ public ProxyRequestContext withPath(String path) { return this; } + /** + * @return The name of the operation being performed + * */ + public String getOperationName() { + return operationName; + } + + /** + * @param operationName The name of the operation being performed + * */ + public void setOperationName(String operationName) { + this.operationName = operationName; + } + + public ProxyRequestContext withOperationName(String operationName) { + this.setOperationName(operationName); + return this; + } + + /** + * @return The API Gateway Extended Request Id + */ + public String getExtendedRequestId() { + return extendedRequestId; + } + + /** + * @param extendedRequestId The API Gateway Extended Request Id + */ + public void setExtendedRequestId(String extendedRequestId) { + this.extendedRequestId = extendedRequestId; + } + + /** + * @param extendedRequestId The API Gateway Extended Request Id + * @return ProxyRequestContext object + */ + public ProxyRequestContext withExtendedRequestId(String extendedRequestId) { + this.setExtendedRequestId(extendedRequestId); + return this; + } + + /** + * @return The CLF-formatted request time (dd/MMM/yyyy:HH:mm:ss +-hhmm). + */ + public String getRequestTime() { + return requestTime; + } + + /** + * @param requestTime The CLF-formatted request time (dd/MMM/yyyy:HH:mm:ss +-hhmm). + */ + public void setRequestTime(String requestTime) { + this.requestTime = requestTime; + } + + /** + * @param requestTime The CLF-formatted request time (dd/MMM/yyyy:HH:mm:ss +-hhmm). + * @return ProxyRequestContext object + */ + public ProxyRequestContext withRequestTime(String requestTime) { + this.setRequestTime(requestTime); + return this; + } + + /** + * @return The Epoch-formatted request time (in millis) + */ + public Long getRequestTimeEpoch() { + return requestTimeEpoch; + } + + /** + * @param requestTimeEpoch The Epoch-formatted request time (in millis) + */ + public void setRequestTimeEpoch(Long requestTimeEpoch) { + this.requestTimeEpoch = requestTimeEpoch; + } + + /** + * @param requestTimeEpoch The Epoch-formatted request time (in millis) + * @return ProxyRequestContext object + */ + public ProxyRequestContext withRequestTimeEpoch(Long requestTimeEpoch) { + this.setRequestTimeEpoch(requestTimeEpoch); + return this; + } + + /** + * @return The full domain name used to invoke the API. This should be the same as the incoming Host header. + */ + public String getDomainName() { + return domainName; + } + + /** + * @param domainName The full domain name used to invoke the API. + * This should be the same as the incoming Host header. + */ + public void setDomainName(String domainName) { + this.domainName = domainName; + } + + /** + * @param domainName The full domain name used to invoke the API. + * This should be the same as the incoming Host header. + * @return ProxyRequestContext object + */ + public ProxyRequestContext withDomainName(String domainName) { + this.setDomainName(domainName); + return this; + } + + /** + * @return The first label of the domainName. This is often used as a caller/customer identifier. + */ + public String getDomainPrefix() { + return domainPrefix; + } + + /** + * @param domainPrefix The first label of the domainName. This is often used as a caller/customer identifier. + */ + public void setDomainPrefix(String domainPrefix) { + this.domainPrefix = domainPrefix; + } + + /** + * @param domainPrefix The first label of the domainName. This is often used as a caller/customer identifier. + * @return + */ + public ProxyRequestContext withDomainPrefix(String domainPrefix) { + this.setDomainPrefix(domainPrefix); + return this; + } + /** + * @return The request protocol, for example, HTTP/1.1. + */ + public String getProtocol() { + return protocol; + } + + /** + * @param protocol The request protocol, for example, HTTP/1.1. + */ + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + /** + * @param protocol The request protocol, for example, HTTP/1.1. + * @return ProxyRequestContext object + */ + public ProxyRequestContext withProtocol(String protocol) { + this.setProtocol(protocol); + return this; + } + /** * Returns a string representation of this object; useful for testing and debugging. * @@ -313,6 +487,20 @@ public String toString() { sb.append("path: ").append(getPath()).append(","); if (getAuthorizer() != null) sb.append("authorizer: ").append(getAuthorizer().toString()); + if (getOperationName() != null) + sb.append("operationName: ").append(getOperationName().toString()); + if (getExtendedRequestId() != null) + sb.append("extendedRequestId: ").append(getExtendedRequestId()).append(","); + if (getRequestTime() != null) + sb.append("requestTime: ").append(getRequestTime()).append(","); + if (getProtocol() != null) + sb.append("protocol: ").append(getProtocol()).append(","); + if (getRequestTimeEpoch() != null) + sb.append("requestTimeEpoch: ").append(getRequestTimeEpoch()).append(","); + if (getDomainPrefix() != null) + sb.append("domainPrefix: ").append(getDomainPrefix()).append(","); + if (getDomainName() != null) + sb.append("domainName: ").append(getDomainName()); sb.append("}"); return sb.toString(); } @@ -367,6 +555,34 @@ public boolean equals(Object obj) { return false; if (other.getAuthorizer() != null && !other.getAuthorizer().equals(this.getAuthorizer())) return false; + if (other.getOperationName() == null ^ this.getOperationName() == null) + return false; + if (other.getOperationName() != null && !other.getOperationName().equals(this.getOperationName())) + return false; + if (other.getExtendedRequestId() == null ^ this.getExtendedRequestId() == null) + return false; + if (other.getExtendedRequestId() != null && other.getExtendedRequestId().equals(this.getExtendedRequestId()) == false) + return false; + if (other.getRequestTime() == null ^ this.getRequestTime() == null) + return false; + if (other.getRequestTime() != null && other.getRequestTime().equals(this.getRequestTime()) == false) + return false; + if (other.getRequestTimeEpoch() == null ^ this.getRequestTimeEpoch() == null) + return false; + if (other.getRequestTimeEpoch() != null && other.getRequestTimeEpoch().equals(this.getRequestTimeEpoch()) == false) + return false; + if (other.getDomainName() == null ^ this.getDomainName() == null) + return false; + if (other.getDomainName() != null && other.getDomainName().equals(this.getDomainName()) == false) + return false; + if (other.getDomainPrefix() == null ^ this.getDomainPrefix() == null) + return false; + if (other.getDomainPrefix() != null && other.getDomainPrefix().equals(this.getDomainPrefix()) == false) + return false; + if (other.getProtocol() == null ^ this.getProtocol() == null) + return false; + if (other.getProtocol() != null && other.getProtocol().equals(this.getProtocol()) == false) + return false; return true; } @@ -385,6 +601,13 @@ public int hashCode() { hashCode = prime * hashCode + ((getApiId() == null) ? 0 : getApiId().hashCode()); hashCode = prime * hashCode + ((getPath() == null) ? 0 : getPath().hashCode()); hashCode = prime * hashCode + ((getAuthorizer() == null) ? 0 : getAuthorizer().hashCode()); + hashCode = prime * hashCode + ((getOperationName() == null) ? 0: getOperationName().hashCode()); + hashCode = prime * hashCode + ((getExtendedRequestId() == null) ? 0 : getExtendedRequestId().hashCode()); + hashCode = prime * hashCode + ((getRequestTime() == null) ? 0 : getRequestTime().hashCode()); + hashCode = prime * hashCode + ((getRequestTimeEpoch() == null) ? 0 : getRequestTimeEpoch().hashCode()); + hashCode = prime * hashCode + ((getDomainName() == null) ? 0 : getDomainName().hashCode()); + hashCode = prime * hashCode + ((getDomainPrefix() == null) ? 0 : getDomainPrefix().hashCode()); + hashCode = prime * hashCode + ((getProtocol() == null) ? 0 : getProtocol().hashCode()); return hashCode; } @@ -396,7 +619,6 @@ public ProxyRequestContext clone() { throw new IllegalStateException("Got a CloneNotSupportedException from Object.clone()", e); } } - } public static class RequestIdentity implements Serializable, Cloneable { @@ -413,6 +635,8 @@ public static class RequestIdentity implements Serializable, Cloneable { private String apiKey; + private String principalOrgId; + private String sourceIp; private String cognitoAuthenticationType; @@ -547,6 +771,29 @@ public RequestIdentity withApiKey(String apiKey) { return this; } + /** + * @return the principal org Id + */ + public String getPrincipalOrgId() { + return principalOrgId; + } + + /** + * @param principalOrgId the principal org Id + */ + public void setPrincipalOrgId(String principalOrgId) { + this.principalOrgId = principalOrgId; + } + + /** + * @param principalOrgId the principal org Id + * @return RequestIdentity object + */ + public RequestIdentity withPrincipalOrgId(String principalOrgId) { + this.setPrincipalOrgId(principalOrgId); + return this; + } + /** * @return source ip address */ @@ -729,6 +976,8 @@ public String toString() { sb.append("caller: ").append(getCaller()).append(","); if (getApiKey() != null) sb.append("apiKey: ").append(getApiKey()).append(","); + if (getPrincipalOrgId() != null) + sb.append("principalOrgId: ").append(getPrincipalOrgId()).append(","); if (getSourceIp() != null) sb.append("sourceIp: ").append(getSourceIp()).append(","); if (getCognitoAuthenticationType() != null) @@ -777,6 +1026,10 @@ public boolean equals(Object obj) { return false; if (other.getApiKey() != null && other.getApiKey().equals(this.getApiKey()) == false) return false; + if (other.getPrincipalOrgId() == null ^ this.getPrincipalOrgId() == null) + return false; + if (other.getPrincipalOrgId() != null && other.getPrincipalOrgId().equals(this.getPrincipalOrgId()) == false) + return false; if (other.getSourceIp() == null ^ this.getSourceIp() == null) return false; if (other.getSourceIp() != null && other.getSourceIp().equals(this.getSourceIp()) == false) @@ -819,6 +1072,7 @@ public int hashCode() { hashCode = prime * hashCode + ((getCognitoIdentityId() == null) ? 0 : getCognitoIdentityId().hashCode()); hashCode = prime * hashCode + ((getCaller() == null) ? 0 : getCaller().hashCode()); hashCode = prime * hashCode + ((getApiKey() == null) ? 0 : getApiKey().hashCode()); + hashCode = prime * hashCode + ((getPrincipalOrgId() == null) ? 0 : getPrincipalOrgId().hashCode()); hashCode = prime * hashCode + ((getSourceIp() == null) ? 0 : getSourceIp().hashCode()); hashCode = prime * hashCode + ((getCognitoAuthenticationType() == null) ? 0 : getCognitoAuthenticationType().hashCode()); hashCode = prime * hashCode + ((getCognitoAuthenticationProvider() == null) ? 0 : getCognitoAuthenticationProvider().hashCode()); @@ -844,6 +1098,29 @@ public RequestIdentity clone() { */ public APIGatewayProxyRequestEvent() {} + /** + * @return The payload format version + */ + public String getVersion() { + return version; + } + + /** + * @param version The payload format version + */ + public void setVersion(String version) { + this.version = version; + } + + /** + * @param version The payload format version + * @return + */ + public APIGatewayProxyRequestEvent withVersion(String version) { + this.setVersion(version); + return this; + } + /** * @return The resource path defined in API Gateway */ @@ -958,7 +1235,7 @@ public APIGatewayProxyRequestEvent withMultiValueHeaders(Map headers; + + private Map> multiValueHeaders; private String body; @@ -69,6 +72,30 @@ public APIGatewayProxyResponseEvent withHeaders(Map headers) { return this; } + /** + * @return the Http multi value headers to return in the response + */ + public Map> getMultiValueHeaders() { + return multiValueHeaders; + } + + /** + * @param multiValueHeaders the Http multi value headers to return in the response + */ + public void setMultiValueHeaders(Map> multiValueHeaders) { + this.multiValueHeaders = multiValueHeaders; + } + + /** + * + * @param multiValueHeaders the Http multi value headers to return in the response + * @return APIGatewayProxyResponseEvent + */ + public APIGatewayProxyResponseEvent withMultiValueHeaders(Map> multiValueHeaders) { + this.setMultiValueHeaders(multiValueHeaders); + return this; + } + /** * @return The response body */ @@ -130,6 +157,8 @@ public String toString() { sb.append("statusCode: ").append(getStatusCode()).append(","); if (getHeaders() != null) sb.append("headers: ").append(getHeaders().toString()).append(","); + if (getMultiValueHeaders() != null) + sb.append("multiValueHeaders: ").append(getMultiValueHeaders().toString()).append(","); if (getBody() != null) sb.append("body: ").append(getBody()); sb.append("}"); @@ -154,6 +183,10 @@ public boolean equals(Object obj) { return false; if (other.getHeaders() != null && other.getHeaders().equals(this.getHeaders()) == false) return false; + if (other.getMultiValueHeaders() == null ^ this.getMultiValueHeaders() == null) + return false; + if (other.getMultiValueHeaders() != null && other.getMultiValueHeaders().equals(this.getMultiValueHeaders()) == false) + return false; if (other.getBody() == null ^ this.getBody() == null) return false; if (other.getBody() != null && other.getBody().equals(this.getBody()) == false) @@ -168,6 +201,7 @@ public int hashCode() { hashCode = prime * hashCode + ((getStatusCode() == null) ? 0 : getStatusCode().hashCode()); hashCode = prime * hashCode + ((getHeaders() == null) ? 0 : getHeaders().hashCode()); + hashCode = prime * hashCode + ((getMultiValueHeaders() == null) ? 0 : getMultiValueHeaders().hashCode()); hashCode = prime * hashCode + ((getBody() == null) ? 0 : getBody().hashCode()); return hashCode; } diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2CustomAuthorizerEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2CustomAuthorizerEvent.java new file mode 100644 index 000000000..6abfe0513 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2CustomAuthorizerEvent.java @@ -0,0 +1,80 @@ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; + +import java.time.Instant; +import java.util.List; +import java.util.Map; + +/** + * The V2 API Gateway customer authorizer event object as described - https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html + * + */ + +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class APIGatewayV2CustomAuthorizerEvent { + + private String version; + private String type; + private String routeArn; + private List identitySource; + private String routeKey; + private String rawPath; + private String rawQueryString; + private List cookies; + private Map headers; + private Map queryStringParameters; + private RequestContext requestContext; + private Map pathParameters; + private Map stageVariables; + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class RequestContext { + + private static DateTimeFormatter fmt = DateTimeFormat.forPattern("dd/MMM/yyyy:HH:mm:ss Z"); + + private String accountId; + private String apiId; + private String domainName; + private String domainPrefix; + private Http http; + private String requestId; + private String routeKey; + private String stage; + private String time; + private long timeEpoch; + + public Instant getTimeEpoch() { + return Instant.ofEpochMilli(timeEpoch); + } + + public DateTime getTime() { + return fmt.parseDateTime(time); + } + } + + @AllArgsConstructor + @Builder(setterPrefix = "with") + @Data + @NoArgsConstructor + public static class Http { + + private String method; + private String path; + private String protocol; + private String sourceIp; + private String userAgent; + } +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2HTTPEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2HTTPEvent.java new file mode 100644 index 000000000..3393822ec --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2HTTPEvent.java @@ -0,0 +1,117 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ + +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +@AllArgsConstructor +@Builder(setterPrefix = "with") +@Data +@NoArgsConstructor +/** + * API Gateway v2 event: https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html + */ +public class APIGatewayV2HTTPEvent { + private String version; + private String routeKey; + private String rawPath; + private String rawQueryString; + private List cookies; + private Map headers; + private Map queryStringParameters; + private Map pathParameters; + private Map stageVariables; + private String body; + private boolean isBase64Encoded; + private RequestContext requestContext; + + @AllArgsConstructor + @Builder(setterPrefix = "with") + @Data + @NoArgsConstructor + public static class RequestContext { + private String routeKey; + private String accountId; + private String stage; + private String apiId; + private String domainName; + private String domainPrefix; + private String time; + private long timeEpoch; + private Http http; + private Authorizer authorizer; + private String requestId; + + @AllArgsConstructor + @Builder(setterPrefix = "with") + @Data + @NoArgsConstructor + public static class Authorizer { + private JWT jwt; + private Map lambda; + private IAM iam; + + @AllArgsConstructor + @Builder(setterPrefix = "with") + @Data + @NoArgsConstructor + public static class JWT { + private Map claims; + private List scopes; + } + } + + @AllArgsConstructor + @Builder(setterPrefix = "with") + @Data + @NoArgsConstructor + public static class Http { + private String method; + private String path; + private String protocol; + private String sourceIp; + private String userAgent; + } + + @AllArgsConstructor + @Builder(setterPrefix = "with") + @Data + @NoArgsConstructor + public static class IAM { + private String accessKey; + private String accountId; + private String callerId; + private CognitoIdentity cognitoIdentity; + private String principalOrgId; + private String userArn; + private String userId; + } + + @AllArgsConstructor + @Builder(setterPrefix = "with") + @Data + @NoArgsConstructor + public static class CognitoIdentity { + private List amr; + private String identityId; + private String identityPoolId; + } + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2HTTPResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2HTTPResponse.java new file mode 100644 index 000000000..2bd81fad5 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2HTTPResponse.java @@ -0,0 +1,35 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ + +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +@AllArgsConstructor +@Builder(setterPrefix = "with") +@Data +@NoArgsConstructor +public class APIGatewayV2HTTPResponse { + private int statusCode; + private Map headers; + private Map> multiValueHeaders; + private List cookies; + private String body; + private boolean isBase64Encoded; +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2ProxyRequestEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2ProxyRequestEvent.java new file mode 100644 index 000000000..c8a641495 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2ProxyRequestEvent.java @@ -0,0 +1,11 @@ +package com.amazonaws.services.lambda.runtime.events; + +/** + * @deprecated + * This class is for use with API Gateway WebSockets, and has been renamed explicitly as {@link APIGatewayV2WebSocketEvent} + * To integrate with API Gateway's HTTP API Events, use one of: + * * {@link APIGatewayV2HTTPEvent} (payload version 2.0) + * * {@link APIGatewayProxyRequestEvent} (payload version 1.0) + */ +@Deprecated() +public class APIGatewayV2ProxyRequestEvent extends APIGatewayV2WebSocketEvent {} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2ProxyResponseEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2ProxyResponseEvent.java new file mode 100644 index 000000000..d920e784d --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2ProxyResponseEvent.java @@ -0,0 +1,9 @@ +package com.amazonaws.services.lambda.runtime.events; + +/** + * @deprecated + * This class is for responding to API Gateway WebSocket events, and has been renamed explicitly as {@link APIGatewayV2WebSocketResponse} + * To response to API Gateway's HTTP API Events, use {@link APIGatewayV2HTTPResponse} + */ +@Deprecated +public class APIGatewayV2ProxyResponseEvent extends APIGatewayV2WebSocketResponse {} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2WebSocketEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2WebSocketEvent.java new file mode 100644 index 000000000..cb6ffa991 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2WebSocketEvent.java @@ -0,0 +1,727 @@ +package com.amazonaws.services.lambda.runtime.events; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @author Tim Gustafson + */ +public class APIGatewayV2WebSocketEvent implements Serializable, Cloneable { + + private static final long serialVersionUID = 5695319264103347099L; + + public static class RequestIdentity implements Serializable, Cloneable { + + private static final long serialVersionUID = -3276649362684921217L; + + private String cognitoIdentityPoolId; + private String accountId; + private String cognitoIdentityId; + private String caller; + private String apiKey; + private String sourceIp; + private String cognitoAuthenticationType; + private String cognitoAuthenticationProvider; + private String userArn; + private String userAgent; + private String user; + private String accessKey; + + public String getCognitoIdentityPoolId() { + return cognitoIdentityPoolId; + } + + public void setCognitoIdentityPoolId(String cognitoIdentityPoolId) { + this.cognitoIdentityPoolId = cognitoIdentityPoolId; + } + + public String getAccountId() { + return accountId; + } + + public void setAccountId(String accountId) { + this.accountId = accountId; + } + + public String getCognitoIdentityId() { + return cognitoIdentityId; + } + + public void setCognitoIdentityId(String cognitoIdentityId) { + this.cognitoIdentityId = cognitoIdentityId; + } + + public String getCaller() { + return caller; + } + + public void setCaller(String caller) { + this.caller = caller; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getSourceIp() { + return sourceIp; + } + + public void setSourceIp(String sourceIp) { + this.sourceIp = sourceIp; + } + + public String getCognitoAuthenticationType() { + return cognitoAuthenticationType; + } + + public void setCognitoAuthenticationType(String cognitoAuthenticationType) { + this.cognitoAuthenticationType = cognitoAuthenticationType; + } + + public String getCognitoAuthenticationProvider() { + return cognitoAuthenticationProvider; + } + + public void setCognitoAuthenticationProvider(String cognitoAuthenticationProvider) { + this.cognitoAuthenticationProvider = cognitoAuthenticationProvider; + } + + public String getUserArn() { + return userArn; + } + + public void setUserArn(String userArn) { + this.userArn = userArn; + } + + public String getUserAgent() { + return userAgent; + } + + public void setUserAgent(String userAgent) { + this.userAgent = userAgent; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 29 * hash + (this.cognitoIdentityPoolId != null ? this.cognitoIdentityPoolId.hashCode() : 0); + hash = 29 * hash + (this.accountId != null ? this.accountId.hashCode() : 0); + hash = 29 * hash + (this.cognitoIdentityId != null ? this.cognitoIdentityId.hashCode() : 0); + hash = 29 * hash + (this.caller != null ? this.caller.hashCode() : 0); + hash = 29 * hash + (this.apiKey != null ? this.apiKey.hashCode() : 0); + hash = 29 * hash + (this.sourceIp != null ? this.sourceIp.hashCode() : 0); + hash = 29 * hash + (this.cognitoAuthenticationType != null ? this.cognitoAuthenticationType.hashCode() : 0); + hash = 29 * hash + (this.cognitoAuthenticationProvider != null ? this.cognitoAuthenticationProvider.hashCode() : 0); + hash = 29 * hash + (this.userArn != null ? this.userArn.hashCode() : 0); + hash = 29 * hash + (this.userAgent != null ? this.userAgent.hashCode() : 0); + hash = 29 * hash + (this.user != null ? this.user.hashCode() : 0); + hash = 29 * hash + (this.accessKey != null ? this.accessKey.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final RequestIdentity other = (RequestIdentity) obj; + if ((this.cognitoIdentityPoolId == null) ? (other.cognitoIdentityPoolId != null) : !this.cognitoIdentityPoolId.equals(other.cognitoIdentityPoolId)) { + return false; + } + if ((this.accountId == null) ? (other.accountId != null) : !this.accountId.equals(other.accountId)) { + return false; + } + if ((this.cognitoIdentityId == null) ? (other.cognitoIdentityId != null) : !this.cognitoIdentityId.equals(other.cognitoIdentityId)) { + return false; + } + if ((this.caller == null) ? (other.caller != null) : !this.caller.equals(other.caller)) { + return false; + } + if ((this.apiKey == null) ? (other.apiKey != null) : !this.apiKey.equals(other.apiKey)) { + return false; + } + if ((this.sourceIp == null) ? (other.sourceIp != null) : !this.sourceIp.equals(other.sourceIp)) { + return false; + } + if ((this.cognitoAuthenticationType == null) ? (other.cognitoAuthenticationType != null) : !this.cognitoAuthenticationType.equals(other.cognitoAuthenticationType)) { + return false; + } + if ((this.cognitoAuthenticationProvider == null) ? (other.cognitoAuthenticationProvider != null) : !this.cognitoAuthenticationProvider.equals(other.cognitoAuthenticationProvider)) { + return false; + } + if ((this.userArn == null) ? (other.userArn != null) : !this.userArn.equals(other.userArn)) { + return false; + } + if ((this.userAgent == null) ? (other.userAgent != null) : !this.userAgent.equals(other.userAgent)) { + return false; + } + if ((this.user == null) ? (other.user != null) : !this.user.equals(other.user)) { + return false; + } + if ((this.accessKey == null) ? (other.accessKey != null) : !this.accessKey.equals(other.accessKey)) { + return false; + } + return true; + } + + @Override + public String toString() { + return "{cognitoIdentityPoolId=" + cognitoIdentityPoolId + + ", accountId=" + accountId + + ", cognitoIdentityId=" + cognitoIdentityId + + ", caller=" + caller + + ", apiKey=" + apiKey + + ", sourceIp=" + sourceIp + + ", cognitoAuthenticationType=" + cognitoAuthenticationType + + ", cognitoAuthenticationProvider=" + cognitoAuthenticationProvider + + ", userArn=" + userArn + + ", userAgent=" + userAgent + + ", user=" + user + + ", accessKey=" + accessKey + + "}"; + } + } + + public static class RequestContext implements Serializable, Cloneable { + + private static final long serialVersionUID = -6641935365992304860L; + + private String accountId; + private String resourceId; + private String stage; + private String requestId; + private RequestIdentity identity; + private String ResourcePath; + private Map authorizer; + private String httpMethod; + private String apiId; + private long connectedAt; + private String connectionId; + private String domainName; + private String error; + private String eventType; + private String extendedRequestId; + private String integrationLatency; + private String messageDirection; + private String messageId; + private String requestTime; + private long requestTimeEpoch; + private String routeKey; + private String status; + + public String getAccountId() { + return accountId; + } + + public void setAccountId(String accountId) { + this.accountId = accountId; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getStage() { + return stage; + } + + public void setStage(String stage) { + this.stage = stage; + } + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public RequestIdentity getIdentity() { + return identity; + } + + public void setIdentity(RequestIdentity identity) { + this.identity = identity; + } + + public String getResourcePath() { + return ResourcePath; + } + + public void setResourcePath(String ResourcePath) { + this.ResourcePath = ResourcePath; + } + + public Map getAuthorizer() { + return authorizer; + } + + public void setAuthorizer(Map authorizer) { + this.authorizer = authorizer; + } + + public String getHttpMethod() { + return httpMethod; + } + + public void setHttpMethod(String httpMethod) { + this.httpMethod = httpMethod; + } + + public String getApiId() { + return apiId; + } + + public void setApiId(String apiId) { + this.apiId = apiId; + } + + public long getConnectedAt() { + return connectedAt; + } + + public void setConnectedAt(long connectedAt) { + this.connectedAt = connectedAt; + } + + public String getConnectionId() { + return connectionId; + } + + public void setConnectionId(String connectionId) { + this.connectionId = connectionId; + } + + public String getDomainName() { + return domainName; + } + + public void setDomainName(String domainName) { + this.domainName = domainName; + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + + public String getEventType() { + return eventType; + } + + public void setEventType(String eventType) { + this.eventType = eventType; + } + + public String getExtendedRequestId() { + return extendedRequestId; + } + + public void setExtendedRequestId(String extendedRequestId) { + this.extendedRequestId = extendedRequestId; + } + + public String getIntegrationLatency() { + return integrationLatency; + } + + public void setIntegrationLatency(String integrationLatency) { + this.integrationLatency = integrationLatency; + } + + public String getMessageDirection() { + return messageDirection; + } + + public void setMessageDirection(String messageDirection) { + this.messageDirection = messageDirection; + } + + public String getMessageId() { + return messageId; + } + + public void setMessageId(String messageId) { + this.messageId = messageId; + } + + public String getRequestTime() { + return requestTime; + } + + public void setRequestTime(String requestTime) { + this.requestTime = requestTime; + } + + public long getRequestTimeEpoch() { + return requestTimeEpoch; + } + + public void setRequestTimeEpoch(long requestTimeEpoch) { + this.requestTimeEpoch = requestTimeEpoch; + } + + public String getRouteKey() { + return routeKey; + } + + public void setRouteKey(String routeKey) { + this.routeKey = routeKey; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 59 * hash + (this.accountId != null ? this.accountId.hashCode() : 0); + hash = 59 * hash + (this.resourceId != null ? this.resourceId.hashCode() : 0); + hash = 59 * hash + (this.stage != null ? this.stage.hashCode() : 0); + hash = 59 * hash + (this.requestId != null ? this.requestId.hashCode() : 0); + hash = 59 * hash + (this.identity != null ? this.identity.hashCode() : 0); + hash = 59 * hash + (this.ResourcePath != null ? this.ResourcePath.hashCode() : 0); + hash = 59 * hash + (this.authorizer != null ? this.authorizer.hashCode() : 0); + hash = 59 * hash + (this.httpMethod != null ? this.httpMethod.hashCode() : 0); + hash = 59 * hash + (this.apiId != null ? this.apiId.hashCode() : 0); + hash = 59 * hash + (int) (this.connectedAt ^ (this.connectedAt >>> 32)); + hash = 59 * hash + (this.connectionId != null ? this.connectionId.hashCode() : 0); + hash = 59 * hash + (this.domainName != null ? this.domainName.hashCode() : 0); + hash = 59 * hash + (this.error != null ? this.error.hashCode() : 0); + hash = 59 * hash + (this.eventType != null ? this.eventType.hashCode() : 0); + hash = 59 * hash + (this.extendedRequestId != null ? this.extendedRequestId.hashCode() : 0); + hash = 59 * hash + (this.integrationLatency != null ? this.integrationLatency.hashCode() : 0); + hash = 59 * hash + (this.messageDirection != null ? this.messageDirection.hashCode() : 0); + hash = 59 * hash + (this.messageId != null ? this.messageId.hashCode() : 0); + hash = 59 * hash + (this.requestTime != null ? this.requestTime.hashCode() : 0); + hash = 59 * hash + (int) (this.requestTimeEpoch ^ (this.requestTimeEpoch >>> 32)); + hash = 59 * hash + (this.routeKey != null ? this.routeKey.hashCode() : 0); + hash = 59 * hash + (this.status != null ? this.status.hashCode() : 0); + return hash; + } + + @Override + public String toString() { + return "{accountId=" + accountId + + ", resourceId=" + resourceId + + ", stage=" + stage + + ", requestId=" + requestId + + ", identity=" + identity + + ", ResourcePath=" + ResourcePath + + ", authorizer=" + authorizer + + ", httpMethod=" + httpMethod + + ", apiId=" + apiId + + ", connectedAt=" + connectedAt + + ", connectionId=" + connectionId + + ", domainName=" + domainName + + ", error=" + error + + ", eventType=" + eventType + + ", extendedRequestId=" + extendedRequestId + + ", integrationLatency=" + integrationLatency + + ", messageDirection=" + messageDirection + + ", messageId=" + messageId + + ", requestTime=" + requestTime + + ", requestTimeEpoch=" + requestTimeEpoch + + ", routeKey=" + routeKey + + ", status=" + status + + "}"; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final RequestContext other = (RequestContext) obj; + if (this.connectedAt != other.connectedAt) { + return false; + } + if (this.requestTimeEpoch != other.requestTimeEpoch) { + return false; + } + if ((this.accountId == null) ? (other.accountId != null) : !this.accountId.equals(other.accountId)) { + return false; + } + if ((this.resourceId == null) ? (other.resourceId != null) : !this.resourceId.equals(other.resourceId)) { + return false; + } + if ((this.stage == null) ? (other.stage != null) : !this.stage.equals(other.stage)) { + return false; + } + if ((this.requestId == null) ? (other.requestId != null) : !this.requestId.equals(other.requestId)) { + return false; + } + if ((this.ResourcePath == null) ? (other.ResourcePath != null) : !this.ResourcePath.equals(other.ResourcePath)) { + return false; + } + if ((this.authorizer == null) ? (other.authorizer != null) : !this.authorizer.equals(other.authorizer)) { + return false; + } + if ((this.httpMethod == null) ? (other.httpMethod != null) : !this.httpMethod.equals(other.httpMethod)) { + return false; + } + if ((this.apiId == null) ? (other.apiId != null) : !this.apiId.equals(other.apiId)) { + return false; + } + if ((this.connectionId == null) ? (other.connectionId != null) : !this.connectionId.equals(other.connectionId)) { + return false; + } + if ((this.domainName == null) ? (other.domainName != null) : !this.domainName.equals(other.domainName)) { + return false; + } + if ((this.error == null) ? (other.error != null) : !this.error.equals(other.error)) { + return false; + } + if ((this.eventType == null) ? (other.eventType != null) : !this.eventType.equals(other.eventType)) { + return false; + } + if ((this.extendedRequestId == null) ? (other.extendedRequestId != null) : !this.extendedRequestId.equals(other.extendedRequestId)) { + return false; + } + if ((this.integrationLatency == null) ? (other.integrationLatency != null) : !this.integrationLatency.equals(other.integrationLatency)) { + return false; + } + if ((this.messageDirection == null) ? (other.messageDirection != null) : !this.messageDirection.equals(other.messageDirection)) { + return false; + } + if ((this.messageId == null) ? (other.messageId != null) : !this.messageId.equals(other.messageId)) { + return false; + } + if ((this.requestTime == null) ? (other.requestTime != null) : !this.requestTime.equals(other.requestTime)) { + return false; + } + if ((this.routeKey == null) ? (other.routeKey != null) : !this.routeKey.equals(other.routeKey)) { + return false; + } + if ((this.status == null) ? (other.status != null) : !this.status.equals(other.status)) { + return false; + } + if (this.identity != other.identity && (this.identity == null || !this.identity.equals(other.identity))) { + return false; + } + return true; + } + + } + + private String resource; + private String path; + private String httpMethod; + private Map headers; + private Map> multiValueHeaders; + private Map queryStringParameters; + private Map> multiValueQueryStringParameters; + private Map pathParameters; + private Map stageVariables; + private RequestContext requestContext; + private String body; + private boolean isBase64Encoded = false; + + public String getResource() { + return resource; + } + + public void setResource(String resource) { + this.resource = resource; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getHttpMethod() { + return httpMethod; + } + + public void setHttpMethod(String httpMethod) { + this.httpMethod = httpMethod; + } + + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + + public Map> getMultiValueHeaders() { + return multiValueHeaders; + } + + public void setMultiValueHeaders(Map> multiValueHeaders) { + this.multiValueHeaders = multiValueHeaders; + } + + public Map getQueryStringParameters() { + return queryStringParameters; + } + + public void setQueryStringParameters(Map queryStringParameters) { + this.queryStringParameters = queryStringParameters; + } + + public Map> getMultiValueQueryStringParameters() { + return multiValueQueryStringParameters; + } + + public void setMultiValueQueryStringParameters(Map> multiValueQueryStringParameters) { + this.multiValueQueryStringParameters = multiValueQueryStringParameters; + } + + public Map getPathParameters() { + return pathParameters; + } + + public void setPathParameters(Map pathParameters) { + this.pathParameters = pathParameters; + } + + public Map getStageVariables() { + return stageVariables; + } + + public void setStageVariables(Map stageVariables) { + this.stageVariables = stageVariables; + } + + public RequestContext getRequestContext() { + return requestContext; + } + + public void setRequestContext(RequestContext requestContext) { + this.requestContext = requestContext; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public boolean isIsBase64Encoded() { + return isBase64Encoded; + } + + public void setIsBase64Encoded(boolean isBase64Encoded) { + this.isBase64Encoded = isBase64Encoded; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + APIGatewayV2WebSocketEvent that = (APIGatewayV2WebSocketEvent) o; + + if (isBase64Encoded != that.isBase64Encoded) return false; + if (resource != null ? !resource.equals(that.resource) : that.resource != null) return false; + if (path != null ? !path.equals(that.path) : that.path != null) return false; + if (httpMethod != null ? !httpMethod.equals(that.httpMethod) : that.httpMethod != null) return false; + if (headers != null ? !headers.equals(that.headers) : that.headers != null) return false; + if (multiValueHeaders != null ? !multiValueHeaders.equals(that.multiValueHeaders) : that.multiValueHeaders != null) + return false; + if (queryStringParameters != null ? !queryStringParameters.equals(that.queryStringParameters) : that.queryStringParameters != null) + return false; + if (multiValueQueryStringParameters != null ? !multiValueQueryStringParameters.equals(that.multiValueQueryStringParameters) : that.multiValueQueryStringParameters != null) + return false; + if (pathParameters != null ? !pathParameters.equals(that.pathParameters) : that.pathParameters != null) + return false; + if (stageVariables != null ? !stageVariables.equals(that.stageVariables) : that.stageVariables != null) + return false; + if (requestContext != null ? !requestContext.equals(that.requestContext) : that.requestContext != null) + return false; + return body != null ? body.equals(that.body) : that.body == null; + } + + @Override + public int hashCode() { + int result = resource != null ? resource.hashCode() : 0; + result = 31 * result + (path != null ? path.hashCode() : 0); + result = 31 * result + (httpMethod != null ? httpMethod.hashCode() : 0); + result = 31 * result + (headers != null ? headers.hashCode() : 0); + result = 31 * result + (multiValueHeaders != null ? multiValueHeaders.hashCode() : 0); + result = 31 * result + (queryStringParameters != null ? queryStringParameters.hashCode() : 0); + result = 31 * result + (multiValueQueryStringParameters != null ? multiValueQueryStringParameters.hashCode() : 0); + result = 31 * result + (pathParameters != null ? pathParameters.hashCode() : 0); + result = 31 * result + (stageVariables != null ? stageVariables.hashCode() : 0); + result = 31 * result + (requestContext != null ? requestContext.hashCode() : 0); + result = 31 * result + (body != null ? body.hashCode() : 0); + result = 31 * result + (isBase64Encoded ? 1 : 0); + return result; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("APIGatewayV2WebSocketEvent{"); + sb.append("resource='").append(resource).append('\''); + sb.append(", path='").append(path).append('\''); + sb.append(", httpMethod='").append(httpMethod).append('\''); + sb.append(", headers=").append(headers); + sb.append(", multiValueHeaders=").append(multiValueHeaders); + sb.append(", queryStringParameters=").append(queryStringParameters); + sb.append(", multiValueQueryStringParameters=").append(multiValueQueryStringParameters); + sb.append(", pathParameters=").append(pathParameters); + sb.append(", stageVariables=").append(stageVariables); + sb.append(", requestContext=").append(requestContext); + sb.append(", body='").append(body).append('\''); + sb.append(", isBase64Encoded=").append(isBase64Encoded); + sb.append('}'); + return sb.toString(); + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2WebSocketResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2WebSocketResponse.java new file mode 100644 index 000000000..87e4284cd --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2WebSocketResponse.java @@ -0,0 +1,110 @@ +package com.amazonaws.services.lambda.runtime.events; + +import java.io.Serializable; +import java.util.Map; + +/** + * @author Tim Gustafson + */ +public class APIGatewayV2WebSocketResponse implements Serializable, Cloneable { + + private static final long serialVersionUID = -5155789062248356200L; + + private boolean isBase64Encoded = false; + private int statusCode; + private Map headers; + private Map multiValueHeaders; + private String body; + + public boolean isIsBase64Encoded() { + return isBase64Encoded; + } + + public void setIsBase64Encoded(boolean isBase64Encoded) { + this.isBase64Encoded = isBase64Encoded; + } + + public int getStatusCode() { + return statusCode; + } + + public void setStatusCode(int statusCode) { + this.statusCode = statusCode; + } + + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + + public Map getMultiValueHeaders() { + return multiValueHeaders; + } + + public void setMultiValueHeaders(Map multiValueHeaders) { + this.multiValueHeaders = multiValueHeaders; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 71 * hash + (this.isBase64Encoded ? 1 : 0); + hash = 71 * hash + this.statusCode; + hash = 71 * hash + (this.headers != null ? this.headers.hashCode() : 0); + hash = 71 * hash + (this.multiValueHeaders != null ? this.multiValueHeaders.hashCode() : 0); + hash = 71 * hash + (this.body != null ? this.body.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final APIGatewayV2WebSocketResponse other = (APIGatewayV2WebSocketResponse) obj; + if (this.isBase64Encoded != other.isBase64Encoded) { + return false; + } + if (this.statusCode != other.statusCode) { + return false; + } + if ((this.body == null) ? (other.body != null) : !this.body.equals(other.body)) { + return false; + } + if (this.headers != other.headers && (this.headers == null || !this.headers.equals(other.headers))) { + return false; + } + if (this.multiValueHeaders != other.multiValueHeaders && (this.multiValueHeaders == null || !this.multiValueHeaders.equals(other.multiValueHeaders))) { + return false; + } + return true; + } + + @Override + public String toString() { + return "{isBase64Encoded=" + isBase64Encoded + + ", statusCode=" + statusCode + + ", headers=" + headers + + ", multiValueHeaders=" + multiValueHeaders + + ", body=" + body + + "}"; + } + +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ActiveMQEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ActiveMQEvent.java new file mode 100644 index 000000000..e896a223e --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ActiveMQEvent.java @@ -0,0 +1,67 @@ +/* + * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import java.util.List; +import java.util.Map; + +/** +* Represents an Active MQ event sent to Lambda +* Onboarding Amazon MQ as event source to Lambda +*/ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder(setterPrefix = "with") +public class ActiveMQEvent { + private String eventSource; + private String eventSourceArn; + private List messages; + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder(setterPrefix = "with") + public static class ActiveMQMessage { + private String messageID; + private String messageType; + private long timestamp; + private int deliveryMode; + private String correlationID; + private String replyTo; + private Destination destination; + private boolean redelivered; + private String type; + private long expiration; + private int priority; + /** Message data sent to Active MQ broker encooded in Base 64 **/ + private String data; + private long brokerInTime; + private long brokerOutTime; + private Map properties; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder(setterPrefix = "with") + public static class Destination { + /** Queue Name **/ + private String physicalName; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/AppSyncLambdaAuthorizerEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/AppSyncLambdaAuthorizerEvent.java new file mode 100644 index 000000000..0bb6c8b06 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/AppSyncLambdaAuthorizerEvent.java @@ -0,0 +1,49 @@ +/* + * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import java.util.Map; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Class that represents the input to an AppSync Lambda authorizer invocation. + */ +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class AppSyncLambdaAuthorizerEvent { + + private RequestContext requestContext; + private String authorizationToken; + private Map requestHeaders; + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class RequestContext { + + private String apiId; + private String accountId; + private String requestId; + private String queryDocument; + private String operationName; + private Map variables; + } + +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/AppSyncLambdaAuthorizerResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/AppSyncLambdaAuthorizerResponse.java new file mode 100644 index 000000000..4eec5aa3d --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/AppSyncLambdaAuthorizerResponse.java @@ -0,0 +1,36 @@ +/* + * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import java.util.Map; +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Class that represents the output from an AppSync Lambda authorizer invocation. + */ +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class AppSyncLambdaAuthorizerResponse { + + private boolean isAuthorized; + private Map resolverContext; + private List deniedFields; + private int ttlOverride; +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerRequestEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerRequestEvent.java new file mode 100644 index 000000000..e7b33117e --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerRequestEvent.java @@ -0,0 +1,48 @@ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * Class to represent the request event from Application Load Balancer. + * + * @see Using AWS Lambda with an Application Load Balancer + * + * @author msailes + */ + +@NoArgsConstructor +@Data +public class ApplicationLoadBalancerRequestEvent implements Serializable, Cloneable { + + @NoArgsConstructor + @Data + public static class Elb implements Serializable, Cloneable { + + private String targetGroupArn; + + } + + @NoArgsConstructor + @Data + public static class RequestContext implements Serializable, Cloneable { + + private Elb elb; + + } + + private RequestContext requestContext; + private String httpMethod; + private String path; + private Map queryStringParameters; + private Map> multiValueQueryStringParameters; + private Map headers; + private Map> multiValueHeaders; + private String body; + private boolean isBase64Encoded; + +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerResponseEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerResponseEvent.java new file mode 100644 index 000000000..135de143f --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerResponseEvent.java @@ -0,0 +1,29 @@ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * Class to represent the response event to Application Load Balancer. + * + * @see Using AWS Lambda with an Application Load Balancer + * + * @author msailes + */ + +@NoArgsConstructor +@Data +public class ApplicationLoadBalancerResponseEvent implements Serializable, Cloneable { + + private int statusCode; + private String statusDescription; + private boolean isBase64Encoded; + private Map headers; + private Map> multiValueHeaders; + private String body; + +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudFormationCustomResourceEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudFormationCustomResourceEvent.java new file mode 100644 index 000000000..37c00a903 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudFormationCustomResourceEvent.java @@ -0,0 +1,50 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Map; + +/** + * Class to represent the custom resource request event from CloudFormation. + * + * CloudFormation invokes your Lambda function asynchronously with this event and includes a callback URL. The function + * is responsible for returning a response to the callback URL that indicates success or failure. + * + * @see Using AWS Lambda with AWS CloudFormation + * + * @author msailes + */ + +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class CloudFormationCustomResourceEvent implements Serializable, Cloneable { + + private String requestType; + private String serviceToken; + private String responseUrl; + private String stackId; + private String requestId; + private String logicalResourceId; + private String physicalResourceId; + private String resourceType; + private Map resourceProperties; + private Map oldResourceProperties; +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudWatchCompositeAlarmEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudWatchCompositeAlarmEvent.java new file mode 100644 index 000000000..d4090b55b --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudWatchCompositeAlarmEvent.java @@ -0,0 +1,70 @@ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Represents an CloudWatch Composite Alarm event. This event occurs when a composite alarm is triggered. + * + * @see Using Amazon CloudWatch alarms + */ +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class CloudWatchCompositeAlarmEvent { + private String source; + private String alarmArn; + private String accountId; + private String time; + private String region; + private AlarmData alarmData; + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class AlarmData { + private String alarmName; + private State state; + private PreviousState previousState; + private Configuration configuration; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class State { + private String value; + private String reason; + private String reasonData; + private String timestamp; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class PreviousState { + private String value; + private String reason; + private String reasonData; + private String timestamp; + private String actionsSuppressedBy; + private String actionsSuppressedReason; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Configuration { + private String alarmRule; + private String actionsSuppressor; + private Integer actionsSuppressorWaitPeriod; + private Integer actionsSuppressorExtensionPeriod; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudWatchMetricAlarmEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudWatchMetricAlarmEvent.java new file mode 100644 index 000000000..2b5f503c3 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudWatchMetricAlarmEvent.java @@ -0,0 +1,99 @@ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +/** + * Represents an CloudWatch Metric Alarm event. This event occurs when a metric alarm is triggered. + * + * @see Using Amazon CloudWatch alarms + */ +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class CloudWatchMetricAlarmEvent { + private String source; + private String alarmArn; + private String accountId; + private String time; + private String region; + private AlarmData alarmData; + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class AlarmData { + private String alarmName; + private State state; + private PreviousState previousState; + private Configuration configuration; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class State { + private String value; + private String reason; + private String timestamp; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class PreviousState { + private String value; + private String reason; + private String reasonData; + private String timestamp; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Configuration { + private String description; + private List metrics; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Metric { + private String id; + private MetricStat metricStat; + private Boolean returnData; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class MetricStat { + private MetricDetail metric; + private Integer period; + private String stat; + private String unit; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class MetricDetail { + private String namespace; + private String name; + private Map dimensions; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoEvent.java index d250dc17b..452d3d6f2 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoEvent.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoEvent.java @@ -18,7 +18,7 @@ /** * - * Represents an Amazon Congnito event sent to Lambda Functions + * Represents an Amazon Cognito event sent to Lambda Functions * */ public class CognitoEvent implements Serializable, Cloneable { diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolCreateAuthChallengeEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolCreateAuthChallengeEvent.java new file mode 100644 index 000000000..6074ca9b5 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolCreateAuthChallengeEvent.java @@ -0,0 +1,124 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.*; + +import java.util.Map; + +/** + * Represent the class for the Cognito User Pool Create Auth Challenge Lambda Trigger + * + * See Create Auth Challenge Lambda Trigger + * + * @author jvdl + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@ToString(callSuper = true) +public class CognitoUserPoolCreateAuthChallengeEvent extends CognitoUserPoolEvent { + + /** + * The request from the Amazon Cognito service. + */ + private Request request; + + /** + * The response from your Lambda trigger. + */ + private Response response; + + @Builder(setterPrefix = "with") + public CognitoUserPoolCreateAuthChallengeEvent( + String version, + String triggerSource, + String region, + String userPoolId, + String userName, + CallerContext callerContext, + Request request, + Response response) { + super(version, triggerSource, region, userPoolId, userName, callerContext); + this.request = request; + this.response = response; + } + + @Data + @EqualsAndHashCode(callSuper = true) + @NoArgsConstructor + @ToString(callSuper = true) + public static class Request extends CognitoUserPoolEvent.Request { + /** + * One or more key-value pairs that you can provide as custom input to the Lambda function that you specify for the create auth challenge trigger. + */ + private Map clientMetadata; + /** + * The name of the new challenge. + */ + private String challengeName; + private ChallengeResult[] session; + /** + * This boolean is populated when PreventUserExistenceErrors is set to ENABLED for your User Pool client. + */ + private boolean userNotFound; + + @Builder(setterPrefix = "with") + public Request(Map userAttributes, Map clientMetadata, String challengeName, ChallengeResult[] session, boolean userNotFound) { + super(userAttributes); + this.clientMetadata = clientMetadata; + this.session = session; + this.userNotFound = userNotFound; + this.challengeName = challengeName; + } + } + + @AllArgsConstructor + @Builder(setterPrefix = "with") + @Data + @NoArgsConstructor + public static class ChallengeResult { + /** + * The challenge type. One of: "CUSTOM_CHALLENGE", "PASSWORD_VERIFIER", "SMS_MFA", "DEVICE_SRP_AUTH", "DEVICE_PASSWORD_VERIFIER", or "ADMIN_NO_SRP_AUTH". + */ + private String challengeName; + /** + * Set to true if the user successfully completed the challenge, or false otherwise. + */ + private boolean challengeResult; + /** + * Your name for the custom challenge. Used only if challengeName is CUSTOM_CHALLENGE. + */ + private String challengeMetadata; + } + + @AllArgsConstructor + @Builder(setterPrefix = "with") + @Data + @NoArgsConstructor + public static class Response { + /** + * One or more key-value pairs for the client app to use in the challenge to be presented to the user. + * Contains the question that is presented to the user. + */ + private Map publicChallengeParameters; + /** + * Contains the valid answers for the question in publicChallengeParameters + */ + private Map privateChallengeParameters; + /** + * Your name for the custom challenge, if this is a custom challenge. + */ + private String challengeMetadata; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolCustomMessageEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolCustomMessageEvent.java new file mode 100644 index 000000000..403f85393 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolCustomMessageEvent.java @@ -0,0 +1,101 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.*; + +import java.util.Map; + +/** + * Represent the class for the Cognito User Pool Custom Message Lambda Trigger + * + * See Custom Message Lambda Trigger + * + * @author jvdl + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@ToString(callSuper = true) +public class CognitoUserPoolCustomMessageEvent extends CognitoUserPoolEvent { + /** + * The request from the Amazon Cognito service. + */ + private Request request; + + /** + * The response from your Lambda trigger. + */ + private Response response; + + @Builder(setterPrefix = "with") + public CognitoUserPoolCustomMessageEvent( + String version, + String triggerSource, + String region, + String userPoolId, + String userName, + CallerContext callerContext, + Request request, + Response response) { + super(version, triggerSource, region, userPoolId, userName, callerContext); + this.request = request; + this.response = response; + } + + @Data + @EqualsAndHashCode(callSuper = true) + @NoArgsConstructor + @ToString(callSuper = true) + public static class Request extends CognitoUserPoolEvent.Request { + /** + * One or more key-value pairs that you can provide as custom input to the Lambda function that you specify for the custom message trigger. + */ + private Map clientMetadata; + /** + * A string for you to use as the placeholder for the verification code in the custom message. + */ + private String codeParameter; + /** + * The username parameter. It is a required request parameter for the admin create user flow. + */ + private String usernameParameter; + + @Builder(setterPrefix = "with") + public Request(Map userAttributes, Map clientMetadata, String codeParameter, String usernameParameter) { + super(userAttributes); + this.clientMetadata = clientMetadata; + this.codeParameter = codeParameter; + this.usernameParameter = usernameParameter; + } + } + + @Data + @AllArgsConstructor + @Builder(setterPrefix = "with") + @NoArgsConstructor + public static class Response { + /** + * The custom SMS message to be sent to your users. Must include the codeParameter value received in the request. + */ + private String smsMessage; + /** + * The custom email message to be sent to your users. Must include the codeParameter value received in the request. + */ + private String emailMessage; + /** + * The subject line for the custom message. + */ + private String emailSubject; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolDefineAuthChallengeEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolDefineAuthChallengeEvent.java new file mode 100644 index 000000000..8577c9f7a --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolDefineAuthChallengeEvent.java @@ -0,0 +1,123 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.*; + +import java.util.Map; + +/** + * Represent the class for the Cognito User Pool Define Auth Challenge Lambda Trigger + * + * See Define Auth Challenge Lambda Trigger + * + * @author jvdl + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@ToString(callSuper = true) +public class CognitoUserPoolDefineAuthChallengeEvent extends CognitoUserPoolEvent { + + /** + * The request from the Amazon Cognito service. + */ + private Request request; + + /** + * The response from your Lambda trigger. + */ + private Response response; + + @Builder(setterPrefix = "with") + public CognitoUserPoolDefineAuthChallengeEvent( + String version, + String triggerSource, + String region, + String userPoolId, + String userName, + CallerContext callerContext, + Request request, + Response response) { + super(version, triggerSource, region, userPoolId, userName, callerContext); + this.request = request; + this.response = response; + } + + @Data + @EqualsAndHashCode(callSuper = true) + @NoArgsConstructor + @ToString(callSuper = true) + public static class Request extends CognitoUserPoolEvent.Request { + /** + * One or more key-value pairs that you can provide as custom input to the Lambda function that you specify for the define auth challenge trigger. + */ + private Map clientMetadata; + + private ChallengeResult[] session; + + /** + * A Boolean that is populated when PreventUserExistenceErrors is set to ENABLED for your user pool client. + * A value of true means that the user id (user name, email address, etc.) did not match any existing users. + */ + private boolean userNotFound; + + @Builder(setterPrefix = "with") + public Request(Map userAttributes, Map clientMetadata, ChallengeResult[] session, boolean userNotFound) { + super(userAttributes); + this.clientMetadata = clientMetadata; + this.session = session; + this.userNotFound = userNotFound; + } + } + + @Data + @AllArgsConstructor + @Builder(setterPrefix = "with") + @NoArgsConstructor + public static class ChallengeResult { + /** + * The challenge type. One of: CUSTOM_CHALLENGE, SRP_A, PASSWORD_VERIFIER, SMS_MFA, DEVICE_SRP_AUTH, DEVICE_PASSWORD_VERIFIER, or ADMIN_NO_SRP_AUTH. + */ + private String challengeName; + /** + * Set to true if the user successfully completed the challenge, or false otherwise. + */ + private boolean challengeResult; + /** + * Your name for the custom challenge. Used only if challengeName is CUSTOM_CHALLENGE. + */ + private String challengeMetadata; + } + + @Data + @AllArgsConstructor + @Builder(setterPrefix = "with") + @NoArgsConstructor + public static class Response { + /** + * Name of the next challenge, if you want to present a new challenge to your user. + */ + private String challengeName; + + /** + * Set to true if you determine that the user has been sufficiently authenticated by completing the challenges, or false otherwise. + */ + private boolean issueTokens; + + /** + * Set to true if you want to terminate the current authentication process, or false otherwise. + */ + private boolean failAuthentication; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolEvent.java new file mode 100644 index 000000000..17c4b409d --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolEvent.java @@ -0,0 +1,89 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Map; + +/** + * Represent the base class for all Cognito User Pool Events + * + * See Customizing User Pool Workflows with Lambda Triggers + * + * @author jvdl + */ +@AllArgsConstructor +@Data +@NoArgsConstructor +public abstract class CognitoUserPoolEvent { + + /** + * The version number of your Lambda function. + */ + private String version; + + /** + * The name of the event that triggered the Lambda function. + */ + private String triggerSource; + + /** + * The AWS Region. + */ + private String region; + + /** + * The user pool ID for the user pool. + */ + private String userPoolId; + + /** + * The username of the current user. + */ + private String userName; + + /** + * The caller context. + */ + private CallerContext callerContext; + + @AllArgsConstructor + @Data + @NoArgsConstructor + public static abstract class Request { + /** + * One or more pairs of user attribute names and values. + */ + private Map userAttributes; + } + + @AllArgsConstructor + @Builder(setterPrefix = "with") + @Data + @NoArgsConstructor + public static class CallerContext { + /** + * The AWS SDK version number. + */ + private String awsSdkVersion; + + /** + * The ID of the client associated with the user pool. + */ + private String clientId; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolMigrateUserEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolMigrateUserEvent.java new file mode 100644 index 000000000..381010a76 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolMigrateUserEvent.java @@ -0,0 +1,121 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.*; + +import java.util.Map; + +/** + * Represent the class for the Cognito User Pool Migrate User Lambda Trigger + * + * See Migrate User Lambda Trigger + * + * @author jvdl + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@ToString(callSuper = true) +public class CognitoUserPoolMigrateUserEvent extends CognitoUserPoolEvent { + /** + * The request from the Amazon Cognito service. + */ + private Request request; + + /** + * The response from your Lambda trigger. + */ + private Response response; + + @Builder(setterPrefix = "with") + public CognitoUserPoolMigrateUserEvent( + String version, + String triggerSource, + String region, + String userPoolId, + String userName, + CallerContext callerContext, + Request request, + Response response) { + super(version, triggerSource, region, userPoolId, userName, callerContext); + this.request = request; + this.response = response; + } + + @Data + @EqualsAndHashCode(callSuper = true) + @NoArgsConstructor + @ToString(callSuper = true) + public static class Request extends CognitoUserPoolEvent.Request { + /** + * The username entered by the user. + */ + private String userName; + /** + * The password entered by the user for sign-in. It is not set in the forgot-password flow. + */ + private String password; + /** + * One or more key-value pairs containing the validation data in the user's sign-in request. + */ + private Map validationData; + /** + * One or more key-value pairs that you can provide as custom input to the Lambda function that you specify for the migrate user trigger. + */ + private Map clientMetadata; + + @Builder(setterPrefix = "with") + public Request(Map userAttributes, Map validationData, Map clientMetadata, String userName, String password) { + super(userAttributes); + this.validationData = validationData; + this.clientMetadata = clientMetadata; + this.userName = userName; + this.password = password; + } + } + + @AllArgsConstructor + @Builder(setterPrefix = "with") + @Data + @NoArgsConstructor + public static class Response { + + /** + * It must contain one or more name-value pairs representing user attributes to be stored in the user profile in your user pool. + */ + private Map userAttributes; + + /** + * During sign-in, this attribute can be set to CONFIRMED, or not set, to auto-confirm your users and allow them to sign-in with their previous passwords. + */ + private String finalUserStatus; + + /** + * This attribute can be set to "SUPPRESS" to suppress the welcome message usually sent by Amazon Cognito to new users. + * If this attribute is not returned, the welcome message will be sent. + */ + private String messageAction; + + /** + * This attribute can be set to "EMAIL" to send the welcome message by email, or "SMS" to send the welcome message by SMS. + * If this attribute is not returned, the welcome message will be sent by SMS. + */ + private String[] desiredDeliveryMediums; + + /** + * If this parameter is set to "true" and the phone number or email address specified in the UserAttributes parameter already exists as an alias with a different user, the API call will migrate the alias from the previous user to the newly created user. + */ + private boolean forceAliasCreation; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPostAuthenticationEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPostAuthenticationEvent.java new file mode 100644 index 000000000..de1af6565 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPostAuthenticationEvent.java @@ -0,0 +1,76 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.util.Map; + +/** + * Represent the class for the Cognito User Pool Post Authentication Lambda Trigger + * + * See Post Authentication Lambda Trigger + * + * @author jvdl + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@ToString(callSuper = true) +public class CognitoUserPoolPostAuthenticationEvent extends CognitoUserPoolEvent { + + /** + * The request from the Amazon Cognito service. + */ + private Request request; + + @Builder(setterPrefix = "with") + public CognitoUserPoolPostAuthenticationEvent( + String version, + String triggerSource, + String region, + String userPoolId, + String userName, + CallerContext callerContext, + Request request) { + super(version, triggerSource, region, userPoolId, userName, callerContext); + this.request = request; + } + + @Data + @EqualsAndHashCode(callSuper = true) + @NoArgsConstructor + @ToString(callSuper = true) + public static class Request extends CognitoUserPoolEvent.Request { + /** + * One or more key-value pairs that you can provide as custom input to the Lambda function that you specify for the post authentication trigger. + */ + private Map clientMetadata; + + /** + * This flag indicates if the user has signed in on a new device. + */ + private boolean newDeviceUsed; + + @Builder(setterPrefix = "with") + public Request(Map userAttributes, Map clientMetadata, boolean newDeviceUsed) { + super(userAttributes); + this.clientMetadata = clientMetadata; + this.newDeviceUsed = newDeviceUsed; + } + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPostConfirmationEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPostConfirmationEvent.java new file mode 100644 index 000000000..4a835489d --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPostConfirmationEvent.java @@ -0,0 +1,70 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.util.Map; + +/** + * Represent the class for the Cognito User Pool Post Confirmation Lambda Trigger + * + * See Post Confirmation Lambda Trigger + * + * @author jvdl + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@ToString(callSuper = true) +public class CognitoUserPoolPostConfirmationEvent extends CognitoUserPoolEvent { + + /** + * The request from the Amazon Cognito service. + */ + private Request request; + + @Builder(setterPrefix = "with") + public CognitoUserPoolPostConfirmationEvent( + String version, + String triggerSource, + String region, + String userPoolId, + String userName, + CallerContext callerContext, + Request request) { + super(version, triggerSource, region, userPoolId, userName, callerContext); + this.request = request; + } + + @Data + @EqualsAndHashCode(callSuper = true) + @NoArgsConstructor + @ToString(callSuper = true) + public static class Request extends CognitoUserPoolEvent.Request { + /** + * One or more key-value pairs that you can provide as custom input to the Lambda function that you specify for the post confirmation trigger. + */ + private Map clientMetadata; + + @Builder(setterPrefix = "with") + public Request(Map userAttributes, Map clientMetadata) { + super(userAttributes); + this.clientMetadata = clientMetadata; + } + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPreAuthenticationEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPreAuthenticationEvent.java new file mode 100644 index 000000000..110160415 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPreAuthenticationEvent.java @@ -0,0 +1,77 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.util.Map; + +/** + * Represent the class for the Cognito User Pool Pre Authentication Lambda Trigger + * + * See Pre Authentication Lambda Trigger + * + * @author jvdl + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@ToString(callSuper = true) +public class CognitoUserPoolPreAuthenticationEvent extends CognitoUserPoolEvent { + + /** + * The request from the Amazon Cognito service. + */ + private Request request; + + @Builder(setterPrefix = "with") + public CognitoUserPoolPreAuthenticationEvent( + String version, + String triggerSource, + String region, + String userPoolId, + String userName, + CallerContext callerContext, + Request request) { + super(version, triggerSource, region, userPoolId, userName, callerContext); + this.request = request; + } + + @Data + @EqualsAndHashCode(callSuper = true) + @NoArgsConstructor + @ToString(callSuper = true) + public static class Request extends CognitoUserPoolEvent.Request { + /** + * One or more name-value pairs containing the validation data in the request to register a user. + * The validation data is set and then passed from the client in the request to register a user. + */ + private Map validationData; + + /** + * This boolean is populated when PreventUserExistenceErrors is set to ENABLED for your User Pool client. + */ + private boolean userNotFound; + + @Builder(setterPrefix = "with") + public Request(Map userAttributes, Map validationData, boolean userNotFound) { + super(userAttributes); + this.validationData = validationData; + this.userNotFound = userNotFound; + } + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPreSignUpEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPreSignUpEvent.java new file mode 100644 index 000000000..da7a848e5 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPreSignUpEvent.java @@ -0,0 +1,104 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.*; + +import java.util.Map; + +/** + * Represent the class for the Cognito User Pool Pre Sign-up Lambda Trigger + * + * See Pre Sign-up Lambda Trigger + * + * @author jvdl + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@ToString(callSuper = true) +public class CognitoUserPoolPreSignUpEvent extends CognitoUserPoolEvent { + + /** + * The request from the Amazon Cognito service. + */ + private Request request; + + /** + * The response from your Lambda trigger. + */ + private Response response; + + @Builder(setterPrefix = "with") + public CognitoUserPoolPreSignUpEvent( + String version, + String triggerSource, + String region, + String userPoolId, + String userName, + CallerContext callerContext, + Request request, + Response response) { + super(version, triggerSource, region, userPoolId, userName, callerContext); + this.request = request; + this.response = response; + } + + @Data + @EqualsAndHashCode(callSuper = true) + @NoArgsConstructor + @ToString(callSuper = true) + public static class Request extends CognitoUserPoolEvent.Request { + /** + * One or more name-value pairs containing the validation data in the request to register a user. + * The validation data is set and then passed from the client in the request to register a user. + */ + private Map validationData; + + /** + * One or more key-value pairs that you can provide as custom input + * to the Lambda function that you specify for the pre sign-up trigger. + */ + private Map clientMetadata; + + @Builder(setterPrefix = "with") + public Request(Map userAttributes, Map validationData, Map clientMetadata) { + super(userAttributes); + this.validationData = validationData; + this.clientMetadata = clientMetadata; + } + } + + @AllArgsConstructor + @Builder(setterPrefix = "with") + @Data + @NoArgsConstructor + public static class Response { + /** + * Set to true to auto-confirm the user, or false otherwise. + */ + private boolean autoConfirmUser; + + /** + * Set to true to set as verified the phone number of a user who is signing up, or false otherwise. + * If autoVerifyPhone is set to true, the phone_number attribute must have a valid, non-null value. + */ + private boolean autoVerifyPhone; + + /** + * Set to true to set as verified the email of a user who is signing up, or false otherwise. + * If autoVerifyEmail is set to true, the email attribute must have a valid, non-null value. + */ + private boolean autoVerifyEmail; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPreTokenGenerationEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPreTokenGenerationEvent.java new file mode 100644 index 000000000..e49ce3c40 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPreTokenGenerationEvent.java @@ -0,0 +1,125 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.*; + +import java.util.Map; + +/** + * Represent the class for the Cognito User Pool Pre Token Generation Lambda Trigger + * + * See Pre Token Generation Lambda Trigger + * + * @author jvdl + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@ToString(callSuper = true) +public class CognitoUserPoolPreTokenGenerationEvent extends CognitoUserPoolEvent { + /** + * The request from the Amazon Cognito service. + */ + private Request request; + + /** + * The response from your Lambda trigger. + */ + private Response response; + + @Builder(setterPrefix = "with") + public CognitoUserPoolPreTokenGenerationEvent( + String version, + String triggerSource, + String region, + String userPoolId, + String userName, + CallerContext callerContext, + Request request, + Response response) { + super(version, triggerSource, region, userPoolId, userName, callerContext); + this.request = request; + this.response = response; + } + + @Data + @EqualsAndHashCode(callSuper = true) + @NoArgsConstructor + @ToString(callSuper = true) + public static class Request extends CognitoUserPoolEvent.Request { + /** + * One or more key-value pairs that you can provide as custom input to the Lambda function that you specify for the pre token generation trigger. + */ + private Map clientMetadata; + + /** + * The input object containing the current group configuration. + */ + private GroupConfiguration groupConfiguration; + + @Builder(setterPrefix = "with") + public Request(Map userAttributes, Map clientMetadata, GroupConfiguration groupConfiguration) { + super(userAttributes); + this.clientMetadata = clientMetadata; + this.groupConfiguration = groupConfiguration; + } + } + + @Data + @AllArgsConstructor + @Builder(setterPrefix = "with") + @NoArgsConstructor + public static class GroupConfiguration { + /** + * A list of the group names that are associated with the user that the identity token is issued for. + */ + private String[] groupsToOverride; + /** + * A list of the current IAM roles associated with these groups. + */ + private String[] iamRolesToOverride; + /** + * Indicates the preferred IAM role. + */ + private String preferredRole; + } + + @Data + @AllArgsConstructor + @Builder(setterPrefix = "with") + @NoArgsConstructor + public static class Response { + private ClaimsOverrideDetails claimsOverrideDetails; + } + + @Data + @AllArgsConstructor + @Builder(setterPrefix = "with") + @NoArgsConstructor + public static class ClaimsOverrideDetails { + /** + * A map of one or more key-value pairs of claims to add or override. + * For group related claims, use groupOverrideDetails instead. + */ + private Map claimsToAddOrOverride; + /** + * A list that contains claims to be suppressed from the identity token. + */ + private String[] claimsToSuppress; + /** + * The output object containing the current group configuration. + */ + private GroupConfiguration groupOverrideDetails; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPreTokenGenerationEventV2.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPreTokenGenerationEventV2.java new file mode 100644 index 000000000..9faeb9704 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolPreTokenGenerationEventV2.java @@ -0,0 +1,134 @@ +/* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. */ + +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.util.Map; + +/** + * Represent the class for the Cognito User Pool Pre Token Generation Lambda Trigger V2 + *

+ * See Pre Token Generation Lambda Trigger + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@ToString(callSuper = true) +public class CognitoUserPoolPreTokenGenerationEventV2 extends CognitoUserPoolEvent { + /** + * The request from the Amazon Cognito service. + */ + private Request request; + + /** + * The response from your Lambda trigger. + */ + private Response response; + + @Builder(setterPrefix = "with") + public CognitoUserPoolPreTokenGenerationEventV2( + String version, + String triggerSource, + String region, + String userPoolId, + String userName, + CallerContext callerContext, + Request request, + Response response) { + super(version, triggerSource, region, userPoolId, userName, callerContext); + this.request = request; + this.response = response; + } + + @Data + @EqualsAndHashCode(callSuper = true) + @NoArgsConstructor + @ToString(callSuper = true) + public static class Request extends CognitoUserPoolEvent.Request { + + private String[] scopes; + private GroupConfiguration groupConfiguration; + private Map clientMetadata; + + @Builder(setterPrefix = "with") + public Request(Map userAttributes, String[] scopes, GroupConfiguration groupConfiguration, Map clientMetadata) { + super(userAttributes); + this.scopes = scopes; + this.groupConfiguration = groupConfiguration; + this.clientMetadata = clientMetadata; + } + } + + @Data + @AllArgsConstructor + @Builder(setterPrefix = "with") + @NoArgsConstructor + public static class GroupConfiguration { + /** + * A list of the group names that are associated with the user that the identity token is issued for. + */ + private String[] groupsToOverride; + /** + * A list of the current IAM roles associated with these groups. + */ + private String[] iamRolesToOverride; + /** + * Indicates the preferred IAM role. + */ + private String preferredRole; + } + + @Data + @AllArgsConstructor + @Builder(setterPrefix = "with") + @NoArgsConstructor + public static class Response { + private ClaimsAndScopeOverrideDetails claimsAndScopeOverrideDetails; + } + + @Data + @AllArgsConstructor + @Builder(setterPrefix = "with") + @NoArgsConstructor + public static class ClaimsAndScopeOverrideDetails { + private IdTokenGeneration idTokenGeneration; + private AccessTokenGeneration accessTokenGeneration; + private GroupOverrideDetails groupOverrideDetails; + } + + @Data + @AllArgsConstructor + @Builder(setterPrefix = "with") + @NoArgsConstructor + public static class IdTokenGeneration { + private Map claimsToAddOrOverride; + private String[] claimsToSuppress; + } + + @Data + @AllArgsConstructor + @Builder(setterPrefix = "with") + @NoArgsConstructor + public static class AccessTokenGeneration { + private Map claimsToAddOrOverride; + private String[] claimsToSuppress; + private String[] scopesToAdd; + private String[] scopesToSuppress; + } + + @Data + @AllArgsConstructor + @Builder(setterPrefix = "with") + @NoArgsConstructor + public static class GroupOverrideDetails { + private String[] groupsToOverride; + private String[] iamRolesToOverride; + private String preferredRole; + } +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolVerifyAuthChallengeResponseEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolVerifyAuthChallengeResponseEvent.java new file mode 100644 index 000000000..982ff72fd --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CognitoUserPoolVerifyAuthChallengeResponseEvent.java @@ -0,0 +1,102 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.*; + +import java.util.Map; + +/** + * Represent the class for the Cognito User Pool Verify Auth Challenge Response Lambda Trigger + * + * See Verify Auth Challenge Response Lambda Trigger + * + * @author jvdl + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@ToString(callSuper = true) +public class CognitoUserPoolVerifyAuthChallengeResponseEvent extends CognitoUserPoolEvent { + /** + * The request from the Amazon Cognito service. + */ + private Request request; + + /** + * The response from your Lambda trigger. + */ + private Response response; + + @Builder(setterPrefix = "with") + public CognitoUserPoolVerifyAuthChallengeResponseEvent( + String version, + String triggerSource, + String region, + String userPoolId, + String userName, + CallerContext callerContext, + Request request, + Response response) { + super(version, triggerSource, region, userPoolId, userName, callerContext); + this.request = request; + this.response = response; + } + + @Data + @EqualsAndHashCode(callSuper = true) + @NoArgsConstructor + @ToString(callSuper = true) + public static class Request extends CognitoUserPoolEvent.Request { + /** + * One or more key-value pairs that you can provide as custom input to the Lambda function that you specify for the verify auth challenge trigger. + */ + private Map clientMetadata; + /** + * This parameter comes from the Create Auth Challenge trigger, and is compared against a user's challengeAnswer to determine whether the user passed the challenge. + */ + private Map privateChallengeParameters; + /** + * The answer from the user's response to the challenge. + */ + private String challengeAnswer; + /** + * This boolean is populated when PreventUserExistenceErrors is set to ENABLED for your User Pool client + */ + private boolean userNotFound; + + @Builder(setterPrefix = "with") + public Request(Map userAttributes, + Map clientMetadata, + String challengeAnswer, + Map privateChallengeParameters, + boolean userNotFound) { + super(userAttributes); + this.clientMetadata = clientMetadata; + this.userNotFound = userNotFound; + this.challengeAnswer = challengeAnswer; + this.privateChallengeParameters = privateChallengeParameters; + } + } + + @AllArgsConstructor + @Builder(setterPrefix = "with") + @Data + @NoArgsConstructor + public static class Response { + /** + * Set to true if the user has successfully completed the challenge, or false otherwise. + */ + private boolean answerCorrect; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ConnectEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ConnectEvent.java new file mode 100644 index 000000000..e94875614 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ConnectEvent.java @@ -0,0 +1,92 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Map; + +/** + * Class to represent an Amazon Connect contact flow event. + * + * @see parameters; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class ContactData implements Serializable, Cloneable { + private Map attributes; + private String channel; + private String contactId; + private CustomerEndpoint customerEndpoint; + private String initialContactId; + private String initiationMethod; + private String instanceArn; + private String previousContactId; + private Queue queue; + private SystemEndpoint systemEndpoint; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class CustomerEndpoint implements Serializable, Cloneable { + private String address; + private String type; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class SystemEndpoint implements Serializable, Cloneable { + private String address; + private String type; + } + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Queue implements Serializable, Cloneable { + private String name; + private String ARN; + } + +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/DynamodbEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/DynamodbEvent.java index 6853e381d..353f587f0 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/DynamodbEvent.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/DynamodbEvent.java @@ -1,9 +1,17 @@ -/* Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. */ - +/* + * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ package com.amazonaws.services.lambda.runtime.events; -import com.amazonaws.services.dynamodbv2.model.Record; - import java.io.Serializable; import java.util.List; @@ -19,7 +27,7 @@ public class DynamodbEvent implements Serializable, Cloneable { /** * The unit of data of an Amazon DynamoDB event */ - public static class DynamodbStreamRecord extends Record { + public static class DynamodbStreamRecord extends com.amazonaws.services.lambda.runtime.events.models.dynamodb.Record { private static final long serialVersionUID = 3638381544604354963L; @@ -52,7 +60,7 @@ public void setEventSourceARN(String eventSourceARN) { * * @return A string representation of this object. * - * @see java.lang.Object#toString() + * @see Object#toString() */ @Override public String toString() { diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/DynamodbTimeWindowEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/DynamodbTimeWindowEvent.java new file mode 100644 index 000000000..64ed9fb29 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/DynamodbTimeWindowEvent.java @@ -0,0 +1,83 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ + +package com.amazonaws.services.lambda.runtime.events; + +import com.amazonaws.services.lambda.runtime.events.models.TimeWindow; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * Represents an Amazon Dynamodb event when using time windows. + */ +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class DynamodbTimeWindowEvent extends DynamodbEvent implements Serializable, Cloneable { + + private static final long serialVersionUID = -5449871161108629510L; + + /** + * Time window for the records in the event. + */ + private TimeWindow window; + + /** + * State being built up to this invoke in the time window. + */ + private Map state; + + /** + * Shard id of the records + */ + private String shardId; + + /** + * Dynamodb stream arn. + */ + private String eventSourceArn; + + /** + * Set to true for the last invoke of the time window. Subsequent invoke will start a new time window along with a fresh state. + */ + private Boolean isFinalInvokeForWindow; + + /** + * Set to true if window is terminated prematurely. Subsequent invoke will continue the same window with a fresh state. + */ + private Boolean isWindowTerminatedEarly; + + @Builder(setterPrefix = "with") + public DynamodbTimeWindowEvent( + final List records, + final TimeWindow window, + final Map state, + final String shardId, + final String eventSourceArn, + final Boolean isFinalInvokeForWindow, + final Boolean isWindowTerminatedEarly) { + this.setRecords(records); + this.window = window; + this.state = state; + this.shardId = shardId; + this.eventSourceArn = eventSourceArn; + this.isFinalInvokeForWindow = isFinalInvokeForWindow; + this.isWindowTerminatedEarly = isWindowTerminatedEarly; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java new file mode 100644 index 000000000..e8d3b13d9 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java @@ -0,0 +1,92 @@ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * The IAM Policy Response required for API Gateway HTTP APIs + * + * https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html + * + */ + +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class IamPolicyResponse implements Serializable, Cloneable { + + public static final String EXECUTE_API_INVOKE = "execute-api:Invoke"; + public static final String VERSION_2012_10_17 = "2012-10-17"; + public static final String ALLOW = "Allow"; + public static final String DENY = "Deny"; + + private String principalId; + private PolicyDocument policyDocument; + private Map context; + + public Map getPolicyDocument() { + Map serializablePolicy = new HashMap<>(); + serializablePolicy.put("Version", policyDocument.getVersion()); + + int numberOfStatements = policyDocument.getStatement().size(); + Map[] serializableStatementArray = new Map[numberOfStatements]; + for (int i = 0; i < numberOfStatements; i++) { + Statement statement = policyDocument.getStatement().get(i); + Map serializableStatement = new HashMap<>(); + serializableStatement.put("Effect", statement.getEffect()); + serializableStatement.put("Action", statement.getAction()); + serializableStatement.put("Resource", statement.getResource().toArray(new String[0])); + serializableStatement.put("Condition", statement.getCondition()); + serializableStatementArray[i] = serializableStatement; + } + serializablePolicy.put("Statement", serializableStatementArray); + return serializablePolicy; + } + + public static Statement allowStatement(String resource) { + return Statement.builder() + .withEffect(ALLOW) + .withResource(Collections.singletonList(resource)) + .withAction(EXECUTE_API_INVOKE) + .build(); + } + + public static Statement denyStatement(String resource) { + return Statement.builder() + .withEffect(DENY) + .withResource(Collections.singletonList(resource)) + .withAction(EXECUTE_API_INVOKE) + .build(); + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class PolicyDocument implements Serializable, Cloneable { + + private String version; + private List statement; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Statement implements Serializable, Cloneable { + + private String action; + private String effect; + private List resource; + private Map> condition; + } +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseV1.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseV1.java new file mode 100644 index 000000000..a4316536f --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseV1.java @@ -0,0 +1,93 @@ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * The IAM Policy Response required for API Gateway REST APIs + * + * https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html + * + */ + +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class IamPolicyResponseV1 implements Serializable, Cloneable { + + public static final String EXECUTE_API_INVOKE = "execute-api:Invoke"; + public static final String VERSION_2012_10_17 = "2012-10-17"; + public static final String ALLOW = "Allow"; + public static final String DENY = "Deny"; + + private String principalId; + private PolicyDocument policyDocument; + private Map context; + private String usageIdentifierKey; + + public Map getPolicyDocument() { + Map serializablePolicy = new HashMap<>(); + serializablePolicy.put("Version", policyDocument.getVersion()); + + int numberOfStatements = policyDocument.getStatement().size(); + Map[] serializableStatementArray = new Map[numberOfStatements]; + for (int i = 0; i < numberOfStatements; i++) { + Statement statement = policyDocument.getStatement().get(i); + Map serializableStatement = new HashMap<>(); + serializableStatement.put("Effect", statement.getEffect()); + serializableStatement.put("Action", statement.getAction()); + serializableStatement.put("Resource", statement.getResource().toArray(new String[0])); + serializableStatement.put("Condition", statement.getCondition()); + serializableStatementArray[i] = serializableStatement; + } + serializablePolicy.put("Statement", serializableStatementArray); + return serializablePolicy; + } + + public static Statement allowStatement(String resource) { + return Statement.builder() + .withEffect(ALLOW) + .withResource(Collections.singletonList(resource)) + .withAction(EXECUTE_API_INVOKE) + .build(); + } + + public static Statement denyStatement(String resource) { + return Statement.builder() + .withEffect(DENY) + .withResource(Collections.singletonList(resource)) + .withAction(EXECUTE_API_INVOKE) + .build(); + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class PolicyDocument implements Serializable, Cloneable { + + private String version; + private List statement; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Statement implements Serializable, Cloneable { + + private String action; + private String effect; + private List resource; + private Map> condition; + } +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/KafkaEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/KafkaEvent.java new file mode 100644 index 000000000..aa6c00de3 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/KafkaEvent.java @@ -0,0 +1,73 @@ +/* + * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import java.util.List; +import java.util.Map; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder(setterPrefix = "with") +/** Represents a Kafka Event. **/ +public class KafkaEvent { + private Map> records; + private String eventSource; + private String eventSourceArn; + private String bootstrapServers; + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder(setterPrefix = "with") + public static class KafkaEventRecord { + private String topic; + private int partition; + private long offset; + private long timestamp; + private String timestampType; + private String key; + private String value; + private List> headers; + private SchemaMetadata keySchemaMetadata; + private SchemaMetadata valueSchemaMetadata; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder(setterPrefix = "with") + public static class TopicPartition { + private String topic; + private int partition; + + @Override + public String toString() { + //Kafka also uses '-' for toString() + return topic + "-" + partition; + } + } + + @Data + @AllArgsConstructor + @NoArgsConstructor + @Builder(setterPrefix = "with") + public static class SchemaMetadata { + private String schemaId; + private String dataFormat; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/KinesisEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/KinesisEvent.java index 6d1e53000..cce378035 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/KinesisEvent.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/KinesisEvent.java @@ -1,6 +1,17 @@ -/* Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. */ - +/* + * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ package com.amazonaws.services.lambda.runtime.events; + import java.io.Serializable; import java.util.List; @@ -16,7 +27,7 @@ public class KinesisEvent implements Serializable, Cloneable { /** * The unit of data of an Amazon Kinesis stream */ - public static class Record extends com.amazonaws.services.kinesis.model.Record { + public static class Record extends com.amazonaws.services.lambda.runtime.events.models.kinesis.Record { private static final long serialVersionUID = 7856672931457425976L; @@ -49,7 +60,7 @@ public void setKinesisSchemaVersion(String kinesisSchemaVersion) { * * @return A string representation of this object. * - * @see java.lang.Object#toString() + * @see Object#toString() */ @Override public String toString() { @@ -109,7 +120,7 @@ public boolean equals(Object obj) { } /* (non-Javadoc) - * @see com.amazonaws.services.kinesis.model.Record#hashCode() + * @see com.amazonaws.services.lambda.runtime.events.models.kinesis.Record#hashCode() */ @Override public int hashCode() { @@ -288,7 +299,7 @@ public void setAwsRegion(String awsRegion) { * * @return A string representation of this object. * - * @see java.lang.Object#toString() + * @see Object#toString() */ @Override public String toString() { @@ -305,7 +316,7 @@ public String toString() { if (getEventName() != null) sb.append("eventName: ").append(getEventName()).append(","); if (getEventVersion() != null) - sb.append("eventSourceARN: ").append(getEventSourceARN()).append(","); + sb.append("eventVersion: ").append(getEventVersion()).append(","); if (getEventSourceARN() != null) sb.append("eventSourceARN: ").append(getEventSourceARN()).append(","); if (getAwsRegion() != null) @@ -413,7 +424,7 @@ public void setRecords(List records) { * * @return A string representation of this object. * - * @see java.lang.Object#toString() + * @see Object#toString() */ @Override public String toString() { diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/KinesisTimeWindowEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/KinesisTimeWindowEvent.java new file mode 100644 index 000000000..f5e982a1b --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/KinesisTimeWindowEvent.java @@ -0,0 +1,83 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ + +package com.amazonaws.services.lambda.runtime.events; + +import com.amazonaws.services.lambda.runtime.events.models.TimeWindow; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * Represents an Amazon Kinesis event when using time windows. + */ +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class KinesisTimeWindowEvent extends KinesisEvent implements Serializable, Cloneable { + + private static final long serialVersionUID = 8926430039233062266L; + + /** + * Time window for the records in the event. + */ + private TimeWindow window; + + /** + * State being built up to this invoke in the time window. + */ + private Map state; + + /** + * Shard id of the records + */ + private String shardId; + + /** + * Kinesis stream or consumer arn. + */ + private String eventSourceArn; + + /** + * Set to true for the last invoke of the time window. Subsequent invoke will start a new time window along with a fresh state. + */ + private Boolean isFinalInvokeForWindow; + + /** + * Set to true if window is terminated prematurely. Subsequent invoke will continue the same window with a fresh state. + */ + private Boolean isWindowTerminatedEarly; + + @Builder(setterPrefix = "with") + public KinesisTimeWindowEvent( + final List records, + final TimeWindow window, + final Map state, + final String shardId, + final String eventSourceArn, + final Boolean isFinalInvokeForWindow, + final Boolean isWindowTerminatedEarly) { + this.setRecords(records); + this.window = window; + this.state = state; + this.shardId = shardId; + this.eventSourceArn = eventSourceArn; + this.isFinalInvokeForWindow = isFinalInvokeForWindow; + this.isWindowTerminatedEarly = isWindowTerminatedEarly; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/LambdaDestinationEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/LambdaDestinationEvent.java new file mode 100644 index 000000000..eaa4611fc --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/LambdaDestinationEvent.java @@ -0,0 +1,55 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.joda.time.DateTime; + +import java.io.Serializable; +import java.util.Map; + +/** + * Class to represent an invocation record for a Lambda event. + * + * @see requestPayload; + private Object responseContext; + private Object responsePayload; + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class RequestContext implements Serializable, Cloneable { + private String requestId; + private String functionArn; + private String condition; + private int approximateInvokeCount; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/MSKFirehoseEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/MSKFirehoseEvent.java new file mode 100644 index 000000000..1af40ce43 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/MSKFirehoseEvent.java @@ -0,0 +1,51 @@ +/* +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package com.amazonaws.services.lambda.runtime.events; + +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Map; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor + +public class MSKFirehoseEvent { + + private String invocationId; + + private String deliveryStreamArn; + + private String sourceMSKArn; + + private String region; + + private List records; + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Record { + + private ByteBuffer kafkaRecordValue; + + private String recordId; + + private Long approximateArrivalEpoch; + + private Long approximateArrivalTimestamp; + + private Map mskRecordMetadata; + + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/MSKFirehoseResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/MSKFirehoseResponse.java new file mode 100644 index 000000000..18b5aa13f --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/MSKFirehoseResponse.java @@ -0,0 +1,61 @@ +/* +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package com.amazonaws.services.lambda.runtime.events; + +import java.nio.ByteBuffer; +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Response model for Amazon Data Firehose Lambda transformation with MSK as a source. + * [+] Amazon Data Firehose Data Transformation - Data Transformation and Status Model - ... + * OK : Indicates that processing of this item succeeded. + * ProcessingFailed : Indicate that the processing of this item failed. + * Dropped : Indicates that this item should be silently dropped + */ + +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor + +public class MSKFirehoseResponse { + + public enum Result { + + /** + * Indicates that processing of this item succeeded. + */ + Ok, + + /** + * Indicate that the processing of this item failed + */ + ProcessingFailed, + + /** + * Indicates that this item should be silently dropped + */ + Dropped + } + public List records; + + @Data + @NoArgsConstructor + @Builder(setterPrefix = "with") + @AllArgsConstructor + + public static class Record { + public String recordId; + public Result result; + public ByteBuffer kafkaRecordValue; + + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/RabbitMQEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/RabbitMQEvent.java new file mode 100644 index 000000000..24fe946c5 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/RabbitMQEvent.java @@ -0,0 +1,57 @@ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +/** + * Represents a Rabbit MQ event sent to Lambda + * Onboarding Amazon MQ as event source to Lambda + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder(setterPrefix = "with") +public class RabbitMQEvent { + + private String eventSource; + private String eventSourceArn; + private Map> rmqMessagesByQueue; + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder(setterPrefix = "with") + public static class RabbitMessage { + private BasicProperties basicProperties; + private boolean redelivered; + private String data; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder(setterPrefix = "with") + public static class BasicProperties { + + private String contentType; + private String contentEncoding; + private Map headers; + private int deliveryMode; + private int priority; + private String correlationId; + private String replyTo; + private int expiration; + private String messageId; + private String timestamp; + private String type; + private String userId; + private String appId; + private String clusterId; + private int bodySize; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3BatchEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3BatchEvent.java new file mode 100644 index 000000000..a3e8d682b --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3BatchEvent.java @@ -0,0 +1,48 @@ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * Event to represent the payload which is sent to Lambda by S3 Batch to perform a custom + * action. + * + * https://docs.aws.amazon.com/AmazonS3/latest/dev/batch-ops-invoke-lambda.html + */ + +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class S3BatchEvent { + + private String invocationSchemaVersion; + private String invocationId; + private Job job; + private List tasks; + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Job { + + private String id; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Task { + + private String taskId; + private String s3Key; + private String s3VersionId; + private String s3BucketArn; + } +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3BatchEventV2.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3BatchEventV2.java new file mode 100644 index 000000000..e9beb1f41 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3BatchEventV2.java @@ -0,0 +1,50 @@ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +/** + * Event to represent the payload which is sent to Lambda by S3 Batch to perform a custom + * action when using invocation schema version 2.0. + * + * https://docs.aws.amazon.com/AmazonS3/latest/dev/batch-ops-invoke-lambda.html + */ + +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class S3BatchEventV2 { + + private String invocationSchemaVersion; + private String invocationId; + private Job job; + private List tasks; + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Job { + + private String id; + private Map userArguments; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Task { + + private String taskId; + private String s3Key; + private String s3VersionId; + private String s3Bucket; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3BatchResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3BatchResponse.java new file mode 100644 index 000000000..d584a31dd --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3BatchResponse.java @@ -0,0 +1,71 @@ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * Event to represent the response which should be returned as part of a S3 Batch custom + * action. + * + * https://docs.aws.amazon.com/AmazonS3/latest/dev/batch-ops-invoke-lambda.html + */ + +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class S3BatchResponse { + + private String invocationSchemaVersion; + private ResultCode treatMissingKeysAs; + private String invocationId; + private List results; + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Result { + + private String taskId; + private ResultCode resultCode; + private String resultString; + } + + public enum ResultCode { + + /** + * The task completed normally. If you requested a job completion report, + * the task's result string is included in the report. + */ + Succeeded, + /** + * The task suffered a temporary failure and will be redriven before the job + * completes. The result string is ignored. If this is the final redrive, + * the error message is included in the final report. + */ + TemporaryFailure, + /** + * The task suffered a permanent failure. If you requested a job-completion + * report, the task is marked as Failed and includes the error message + * string. Result strings from failed tasks are ignored. + */ + PermanentFailure + } + + public static S3BatchResponseBuilder fromS3BatchEvent(S3BatchEvent s3BatchEvent) { + return S3BatchResponse.builder() + .withInvocationId(s3BatchEvent.getInvocationId()) + .withInvocationSchemaVersion(s3BatchEvent.getInvocationSchemaVersion()); + } + + public static S3BatchResponseBuilder fromS3BatchEvent(S3BatchEventV2 s3BatchEvent) { + return S3BatchResponse.builder() + .withInvocationId(s3BatchEvent.getInvocationId()) + .withInvocationSchemaVersion(s3BatchEvent.getInvocationSchemaVersion()); + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3Event.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3Event.java index c1a83ee0f..a51acf7c0 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3Event.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3Event.java @@ -1,8 +1,18 @@ -/* Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. */ - +/* + * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ package com.amazonaws.services.lambda.runtime.events; -import com.amazonaws.services.s3.event.S3EventNotification; +import com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification; import java.io.Serializable; import java.util.ArrayList; @@ -28,7 +38,7 @@ public S3Event() { * Create a new instance of S3Event * @param records A list of S3 event notification records */ - public S3Event(List records) { + public S3Event(List records) { super(records); } diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3ObjectLambdaEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3ObjectLambdaEvent.java new file mode 100644 index 000000000..35c836381 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/S3ObjectLambdaEvent.java @@ -0,0 +1,136 @@ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Map; + +/** + * Event to allow transformations to occur before an S3 object is returned to the calling service. + * + * Documentation + * + * Writing and debugging Lambda functions for S3 Object Lambda Access Points + * + * Example: + * + *

+ * import com.amazonaws.services.lambda.runtime.Context;
+ * import com.amazonaws.services.lambda.runtime.events.S3ObjectLambdaEvent;
+ * import org.apache.http.client.fluent.Request;
+ * import software.amazon.awssdk.services.s3.S3Client;
+ * import software.amazon.awssdk.services.s3.model.WriteGetObjectResponseRequest;
+ *
+ * import java.io.IOException;
+ *
+ * import static software.amazon.awssdk.core.sync.RequestBody.fromString;
+ *
+ * public class S3ObjectRequestHandler {
+ *
+ *      private static final S3Client s3Client = S3Client.create();
+ *
+ *      public void handleRequest(S3ObjectLambdaEvent event, Context context) throws IOException {
+ *          String s3Body = Request.Get(event.inputS3Url()).execute().returnContent().asString();
+ *
+ *          String responseBody = s3Body.toUpperCase();
+ *
+ *          WriteGetObjectResponseRequest request = WriteGetObjectResponseRequest.builder()
+ *              .requestRoute(event.outputRoute())
+ *              .requestToken(event.outputToken())
+ *              .build();
+ *          s3Client.writeGetObjectResponse(request, fromString(responseBody));
+ *      }
+ * }
+ * 
+ * 
+ */ + +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class S3ObjectLambdaEvent { + + private String xAmzRequestId; + private GetObjectContext getObjectContext; + private Configuration configuration; + private UserRequest userRequest; + private UserIdentity userIdentity; + private String protocolVersion; + + /** + * A pre-signed URL that can be used to fetch the original object from Amazon S3. + * + * The URL is signed using the original caller's identity, and their permissions + * will apply when the URL is used. If there are signed headers in the URL, the + * Lambda function must include these in the call to Amazon S3, except for the Host. + * + * @return A pre-signed URL that can be used to fetch the original object from Amazon S3. + */ + public String inputS3Url() { + return getGetObjectContext().getInputS3Url(); + } + + /** + * A routing token that is added to the S3 Object Lambda URL when the Lambda function + * calls the S3 API WriteGetObjectResponse. + * + * @return the outputRoute + */ + public String outputRoute() { + return getGetObjectContext().getOutputRoute(); + } + + /** + * An opaque token used by S3 Object Lambda to match the WriteGetObjectResponse call + * with the original caller. + * + * @return the outputToken + */ + public String outputToken() { + return getGetObjectContext().getOutputToken(); + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class GetObjectContext { + private String inputS3Url; + private String outputRoute; + private String outputToken; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Configuration { + private String accessPointArn; + private String supportingAccessPointArn; + private String payload; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class UserRequest { + private String url; + private Map headers; + } + + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class UserIdentity { + private String type; + private String principalId; + private String arn; + private String accountId; + private String accessKeyId; + } +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/SQSBatchResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/SQSBatchResponse.java new file mode 100644 index 000000000..c1f728f1b --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/SQSBatchResponse.java @@ -0,0 +1,53 @@ +/* + * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ + +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * Function response type to report batch item failures for {@link SQSEvent}. + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder(setterPrefix = "with") +public class SQSBatchResponse implements Serializable { + + private static final long serialVersionUID = 5075170615239078773L; + + /** + * A list of messageIds that failed processing. These messageIds will be retried. + */ + private List batchItemFailures; + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder(setterPrefix = "with") + public static class BatchItemFailure implements Serializable { + + private static final long serialVersionUID = 40727862494377907L; + + /** + * MessageId that failed processing + */ + String itemIdentifier; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ScheduledEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ScheduledEvent.java index 5908c39c3..405ede583 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ScheduledEvent.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ScheduledEvent.java @@ -26,6 +26,8 @@ public class ScheduledEvent implements Serializable, Cloneable { private static final long serialVersionUID = -5810383198587331146L; + private String version; + private String account; private String region; @@ -47,6 +49,29 @@ public class ScheduledEvent implements Serializable, Cloneable { */ public ScheduledEvent() {} + /** + * @return the version number + */ + public String getVersion() { + return version; + } + + /** + * @param version the version number + */ + public void setVersion(String version) { + this.version = version; + } + + /** + * @param version version number + * @return ScheduledEvent + */ + public ScheduledEvent withVersion(String version) { + setVersion(version); + return this; + } + /** * @return the account id */ @@ -69,7 +94,7 @@ public ScheduledEvent withAccount(String account) { setAccount(account); return this; } - + /** * @return the aws region */ @@ -92,7 +117,7 @@ public ScheduledEvent withRegion(String region) { setRegion(region); return this; } - + /** * @return The details of the events (usually left blank) */ @@ -115,7 +140,7 @@ public ScheduledEvent withDetail(Map detail) { setDetail(detail); return this; } - + /** * @return The details type - see cloud watch events for more info */ @@ -138,19 +163,19 @@ public ScheduledEvent withDetailType(String detailType) { setDetailType(detailType); return this; } - + /** - * @return the soruce of the event + * @return the source of the event */ public String getSource() { return source; } /** - * @param soruce the soruce of the event + * @param source the source of the event */ - public void setSource(String soruce) { - this.source = soruce; + public void setSource(String source) { + this.source = source; } /** @@ -161,7 +186,7 @@ public ScheduledEvent withSource(String source) { setSource(source); return this; } - + /** * @return the timestamp for when the event is scheduled */ @@ -184,7 +209,7 @@ public ScheduledEvent withTime(DateTime time) { setTime(time); return this; } - + /** * @return the id of the event */ @@ -207,7 +232,7 @@ public ScheduledEvent withId(String id) { setId(id); return this; } - + /** * @return the resources used by event */ @@ -242,6 +267,8 @@ public ScheduledEvent withResources(List resources) { public String toString() { StringBuilder sb = new StringBuilder(); sb.append("{"); + if (getVersion() != null) + sb.append("version: ").append(getVersion()).append(","); if (getAccount() != null) sb.append("account: ").append(getAccount()).append(","); if (getRegion() != null) @@ -272,6 +299,10 @@ public boolean equals(Object obj) { if (obj instanceof ScheduledEvent == false) return false; ScheduledEvent other = (ScheduledEvent) obj; + if (other.getVersion() == null ^ this.getVersion() == null) + return false; + if (other.getVersion() != null && other.getVersion().equals(this.getVersion()) == false) + return false; if (other.getAccount() == null ^ this.getAccount() == null) return false; if (other.getAccount() != null && other.getAccount().equals(this.getAccount()) == false) @@ -312,6 +343,7 @@ public int hashCode() { final int prime = 31; int hashCode = 1; + hashCode = prime * hashCode + ((getVersion() == null) ? 0 : getVersion().hashCode()); hashCode = prime * hashCode + ((getAccount() == null) ? 0 : getAccount().hashCode()); hashCode = prime * hashCode + ((getRegion() == null) ? 0 : getRegion().hashCode()); hashCode = prime * hashCode + ((getDetail() == null) ? 0 : getDetail().hashCode()); @@ -331,5 +363,5 @@ public ScheduledEvent clone() { throw new IllegalStateException("Got a CloneNotSupportedException from Object.clone()", e); } } - + } diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/SecretsManagerRotationEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/SecretsManagerRotationEvent.java new file mode 100644 index 000000000..3e8df5bce --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/SecretsManagerRotationEvent.java @@ -0,0 +1,40 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ + +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Class to represent the events which are sent during a Secrets Manager rotation process. + * + * @see Rotating secrets lambda function overview + * + * @author msailes + */ + +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class SecretsManagerRotationEvent { + + private String step; + private String secretId; + private String clientRequestToken; + private String rotationToken; + +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/SimpleIAMPolicyResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/SimpleIAMPolicyResponse.java new file mode 100644 index 000000000..030a1468d --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/SimpleIAMPolicyResponse.java @@ -0,0 +1,23 @@ +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Map; + +/** + * The simplified IAM Policy response object as described in https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html + * + */ + +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class SimpleIAMPolicyResponse { + + private boolean isAuthorized; + private Map context; +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/StreamsEventResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/StreamsEventResponse.java new file mode 100644 index 000000000..9d2990f9d --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/StreamsEventResponse.java @@ -0,0 +1,52 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ + +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * Function response type to report batch item failures for {@link KinesisEvent} and {@link DynamodbEvent}. + * https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html#services-kinesis-batchfailurereporting + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder(setterPrefix = "with") +public class StreamsEventResponse implements Serializable { + private static final long serialVersionUID = 3232053116472095907L; + + /** + * A list of records which failed processing. Returning the first record which failed would retry all remaining records from the batch. + */ + private List batchItemFailures; + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder(setterPrefix = "with") + public static class BatchItemFailure implements Serializable { + private static final long serialVersionUID = 1473983466096085881L; + + /** + * Sequence number of the record which failed processing. + */ + String itemIdentifier; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/TimeWindowEventResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/TimeWindowEventResponse.java new file mode 100644 index 000000000..8d1440757 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/TimeWindowEventResponse.java @@ -0,0 +1,58 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ + +package com.amazonaws.services.lambda.runtime.events; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * Response type to return a new state for the time window and to report batch item failures. This should be used along with {@link KinesisTimeWindowEvent} or {@link DynamodbTimeWindowEvent}. + * https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html#services-kinesis-windows + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder(setterPrefix = "with") +public class TimeWindowEventResponse implements Serializable { + private static final long serialVersionUID = 2259096191791166028L; + + /** + * New state after processing a batch of records. + */ + private Map state; + + /** + * A list of records which failed processing. Returning the first record which failed would retry all remaining records from the batch. + */ + private List batchItemFailures; + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder(setterPrefix = "with") + public static class BatchItemFailure implements Serializable { + private static final long serialVersionUID = 5224634072234167773L; + + /** + * Sequence number of the record which failed processing. + */ + String itemIdentifier; + } +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/TimeWindow.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/TimeWindow.java new file mode 100644 index 000000000..77d0452fa --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/TimeWindow.java @@ -0,0 +1,39 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ + +package com.amazonaws.services.lambda.runtime.events.models; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Represents a time window. + */ +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class TimeWindow { + + /** + * Window start instant represented as ISO-8601 string. + */ + private String start; + + /** + * Window end instant represented as ISO-8601 string. + */ + private String end; +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/dynamodb/AttributeValue.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/dynamodb/AttributeValue.java new file mode 100644 index 000000000..555b42f81 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/dynamodb/AttributeValue.java @@ -0,0 +1,1111 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events.models.dynamodb; + +import java.io.Serializable; + +/** + *

+ * Represents the data for an attribute. + *

+ *

+ * Each attribute value is described as a name-value pair. The name is the data type, and the value is the data itself. + *

+ *

+ * For more information, see Data Types in the Amazon DynamoDB Developer Guide. + *

+ * + * @see AWS API + * Documentation + */ +public class AttributeValue implements Serializable, Cloneable { + + /** + *

+ * An attribute of type String. For example: + *

+ *

+ * "S": "Hello" + *

+ */ + private String s; + /** + *

+ * An attribute of type Number. For example: + *

+ *

+ * "N": "123.45" + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and + * libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + *

+ */ + private String n; + /** + *

+ * An attribute of type Binary. For example: + *

+ *

+ * "B": "dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk" + *

+ */ + private java.nio.ByteBuffer b; + /** + *

+ * An attribute of type String Set. For example: + *

+ *

+ * "SS": ["Giraffe", "Hippo" ,"Zebra"] + *

+ */ + private java.util.List sS; + /** + *

+ * An attribute of type Number Set. For example: + *

+ *

+ * "NS": ["42.2", "-19", "7.5", "3.14"] + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and + * libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + *

+ */ + private java.util.List nS; + /** + *

+ * An attribute of type Binary Set. For example: + *

+ *

+ * "BS": ["U3Vubnk=", "UmFpbnk=", "U25vd3k="] + *

+ */ + private java.util.List bS; + /** + *

+ * An attribute of type Map. For example: + *

+ *

+ * "M": {"Name": {"S": "Joe"}, "Age": {"N": "35"}} + *

+ */ + private java.util.Map m; + /** + *

+ * An attribute of type List. For example: + *

+ *

+ * "L": [ {"S": "Cookies"} , {"S": "Coffee"}, {"N", "3.14159"}] + *

+ */ + private java.util.List l; + /** + *

+ * An attribute of type Null. For example: + *

+ *

+ * "NULL": true + *

+ */ + private Boolean nULLValue; + /** + *

+ * An attribute of type Boolean. For example: + *

+ *

+ * "BOOL": true + *

+ */ + private Boolean bOOL; + + /** + * Default constructor for DynamodbAttributeValue object. Callers should use the setter or fluent setter (with...) methods + * to initialize the object after creating it. + */ + public AttributeValue() { + } + + /** + * Constructs a new DynamodbAttributeValue object. Callers should use the setter or fluent setter (with...) methods to + * initialize any additional object members. + * + * @param s + * An attribute of type String. For example:

+ *

+ * "S": "Hello" + */ + public AttributeValue(String s) { + setS(s); + } + + /** + * Constructs a new DynamodbAttributeValue object. Callers should use the setter or fluent setter (with...) methods to + * initialize any additional object members. + * + * @param sS + * An attribute of type String Set. For example:

+ *

+ * "SS": ["Giraffe", "Hippo" ,"Zebra"] + */ + public AttributeValue(java.util.List sS) { + setSS(sS); + } + + /** + *

+ * An attribute of type String. For example: + *

+ *

+ * "S": "Hello" + *

+ * + * @param s + * An attribute of type String. For example:

+ *

+ * "S": "Hello" + */ + + public void setS(String s) { + this.s = s; + } + + /** + *

+ * An attribute of type String. For example: + *

+ *

+ * "S": "Hello" + *

+ * + * @return An attribute of type String. For example:

+ *

+ * "S": "Hello" + */ + + public String getS() { + return this.s; + } + + /** + *

+ * An attribute of type String. For example: + *

+ *

+ * "S": "Hello" + *

+ * + * @param s + * An attribute of type String. For example:

+ *

+ * "S": "Hello" + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue withS(String s) { + setS(s); + return this; + } + + /** + *

+ * An attribute of type Number. For example: + *

+ *

+ * "N": "123.45" + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and + * libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + *

+ * + * @param n + * An attribute of type Number. For example:

+ *

+ * "N": "123.45" + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and + * libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + */ + + public void setN(String n) { + this.n = n; + } + + /** + *

+ * An attribute of type Number. For example: + *

+ *

+ * "N": "123.45" + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and + * libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + *

+ * + * @return An attribute of type Number. For example:

+ *

+ * "N": "123.45" + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages + * and libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + */ + + public String getN() { + return this.n; + } + + /** + *

+ * An attribute of type Number. For example: + *

+ *

+ * "N": "123.45" + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and + * libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + *

+ * + * @param n + * An attribute of type Number. For example:

+ *

+ * "N": "123.45" + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and + * libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue withN(String n) { + setN(n); + return this; + } + + /** + *

+ * An attribute of type Binary. For example: + *

+ *

+ * "B": "dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk" + *

+ *

+ * The AWS SDK for Java performs a Base64 encoding on this field before sending this request to the AWS service. + * Users of the SDK should not perform Base64 encoding on this field. + *

+ *

+ * Warning: ByteBuffers returned by the SDK are mutable. Changes to the content or position of the byte buffer will + * be seen by all objects that have a reference to this object. It is recommended to call ByteBuffer.duplicate() or + * ByteBuffer.asReadOnlyBuffer() before using or reading from the buffer. This behavior will be changed in a future + * major version of the SDK. + *

+ * + * @param b + * An attribute of type Binary. For example:

+ *

+ * "B": "dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk" + */ + + public void setB(java.nio.ByteBuffer b) { + this.b = b; + } + + /** + *

+ * An attribute of type Binary. For example: + *

+ *

+ * "B": "dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk" + *

+ *

+ * {@code ByteBuffer}s are stateful. Calling their {@code get} methods changes their {@code position}. We recommend + * using {@link java.nio.ByteBuffer#asReadOnlyBuffer()} to create a read-only view of the buffer with an independent + * {@code position}, and calling {@code get} methods on this rather than directly on the returned {@code ByteBuffer}. + * Doing so will ensure that anyone else using the {@code ByteBuffer} will not be affected by changes to the + * {@code position}. + *

+ * + * @return An attribute of type Binary. For example:

+ *

+ * "B": "dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk" + */ + + public java.nio.ByteBuffer getB() { + return this.b; + } + + /** + *

+ * An attribute of type Binary. For example: + *

+ *

+ * "B": "dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk" + *

+ *

+ * The AWS SDK for Java performs a Base64 encoding on this field before sending this request to the AWS service. + * Users of the SDK should not perform Base64 encoding on this field. + *

+ *

+ * Warning: ByteBuffers returned by the SDK are mutable. Changes to the content or position of the byte buffer will + * be seen by all objects that have a reference to this object. It is recommended to call ByteBuffer.duplicate() or + * ByteBuffer.asReadOnlyBuffer() before using or reading from the buffer. This behavior will be changed in a future + * major version of the SDK. + *

+ * + * @param b + * An attribute of type Binary. For example:

+ *

+ * "B": "dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk" + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue withB(java.nio.ByteBuffer b) { + setB(b); + return this; + } + + /** + *

+ * An attribute of type String Set. For example: + *

+ *

+ * "SS": ["Giraffe", "Hippo" ,"Zebra"] + *

+ * + * @return An attribute of type String Set. For example:

+ *

+ * "SS": ["Giraffe", "Hippo" ,"Zebra"] + */ + + public java.util.List getSS() { + return sS; + } + + /** + *

+ * An attribute of type String Set. For example: + *

+ *

+ * "SS": ["Giraffe", "Hippo" ,"Zebra"] + *

+ * + * @param sS + * An attribute of type String Set. For example:

+ *

+ * "SS": ["Giraffe", "Hippo" ,"Zebra"] + */ + + public void setSS(java.util.Collection sS) { + if (sS == null) { + this.sS = null; + return; + } + + this.sS = new java.util.ArrayList(sS); + } + + /** + *

+ * An attribute of type String Set. For example: + *

+ *

+ * "SS": ["Giraffe", "Hippo" ,"Zebra"] + *

+ *

+ * NOTE: This method appends the values to the existing list (if any). Use + * {@link #setSS(java.util.Collection)} or {@link #withSS(java.util.Collection)} if you want to override the + * existing values. + *

+ * + * @param sS + * An attribute of type String Set. For example:

+ *

+ * "SS": ["Giraffe", "Hippo" ,"Zebra"] + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue withSS(String... sS) { + if (this.sS == null) { + setSS(new java.util.ArrayList(sS.length)); + } + for (String ele : sS) { + this.sS.add(ele); + } + return this; + } + + /** + *

+ * An attribute of type String Set. For example: + *

+ *

+ * "SS": ["Giraffe", "Hippo" ,"Zebra"] + *

+ * + * @param sS + * An attribute of type String Set. For example:

+ *

+ * "SS": ["Giraffe", "Hippo" ,"Zebra"] + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue withSS(java.util.Collection sS) { + setSS(sS); + return this; + } + + /** + *

+ * An attribute of type Number Set. For example: + *

+ *

+ * "NS": ["42.2", "-19", "7.5", "3.14"] + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and + * libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + *

+ * + * @return An attribute of type Number Set. For example:

+ *

+ * "NS": ["42.2", "-19", "7.5", "3.14"] + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages + * and libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + */ + + public java.util.List getNS() { + return nS; + } + + /** + *

+ * An attribute of type Number Set. For example: + *

+ *

+ * "NS": ["42.2", "-19", "7.5", "3.14"] + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and + * libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + *

+ * + * @param nS + * An attribute of type Number Set. For example:

+ *

+ * "NS": ["42.2", "-19", "7.5", "3.14"] + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and + * libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + */ + + public void setNS(java.util.Collection nS) { + if (nS == null) { + this.nS = null; + return; + } + + this.nS = new java.util.ArrayList(nS); + } + + /** + *

+ * An attribute of type Number Set. For example: + *

+ *

+ * "NS": ["42.2", "-19", "7.5", "3.14"] + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and + * libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + *

+ *

+ * NOTE: This method appends the values to the existing list (if any). Use + * {@link #setNS(java.util.Collection)} or {@link #withNS(java.util.Collection)} if you want to override the + * existing values. + *

+ * + * @param nS + * An attribute of type Number Set. For example:

+ *

+ * "NS": ["42.2", "-19", "7.5", "3.14"] + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and + * libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue withNS(String... nS) { + if (this.nS == null) { + setNS(new java.util.ArrayList(nS.length)); + } + for (String ele : nS) { + this.nS.add(ele); + } + return this; + } + + /** + *

+ * An attribute of type Number Set. For example: + *

+ *

+ * "NS": ["42.2", "-19", "7.5", "3.14"] + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and + * libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + *

+ * + * @param nS + * An attribute of type Number Set. For example:

+ *

+ * "NS": ["42.2", "-19", "7.5", "3.14"] + *

+ *

+ * Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and + * libraries. However, DynamoDB treats them as number type attributes for mathematical operations. + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue withNS(java.util.Collection nS) { + setNS(nS); + return this; + } + + /** + *

+ * An attribute of type Binary Set. For example: + *

+ *

+ * "BS": ["U3Vubnk=", "UmFpbnk=", "U25vd3k="] + *

+ * + * @return An attribute of type Binary Set. For example:

+ *

+ * "BS": ["U3Vubnk=", "UmFpbnk=", "U25vd3k="] + */ + + public java.util.List getBS() { + return bS; + } + + /** + *

+ * An attribute of type Binary Set. For example: + *

+ *

+ * "BS": ["U3Vubnk=", "UmFpbnk=", "U25vd3k="] + *

+ * + * @param bS + * An attribute of type Binary Set. For example:

+ *

+ * "BS": ["U3Vubnk=", "UmFpbnk=", "U25vd3k="] + */ + + public void setBS(java.util.Collection bS) { + if (bS == null) { + this.bS = null; + return; + } + + this.bS = new java.util.ArrayList(bS); + } + + /** + *

+ * An attribute of type Binary Set. For example: + *

+ *

+ * "BS": ["U3Vubnk=", "UmFpbnk=", "U25vd3k="] + *

+ *

+ * NOTE: This method appends the values to the existing list (if any). Use + * {@link #setBS(java.util.Collection)} or {@link #withBS(java.util.Collection)} if you want to override the + * existing values. + *

+ * + * @param bS + * An attribute of type Binary Set. For example:

+ *

+ * "BS": ["U3Vubnk=", "UmFpbnk=", "U25vd3k="] + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue withBS(java.nio.ByteBuffer... bS) { + if (this.bS == null) { + setBS(new java.util.ArrayList(bS.length)); + } + for (java.nio.ByteBuffer ele : bS) { + this.bS.add(ele); + } + return this; + } + + /** + *

+ * An attribute of type Binary Set. For example: + *

+ *

+ * "BS": ["U3Vubnk=", "UmFpbnk=", "U25vd3k="] + *

+ * + * @param bS + * An attribute of type Binary Set. For example:

+ *

+ * "BS": ["U3Vubnk=", "UmFpbnk=", "U25vd3k="] + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue withBS(java.util.Collection bS) { + setBS(bS); + return this; + } + + /** + *

+ * An attribute of type Map. For example: + *

+ *

+ * "M": {"Name": {"S": "Joe"}, "Age": {"N": "35"}} + *

+ * + * @return An attribute of type Map. For example:

+ *

+ * "M": {"Name": {"S": "Joe"}, "Age": {"N": "35"}} + */ + + public java.util.Map getM() { + return m; + } + + /** + *

+ * An attribute of type Map. For example: + *

+ *

+ * "M": {"Name": {"S": "Joe"}, "Age": {"N": "35"}} + *

+ * + * @param m + * An attribute of type Map. For example:

+ *

+ * "M": {"Name": {"S": "Joe"}, "Age": {"N": "35"}} + */ + + public void setM(java.util.Map m) { + this.m = m; + } + + /** + *

+ * An attribute of type Map. For example: + *

+ *

+ * "M": {"Name": {"S": "Joe"}, "Age": {"N": "35"}} + *

+ * + * @param m + * An attribute of type Map. For example:

+ *

+ * "M": {"Name": {"S": "Joe"}, "Age": {"N": "35"}} + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue withM(java.util.Map m) { + setM(m); + return this; + } + + public AttributeValue addMEntry(String key, AttributeValue value) { + if (null == this.m) { + this.m = new java.util.HashMap(); + } + if (this.m.containsKey(key)) + throw new IllegalArgumentException("Duplicated keys (" + key.toString() + ") are provided."); + this.m.put(key, value); + return this; + } + + /** + * Removes all the entries added into M. + * + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue clearMEntries() { + this.m = null; + return this; + } + + /** + *

+ * An attribute of type List. For example: + *

+ *

+ * "L": [ {"S": "Cookies"} , {"S": "Coffee"}, {"N", "3.14159"}] + *

+ * + * @return An attribute of type List. For example:

+ *

+ * "L": [ {"S": "Cookies"} , {"S": "Coffee"}, {"N", "3.14159"}] + */ + + public java.util.List getL() { + return l; + } + + /** + *

+ * An attribute of type List. For example: + *

+ *

+ * "L": [ {"S": "Cookies"} , {"S": "Coffee"}, {"N", "3.14159"}] + *

+ * + * @param l + * An attribute of type List. For example:

+ *

+ * "L": [ {"S": "Cookies"} , {"S": "Coffee"}, {"N", "3.14159"}] + */ + + public void setL(java.util.Collection l) { + if (l == null) { + this.l = null; + return; + } + + this.l = new java.util.ArrayList(l); + } + + /** + *

+ * An attribute of type List. For example: + *

+ *

+ * "L": [ {"S": "Cookies"} , {"S": "Coffee"}, {"N", "3.14159"}] + *

+ *

+ * NOTE: This method appends the values to the existing list (if any). Use + * {@link #setL(java.util.Collection)} or {@link #withL(java.util.Collection)} if you want to override the existing + * values. + *

+ * + * @param l + * An attribute of type List. For example:

+ *

+ * "L": [ {"S": "Cookies"} , {"S": "Coffee"}, {"N", "3.14159"}] + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue withL(AttributeValue... l) { + if (this.l == null) { + setL(new java.util.ArrayList(l.length)); + } + for (AttributeValue ele : l) { + this.l.add(ele); + } + return this; + } + + /** + *

+ * An attribute of type List. For example: + *

+ *

+ * "L": [ {"S": "Cookies"} , {"S": "Coffee"}, {"N", "3.14159"}] + *

+ * + * @param l + * An attribute of type List. For example:

+ *

+ * "L": [ {"S": "Cookies"} , {"S": "Coffee"}, {"N", "3.14159"}] + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue withL(java.util.Collection l) { + setL(l); + return this; + } + + /** + *

+ * An attribute of type Null. For example: + *

+ *

+ * "NULL": true + *

+ * + * @param nULLValue + * An attribute of type Null. For example:

+ *

+ * "NULL": true + */ + + public void setNULL(Boolean nULLValue) { + this.nULLValue = nULLValue; + } + + /** + *

+ * An attribute of type Null. For example: + *

+ *

+ * "NULL": true + *

+ * + * @return An attribute of type Null. For example:

+ *

+ * "NULL": true + */ + + public Boolean getNULL() { + return this.nULLValue; + } + + /** + *

+ * An attribute of type Null. For example: + *

+ *

+ * "NULL": true + *

+ * + * @param nULLValue + * An attribute of type Null. For example:

+ *

+ * "NULL": true + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue withNULL(Boolean nULLValue) { + setNULL(nULLValue); + return this; + } + + /** + *

+ * An attribute of type Null. For example: + *

+ *

+ * "NULL": true + *

+ * + * @return An attribute of type Null. For example:

+ *

+ * "NULL": true + */ + + public Boolean isNULL() { + return this.nULLValue; + } + + /** + *

+ * An attribute of type Boolean. For example: + *

+ *

+ * "BOOL": true + *

+ * + * @param bOOL + * An attribute of type Boolean. For example:

+ *

+ * "BOOL": true + */ + + public void setBOOL(Boolean bOOL) { + this.bOOL = bOOL; + } + + /** + *

+ * An attribute of type Boolean. For example: + *

+ *

+ * "BOOL": true + *

+ * + * @return An attribute of type Boolean. For example:

+ *

+ * "BOOL": true + */ + + public Boolean getBOOL() { + return this.bOOL; + } + + /** + *

+ * An attribute of type Boolean. For example: + *

+ *

+ * "BOOL": true + *

+ * + * @param bOOL + * An attribute of type Boolean. For example:

+ *

+ * "BOOL": true + * @return Returns a reference to this object so that method calls can be chained together. + */ + + public AttributeValue withBOOL(Boolean bOOL) { + setBOOL(bOOL); + return this; + } + + /** + *

+ * An attribute of type Boolean. For example: + *

+ *

+ * "BOOL": true + *

+ * + * @return An attribute of type Boolean. For example:

+ *

+ * "BOOL": true + */ + + public Boolean isBOOL() { + return this.bOOL; + } + + /** + * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be + * redacted from this string using a placeholder value. + * + * @return A string representation of this object. + * + * @see Object#toString() + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{"); + if (getS() != null) + sb.append("S: ").append(getS()).append(","); + if (getN() != null) + sb.append("N: ").append(getN()).append(","); + if (getB() != null) + sb.append("B: ").append(getB()).append(","); + if (getSS() != null) + sb.append("SS: ").append(getSS()).append(","); + if (getNS() != null) + sb.append("NS: ").append(getNS()).append(","); + if (getBS() != null) + sb.append("BS: ").append(getBS()).append(","); + if (getM() != null) + sb.append("M: ").append(getM()).append(","); + if (getL() != null) + sb.append("L: ").append(getL()).append(","); + if (getNULL() != null) + sb.append("NULL: ").append(getNULL()).append(","); + if (getBOOL() != null) + sb.append("BOOL: ").append(getBOOL()); + sb.append("}"); + return sb.toString(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + + if (obj instanceof AttributeValue == false) + return false; + AttributeValue other = (AttributeValue) obj; + if (other.getS() == null ^ this.getS() == null) + return false; + if (other.getS() != null && other.getS().equals(this.getS()) == false) + return false; + if (other.getN() == null ^ this.getN() == null) + return false; + if (other.getN() != null && other.getN().equals(this.getN()) == false) + return false; + if (other.getB() == null ^ this.getB() == null) + return false; + if (other.getB() != null && other.getB().equals(this.getB()) == false) + return false; + if (other.getSS() == null ^ this.getSS() == null) + return false; + if (other.getSS() != null && other.getSS().equals(this.getSS()) == false) + return false; + if (other.getNS() == null ^ this.getNS() == null) + return false; + if (other.getNS() != null && other.getNS().equals(this.getNS()) == false) + return false; + if (other.getBS() == null ^ this.getBS() == null) + return false; + if (other.getBS() != null && other.getBS().equals(this.getBS()) == false) + return false; + if (other.getM() == null ^ this.getM() == null) + return false; + if (other.getM() != null && other.getM().equals(this.getM()) == false) + return false; + if (other.getL() == null ^ this.getL() == null) + return false; + if (other.getL() != null && other.getL().equals(this.getL()) == false) + return false; + if (other.getNULL() == null ^ this.getNULL() == null) + return false; + if (other.getNULL() != null && other.getNULL().equals(this.getNULL()) == false) + return false; + if (other.getBOOL() == null ^ this.getBOOL() == null) + return false; + if (other.getBOOL() != null && other.getBOOL().equals(this.getBOOL()) == false) + return false; + return true; + } + + @Override + public int hashCode() { + final int prime = 31; + int hashCode = 1; + + hashCode = prime * hashCode + ((getS() == null) ? 0 : getS().hashCode()); + hashCode = prime * hashCode + ((getN() == null) ? 0 : getN().hashCode()); + hashCode = prime * hashCode + ((getB() == null) ? 0 : getB().hashCode()); + hashCode = prime * hashCode + ((getSS() == null) ? 0 : getSS().hashCode()); + hashCode = prime * hashCode + ((getNS() == null) ? 0 : getNS().hashCode()); + hashCode = prime * hashCode + ((getBS() == null) ? 0 : getBS().hashCode()); + hashCode = prime * hashCode + ((getM() == null) ? 0 : getM().hashCode()); + hashCode = prime * hashCode + ((getL() == null) ? 0 : getL().hashCode()); + hashCode = prime * hashCode + ((getNULL() == null) ? 0 : getNULL().hashCode()); + hashCode = prime * hashCode + ((getBOOL() == null) ? 0 : getBOOL().hashCode()); + return hashCode; + } + + @Override + public AttributeValue clone() { + try { + return (AttributeValue) super.clone(); + } catch (CloneNotSupportedException e) { + throw new IllegalStateException("Got a CloneNotSupportedException from Object.clone() even though we're Cloneable!", e); + } + } + +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/dynamodb/Identity.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/dynamodb/Identity.java new file mode 100644 index 000000000..12b2fbba1 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/dynamodb/Identity.java @@ -0,0 +1,182 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events.models.dynamodb; + +import java.io.Serializable; + +/** + *

+ * Contains details about the type of identity that made the request. + *

+ * + * @see AWS API + * Documentation + */ +public class Identity implements Serializable, Cloneable { + + /** + *

+ * A unique identifier for the entity that made the call. For Time To Live, the principalId is + * "dynamodb.amazonaws.com". + *

+ */ + private String principalId; + + /** + *

+ * The type of the identity. For Time To Live, the type is "Service". + *

+ */ + private String type; + + /** + *

+ * A unique identifier for the entity that made the call. For Time To Live, the principalId is + * "dynamodb.amazonaws.com". + *

+ * + * @param principalId + * A unique identifier for the entity that made the call. For Time To Live, the principalId is + * "dynamodb.amazonaws.com". + */ + public void setPrincipalId(String principalId) { + this.principalId = principalId; + } + + /** + *

+ * A unique identifier for the entity that made the call. For Time To Live, the principalId is + * "dynamodb.amazonaws.com". + *

+ * + * @return A unique identifier for the entity that made the call. For Time To Live, the principalId is + * "dynamodb.amazonaws.com". + */ + public String getPrincipalId() { + return this.principalId; + } + + /** + *

+ * A unique identifier for the entity that made the call. For Time To Live, the principalId is + * "dynamodb.amazonaws.com". + *

+ * + * @param principalId + * A unique identifier for the entity that made the call. For Time To Live, the principalId is + * "dynamodb.amazonaws.com". + * @return Returns a reference to this object so that method calls can be chained together. + */ + public Identity withPrincipalId(String principalId) { + setPrincipalId(principalId); + return this; + } + + /** + *

+ * The type of the identity. For Time To Live, the type is "Service". + *

+ * + * @param type + * The type of the identity. For Time To Live, the type is "Service". + */ + public void setType(String type) { + this.type = type; + } + + /** + *

+ * The type of the identity. For Time To Live, the type is "Service". + *

+ * + * @return The type of the identity. For Time To Live, the type is "Service". + */ + public String getType() { + return this.type; + } + + /** + *

+ * The type of the identity. For Time To Live, the type is "Service". + *

+ * + * @param type + * The type of the identity. For Time To Live, the type is "Service". + * @return Returns a reference to this object so that method calls can be chained together. + */ + public Identity withType(String type) { + setType(type); + return this; + } + + /** + * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be + * redacted from this string using a placeholder value. + * + * @return A string representation of this object. + * + * @see Object#toString() + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{"); + if (getPrincipalId() != null) + sb.append("PrincipalId: ").append(getPrincipalId()).append(","); + if (getType() != null) + sb.append("Type: ").append(getType()); + sb.append("}"); + return sb.toString(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + + if (obj instanceof Identity == false) + return false; + Identity other = (Identity) obj; + if (other.getPrincipalId() == null ^ this.getPrincipalId() == null) + return false; + if (other.getPrincipalId() != null && other.getPrincipalId().equals(this.getPrincipalId()) == false) + return false; + if (other.getType() == null ^ this.getType() == null) + return false; + if (other.getType() != null && other.getType().equals(this.getType()) == false) + return false; + return true; + } + + @Override + public int hashCode() { + final int prime = 31; + int hashCode = 1; + + hashCode = prime * hashCode + ((getPrincipalId() == null) ? 0 : getPrincipalId().hashCode()); + hashCode = prime * hashCode + ((getType() == null) ? 0 : getType().hashCode()); + return hashCode; + } + + @Override + public Identity clone() { + try { + return (Identity) super.clone(); + } catch (CloneNotSupportedException e) { + throw new IllegalStateException("Got a CloneNotSupportedException from Object.clone() " + "even though we're Cloneable!", e); + } + } + +} diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/dynamodb/OperationType.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/dynamodb/OperationType.java new file mode 100644 index 000000000..8d5574ee1 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/dynamodb/OperationType.java @@ -0,0 +1,54 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events.models.dynamodb; + +public enum OperationType { + + INSERT("INSERT"), + MODIFY("MODIFY"), + REMOVE("REMOVE"); + + private String value; + + private OperationType(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + /** + * Use this in place of valueOf. + * + * @param value + * real value + * @return OperationType corresponding to the value + * + * @throws IllegalArgumentException + * If the specified value does not map to one of the known values in this enum. + */ + public static OperationType fromValue(String value) { + if (value == null || "".equals(value)) { + throw new IllegalArgumentException("Value cannot be null or empty!"); + } + + for (OperationType enumEntry : OperationType.values()) { + if (enumEntry.toString().equals(value)) { + return enumEntry; + } + } + throw new IllegalArgumentException("Cannot create enum from " + value + " value!"); + } +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/dynamodb/Record.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/dynamodb/Record.java new file mode 100644 index 000000000..81065811f --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/dynamodb/Record.java @@ -0,0 +1,801 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +package com.amazonaws.services.lambda.runtime.events.models.dynamodb; + +import java.io.Serializable; + +/** + *

+ * A description of a unique event within a stream. + *

+ * + * @see AWS API + * Documentation + */ +public class Record implements Serializable, Cloneable { + + /** + *

+ * A globally unique identifier for the event that was recorded in this stream record. + *

+ */ + private String eventID; + /** + *

+ * The type of data modification that was performed on the DynamoDB table: + *

+ *
    + *
  • + *

    + * INSERT - a new item was added to the table. + *

    + *
  • + *
  • + *

    + * MODIFY - one or more of an existing item's attributes were modified. + *

    + *
  • + *
  • + *

    + * REMOVE - the item was deleted from the table + *

    + *
  • + *
+ */ + private String eventName; + /** + *

+ * The version number of the stream record format. This number is updated whenever the structure of + * Record is modified. + *

+ *

+ * Client applications must not assume that eventVersion will remain at a particular value, as this + * number is subject to change at any time. In general, eventVersion will only increase as the + * low-level DynamoDB Streams API evolves. + *

+ */ + private String eventVersion; + /** + *

+ * The AWS service from which the stream record originated. For DynamoDB Streams, this is aws:dynamodb. + *

+ */ + private String eventSource; + /** + *

+ * The region in which the GetRecords request was received. + *

+ */ + private String awsRegion; + /** + *

+ * The main body of the stream record, containing all of the DynamoDB-specific fields. + *

+ */ + private StreamRecord dynamodb; + /** + *

+ * Items that are deleted by the Time to Live process after expiration have the following fields: + *

+ *
    + *
  • + *

    + * Records[].userIdentity.type + *

    + *

    + * "Service" + *

    + *
  • + *
  • + *

    + * Records[].userIdentity.principalId + *

    + *

    + * "dynamodb.amazonaws.com" + *

    + *
  • + *
+ */ + private Identity userIdentity; + + /** + *

+ * A globally unique identifier for the event that was recorded in this stream record. + *

+ * + * @param eventID + * A globally unique identifier for the event that was recorded in this stream record. + */ + public void setEventID(String eventID) { + this.eventID = eventID; + } + + /** + *

+ * A globally unique identifier for the event that was recorded in this stream record. + *

+ * + * @return A globally unique identifier for the event that was recorded in this stream record. + */ + public String getEventID() { + return this.eventID; + } + + /** + *

+ * A globally unique identifier for the event that was recorded in this stream record. + *

+ * + * @param eventID + * A globally unique identifier for the event that was recorded in this stream record. + * @return Returns a reference to this object so that method calls can be chained together. + */ + public Record withEventID(String eventID) { + setEventID(eventID); + return this; + } + + /** + *

+ * The type of data modification that was performed on the DynamoDB table: + *

+ *
    + *
  • + *

    + * INSERT - a new item was added to the table. + *

    + *
  • + *
  • + *

    + * MODIFY - one or more of an existing item's attributes were modified. + *

    + *
  • + *
  • + *

    + * REMOVE - the item was deleted from the table + *

    + *
  • + *
+ * + * @param eventName + * The type of data modification that was performed on the DynamoDB table:

+ *