Skip to content

Commit 7cc5681

Browse files
committed
add node ecs test
1 parent 58c45c2 commit 7cc5681

File tree

13 files changed

+792
-0
lines changed

13 files changed

+792
-0
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
## SPDX-License-Identifier: Apache-2.0
3+
4+
## This workflow aims to run the Application Signals Python end-to-end tests as a canary to
5+
## test the artifacts for Application Signals enablement. It will deploy a sample app onto an ECS cluster,
6+
## call the APIs, and validate the generated telemetry, including logs, metrics, and traces.
7+
name: Node ECS Enablement Canary Testing
8+
on:
9+
push:
10+
branches:
11+
- add-node-ecs-test
12+
workflow_dispatch: # be able to run the workflow on demand
13+
14+
permissions:
15+
id-token: write
16+
contents: read
17+
18+
jobs:
19+
ecs:
20+
strategy:
21+
fail-fast: false
22+
matrix:
23+
aws-region: ['us-east-1']
24+
uses: ./.github/workflows/node-ecs-retry.yml
25+
secrets: inherit
26+
with:
27+
aws-region: ${{ matrix.aws-region }}
28+
caller-workflow-name: 'appsignals-e2e-node-ecs-release-test'
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
## SPDX-License-Identifier: Apache-2.0
3+
4+
# This is a reusable workflow for running the Enablement test for App Signals.
5+
# It is meant to be called from another workflow.
6+
# Read more about reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview
7+
name: Node ECS Retry
8+
on:
9+
workflow_call:
10+
inputs:
11+
aws-region:
12+
required: true
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+
jobs:
23+
node-ecs-attempt-1:
24+
uses: ./.github/workflows/node-ecs-test.yml
25+
secrets: inherit
26+
with:
27+
aws-region: ${{ inputs.aws-region }}
28+
caller-workflow-name: ${{ inputs.caller-workflow-name }}
29+
30+
node-ecs-attempt-2:
31+
needs: [ node-ecs-attempt-1 ]
32+
if: ${{ needs.node-ecs-attempt-1.outputs.job-started != 'true' }}
33+
uses: ./.github/workflows/node-ecs-test.yml
34+
secrets: inherit
35+
with:
36+
aws-region: ${{ inputs.aws-region }}
37+
caller-workflow-name: ${{ inputs.caller-workflow-name }}
38+
39+
publish-metric-attempt-1:
40+
needs: [ node-ecs-attempt-1, node-ecs-attempt-2 ]
41+
if: always()
42+
uses: ./.github/workflows/enablement-test-publish-result.yml
43+
secrets: inherit
44+
with:
45+
aws-region: ${{ inputs.aws-region }}
46+
caller-workflow-name: ${{ inputs.caller-workflow-name }}
47+
validation-result: ${{ needs.node-ecs-attempt-1.outputs.validation-result || needs.node-ecs-attempt-2.outputs.validation-result }}
48+
49+
publish-metric-attempt-2:
50+
needs: [ node-ecs-attempt-1, node-ecs-attempt-2, publish-metric-attempt-1 ]
51+
if: ${{ always() && needs.publish-metric-attempt-1.outputs.job-started != 'true' }}
52+
uses: ./.github/workflows/enablement-test-publish-result.yml
53+
secrets: inherit
54+
with:
55+
aws-region: ${{ inputs.aws-region }}
56+
caller-workflow-name: ${{ inputs.caller-workflow-name }}
57+
validation-result: ${{ needs.node-ecs-attempt-1.outputs.validation-result || needs.node-ecs-attempt-2.outputs.validation-result }}
Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
## SPDX-License-Identifier: Apache-2.0
3+
4+
# This is a reusable workflow for running the E2E test for App Signals.
5+
# It is meant to be called from another workflow.
6+
# Read more about reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview
7+
name: Node ECS Use Case
8+
on:
9+
workflow_call:
10+
inputs:
11+
aws-region:
12+
required: true
13+
type: string
14+
caller-workflow-name:
15+
required: true
16+
type: string
17+
adot-image-name:
18+
required: false
19+
type: string
20+
cwagent-image-name:
21+
required: false
22+
type: string
23+
outputs:
24+
job-started:
25+
value: ${{ jobs.node-ecs.outputs.job-started }}
26+
validation-result:
27+
value: ${{ jobs.node-ecs.outputs.validation-result }}
28+
29+
permissions:
30+
id-token: write
31+
contents: read
32+
33+
env:
34+
E2E_TEST_AWS_REGION: ${{ inputs.aws-region }}
35+
CALLER_WORKFLOW_NAME: ${{ inputs.caller-workflow-name }}
36+
ADOT_IMAGE_NAME: ${{ inputs.adot-image-name }}
37+
CLUSTER_NAME: e2e-test-node
38+
SAMPLE_APP_NAME: main-service-node
39+
METRIC_NAMESPACE: ApplicationSignals
40+
LOG_GROUP_NAME: /aws/application-signals/data
41+
TEST_RESOURCES_FOLDER: ${GITHUB_WORKSPACE}
42+
E2E_TEST_ACCOUNT_ID: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ACCOUNT_ID }}
43+
E2E_TEST_ROLE_NAME: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ROLE_NAME }}
44+
45+
jobs:
46+
node-ecs:
47+
runs-on: ubuntu-latest
48+
outputs:
49+
job-started: ${{ steps.job-started.outputs.job-started }}
50+
validation-result: ${{ steps.validation-result.outputs.validation-result }}
51+
steps:
52+
- name: Check if the job started
53+
id: job-started
54+
run: echo "job-started=true" >> $GITHUB_OUTPUT
55+
56+
- name: Generate testing id and sample app namespace
57+
run: |
58+
echo TESTING_ID="${{ github.job }}-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" >> $GITHUB_ENV
59+
60+
- uses: actions/checkout@v4
61+
with:
62+
repository: 'aws-observability/aws-application-signals-test-framework'
63+
ref: ${{ env.CALLER_WORKFLOW_NAME == 'main-build' && 'main' || github.ref }}
64+
fetch-depth: 0
65+
66+
# We initialize Gradlew Daemon early on during the workflow because sometimes initialization
67+
# fails due to transient issues. If it fails here, then we will try again later before the validators
68+
- name: Initiate Gradlew Daemon
69+
id: initiate-gradlew
70+
uses: ./.github/workflows/actions/execute_and_retry
71+
continue-on-error: true
72+
with:
73+
command: "./gradlew :validator:build"
74+
cleanup: "./gradlew clean"
75+
max_retry: 3
76+
sleep_time: 60
77+
78+
- name: Configure AWS Credentials
79+
uses: aws-actions/configure-aws-credentials@v4
80+
with:
81+
role-to-assume: arn:aws:iam::${{ env.E2E_TEST_ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }}
82+
aws-region: us-east-1
83+
84+
- name: Retrieve account
85+
uses: aws-actions/aws-secretsmanager-get-secrets@v1
86+
with:
87+
secret-ids: |
88+
ACCOUNT_ID, region-account/${{ env.E2E_TEST_AWS_REGION }}
89+
NODE_MAIN_SAMPLE_APP_IMAGE, e2e-test/node-main-sample-app-image
90+
NODE_REMOTE_SAMPLE_APP_IMAGE, e2e-test/node-remote-sample-app-image
91+
92+
# If the workflow is running as a canary, then we want to log in to the aws account in the appropriate region
93+
- name: Configure AWS Credentials
94+
if: ${{ github.event.repository.name == 'aws-application-signals-test-framework' }}
95+
uses: aws-actions/configure-aws-credentials@v4
96+
with:
97+
role-to-assume: arn:aws:iam::${{ env.ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }}
98+
aws-region: ${{ env.E2E_TEST_AWS_REGION }}
99+
100+
- name: Initiate Terraform
101+
uses: ./.github/workflows/actions/execute_and_retry
102+
with:
103+
command: "cd ${{ env.TEST_RESOURCES_FOLDER }}/terraform/node/ecs && terraform init && terraform validate"
104+
cleanup: "rm -rf .terraform && rm -rf .terraform.lock.hcl"
105+
max_retry: 6
106+
sleep_time: 60
107+
108+
- name: Set Sample App Image
109+
run: |
110+
echo MAIN_SAMPLE_APP_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/${{ env.NODE_MAIN_SAMPLE_APP_IMAGE }}" >> $GITHUB_ENV
111+
echo REMOTE_SAMPLE_APP_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/${{ env.NODE_REMOTE_SAMPLE_APP_IMAGE }}" >> $GITHUB_ENV
112+
113+
- name: Set ADOT Node image environment variable
114+
run: |
115+
if [ "${{ github.event.repository.name }}" = "aws-otel-js-instrumentation" ]; then
116+
# Use the staging image build by the ADOT node repo
117+
echo ADOT_INSTRUMENTATION_IMAGE_URI="${{ env.ADOT_IMAGE_NAME }}" >> $GITHUB_ENV
118+
else
119+
ADOT_INSTRUMENTATION_IMAGE_TAG=$(curl -s -I -L 'https://github.com/aws-observability/aws-otel-js-instrumentation/releases/latest' | grep -i Location | awk -F'/tag/' '{print $2}' | tr -d '\r')
120+
# ADOT_INSTRUMENTATION_IMAGE_TAG="v0.1.0"
121+
echo ADOT_INSTRUMENTATION_IMAGE_URI="public.ecr.aws/aws-observability/adot-autoinstrumentation-node:$ADOT_INSTRUMENTATION_IMAGE_TAG" >> $GITHUB_ENV
122+
fi
123+
124+
# Switch to use the public image for CW Agent
125+
- name: Set Get CW Agent command environment variable
126+
run: |
127+
if [ "${{ github.event.repository.name }}" = "amazon-cloudwatch-agent" ]; then
128+
echo CWAGENT_IMAGE_URI="${{ secrets.AWS_ECR_PRIVATE_REGISTRY }}/cwagent-integration-test:${{ github.sha }}" >> $GITHUB_ENV
129+
else
130+
# echo CWAGENT_IMAGE_URI="public.ecr.aws/cloudwatch-agent/cloudwatch-agent:latest" >> $GITHUB_ENV
131+
echo CWAGENT_IMAGE_URI="136146983976.dkr.ecr.us-east-1.amazonaws.com/cloudwatch-agent:1.300047.0b872" >> $GITHUB_ENV
132+
fi
133+
134+
- name: Deploy sample app via terraform and wait for the endpoint to come online
135+
id: deploy-sample-app
136+
working-directory: terraform/node/ecs
137+
run: |
138+
# Attempt to deploy the sample app on an EKS instance and wait for its endpoint to come online.
139+
# There may be occasional failures due to transitivity issues, so try up to 2 times.
140+
# deployment_failed of 0 indicates that both the terraform deployment and the endpoint are running, while 1 indicates
141+
# that it failed at some point
142+
retry_counter=0
143+
max_retry=2
144+
while [ $retry_counter -lt $max_retry ]; do
145+
echo "Attempt $retry_counter"
146+
deployment_failed=0
147+
terraform apply -auto-approve \
148+
-var="test_id=${{ env.TESTING_ID }}" \
149+
-var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \
150+
-var="ecs_cluster_name=${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }}" \
151+
-var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \
152+
-var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \
153+
-var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \
154+
-var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \
155+
-var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}" \
156+
|| deployment_failed=$?
157+
158+
if [ $deployment_failed -ne 0 ]; then
159+
echo "Terraform deployment was unsuccessful. Will attempt to retry deployment."
160+
fi
161+
162+
# If the deployment_failed is 1 then either the terraform deployment or the endpoint connection failed, so first destroy the
163+
# resources created from terraform and try again.
164+
if [ $deployment_failed -eq 1 ]; then
165+
echo "Destroying terraform"
166+
terraform destroy -auto-approve \
167+
-var="test_id=${{ env.TESTING_ID }}" \
168+
-var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \
169+
-var="ecs_cluster_name=${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }}" \
170+
-var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \
171+
-var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \
172+
-var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \
173+
-var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \
174+
-var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}"
175+
176+
retry_counter=$(($retry_counter+1))
177+
else
178+
# If deployment succeeded, then exit the loop
179+
break
180+
fi
181+
182+
if [ $retry_counter -ge $max_retry ]; then
183+
echo "Max retry reached, failed to deploy terraform and connect to the endpoint. Exiting code"
184+
exit 1
185+
fi
186+
done
187+
188+
- name: Sleep to Wait for Canary Generated and Log Artifact Versions
189+
run: |
190+
sleep 120
191+
echo "ADOT Image: ${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}";
192+
echo "CW Agent Image: ${{ env.CWAGENT_IMAGE_URI }}";
193+
194+
- name: Initiate Gradlew Daemon
195+
if: steps.initiate-gradlew == 'failure'
196+
uses: ./.github/workflows/actions/execute_and_retry
197+
continue-on-error: true
198+
with:
199+
command: "./gradlew :validator:build"
200+
cleanup: "./gradlew clean"
201+
max_retry: 3
202+
sleep_time: 60
203+
204+
# Validation for app signals telemetry data
205+
- name: Call endpoint and validate generated EMF logs
206+
id: log-validation
207+
if: steps.deploy-sample-app.outcome == 'success' && !cancelled()
208+
run: ./gradlew validator:run --args='-c node/ecs/log-validation.yml
209+
--testing-id ${{ env.TESTING_ID }}
210+
--region ${{ env.E2E_TEST_AWS_REGION }}
211+
--account-id ${{ env.ACCOUNT_ID }}
212+
--metric-namespace ${{ env.METRIC_NAMESPACE }}
213+
--log-group ${{ env.LOG_GROUP_NAME }}
214+
--platform-info ${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }}
215+
--service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}
216+
--rollup'
217+
218+
# - name: Call endpoints and validate generated metrics
219+
# id: metric-validation
220+
# if: (steps.deploy-sample-app.outcome == 'success' || steps.log-validation.outcome == 'failure') && !cancelled()
221+
# run: ./gradlew validator:run --args='-c node/ecs/metric-validation.yml
222+
# --testing-id ${{ env.TESTING_ID }}
223+
# --region ${{ env.E2E_TEST_AWS_REGION }}
224+
# --account-id ${{ env.ACCOUNT_ID }}
225+
# --metric-namespace ${{ env.METRIC_NAMESPACE }}
226+
# --log-group ${{ env.LOG_GROUP_NAME }}
227+
# --platform-info ${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }}
228+
# --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}
229+
# --rollup'
230+
231+
# - name: Call endpoints and validate generated traces
232+
# id: trace-validation
233+
# if: (steps.deploy-sample-app.outcome == 'success' || steps.log-validation.outcome == 'failure' || steps.metric-validation.outcome == 'failure') && !cancelled()
234+
# run: ./gradlew validator:run --args='-c node/ecs/trace-validation.yml
235+
# --testing-id ${{ env.TESTING_ID }}
236+
# --region ${{ env.E2E_TEST_AWS_REGION }}
237+
# --account-id ${{ env.ACCOUNT_ID }}
238+
# --metric-namespace ${{ env.METRIC_NAMESPACE }}
239+
# --log-group ${{ env.LOG_GROUP_NAME }}
240+
# --platform-info ${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }}
241+
# --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}
242+
# --rollup'
243+
244+
# - name: Refresh AWS Credentials
245+
# if: ${{ github.event.repository.name == 'aws-application-signals-test-framework' }}
246+
# uses: aws-actions/configure-aws-credentials@v4
247+
# with:
248+
# role-to-assume: arn:aws:iam::${{ env.ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }}
249+
# aws-region: ${{ env.E2E_TEST_AWS_REGION }}
250+
251+
# - name: Save test results
252+
# if: always()
253+
# id: validation-result
254+
# run: |
255+
# if [ "${{ steps.log-validation.outcome }}" = "success" ] && [ "${{ steps.metric-validation.outcome }}" = "success" ] && [ "${{ steps.trace-validation.outcome }}" = "success" ]; then
256+
# echo "validation-result=success" >> $GITHUB_OUTPUT
257+
# else
258+
# echo "validation-result=failure" >> $GITHUB_OUTPUT
259+
# fi
260+
261+
# Clean up Procedures
262+
263+
# - name: Terraform destroy
264+
# if: always()
265+
# continue-on-error: true
266+
# timeout-minutes: 5
267+
# working-directory: terraform/node/ecs
268+
# run: |
269+
# terraform destroy -auto-approve \
270+
# -var="test_id=${{ env.TESTING_ID }}" \
271+
# -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \
272+
# -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }}" \
273+
# -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \
274+
# -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \
275+
# -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \
276+
# -var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \
277+
# -var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}"

0 commit comments

Comments
 (0)