Skip to content

Commit b110435

Browse files
authored
Prepare 1.31.1 release (#596)
1 parent 6862d20 commit b110435

File tree

332 files changed

+42208
-210
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

332 files changed

+42208
-210
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
## This workflow aims to run the end-to-end tests in canary fashion to
2+
## test the prod artifacts for App Signals enablement.
3+
name: App Signals Enablement - E2E EKS Canary Testing
4+
on:
5+
schedule:
6+
- cron: '0/10 * * * *' # run the workflow every 10 minutes
7+
workflow_dispatch: # be able to run the workflow on demand
8+
9+
concurrency:
10+
group: ${{ github.workflow }}
11+
cancel-in-progress: false
12+
13+
permissions:
14+
id-token: write
15+
contents: read
16+
17+
jobs:
18+
e2e-canary-test:
19+
uses: ./.github/workflows/appsignals-e2e-eks-test.yml
20+
secrets: inherit
21+
with:
22+
test-cluster-name: 'e2e-canary-test'
23+
caller-workflow-name: 'appsignals-e2e-eks-canary-test'
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
# This is a reusable workflow for running the E2E test for App Signals.
2+
# It is meant to be called from another workflow.
3+
# Read more about reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview
4+
name: App Signals Enablement E2E Testing - EKS
5+
on:
6+
workflow_call:
7+
inputs:
8+
test-cluster-name:
9+
required: true
10+
type: string
11+
appsignals-adot-image-name:
12+
required: false
13+
type: string
14+
caller-workflow-name:
15+
required: true
16+
type: string
17+
18+
permissions:
19+
id-token: write
20+
contents: read
21+
22+
env:
23+
AWS_DEFAULT_REGION: us-east-1
24+
TEST_ACCOUNT: ${{ secrets.APP_SIGNALS_E2E_TEST_ACC }}
25+
ENABLEMENT_SCRIPT_S3_BUCKET: ${{ secrets.APP_SIGNALS_E2E_ENABLEMENT_SCRIPT }}
26+
SAMPLE_APP_NAMESPACE: sample-app-namespace
27+
SAMPLE_APP_FRONTEND_SERVICE_IMAGE: ${{ secrets.APP_SIGNALS_E2E_FE_SA_IMG }}
28+
SAMPLE_APP_REMOTE_SERVICE_IMAGE: ${{ secrets.APP_SIGNALS_E2E_RE_SA_IMG }}
29+
METRIC_NAMESPACE: AppSignals
30+
LOG_GROUP_NAME: /aws/appsignals/eks
31+
32+
jobs:
33+
appsignals-e2e-test:
34+
runs-on: ubuntu-latest
35+
steps:
36+
- uses: actions/checkout@v4
37+
with:
38+
fetch-depth: 0
39+
40+
- name: Generate testing id
41+
run: echo TESTING_ID="${{ github.run_id }}-${{ github.run_number }}" >> $GITHUB_ENV
42+
43+
- name: Configure AWS Credentials
44+
uses: aws-actions/configure-aws-credentials@v4
45+
with:
46+
role-to-assume: ${{ secrets.E2E_TEST_ROLE_ARN }}
47+
aws-region: ${{ env.AWS_DEFAULT_REGION }}
48+
49+
# local directory to store the kubernetes config
50+
- name: Create kubeconfig directory
51+
run: mkdir -p ${{ github.workspace }}/.kube
52+
53+
- name: Set KUBECONFIG environment variable
54+
run: echo KUBECONFIG="${{ github.workspace }}/.kube/config" >> $GITHUB_ENV
55+
56+
- name: Set up kubeconfig
57+
run: aws eks update-kubeconfig --name ${{ inputs.test-cluster-name }} --region ${{ env.AWS_DEFAULT_REGION }}
58+
59+
- name: Install eksctl
60+
run: |
61+
mkdir ${{ github.workspace }}/eksctl
62+
curl -sLO "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_Linux_amd64.tar.gz"
63+
tar -xzf eksctl_Linux_amd64.tar.gz -C ${{ github.workspace }}/eksctl && rm eksctl_Linux_amd64.tar.gz
64+
echo "${{ github.workspace }}/eksctl" >> $GITHUB_PATH
65+
66+
- name: Create role for AWS access from the sample app
67+
id: create_service_account
68+
run: |
69+
eksctl create iamserviceaccount \
70+
--name service-account-${{ env.TESTING_ID }} \
71+
--namespace ${{ env.SAMPLE_APP_NAMESPACE }} \
72+
--cluster ${{ inputs.test-cluster-name }} \
73+
--role-name eks-s3-access-${{ env.TESTING_ID }} \
74+
--attach-policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
75+
--region ${{ env.AWS_DEFAULT_REGION }} \
76+
--approve
77+
78+
- name: Set up terraform
79+
uses: hashicorp/setup-terraform@v2
80+
with:
81+
terraform_wrapper: false
82+
83+
- name: Deploy sample app via terraform
84+
working-directory: testing/terraform/eks
85+
run: |
86+
terraform init
87+
terraform validate
88+
terraform apply -auto-approve \
89+
-var="test_id=${{ env.TESTING_ID }}" \
90+
-var="kube_directory_path=${{ github.workspace }}/.kube" \
91+
-var="eks_cluster_name=${{ inputs.test-cluster-name }}" \
92+
-var="eks_cluster_context_name=$(kubectl config current-context)" \
93+
-var="test_namespace=${{ env.SAMPLE_APP_NAMESPACE }}" \
94+
-var="service_account_aws_access=service-account-${{ env.TESTING_ID }}" \
95+
-var="sample_app_image=${{ env.SAMPLE_APP_FRONTEND_SERVICE_IMAGE }}" \
96+
-var="sample_remote_app_image=${{ env.SAMPLE_APP_REMOTE_SERVICE_IMAGE }}"
97+
98+
# Enable App Signals on the test cluster
99+
- name: Pull and unzip enablement script from S3
100+
run: aws s3 cp ${{ env.ENABLEMENT_SCRIPT_S3_BUCKET }} . && unzip -j onboarding.zip
101+
102+
- name: Change ADOT image if main-build
103+
if: inputs.caller-workflow-name == 'main-build'
104+
run: "sed -i 's#image:.*#image: ${{ inputs.appsignals-adot-image-name }}#g' instrumentation.yaml"
105+
106+
- name: Enable App Signals
107+
run: |
108+
./enable-app-signals.sh \
109+
${{ inputs.test-cluster-name }} \
110+
${{ env.AWS_DEFAULT_REGION }} \
111+
${{ env.SAMPLE_APP_NAMESPACE }}
112+
113+
# Application pods need to be restarted for the
114+
# app signals instrumentation to take effect
115+
- name: Restart the app pods
116+
run: kubectl delete pods --all -n ${{ env.SAMPLE_APP_NAMESPACE }}
117+
118+
- name: Wait for sample app pods to come up
119+
run: |
120+
kubectl wait --for=condition=Ready pod --all -n ${{ env.SAMPLE_APP_NAMESPACE }}
121+
122+
- name: Get remote service pod name and IP
123+
run: |
124+
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
125+
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
126+
127+
- name: Verify pod Adot image
128+
run: |
129+
kubectl get pods -n ${{ env.SAMPLE_APP_NAMESPACE }} --output json | \
130+
jq '.items[0].status.initContainerStatuses[0].imageID'
131+
132+
- name: Verify pod CWAgent image
133+
run: |
134+
kubectl get pods -n amazon-cloudwatch --output json | \
135+
jq '.items[0].status.containerStatuses[0].imageID'
136+
137+
- name: Get the sample app endpoint
138+
run: |
139+
echo "APP_ENDPOINT=$(terraform output sample_app_endpoint)" >> $GITHUB_ENV
140+
working-directory: testing/terraform/eks
141+
142+
- name: Wait for app endpoint to come online
143+
id: endpoint-check
144+
run: |
145+
attempt_counter=0
146+
max_attempts=30
147+
until $(curl --output /dev/null --silent --head --fail http://${{ env.APP_ENDPOINT }}); do
148+
if [ ${attempt_counter} -eq ${max_attempts} ];then
149+
echo "Max attempts reached"
150+
exit 1
151+
fi
152+
153+
printf '.'
154+
attempt_counter=$(($attempt_counter+1))
155+
sleep 10
156+
done
157+
158+
# Validation for app signals telemetry data
159+
- name: Call endpoint and validate generated EMF logs
160+
id: log-validation
161+
if: steps.endpoint-check.outcome == 'success' && !cancelled()
162+
run: ./gradlew testing:validator:run --args='-c log-validation.yml
163+
--testing-id ${{ env.TESTING_ID }}
164+
--endpoint http://${{ env.APP_ENDPOINT }}
165+
--region ${{ env.AWS_DEFAULT_REGION }}
166+
--account-id ${{ env.TEST_ACCOUNT }}
167+
--metric-namespace ${{ env.METRIC_NAMESPACE }}
168+
--log-group ${{ env.LOG_GROUP_NAME }}
169+
--app-namespace ${{ env.SAMPLE_APP_NAMESPACE }}
170+
--cluster ${{ inputs.test-cluster-name }}
171+
--service-name sample-application-${{ env.TESTING_ID }}
172+
--remote-service-deployment-name ${{ env.REMOTE_SERVICE_DEPLOYMENT_NAME }}
173+
--request-body ip=${{ env.REMOTE_SERVICE_POD_IP }}
174+
--rollup'
175+
176+
- name: Call endpoints and validate generated metrics
177+
id: metric-validation
178+
if: (success() || steps.log-validation.outcome == 'failure') && !cancelled()
179+
run: ./gradlew testing:validator:run --args='-c metric-validation.yml
180+
--testing-id ${{ env.TESTING_ID }}
181+
--endpoint http://${{ env.APP_ENDPOINT }}
182+
--region ${{ env.AWS_DEFAULT_REGION }}
183+
--account-id ${{ env.TEST_ACCOUNT }}
184+
--metric-namespace ${{ env.METRIC_NAMESPACE }}
185+
--log-group ${{ env.LOG_GROUP_NAME }}
186+
--app-namespace ${{ env.SAMPLE_APP_NAMESPACE }}
187+
--cluster ${{ inputs.test-cluster-name }}
188+
--service-name sample-application-${{ env.TESTING_ID }}
189+
--remote-service-name sample-remote-application-${{ env.TESTING_ID }}
190+
--remote-service-deployment-name ${{ env.REMOTE_SERVICE_DEPLOYMENT_NAME }}
191+
--request-body ip=${{ env.REMOTE_SERVICE_POD_IP }}
192+
--rollup'
193+
194+
- name: Call endpoints and validate generated traces
195+
id: trace-validation
196+
if: (success() || steps.log-validation.outcome == 'failure' || steps.metric-validation.outcome == 'failure') && !cancelled()
197+
run: ./gradlew testing:validator:run --args='-c trace-validation.yml
198+
--testing-id ${{ env.TESTING_ID }}
199+
--endpoint http://${{ env.APP_ENDPOINT }}
200+
--region ${{ env.AWS_DEFAULT_REGION }}
201+
--account-id ${{ env.TEST_ACCOUNT }}
202+
--metric-namespace ${{ env.METRIC_NAMESPACE }}
203+
--log-group ${{ env.LOG_GROUP_NAME }}
204+
--app-namespace ${{ env.SAMPLE_APP_NAMESPACE }}
205+
--cluster ${{ inputs.test-cluster-name }}
206+
--service-name sample-application-${{ env.TESTING_ID }}
207+
--remote-service-deployment-name ${{ env.REMOTE_SERVICE_DEPLOYMENT_NAME }}
208+
--request-body ip=${{ env.REMOTE_SERVICE_POD_IP }}
209+
--rollup'
210+
211+
- name: Publish metric on test result
212+
if: always()
213+
run: |
214+
if [[ "${{ steps.log-validation.outcome }}" == "success" && "${{ steps.metric-validation.outcome }}" == "success" && "${{ steps.trace-validation.outcome }}" == "success" ]]; then
215+
aws cloudwatch put-metric-data --namespace 'ADOT/GitHubActions' \
216+
--metric-name Success \
217+
--dimensions repository=${{ github.repository }},branch=${{ github.ref_name }},workflow=${{ inputs.caller-workflow-name }} \
218+
--value 1.0 \
219+
--region us-west-2
220+
else
221+
aws cloudwatch put-metric-data --namespace 'ADOT/GitHubActions' \
222+
--metric-name Success \
223+
--dimensions repository=${{ github.repository }},branch=${{ github.ref_name }},workflow=${{ inputs.caller-workflow-name }} \
224+
--value 0.0 \
225+
--region us-west-2
226+
fi
227+
228+
# Clean up Procedures
229+
230+
- name: Remove log group deletion command
231+
if: always()
232+
run: |
233+
delete_log_group="aws logs delete-log-group --log-group-name '${{ env.LOG_GROUP_NAME }}' --region \$REGION"
234+
sed -i "s#$delete_log_group##g" clean-app-signals.sh
235+
236+
- name: Clean Up App Signals
237+
if: always()
238+
continue-on-error: true
239+
run: |
240+
./clean-app-signals.sh \
241+
${{ inputs.test-cluster-name }} \
242+
${{ env.AWS_DEFAULT_REGION }} \
243+
${{ env.SAMPLE_APP_NAMESPACE }}
244+
245+
# This step also deletes lingering resources from previous test runs
246+
- name: Delete all sample app resources
247+
if: always()
248+
continue-on-error: true
249+
timeout-minutes: 10
250+
run: kubectl delete namespace ${{ env.SAMPLE_APP_NAMESPACE }}
251+
252+
- name: Terraform destroy
253+
if: always()
254+
continue-on-error: true
255+
working-directory: testing/terraform/eks
256+
run: |
257+
terraform destroy -auto-approve \
258+
-var="test_id=${{ env.TESTING_ID }}" \
259+
-var="kube_directory_path=${{ github.workspace }}/.kube" \
260+
-var="eks_cluster_name=${{ inputs.test-cluster-name }}" \
261+
-var="test_namespace=${{ env.SAMPLE_APP_NAMESPACE }}" \
262+
-var="service_account_aws_access=service-account-${{ env.TESTING_ID }}" \
263+
-var="sample_app_image=${{ env.SAMPLE_APP_IMAGE }}"
264+
265+
- name: Remove aws access service account
266+
if: always()
267+
continue-on-error: true
268+
run: |
269+
eksctl delete iamserviceaccount \
270+
--name service-account-${{ env.TESTING_ID }} \
271+
--namespace ${{ env.SAMPLE_APP_NAMESPACE }} \
272+
--cluster ${{ inputs.test-cluster-name }} \
273+
--region ${{ env.AWS_DEFAULT_REGION }} \

.github/workflows/main-build.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ jobs:
104104
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
105105
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
106106

107+
- name: Pull base image of Contract Tests Sample Apps
108+
run: docker pull public.ecr.aws/docker/library/amazoncorretto:17-alpine
109+
110+
- name: Run contract tests
111+
uses: gradle/gradle-build-action@v2
112+
with:
113+
arguments: contractTests -PlocalDocker=true
114+
107115
- name: Get current version
108116
shell: bash
109117
run: |
@@ -443,6 +451,15 @@ jobs:
443451
APP_IMAGE: public.ecr.aws/aws-otel-test/aws-otel-java-spark-awssdkv1:${{ github.sha }}
444452
VALIDATOR_COMMAND: -c spark-otel-trace-metric-validation.yml --endpoint http://app:4567 --metric-namespace aws-otel-integ-test -t ${{ github.run_id }}-${{ github.run_number }}
445453

454+
e2e-test:
455+
needs: build
456+
uses: ./.github/workflows/appsignals-e2e-eks-test.yml
457+
secrets: inherit
458+
with:
459+
test-cluster-name: "e2e-adot-test"
460+
appsignals-adot-image-name: ${{ env.STAGING_ECR_REGISTRY }}/${{ env.STAGING_ECR_REPOSITORY }}:${{ needs.build.outputs.java_agent_tag }}
461+
caller-workflow-name: 'main-build'
462+
446463
publish-build-status:
447464
needs: [test_Spring_App_With_Java_Agent, test_Spark_App_With_Java_Agent, test_Spark_AWS_SDK_V1_App_With_Java_Agent, run-batch-job]
448465
if: ${{ always() }}

.github/workflows/pr-build.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ jobs:
8181
with:
8282
arguments: build integrationTests --stacktrace -PenableCoverage=true -PlocalDocker=true
8383

84+
- name: Pull base image of Contract Tests Sample Apps
85+
if: ${{ matrix.os == 'ubuntu-latest' }}
86+
run: docker pull public.ecr.aws/docker/library/amazoncorretto:17-alpine
87+
88+
- name: Run contract tests
89+
uses: gradle/gradle-build-action@v2
90+
if: ${{ matrix.os == 'ubuntu-latest' }}
91+
with:
92+
arguments: contractTests -PlocalDocker=true -i
93+
8494
- name: Get current version
8595
if: ${{ matrix.os == 'ubuntu-latest' }}
8696
shell: bash

appsignals-tests/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Introduction
2+
3+
This directory contain tests that are used exclusively for appsignals:
4+
* Contract tests for semantic conventions.
5+
* Contract tests for appsignals specific attributes.
6+
7+
# How it works?
8+
9+
The tests present here rely on the auto-instrumentation of a sample application which will send telemetry signals to
10+
a mock collector. The tests will use the data collected by the mock collector to perform assertions and validate that
11+
the contracts are being respected.
12+
13+
14+
# Types of tested frameworks
15+
16+
The frameworks and libraries that are tested in the contract tests should fall in the following categories (more can be added on demand):
17+
* http-servers - applications meant to test http servers.
18+
* http-clients - applications meant to test http clients.
19+
* aws-sdk - Applications meant to test the AWS SDK
20+
* pub-sub - Asynchronous type of application where you typically have a publisher and a subscriber communicating using a message broker.
21+
22+
When testing a framework, we will create a sample application. The sample applications are stored following this
23+
convention: `appsignals-tests/images/<application-type>/<framework-name>`
24+
25+
# Adding tests for a new library or framework
26+
27+
The steps to add a new test for a library or framework are:
28+
29+
* Create a sample application that can be run inside a docker image using Jib.
30+
* The sample application should be its own gradlew subproject. (you need to add it to `settings.gradle.kts` in the root of this project)
31+
* The sample application should be located in the directory `appsignals-tests/images/<application-type>/<framework-name>`
32+
* Add a test class for the sample application.
33+
* The test class should created in `appsignals-tests/contract/tests`.
34+
* The name of the java package for the test classes should follow this convention: `software.amazon.opentelemetry.appsignals.test.<application-type>`
35+
36+
# How to run the tests locally?
37+
38+
Pre-requirements:
39+
* Ensure Docker is running on your machine.
40+
* Ensure AWS credentials are exported to environment variables.
41+
42+
From the root of this project execute:
43+
44+
```
45+
## login to public ECR
46+
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws
47+
48+
# Run the tests
49+
./gradlew appsignals-tests:contract-tests:contractTests
50+
```

0 commit comments

Comments
 (0)