From 5f54708012c77c7a066280264b670fff634f8120 Mon Sep 17 00:00:00 2001 From: Min Xia Date: Mon, 7 Oct 2024 14:55:53 -0700 Subject: [PATCH] Init Python Layer E2E workflow --- .github/workflows/node-lambda-canary.yml | 29 +++ .github/workflows/node-lambda-retry.yml | 57 +++++ .github/workflows/node-lambda-test.yml | 14 +- .github/workflows/python-lambda-canary.yml | 32 +++ .github/workflows/python-lambda-retry.yml | 80 ++++++ .github/workflows/python-lambda-test.yml | 236 ++++++++++++++++++ terraform/node/lambda/lambda/main.tf | 2 +- terraform/node/lambda/lambda/variables.tf | 4 +- .../python/lambda/api-gateway-proxy/main.tf | 67 +++++ .../lambda/api-gateway-proxy/outputs.tf | 3 + .../lambda/api-gateway-proxy/variables.tf | 26 ++ terraform/python/lambda/lambda/lary_arns.tf | 21 ++ terraform/python/lambda/lambda/main.tf | 70 ++++++ terraform/python/lambda/lambda/outputs.tf | 7 + terraform/python/lambda/lambda/variables.tf | 41 +++ .../PredefinedExpectedTemplate.java | 7 + .../python/lambda/aws-sdk-call-log.mustache | 9 + .../lambda/aws-sdk-call-metric.mustache | 227 +++++++++++++++++ .../python/lambda/aws-sdk-call-trace.mustache | 65 +++++ .../python/lambda/lambda-invoke-log.mustache | 7 + .../lambda/lambda-invoke-metric.mustache | 74 ++++++ .../lambda/lambda-invoke-trace.mustache | 56 +++++ .../python/lambda/log-validation.yml | 10 + .../python/lambda/metric-validation.yml | 11 + .../python/lambda/trace-validation.yml | 5 + 25 files changed, 1154 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/node-lambda-canary.yml create mode 100644 .github/workflows/node-lambda-retry.yml create mode 100644 .github/workflows/python-lambda-canary.yml create mode 100644 .github/workflows/python-lambda-retry.yml create mode 100644 .github/workflows/python-lambda-test.yml create mode 100644 terraform/python/lambda/api-gateway-proxy/main.tf create mode 100644 terraform/python/lambda/api-gateway-proxy/outputs.tf create mode 100644 terraform/python/lambda/api-gateway-proxy/variables.tf create mode 100644 terraform/python/lambda/lambda/lary_arns.tf create mode 100644 terraform/python/lambda/lambda/main.tf create mode 100644 terraform/python/lambda/lambda/outputs.tf create mode 100644 terraform/python/lambda/lambda/variables.tf create mode 100644 validator/src/main/resources/expected-data-template/python/lambda/aws-sdk-call-log.mustache create mode 100644 validator/src/main/resources/expected-data-template/python/lambda/aws-sdk-call-metric.mustache create mode 100644 validator/src/main/resources/expected-data-template/python/lambda/aws-sdk-call-trace.mustache create mode 100644 validator/src/main/resources/expected-data-template/python/lambda/lambda-invoke-log.mustache create mode 100644 validator/src/main/resources/expected-data-template/python/lambda/lambda-invoke-metric.mustache create mode 100644 validator/src/main/resources/expected-data-template/python/lambda/lambda-invoke-trace.mustache create mode 100644 validator/src/main/resources/validations/python/lambda/log-validation.yml create mode 100644 validator/src/main/resources/validations/python/lambda/metric-validation.yml create mode 100644 validator/src/main/resources/validations/python/lambda/trace-validation.yml diff --git a/.github/workflows/node-lambda-canary.yml b/.github/workflows/node-lambda-canary.yml new file mode 100644 index 000000000..dfe3b383c --- /dev/null +++ b/.github/workflows/node-lambda-canary.yml @@ -0,0 +1,29 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +## This workflow aims to run the Application Signals end-to-end tests as a canary to +## test the artifacts for App Signals enablement. +name: Node Lambda Enablement Canary Testing +on: + schedule: + - cron: '*/15 * * * *' # run the workflow every 15 minutes + workflow_dispatch: # be able to run the workflow on demand + +permissions: + id-token: write + contents: read + +jobs: + default: + strategy: + fail-fast: false + matrix: + aws-region: ['af-south-1','ap-east-1','ap-northeast-1','ap-northeast-2','ap-northeast-3','ap-south-1','ap-south-2','ap-southeast-1', + 'ap-southeast-2','ap-southeast-3','ap-southeast-4','ca-central-1','eu-central-1','eu-central-2','eu-north-1', + 'eu-south-1','eu-south-2','eu-west-1','eu-west-2','eu-west-3','il-central-1','me-central-1','me-south-1', 'sa-east-1', + 'us-east-1','us-east-2', 'us-west-1', 'us-west-2'] + uses: ./.github/workflows/node-ec2-default-retry.yml + secrets: inherit + with: + aws-region: ${{ matrix.aws-region }} + caller-workflow-name: 'appsignals-node-e2e-lambda-canary-test' diff --git a/.github/workflows/node-lambda-retry.yml b/.github/workflows/node-lambda-retry.yml new file mode 100644 index 000000000..7d731e1ef --- /dev/null +++ b/.github/workflows/node-lambda-retry.yml @@ -0,0 +1,57 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +# This is a reusable workflow for running the Enablement test for App Signals. +# It is meant to be called from another workflow. +# Read more about reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview +name: Node Lambda Retry +on: + workflow_call: + inputs: + aws-region: + required: true + type: string + caller-workflow-name: + required: true + type: string + +permissions: + id-token: write + contents: read + +jobs: + node-lambda-attempt-1: + uses: ./.github/workflows/node-lambda-test.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + + node-lambda-attempt-2: + needs: [ node-lambda-attempt-1 ] + if: ${{ needs.node-lambda-attempt-1.outputs.job-started != 'true' }} + uses: ./.github/workflows/node-lambda-test.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + + publish-metric-attempt-1: + needs: [ node-lambda-attempt-1, node-lambda-attempt-2 ] + if: always() + uses: ./.github/workflows/enablement-test-publish-result.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + validation-result: ${{ needs.node-lambda-attempt-1.outputs.validation-result || needs.node-lambda-attempt-2.outputs.validation-result }} + + publish-metric-attempt-2: + needs: [ node-lambda-attempt-1, node-lambda-attempt-2, publish-metric-attempt-1 ] + if: ${{ always() && needs.publish-metric-attempt-1.outputs.job-started != 'true' }} + uses: ./.github/workflows/enablement-test-publish-result.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + validation-result: ${{ needs.node-lambda-attempt-1.outputs.validation-result || needs.node-lambda-attempt-2.outputs.validation-result }} \ No newline at end of file diff --git a/.github/workflows/node-lambda-test.yml b/.github/workflows/node-lambda-test.yml index 6d01570eb..0086bd03d 100644 --- a/.github/workflows/node-lambda-test.yml +++ b/.github/workflows/node-lambda-test.yml @@ -36,6 +36,8 @@ env: METRIC_NAMESPACE: ApplicationSignals LOG_GROUP_NAME: /aws/application-signals/data TEST_RESOURCES_FOLDER: ${GITHUB_WORKSPACE} + STAGING_S3_BUCKET: ${{ secrets.STAGING_BUCKET_NAME }} + IS_CANARY: false jobs: node-lambda-default: @@ -95,8 +97,12 @@ jobs: - name: Download Lambda Layer and Function artifacts run: | - aws s3 cp s3://adot-autoinstrumentation-node-staging/layer-${{ github.run_id }}.zip ${{ env.ARTIFACTS_DIR }}/layer.zip | - aws s3 cp s3://adot-autoinstrumentation-node-staging/function-${{ github.run_id }}.zip ${{ env.ARTIFACTS_DIR }}/function.zip + aws s3 cp s3://${{ env.STAGING_S3_BUCKET }}/layer-${{ github.run_id }}.zip ${{ env.ARTIFACTS_DIR }}/layer.zip | + aws s3 cp s3://${{ env.STAGING_S3_BUCKET }}/function-${{ github.run_id }}.zip ${{ env.ARTIFACTS_DIR }}/function.zip + + - name: Set Canary Environment Variable + if: ${{ github.event.inputs.CALLER_WORKFLOW_NAME == 'appsignals-node-e2e-lambda-canary-test' }} + run: echo IS_CANARY=true >> $GITHUB_ENV - name: Set up terraform uses: ./.github/workflows/actions/execute_and_retry @@ -124,7 +130,9 @@ jobs: with: command: 'cd ${{ env.TEST_RESOURCES_FOLDER }}/terraform/node/lambda/lambda && terraform apply -auto-approve -var="sdk_layer_name=AWSOpenTelemetryDistroJs-${{ github.run_id }}" - -var="function_name=${{env.TERRAFORM_LAMBDA_FUNCTION_NAME}}" -var="layer_artifacts_directory=${{ env.ARTIFACTS_DIR }}"' + -var="function_name=${{env.TERRAFORM_LAMBDA_FUNCTION_NAME}}" + -var="layer_artifacts_directory=${{ env.ARTIFACTS_DIR }}" + -var="is_canary=${{ env.IS_CANARY }}"' max_retry: 6 sleep_time: 60 - name: Extract endpoint diff --git a/.github/workflows/python-lambda-canary.yml b/.github/workflows/python-lambda-canary.yml new file mode 100644 index 000000000..24ca1fa49 --- /dev/null +++ b/.github/workflows/python-lambda-canary.yml @@ -0,0 +1,32 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +## This workflow aims to run the Application Signals Python end-to-end tests as a canary to +## test the artifacts for Application Signals enablement. +name: Python Lambda Enablement Canary Testing +on: + schedule: + - cron: '*/15 * * * *' # run the workflow every 15 minutes + workflow_dispatch: # be able to run the workflow on demand + +permissions: + id-token: write + contents: read + +jobs: + github: + strategy: + fail-fast: false + matrix: + aws-region: ['af-south-1','ap-east-1','ap-northeast-1','ap-northeast-2','ap-northeast-3','ap-south-1','ap-south-2','ap-southeast-1', + 'ap-southeast-2','ap-southeast-3','ap-southeast-4','ca-central-1','eu-central-1','eu-central-2','eu-north-1', + 'eu-south-1','eu-south-2','eu-west-1','eu-west-2','eu-west-3','il-central-1','me-central-1','me-south-1', 'sa-east-1', + 'us-east-1','us-east-2', 'us-west-1', 'us-west-2'] + uses: ./.github/workflows/python-lambda-retry.yml + secrets: inherit + with: + aws-region: ${{ matrix.aws-region }} + caller-workflow-name: 'appsignals-python-e2e-lambda-canary-test' + python-version: '3.12' + cpu-architecture: 'x86_64' + diff --git a/.github/workflows/python-lambda-retry.yml b/.github/workflows/python-lambda-retry.yml new file mode 100644 index 000000000..9f81656f8 --- /dev/null +++ b/.github/workflows/python-lambda-retry.yml @@ -0,0 +1,80 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +# This is a reusable workflow for running the Enablement test for App Signals. +# It is meant to be called from another workflow. +# Read more about reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview +name: Python Lambda Default Retry +on: + workflow_call: + inputs: + aws-region: + required: true + type: string + caller-workflow-name: + required: true + type: string + python-version: + required: true + type: string + staging-wheel-name: + required: false + default: 'aws-opentelemetry-distro' + type: string + cpu-architecture: + required: false + type: string + default: "x86_64" + otel-source: + required: false + type: string + default: 'github' + +permissions: + id-token: write + contents: read + +jobs: + python-lambda-attempt-1: + uses: ./.github/workflows/python-lambda-test.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + python-version: ${{ inputs.python-version }} + staging-wheel-name: ${{ inputs.staging-wheel-name }} + otel-source: ${{ inputs.otel-source }} + cpu-architecture: ${{ inputs.cpu-architecture }} + + python-lambda-attempt-2: + needs: [ python-lambda-attempt-1 ] + if: ${{ needs.python-lambda-attempt-1.outputs.job-started != 'true' }} + uses: ./.github/workflows/python-lambda-test.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + python-version: ${{ inputs.python-version }} + staging-wheel-name: ${{ inputs.staging-wheel-name }} + otel-source: ${{ inputs.otel-source }} + cpu-architecture: ${{ inputs.cpu-architecture }} + + publish-metric-attempt-1: + needs: [ python-lambda-attempt-1, python-lambda-attempt-2 ] + if: always() + uses: ./.github/workflows/enablement-test-publish-result.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + validation-result: ${{ needs.python-lambda-attempt-1.outputs.validation-result || needs.python-lambda-attempt-2.outputs.validation-result }} + + publish-metric-attempt-2: + needs: [ python-lambda-attempt-1, python-lambda-attempt-2, publish-metric-attempt-1 ] + if: ${{ always() && needs.publish-metric-attempt-1.outputs.job-started != 'true' }} + uses: ./.github/workflows/enablement-test-publish-result.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + validation-result: ${{ needs.python-lambda-attempt-1.outputs.validation-result || needs.python-lambda-attempt-2.outputs.validation-result }} \ No newline at end of file diff --git a/.github/workflows/python-lambda-test.yml b/.github/workflows/python-lambda-test.yml new file mode 100644 index 000000000..880849bd0 --- /dev/null +++ b/.github/workflows/python-lambda-test.yml @@ -0,0 +1,236 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +# This is a reusable workflow for running the Python Enablement Canary test for Application Signals. +# It is meant to be called from another workflow. +# Read more about reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview +name: Python Lambda Default Use Case +on: + workflow_call: + inputs: + aws-region: + required: true + type: string + caller-workflow-name: + required: true + type: string + python-version: + description: "Currently support version 3.8, 3.9, 3.10, 3.11, 3.12" + required: false + type: string + default: '3.9' + cpu-architecture: + description: "Permitted values: x86_64 or arm64" + required: false + type: string + default: "x86_64" + staging-wheel-name: + required: false + default: 'aws-opentelemetry-distro' + type: string + otel-source: + required: false + type: string + default: 'github' + outputs: + job-started: + value: ${{ jobs.python-ec2-default.outputs.job-started }} + validation-result: + value: ${{ jobs.python-ec2-default.outputs.validation-result }} + +permissions: + id-token: write + contents: read + +env: + E2E_TEST_AWS_REGION: ${{ inputs.aws-region }} + CALLER_WORKFLOW_NAME: ${{ inputs.caller-workflow-name }} + PYTHON_VERSION: ${{ inputs.python-version }} + CPU_ARCHITECTURE: ${{ inputs.cpu-architecture }} + E2E_TEST_ACCOUNT_ID: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ACCOUNT_ID }} + E2E_TEST_ROLE_NAME: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ROLE_NAME }} + METRIC_NAMESPACE: ApplicationSignals + LOG_GROUP_NAME: /aws/application-signals/data + TEST_RESOURCES_FOLDER: ${GITHUB_WORKSPACE} + STAGING_S3_BUCKET: ${{ secrets.STAGING_BUCKET_NAME }} + IS_CANARY: false + +jobs: + python-lambda-default: + runs-on: ubuntu-latest + timeout-minutes: 30 + outputs: + job-started: ${{ steps.job-started.outputs.job-started }} + validation-result: ${{ steps.validation-result.outputs.validation-result }} + steps: + - name: Check if the job started + id: job-started + run: echo "job-started=true" >> $GITHUB_OUTPUT + + - uses: actions/checkout@v4 + with: + repository: 'aws-observability/aws-application-signals-test-framework' + ref: ${{ inputs.caller-workflow-name == 'main-build' && 'main' || github.ref }} + fetch-depth: 0 + + # We initialize Gradlew Daemon early on during the workflow because sometimes initialization + # fails due to transient issues. If it fails here, then we will try again later before the validators + - name: Initiate Gradlew Daemon + id: initiate-gradlew + uses: ./.github/workflows/actions/execute_and_retry + continue-on-error: true + with: + command: "./gradlew :validator:build" + cleanup: "./gradlew clean" + max_retry: 3 + sleep_time: 60 + + - name: Generate testing id + run: echo TESTING_ID="${{ github.run_id }}-${{ github.run_number }}-${RANDOM}" >> $GITHUB_ENV + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ env.E2E_TEST_ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} + aws-region: us-east-1 + + - name: Retrieve account + uses: aws-actions/aws-secretsmanager-get-secrets@v1 + with: + secret-ids: + ACCOUNT_ID, region-account/${{ env.E2E_TEST_AWS_REGION }} + + - name: Configure AWS Credentials + if: ${{ github.event.repository.name == 'aws-application-signals-test-framework' }} + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ env.ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} + aws-region: ${{ env.E2E_TEST_AWS_REGION }} + + - name: Set Lambda Layer artifact directory path + run: echo ARTIFACTS_DIR="${{ github.workspace }}/lambda_artifacts" >> $GITHUB_ENV + + - name: Download Lambda Layer and Function artifacts + run: | + aws s3 cp s3://${{ env.STAGING_S3_BUCKET }}/layer-${{ github.run_id }}.zip ${{ env.ARTIFACTS_DIR }}/layer.zip | + aws s3 cp s3://${{ env.STAGING_S3_BUCKET }}/function-${{ github.run_id }}.zip ${{ env.ARTIFACTS_DIR }}/function.zip + + - name: Set Canary Environment Variable + if: ${{ github.event.inputs.CALLER_WORKFLOW_NAME == 'appsignals-python-e2e-lambda-canary-test' }} + run: echo IS_CANARY=true >> $GITHUB_ENV + + - name: Set up terraform + uses: ./.github/workflows/actions/execute_and_retry + with: + command: "wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg" + post-command: 'echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list + && sudo apt update && sudo apt install terraform' + sleep_time: 60 + + - name: Initiate Terraform + uses: ./.github/workflows/actions/execute_and_retry + with: + command: "cd ${{ env.TEST_RESOURCES_FOLDER }}/terraform/python/lambda/lambda && terraform init && terraform validate" + cleanup: "rm -rf .terraform && rm -rf .terraform.lock.hcl" + max_retry: 6 + sleep_time: 60 + + - name: Get terraform Lambda function name + shell: bash + run: | + echo TERRAFORM_LAMBDA_FUNCTION_NAME="AdotLambdaPythonSampleApp-${{ github.run_id }}"| + tee --append $GITHUB_ENV + + - name: Apply terraform + uses: ./.github/workflows/actions/execute_and_retry + with: + command: 'cd ${{ env.TEST_RESOURCES_FOLDER }}/terraform/python/lambda/lambda && terraform apply -auto-approve + -var="sdk_layer_name=AWSOpenTelemetryDistroPython-${{ github.run_id }}" + -var="function_name=${{env.TERRAFORM_LAMBDA_FUNCTION_NAME}}" + -var="layer_artifacts_directory=${{ env.ARTIFACTS_DIR }}" + -var="is_canary=${{ env.IS_CANARY }}"' + max_retry: 6 + sleep_time: 60 + - name: Extract endpoint + id: extract-endpoint + shell: bash + run: cd ${{ env.TEST_RESOURCES_FOLDER }}/terraform/python/lambda/lambda && echo API_GATEWAY_URL=$(terraform output -raw api-gateway-url) >> $GITHUB_ENV + - name: Send request to endpoint + shell: bash + run: sleep 30s; curl -sS ${{ env.API_GATEWAY_URL }} + + - name: Initiate Gradlew Daemon + if: steps.initiate-gradlew == 'failure' + uses: ./.github/workflows/actions/execute_and_retry + continue-on-error: true + with: + command: "./gradlew :validator:build" + cleanup: "./gradlew clean" + max_retry: 3 + sleep_time: 60 + + # Validation for pulse telemetry data + - name: Validate generated EMF logs + id: log-validation + run: ./gradlew validator:run --args='-c python/lambda/log-validation.yml + --testing-id ${{ env.TESTING_ID }} + --endpoint http://${{ env.API_GATEWAY_URL }} + --region ${{ inputs.aws-region }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --service-name ${{ env.TERRAFORM_LAMBDA_FUNCTION_NAME }} + --rollup' + + - name: Validate generated metrics + id: metric-validation + if: (success() || steps.log-validation.outcome == 'failure') && !cancelled() + run: ./gradlew validator:run --args='-c python/lambda/metric-validation.yml + --testing-id ${{ env.TESTING_ID }} + --endpoint http://${{ env.API_GATEWAY_URL }} + --region ${{ inputs.aws-region }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --service-name ${{ env.TERRAFORM_LAMBDA_FUNCTION_NAME }} + --rollup' + + - name: Validate generated traces + id: trace-validation + if: (success() || steps.log-validation.outcome == 'failure' || steps.metric-validation.outcome == 'failure') && !cancelled() + run: ./gradlew validator:run --args='-c python/lambda/trace-validation.yml + --testing-id ${{ env.TESTING_ID }} + --endpoint http://${{ env.API_GATEWAY_URL }} + --region ${{ inputs.aws-region }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --service-name ${{ env.TERRAFORM_LAMBDA_FUNCTION_NAME }} + --rollup' + + - name: Refresh AWS Credentials + if: ${{ github.event.repository.name == 'aws-application-signals-test-framework' }} + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ env.ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} + aws-region: ${{ env.E2E_TEST_AWS_REGION }} + + - name: Save test results + if: always() + id: validation-result + run: | + if [ "${{ steps.log-validation.outcome }}" = "success" ] && [ "${{ steps.metric-validation.outcome }}" = "success" ] && [ "${{ steps.trace-validation.outcome }}" = "success" ]; then + echo "validation-result=success" >> $GITHUB_OUTPUT + else + echo "validation-result=failure" >> $GITHUB_OUTPUT + fi + + # Clean up Procedures + - name: Terraform destroy + if: always() + continue-on-error: true + run: | + cd ${{ env.TEST_RESOURCES_FOLDER }}/terraform/python/lambda/lambda && terraform destroy -auto-approve \ + -var="sdk_layer_name=AWSOpenTelemetryDistroPython-${{ github.run_id }}" \ + -var="function_name=${{env.TERRAFORM_LAMBDA_FUNCTION_NAME}}" \ + -var="layer_artifacts_directory=${{ env.ARTIFACTS_DIR }}" \ No newline at end of file diff --git a/terraform/node/lambda/lambda/main.tf b/terraform/node/lambda/lambda/main.tf index e289bd20d..f3a74afa7 100644 --- a/terraform/node/lambda/lambda/main.tf +++ b/terraform/node/lambda/lambda/main.tf @@ -5,7 +5,7 @@ resource "aws_lambda_layer_version" "sdk_layer" { count = var.is_canary ? 0 : 1 layer_name = var.sdk_layer_name filename = "${var.layer_artifacts_directory}/layer.zip" - compatible_runtimes = ["nodejs14.x", "nodejs16.x", "nodejs18.x"] + compatible_runtimes = ["nodejs18.x", "nodejs20.x"] license_info = "Apache-2.0" source_code_hash = filebase64sha256("${var.layer_artifacts_directory}/layer.zip") # filename = "${var.kube_directory_path}/config" diff --git a/terraform/node/lambda/lambda/variables.tf b/terraform/node/lambda/lambda/variables.tf index 6154d1371..9bca5c4a9 100644 --- a/terraform/node/lambda/lambda/variables.tf +++ b/terraform/node/lambda/lambda/variables.tf @@ -7,7 +7,7 @@ variable "function_name" { variable "sdk_layer_name" { type = string description = "Name of published SDK layer" - default = "aws-opentelemetry-distro-nodejs" + default = "AWSOpenTelemetryDistroJs" } variable "tracing_mode" { @@ -19,7 +19,7 @@ variable "tracing_mode" { variable "runtime" { type = string description = "NodeJS runtime version used for sample Lambda Function" - default = "nodejs16.x" + default = "nodejs20.x" } variable "architecture" { diff --git a/terraform/python/lambda/api-gateway-proxy/main.tf b/terraform/python/lambda/api-gateway-proxy/main.tf new file mode 100644 index 000000000..4bd8afbe1 --- /dev/null +++ b/terraform/python/lambda/api-gateway-proxy/main.tf @@ -0,0 +1,67 @@ +resource "aws_api_gateway_rest_api" "lambda_api_proxy" { + name = var.name +} + +resource "aws_api_gateway_resource" "lambda_api_proxy" { + rest_api_id = aws_api_gateway_rest_api.lambda_api_proxy.id + parent_id = aws_api_gateway_rest_api.lambda_api_proxy.root_resource_id + path_part = "{proxy+}" +} + +resource "aws_api_gateway_method" "lambda_api_proxy" { + rest_api_id = aws_api_gateway_rest_api.lambda_api_proxy.id + resource_id = aws_api_gateway_resource.lambda_api_proxy.id + http_method = "ANY" + authorization = "NONE" +} + +resource "aws_api_gateway_integration" "lambda_api" { + rest_api_id = aws_api_gateway_rest_api.lambda_api_proxy.id + resource_id = aws_api_gateway_method.lambda_api_proxy.resource_id + http_method = aws_api_gateway_method.lambda_api_proxy.http_method + + integration_http_method = "POST" + type = "AWS_PROXY" + uri = var.function_invoke_arn +} + +resource "aws_api_gateway_method" "lambda_api_proxy_root_nodejs" { + rest_api_id = aws_api_gateway_rest_api.lambda_api_proxy.id + resource_id = aws_api_gateway_rest_api.lambda_api_proxy.root_resource_id + http_method = "ANY" + authorization = "NONE" +} + +resource "aws_api_gateway_integration" "lambda_api_root_nodejs" { + rest_api_id = aws_api_gateway_rest_api.lambda_api_proxy.id + resource_id = aws_api_gateway_method.lambda_api_proxy_root_nodejs.resource_id + http_method = aws_api_gateway_method.lambda_api_proxy_root_nodejs.http_method + + integration_http_method = "POST" + type = "AWS_PROXY" + uri = var.function_invoke_arn +} + +resource "aws_api_gateway_deployment" "lambda_api_proxy" { + depends_on = [ + aws_api_gateway_integration.lambda_api, + aws_api_gateway_integration.lambda_api_root_nodejs, + ] + + rest_api_id = aws_api_gateway_rest_api.lambda_api_proxy.id +} + +resource "aws_api_gateway_stage" "test" { + stage_name = "default" + rest_api_id = aws_api_gateway_rest_api.lambda_api_proxy.id + deployment_id = aws_api_gateway_deployment.lambda_api_proxy.id + xray_tracing_enabled = var.enable_xray_tracing +} + +resource "aws_lambda_permission" "lambda_api_allow_gateway_nodejs" { + action = "lambda:InvokeFunction" + function_name = var.function_name + qualifier = var.function_qualifier + principal = "apigateway.amazonaws.com" + source_arn = "${aws_api_gateway_rest_api.lambda_api_proxy.execution_arn}/*/*" +} diff --git a/terraform/python/lambda/api-gateway-proxy/outputs.tf b/terraform/python/lambda/api-gateway-proxy/outputs.tf new file mode 100644 index 000000000..646329f4d --- /dev/null +++ b/terraform/python/lambda/api-gateway-proxy/outputs.tf @@ -0,0 +1,3 @@ +output "api_gateway_url" { + value = aws_api_gateway_stage.test.invoke_url +} diff --git a/terraform/python/lambda/api-gateway-proxy/variables.tf b/terraform/python/lambda/api-gateway-proxy/variables.tf new file mode 100644 index 000000000..125cd1f20 --- /dev/null +++ b/terraform/python/lambda/api-gateway-proxy/variables.tf @@ -0,0 +1,26 @@ +variable "name" { + type = string + description = "Name of API gateway to create" +} + +variable "function_name" { + type = string + description = "Name of function to proxy to" +} + +variable "function_qualifier" { + type = string + default = null + description = "Qualifier of function to proxy to" +} + +variable "function_invoke_arn" { + type = string + description = "Invoke ARN of function to proxy to" +} + +variable "enable_xray_tracing" { + type = bool + description = "Whether to enable xray tracing of the API gateway" + default = true +} diff --git a/terraform/python/lambda/lambda/lary_arns.tf b/terraform/python/lambda/lambda/lary_arns.tf new file mode 100644 index 000000000..2f89309d8 --- /dev/null +++ b/terraform/python/lambda/lambda/lary_arns.tf @@ -0,0 +1,21 @@ +locals { + sdk_layer_arns_amd64 = { +# TODO: to be updated + "ap-northeast-1" = "arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-18-1:4" + "ap-northeast-2" = "arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-nodejs-amd64-ver-1-18-1:4" + "ap-south-1" = "arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-18-1:4" + "ap-southeast-1" = "arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-18-1:4" + "ap-southeast-2" = "arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-nodejs-amd64-ver-1-18-1:4" + "ca-central-1" = "arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-18-1:4" + "eu-central-1" = "arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-18-1:4" + "eu-north-1" = "arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-18-1:4" + "eu-west-1" = "arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-18-1:4" + "eu-west-2" = "arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-nodejs-amd64-ver-1-18-1:4" + "eu-west-3" = "arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-nodejs-amd64-ver-1-18-1:4" + "sa-east-1" = "arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-18-1:4" + "us-east-1" = "arn:aws:lambda:us-west-1:252610625673:layer:AWSOpenTelemetryDistroJs:1" + "us-east-2" = "arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-nodejs-amd64-ver-1-18-1:4" + "us-west-1" = "arn:aws:lambda:us-west-1:252610625673:layer:AWSOpenTelemetryDistroJs:1" + "us-west-2" = "arn:aws:lambda:us-west-1:252610625673:layer:AWSOpenTelemetryDistroJs:1" + } +} diff --git a/terraform/python/lambda/lambda/main.tf b/terraform/python/lambda/lambda/main.tf new file mode 100644 index 000000000..0d40e7e8b --- /dev/null +++ b/terraform/python/lambda/lambda/main.tf @@ -0,0 +1,70 @@ +locals { + architecture = var.architecture == "x86_64" ? "amd64" : "arm64" +} +resource "aws_lambda_layer_version" "sdk_layer" { + count = var.is_canary ? 0 : 1 + layer_name = var.sdk_layer_name + filename = "${var.layer_artifacts_directory}/layer.zip" + compatible_runtimes = ["python3.10", "python3.11", "python3.12"] + license_info = "Apache-2.0" + source_code_hash = filebase64sha256("${var.layer_artifacts_directory}/layer.zip") +# filename = "${var.kube_directory_path}/config" +} + +module "hello-lambda-function" { + source = "terraform-aws-modules/lambda/aws" + version = ">= 2.24.0" + + architectures = compact([var.architecture]) + function_name = var.function_name + handler = "index.handler" + runtime = var.runtime + + create_package = false + local_existing_package = "${var.layer_artifacts_directory}/function.zip" + + memory_size = 512 + timeout = 30 + + layers = var.is_canary ? [local.sdk_layer_arns_amd64.us-west-1] : [aws_lambda_layer_version.sdk_layer[0].arn] + + environment_variables = { + AWS_LAMBDA_EXEC_WRAPPER = "/opt/otel-instrument" + OTEL_AWS_APPLICATION_SIGNALS_ENABLED = "true" + OTEL_METRICS_EXPORTER = "none" + } + + tracing_mode = var.tracing_mode + + attach_policy_statements = true + policy_statements = { + s3 = { + effect = "Allow" + actions = [ + "s3:ListAllMyBuckets" + ] + resources = [ + "*" + ] + } + } +} + +module "api-gateway" { + source = "../api-gateway-proxy" + + name = var.function_name + function_name = module.hello-lambda-function.lambda_function_name + function_invoke_arn = module.hello-lambda-function.lambda_function_invoke_arn + enable_xray_tracing = var.tracing_mode == "Active" +} + +resource "aws_iam_role_policy_attachment" "hello-lambda-cloudwatch" { + role = module.hello-lambda-function.lambda_function_name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" +} + +resource "aws_iam_role_policy_attachment" "test_xray" { + role = module.hello-lambda-function.lambda_function_name + policy_arn = "arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess" +} diff --git a/terraform/python/lambda/lambda/outputs.tf b/terraform/python/lambda/lambda/outputs.tf new file mode 100644 index 000000000..5de8044c9 --- /dev/null +++ b/terraform/python/lambda/lambda/outputs.tf @@ -0,0 +1,7 @@ +output "api-gateway-url" { + value = module.api-gateway.api_gateway_url +} + +output "function_role_name" { + value = module.hello-lambda-function.lambda_role_name +} diff --git a/terraform/python/lambda/lambda/variables.tf b/terraform/python/lambda/lambda/variables.tf new file mode 100644 index 000000000..1766306b7 --- /dev/null +++ b/terraform/python/lambda/lambda/variables.tf @@ -0,0 +1,41 @@ +variable "function_name" { + type = string + description = "Name of sample app function / API gateway" + default = "aws-opentelemetry-distro-nodejs" +} + +variable "sdk_layer_name" { + type = string + description = "Name of published SDK layer" + default = "AWSOpenTelemetryDistroPython" +} + +variable "tracing_mode" { + type = string + description = "Lambda function tracing mode" + default = "Active" +} + +variable "runtime" { + type = string + description = "Python runtime version used for sample Lambda Function" + default = "python3.12" +} + +variable "architecture" { + type = string + description = "Lambda function architecture, valid values are arm64 or x86_64" + default = "x86_64" +} + +variable "is_canary" { + type = bool + default = false + description = "Whether to create the resource or not" +} + +variable "layer_artifacts_directory" { + type = string + default = "./layer_artifacts" + description = "Lambda layer and function artifacts directory" +} diff --git a/validator/src/main/java/com/amazon/aoc/fileconfigs/PredefinedExpectedTemplate.java b/validator/src/main/java/com/amazon/aoc/fileconfigs/PredefinedExpectedTemplate.java index dfe3efd3c..86da0bfa5 100644 --- a/validator/src/main/java/com/amazon/aoc/fileconfigs/PredefinedExpectedTemplate.java +++ b/validator/src/main/java/com/amazon/aoc/fileconfigs/PredefinedExpectedTemplate.java @@ -351,6 +351,13 @@ public enum PredefinedExpectedTemplate implements FileConfig { NODE_LAMBDA_INVOKE_TRACE("/expected-data-template/node/lambda/lambda-invoke-trace.mustache"), NODE_LAMBDA_AWS_SDK_CALL_LOG("/expected-data-template/node/lambda/aws-sdk-call-log.mustache"), NODE_LAMBDA_AWS_SDK_CALL_METRIC("/expected-data-template/node/lambda/aws-sdk-call-metric.mustache"), + + /** Node Lambda Test Case Validations */ + PYTHON_LAMBDA_INVOKE_LOG("/expected-data-template/python/lambda/lambda-invoke-log.mustache"), + PYTHON_LAMBDA_INVOKE_METRIC("/expected-data-template/python/lambda/lambda-invoke-metric.mustache"), + PYTHON_LAMBDA_INVOKE_TRACE("/expected-data-template/python/lambda/lambda-invoke-trace.mustache"), + PYTHON_LAMBDA_AWS_SDK_CALL_LOG("/expected-data-template/python/lambda/aws-sdk-call-log.mustache"), + PYTHON_LAMBDA_AWS_SDK_CALL_METRIC("/expected-data-template/python/lambda/aws-sdk-call-metric.mustache"), ; private String path; diff --git a/validator/src/main/resources/expected-data-template/python/lambda/aws-sdk-call-log.mustache b/validator/src/main/resources/expected-data-template/python/lambda/aws-sdk-call-log.mustache new file mode 100644 index 000000000..7ee9de180 --- /dev/null +++ b/validator/src/main/resources/expected-data-template/python/lambda/aws-sdk-call-log.mustache @@ -0,0 +1,9 @@ +[{ + "Environment": "^lambda:default$", + "PlatformType": "^AWS:Lambda$", + "Operation": "^{{serviceName}}/Handler", + "Service": "^{{serviceName}}$", + "RemoteService": "AWS::S3", + "RemoteOperation": "ListBuckets", + "Lambda.Function.Name": "^{{serviceName}}$" +}] \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/python/lambda/aws-sdk-call-metric.mustache b/validator/src/main/resources/expected-data-template/python/lambda/aws-sdk-call-metric.mustache new file mode 100644 index 000000000..a9feeb3f7 --- /dev/null +++ b/validator/src/main/resources/expected-data-template/python/lambda/aws-sdk-call-metric.mustache @@ -0,0 +1,227 @@ +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: {{serviceName}}/Handler + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: {{serviceName}}/Handler + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + - + name: RemoteOperation + value: ListBuckets + - + name: RemoteService + value: AWS::S3 + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + - + name: RemoteService + value: AWS::S3 + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + - + name: RemoteOperation + value: ListBuckets + - + name: RemoteService + value: AWS::S3 + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: {{serviceName}}/Handler + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: {{serviceName}}/Handler + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + - + name: RemoteOperation + value: ListBuckets + - + name: RemoteService + value: AWS::S3 + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + - + name: RemoteService + value: AWS::S3 + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + - + name: RemoteOperation + value: ListBuckets + - + name: RemoteService + value: AWS::S3 + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: {{serviceName}}/Handler + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: {{serviceName}}/Handler + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + - + name: RemoteOperation + value: ListBuckets + - + name: RemoteService + value: AWS::S3 + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + - + name: RemoteService + value: AWS::S3 + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + - + name: RemoteOperation + value: ListBuckets + - + name: RemoteService + value: AWS::S3 diff --git a/validator/src/main/resources/expected-data-template/python/lambda/aws-sdk-call-trace.mustache b/validator/src/main/resources/expected-data-template/python/lambda/aws-sdk-call-trace.mustache new file mode 100644 index 000000000..75050a440 --- /dev/null +++ b/validator/src/main/resources/expected-data-template/python/lambda/aws-sdk-call-trace.mustache @@ -0,0 +1,65 @@ +[{ + "name": "^{{serviceName}}$", + "http": { + "request": { + "url": "^{{endpoint}}/aws-sdk-call\\?ip=(([0-9]{1,3}.){3}[0-9]{1,3})&testingId={{testingId}}$", + "method": "^GET$" + }, + "response": { + "status": "^200$" + } + }, + "aws": { + "account_id": "^{{accountId}}$" + }, + "annotations": { + "aws.local.service": "^{{serviceName}}$", + "aws.local.operation": "^GET aws-sdk-call$", + "aws.local.environment": "^ec2:default$" + }, + "metadata": { + "default": { + "EC2.InstanceId": "^{{instanceId}}$", + "PlatformType": "^AWS::EC2$", + "otel.resource.host.image.id": "^{{instanceAmi}}$", + "otel.resource.host.type": "^([a-z0-9]+\\.[a-z0-9]+)$", + "aws.span.kind": "^LOCAL_ROOT$" + } + }, + "subsegments": [ + { + "name": "^S3$", + "http": { + "response": { + "status": "^404$" + } + }, + "aws": { + "operation": "^GetBucketLocation$" + }, + "annotations": { + "aws.local.service": "^{{serviceName}}$", + "aws.local.operation": "^GET aws-sdk-call$", + "aws.remote.service": "^AWS::S3$", + "aws.remote.operation": "^GetBucketLocation$", + "aws.remote.resource.type": "^AWS::S3::Bucket$", + "aws.remote.resource.identifier": "^e2e-test-bucket-name-{{testingId}}$", + "aws.local.environment": "^ec2:default$" + }, + "metadata": { + "default": { + "EC2.InstanceId": "^{{instanceId}}$", + "PlatformType": "^AWS::EC2$", + "aws.span.kind": "^CLIENT$" + } + }, + "namespace": "^aws$" + } + ] +}, +{ + "name": "^S3$", + "aws": { + "operation": "^GetBucketLocation$" + } +}] \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/python/lambda/lambda-invoke-log.mustache b/validator/src/main/resources/expected-data-template/python/lambda/lambda-invoke-log.mustache new file mode 100644 index 000000000..1f9e41284 --- /dev/null +++ b/validator/src/main/resources/expected-data-template/python/lambda/lambda-invoke-log.mustache @@ -0,0 +1,7 @@ +[{ + "Environment": "^lambda:default$", + "Operation": "^{{serviceName}}/Handler", + "PlatformType": "^AWS:Lambda$", + "Service": "^{{serviceName}}$", + "Lambda.Function.Name": "^{{serviceName}}$" +}] \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/python/lambda/lambda-invoke-metric.mustache b/validator/src/main/resources/expected-data-template/python/lambda/lambda-invoke-metric.mustache new file mode 100644 index 000000000..8c4c183bd --- /dev/null +++ b/validator/src/main/resources/expected-data-template/python/lambda/lambda-invoke-metric.mustache @@ -0,0 +1,74 @@ +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Operation + value: {{serviceName}}/Handler + - + name: Environment + value: lambda:default + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Operation + value: {{serviceName}}/Handler + - + name: Environment + value: lambda:default + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: lambda:default + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Operation + value: {{serviceName}}/Handler + - + name: Environment + value: lambda:default diff --git a/validator/src/main/resources/expected-data-template/python/lambda/lambda-invoke-trace.mustache b/validator/src/main/resources/expected-data-template/python/lambda/lambda-invoke-trace.mustache new file mode 100644 index 000000000..27afa67bc --- /dev/null +++ b/validator/src/main/resources/expected-data-template/python/lambda/lambda-invoke-trace.mustache @@ -0,0 +1,56 @@ +[{ + "name": "^{{serviceName}}$", + "annotations": { + "aws.local.service": "^{{serviceName}}$", + "aws.local.operation": "^InternalOperation$", + "aws.local.environment": "^ec2:default$" + }, + "metadata": { + "default": { + "otel.resource.host.image.id": "^{{instanceAmi}}$", + "otel.resource.host.type": "^([a-z0-9]+\\.[a-z0-9]+)$" + } + }, + "subsegments": [ + { + "name": "^local-root-client-call$", + "http": { + "request": { + "url": "^http://local-root-client-call/$", + "method": "^GET$" + } + }, + "annotations": { + "aws.local.service": "^{{serviceName}}$", + "aws.local.operation": "^InternalOperation$", + "aws.remote.service": "^local-root-client-call$", + "aws.remote.operation": "GET /", + "aws.local.environment": "^ec2:default$" + }, + "metadata": { + "default": { + "EC2.InstanceId": "^{{instanceId}}$", + "PlatformType": "^AWS::EC2$", + "aws.span.kind": "^LOCAL_ROOT$" + } + }, + "namespace": "^remote$" + } + ] +}, +{ + "name": "^local-root-client-call$", + "http": { + "request": { + "url": "^http://local-root-client-call/$", + "method": "^GET$" + }, + "response": { + "content_length": 0 + } + }, + "annotations": { + "aws.local.service": "^local-root-client-call$", + "aws.local.operation": "^GET /$" + } +}] \ No newline at end of file diff --git a/validator/src/main/resources/validations/python/lambda/log-validation.yml b/validator/src/main/resources/validations/python/lambda/log-validation.yml new file mode 100644 index 000000000..6692890c7 --- /dev/null +++ b/validator/src/main/resources/validations/python/lambda/log-validation.yml @@ -0,0 +1,10 @@ +- + validationType: "cw-log" + httpPath: "/lambda-invoke" + callingType: "lambda-invoke" + expectedLogStructureTemplate: "PYTHON_LAMBDA_INVOKE_LOG" +- + validationType: "cw-log" + httpPath: "/lambda-aws-sdk" + callingType: "lambda-aws-sdk" + expectedLogStructureTemplate: "PYTHON_LAMBDA_AWS_SDK_CALL_LOG" \ No newline at end of file diff --git a/validator/src/main/resources/validations/python/lambda/metric-validation.yml b/validator/src/main/resources/validations/python/lambda/metric-validation.yml new file mode 100644 index 000000000..9dcf97c50 --- /dev/null +++ b/validator/src/main/resources/validations/python/lambda/metric-validation.yml @@ -0,0 +1,11 @@ +- + validationType: "cw-metric" + httpPath: "/lambda-invoke" + callingType: "lambda-invoke" + expectedLogStructureTemplate: "PYTHON_LAMBDA_INVOKE_METRIC" + +- + validationType: "cw-metric" + httpPath: "/lambda-aws-sdk" + callingType: "lambda-aws-sdk" + expectedLogStructureTemplate: "PYTHON_LAMBDA_AWS_SDK_CALL_METRIC" \ No newline at end of file diff --git a/validator/src/main/resources/validations/python/lambda/trace-validation.yml b/validator/src/main/resources/validations/python/lambda/trace-validation.yml new file mode 100644 index 000000000..1d59d9c16 --- /dev/null +++ b/validator/src/main/resources/validations/python/lambda/trace-validation.yml @@ -0,0 +1,5 @@ +- + validationType: "trace" + httpPath: "/lambda-invoke" + callingType: "lambda-invoke" + expectedTraceTemplate: "PYTHON_LAMBDA_INVOKE_TRACE"