-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #603 from aws-observability/release/v1.31.x
Release/v1.31.x
- Loading branch information
Showing
332 changed files
with
42,287 additions
and
210 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
## This workflow aims to run the end-to-end tests in canary fashion to | ||
## test the prod artifacts for App Signals enablement. | ||
name: App Signals Enablement - E2E EKS Canary Testing | ||
on: | ||
schedule: | ||
- cron: '0/10 * * * *' # run the workflow every 10 minutes | ||
workflow_dispatch: # be able to run the workflow on demand | ||
|
||
concurrency: | ||
group: ${{ github.workflow }} | ||
cancel-in-progress: false | ||
|
||
permissions: | ||
id-token: write | ||
contents: read | ||
|
||
jobs: | ||
e2e-canary-test: | ||
uses: ./.github/workflows/appsignals-e2e-eks-test.yml | ||
secrets: inherit | ||
with: | ||
test-cluster-name: 'e2e-canary-test' | ||
caller-workflow-name: 'appsignals-e2e-eks-canary-test' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,273 @@ | ||
# This is a reusable workflow for running the E2E 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: App Signals Enablement E2E Testing - EKS | ||
on: | ||
workflow_call: | ||
inputs: | ||
test-cluster-name: | ||
required: true | ||
type: string | ||
appsignals-adot-image-name: | ||
required: false | ||
type: string | ||
caller-workflow-name: | ||
required: true | ||
type: string | ||
|
||
permissions: | ||
id-token: write | ||
contents: read | ||
|
||
env: | ||
AWS_DEFAULT_REGION: us-east-1 | ||
TEST_ACCOUNT: ${{ secrets.APP_SIGNALS_E2E_TEST_ACC }} | ||
ENABLEMENT_SCRIPT_S3_BUCKET: ${{ secrets.APP_SIGNALS_E2E_ENABLEMENT_SCRIPT }} | ||
SAMPLE_APP_NAMESPACE: sample-app-namespace | ||
SAMPLE_APP_FRONTEND_SERVICE_IMAGE: ${{ secrets.APP_SIGNALS_E2E_FE_SA_IMG }} | ||
SAMPLE_APP_REMOTE_SERVICE_IMAGE: ${{ secrets.APP_SIGNALS_E2E_RE_SA_IMG }} | ||
METRIC_NAMESPACE: AppSignals | ||
LOG_GROUP_NAME: /aws/appsignals/eks | ||
|
||
jobs: | ||
appsignals-e2e-test: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 0 | ||
|
||
- name: Generate testing id | ||
run: echo TESTING_ID="${{ github.run_id }}-${{ github.run_number }}" >> $GITHUB_ENV | ||
|
||
- name: Configure AWS Credentials | ||
uses: aws-actions/configure-aws-credentials@v4 | ||
with: | ||
role-to-assume: ${{ secrets.E2E_TEST_ROLE_ARN }} | ||
aws-region: ${{ env.AWS_DEFAULT_REGION }} | ||
|
||
# local directory to store the kubernetes config | ||
- name: Create kubeconfig directory | ||
run: mkdir -p ${{ github.workspace }}/.kube | ||
|
||
- name: Set KUBECONFIG environment variable | ||
run: echo KUBECONFIG="${{ github.workspace }}/.kube/config" >> $GITHUB_ENV | ||
|
||
- name: Set up kubeconfig | ||
run: aws eks update-kubeconfig --name ${{ inputs.test-cluster-name }} --region ${{ env.AWS_DEFAULT_REGION }} | ||
|
||
- name: Install eksctl | ||
run: | | ||
mkdir ${{ github.workspace }}/eksctl | ||
curl -sLO "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_Linux_amd64.tar.gz" | ||
tar -xzf eksctl_Linux_amd64.tar.gz -C ${{ github.workspace }}/eksctl && rm eksctl_Linux_amd64.tar.gz | ||
echo "${{ github.workspace }}/eksctl" >> $GITHUB_PATH | ||
- name: Create role for AWS access from the sample app | ||
id: create_service_account | ||
run: | | ||
eksctl create iamserviceaccount \ | ||
--name service-account-${{ env.TESTING_ID }} \ | ||
--namespace ${{ env.SAMPLE_APP_NAMESPACE }} \ | ||
--cluster ${{ inputs.test-cluster-name }} \ | ||
--role-name eks-s3-access-${{ env.TESTING_ID }} \ | ||
--attach-policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \ | ||
--region ${{ env.AWS_DEFAULT_REGION }} \ | ||
--approve | ||
- name: Set up terraform | ||
uses: hashicorp/setup-terraform@v2 | ||
with: | ||
terraform_wrapper: false | ||
|
||
- name: Deploy sample app via terraform | ||
working-directory: testing/terraform/eks | ||
run: | | ||
terraform init | ||
terraform validate | ||
terraform apply -auto-approve \ | ||
-var="test_id=${{ env.TESTING_ID }}" \ | ||
-var="kube_directory_path=${{ github.workspace }}/.kube" \ | ||
-var="eks_cluster_name=${{ inputs.test-cluster-name }}" \ | ||
-var="eks_cluster_context_name=$(kubectl config current-context)" \ | ||
-var="test_namespace=${{ env.SAMPLE_APP_NAMESPACE }}" \ | ||
-var="service_account_aws_access=service-account-${{ env.TESTING_ID }}" \ | ||
-var="sample_app_image=${{ env.SAMPLE_APP_FRONTEND_SERVICE_IMAGE }}" \ | ||
-var="sample_remote_app_image=${{ env.SAMPLE_APP_REMOTE_SERVICE_IMAGE }}" | ||
# Enable App Signals on the test cluster | ||
- name: Pull and unzip enablement script from S3 | ||
run: aws s3 cp ${{ env.ENABLEMENT_SCRIPT_S3_BUCKET }} . && unzip -j onboarding.zip | ||
|
||
- name: Change ADOT image if main-build | ||
if: inputs.caller-workflow-name == 'main-build' | ||
run: "sed -i 's#image:.*#image: ${{ inputs.appsignals-adot-image-name }}#g' instrumentation.yaml" | ||
|
||
- name: Enable App Signals | ||
run: | | ||
./enable-app-signals.sh \ | ||
${{ inputs.test-cluster-name }} \ | ||
${{ env.AWS_DEFAULT_REGION }} \ | ||
${{ env.SAMPLE_APP_NAMESPACE }} | ||
# Application pods need to be restarted for the | ||
# app signals instrumentation to take effect | ||
- name: Restart the app pods | ||
run: kubectl delete pods --all -n ${{ env.SAMPLE_APP_NAMESPACE }} | ||
|
||
- name: Wait for sample app pods to come up | ||
run: | | ||
kubectl wait --for=condition=Ready pod --all -n ${{ env.SAMPLE_APP_NAMESPACE }} | ||
- name: Get remote service pod name and IP | ||
run: | | ||
echo "REMOTE_SERVICE_DEPLOYMENT_NAME=$(kubectl get deployments -n ${{ env.SAMPLE_APP_NAMESPACE }} --selector=app=remote-app -o jsonpath='{.items[0].metadata.name}')" >> $GITHUB_ENV | ||
echo "REMOTE_SERVICE_POD_IP=$(kubectl get pods -n ${{ env.SAMPLE_APP_NAMESPACE }} --selector=app=remote-app -o jsonpath='{.items[0].status.podIP}')" >> $GITHUB_ENV | ||
- name: Verify pod Adot image | ||
run: | | ||
kubectl get pods -n ${{ env.SAMPLE_APP_NAMESPACE }} --output json | \ | ||
jq '.items[0].status.initContainerStatuses[0].imageID' | ||
- name: Verify pod CWAgent image | ||
run: | | ||
kubectl get pods -n amazon-cloudwatch --output json | \ | ||
jq '.items[0].status.containerStatuses[0].imageID' | ||
- name: Get the sample app endpoint | ||
run: | | ||
echo "APP_ENDPOINT=$(terraform output sample_app_endpoint)" >> $GITHUB_ENV | ||
working-directory: testing/terraform/eks | ||
|
||
- name: Wait for app endpoint to come online | ||
id: endpoint-check | ||
run: | | ||
attempt_counter=0 | ||
max_attempts=30 | ||
until $(curl --output /dev/null --silent --head --fail http://${{ env.APP_ENDPOINT }}); do | ||
if [ ${attempt_counter} -eq ${max_attempts} ];then | ||
echo "Max attempts reached" | ||
exit 1 | ||
fi | ||
printf '.' | ||
attempt_counter=$(($attempt_counter+1)) | ||
sleep 10 | ||
done | ||
# Validation for app signals telemetry data | ||
- name: Call endpoint and validate generated EMF logs | ||
id: log-validation | ||
if: steps.endpoint-check.outcome == 'success' && !cancelled() | ||
run: ./gradlew testing:validator:run --args='-c log-validation.yml | ||
--testing-id ${{ env.TESTING_ID }} | ||
--endpoint http://${{ env.APP_ENDPOINT }} | ||
--region ${{ env.AWS_DEFAULT_REGION }} | ||
--account-id ${{ env.TEST_ACCOUNT }} | ||
--metric-namespace ${{ env.METRIC_NAMESPACE }} | ||
--log-group ${{ env.LOG_GROUP_NAME }} | ||
--app-namespace ${{ env.SAMPLE_APP_NAMESPACE }} | ||
--cluster ${{ inputs.test-cluster-name }} | ||
--service-name sample-application-${{ env.TESTING_ID }} | ||
--remote-service-deployment-name ${{ env.REMOTE_SERVICE_DEPLOYMENT_NAME }} | ||
--request-body ip=${{ env.REMOTE_SERVICE_POD_IP }} | ||
--rollup' | ||
|
||
- name: Call endpoints and validate generated metrics | ||
id: metric-validation | ||
if: (success() || steps.log-validation.outcome == 'failure') && !cancelled() | ||
run: ./gradlew testing:validator:run --args='-c metric-validation.yml | ||
--testing-id ${{ env.TESTING_ID }} | ||
--endpoint http://${{ env.APP_ENDPOINT }} | ||
--region ${{ env.AWS_DEFAULT_REGION }} | ||
--account-id ${{ env.TEST_ACCOUNT }} | ||
--metric-namespace ${{ env.METRIC_NAMESPACE }} | ||
--log-group ${{ env.LOG_GROUP_NAME }} | ||
--app-namespace ${{ env.SAMPLE_APP_NAMESPACE }} | ||
--cluster ${{ inputs.test-cluster-name }} | ||
--service-name sample-application-${{ env.TESTING_ID }} | ||
--remote-service-name sample-remote-application-${{ env.TESTING_ID }} | ||
--remote-service-deployment-name ${{ env.REMOTE_SERVICE_DEPLOYMENT_NAME }} | ||
--request-body ip=${{ env.REMOTE_SERVICE_POD_IP }} | ||
--rollup' | ||
|
||
- name: Call endpoints and validate generated traces | ||
id: trace-validation | ||
if: (success() || steps.log-validation.outcome == 'failure' || steps.metric-validation.outcome == 'failure') && !cancelled() | ||
run: ./gradlew testing:validator:run --args='-c trace-validation.yml | ||
--testing-id ${{ env.TESTING_ID }} | ||
--endpoint http://${{ env.APP_ENDPOINT }} | ||
--region ${{ env.AWS_DEFAULT_REGION }} | ||
--account-id ${{ env.TEST_ACCOUNT }} | ||
--metric-namespace ${{ env.METRIC_NAMESPACE }} | ||
--log-group ${{ env.LOG_GROUP_NAME }} | ||
--app-namespace ${{ env.SAMPLE_APP_NAMESPACE }} | ||
--cluster ${{ inputs.test-cluster-name }} | ||
--service-name sample-application-${{ env.TESTING_ID }} | ||
--remote-service-deployment-name ${{ env.REMOTE_SERVICE_DEPLOYMENT_NAME }} | ||
--request-body ip=${{ env.REMOTE_SERVICE_POD_IP }} | ||
--rollup' | ||
|
||
- name: Publish metric on test result | ||
if: always() | ||
run: | | ||
if [[ "${{ steps.log-validation.outcome }}" == "success" && "${{ steps.metric-validation.outcome }}" == "success" && "${{ steps.trace-validation.outcome }}" == "success" ]]; then | ||
aws cloudwatch put-metric-data --namespace 'ADOT/GitHubActions' \ | ||
--metric-name Success \ | ||
--dimensions repository=${{ github.repository }},branch=${{ github.ref_name }},workflow=${{ inputs.caller-workflow-name }} \ | ||
--value 1.0 \ | ||
--region us-west-2 | ||
else | ||
aws cloudwatch put-metric-data --namespace 'ADOT/GitHubActions' \ | ||
--metric-name Success \ | ||
--dimensions repository=${{ github.repository }},branch=${{ github.ref_name }},workflow=${{ inputs.caller-workflow-name }} \ | ||
--value 0.0 \ | ||
--region us-west-2 | ||
fi | ||
# Clean up Procedures | ||
|
||
- name: Remove log group deletion command | ||
if: always() | ||
run: | | ||
delete_log_group="aws logs delete-log-group --log-group-name '${{ env.LOG_GROUP_NAME }}' --region \$REGION" | ||
sed -i "s#$delete_log_group##g" clean-app-signals.sh | ||
- name: Clean Up App Signals | ||
if: always() | ||
continue-on-error: true | ||
run: | | ||
./clean-app-signals.sh \ | ||
${{ inputs.test-cluster-name }} \ | ||
${{ env.AWS_DEFAULT_REGION }} \ | ||
${{ env.SAMPLE_APP_NAMESPACE }} | ||
# This step also deletes lingering resources from previous test runs | ||
- name: Delete all sample app resources | ||
if: always() | ||
continue-on-error: true | ||
timeout-minutes: 10 | ||
run: kubectl delete namespace ${{ env.SAMPLE_APP_NAMESPACE }} | ||
|
||
- name: Terraform destroy | ||
if: always() | ||
continue-on-error: true | ||
working-directory: testing/terraform/eks | ||
run: | | ||
terraform destroy -auto-approve \ | ||
-var="test_id=${{ env.TESTING_ID }}" \ | ||
-var="kube_directory_path=${{ github.workspace }}/.kube" \ | ||
-var="eks_cluster_name=${{ inputs.test-cluster-name }}" \ | ||
-var="test_namespace=${{ env.SAMPLE_APP_NAMESPACE }}" \ | ||
-var="service_account_aws_access=service-account-${{ env.TESTING_ID }}" \ | ||
-var="sample_app_image=${{ env.SAMPLE_APP_IMAGE }}" | ||
- name: Remove aws access service account | ||
if: always() | ||
continue-on-error: true | ||
run: | | ||
eksctl delete iamserviceaccount \ | ||
--name service-account-${{ env.TESTING_ID }} \ | ||
--namespace ${{ env.SAMPLE_APP_NAMESPACE }} \ | ||
--cluster ${{ inputs.test-cluster-name }} \ | ||
--region ${{ env.AWS_DEFAULT_REGION }} \ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# Introduction | ||
|
||
This directory contain tests that are used exclusively for appsignals: | ||
* Contract tests for semantic conventions. | ||
* Contract tests for appsignals specific attributes. | ||
|
||
# How it works? | ||
|
||
The tests present here rely on the auto-instrumentation of a sample application which will send telemetry signals to | ||
a mock collector. The tests will use the data collected by the mock collector to perform assertions and validate that | ||
the contracts are being respected. | ||
|
||
|
||
# Types of tested frameworks | ||
|
||
The frameworks and libraries that are tested in the contract tests should fall in the following categories (more can be added on demand): | ||
* http-servers - applications meant to test http servers. | ||
* http-clients - applications meant to test http clients. | ||
* aws-sdk - Applications meant to test the AWS SDK | ||
* pub-sub - Asynchronous type of application where you typically have a publisher and a subscriber communicating using a message broker. | ||
|
||
When testing a framework, we will create a sample application. The sample applications are stored following this | ||
convention: `appsignals-tests/images/<application-type>/<framework-name>` | ||
|
||
# Adding tests for a new library or framework | ||
|
||
The steps to add a new test for a library or framework are: | ||
|
||
* Create a sample application that can be run inside a docker image using Jib. | ||
* The sample application should be its own gradlew subproject. (you need to add it to `settings.gradle.kts` in the root of this project) | ||
* The sample application should be located in the directory `appsignals-tests/images/<application-type>/<framework-name>` | ||
* Add a test class for the sample application. | ||
* The test class should created in `appsignals-tests/contract/tests`. | ||
* The name of the java package for the test classes should follow this convention: `software.amazon.opentelemetry.appsignals.test.<application-type>` | ||
|
||
# How to run the tests locally? | ||
|
||
Pre-requirements: | ||
* Ensure Docker is running on your machine. | ||
* Ensure AWS credentials are exported to environment variables. | ||
|
||
From the root of this project execute: | ||
|
||
``` | ||
## login to public ECR | ||
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws | ||
# Run the tests | ||
./gradlew appsignals-tests:contract-tests:contractTests | ||
``` |
Oops, something went wrong.