Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/java-ec2-canary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ jobs:
caller-workflow-name: 'appsignals-e2e-ec2-maven-canary-test'
otel-source: 'maven'
java-version: '11'
cpu-architecture: 'x86_64'
cpu-architecture: 'x86_64'
293 changes: 293 additions & 0 deletions .github/workflows/java-ec2-ubuntu-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
## 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: Java EC2 Default Use Case
on:
workflow_call:
inputs:
aws-region:
required: true
type: string
caller-workflow-name:
required: true
type: string
java-version:
description: "Currently support version 8, 11, 17, 21, 22"
required: false
type: string
default: '11'
cpu-architecture:
description: "Permitted values: x86_64 or arm64"
required: false
type: string
default: "x86_64"
otel-source:
required: false
type: string
default: 'github'

outputs:
job-started:
value: ${{ jobs.java-ec2-default.outputs.job-started }}
validation-result:
value: ${{ jobs.java-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 }}
JAVA_VERSION: ${{ inputs.java-version }}
OTEL_SOURCE: ${{ inputs.otel-source }}
CPU_ARCHITECTURE: ${{ inputs.cpu-architecture }}
SAMPLE_APP_FRONTEND_SERVICE_JAR: s3://aws-appsignals-sample-app-prod-${{ inputs.aws-region }}//java-main-service-v${{ inputs.java-version }}.jar
SAMPLE_APP_REMOTE_SERVICE_JAR: s3://aws-appsignals-sample-app-prod-${{ inputs.aws-region }}//java-remote-service-v${{ inputs.java-version }}.jar
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}

jobs:
java-ec2-ubuntu:
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

- name: Generate testing id
run: echo TESTING_ID="${{ github.run_id }}-${{ github.run_number }}-${RANDOM}" >> $GITHUB_ENV

- uses: actions/checkout@v4
with:
repository: 'aws-observability/aws-application-signals-test-framework'
ref: ${{ env.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: 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 }}
# If the workflow is running as a canary, then we want to log in to the aws account in the appropriate 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 }}

# TODO: Use Latest version from Maven by latest_version=$(curl -s "https://search.maven.org/solrsearch/select?q=g:software.amazon.opentelemetry+a:aws-opentelemetry-agent&core=gav&rows=1&wt=json" | jq -r '.response.docs[0].v')
- name: Set Get ADOT Wheel command environment variable
run: |
if [ "${{ github.event.repository.name }}" = "aws-otel-java-instrumentation" ]; then
# Reusing the adot-main-build-staging-jar bucket to store the python wheel file
echo GET_ADOT_JAR_COMMAND="aws s3 cp s3://adot-main-build-staging-jar/aws-opentelemetry-agent.jar ./adot.jar" >> $GITHUB_ENV
elif [ "${{ env.OTEL_SOURCE }}" == "maven" ]; then
echo "Latest version for Maven is: 1.32.5"
echo GET_ADOT_JAR_COMMAND="wget -O adot.jar https://repo1.maven.org/maven2/software/amazon/opentelemetry/aws-opentelemetry-agent/1.32.5/aws-opentelemetry-agent-1.32.5.jar" >> $GITHUB_ENV
else
echo GET_ADOT_JAR_COMMAND="wget -O adot.jar https://github.com/aws-observability/aws-otel-java-instrumentation/releases/latest/download/aws-opentelemetry-agent.jar" >> $GITHUB_ENV
fi
- name: Set Get CW Agent command environment variable
run: |
if [ "${{ github.event.repository.name }}" = "amazon-cloudwatch-agent" ]; then
# Reusing the adot-main-build-staging-jar bucket to store the python wheel file
echo GET_CW_AGENT_DEB_COMMAND= "aws s3 cp s3://${{ secrets.S3_INTEGRATION_BUCKET }}/integration-test/binary/${{ github.sha }}/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb ./cw-agent.deb" >> $GITHUB_ENV
else
echo GET_CW_AGENT_DEB_COMMAND="wget -O cw-agent.deb https://amazoncloudwatch-agent-${{ inputs.aws-region }}.s3.${{ inputs.aws-region }}.amazonaws.com/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb" >> $GITHUB_ENV
fi
- 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/java/ec2/default && terraform init && terraform validate"
cleanup: "rm -rf .terraform && rm -rf .terraform.lock.hcl"
max_retry: 6
sleep_time: 60

- name: Deploy sample app via terraform and wait for endpoint to come online
working-directory: terraform/java/ec2/ubuntu
run: |
# Attempt to deploy the sample app on an EC2 instance and wait for its endpoint to come online.
# There may be occasional failures due to transitivity issues, so try up to 2 times.
# deployment_failed of 0 indicates that both the terraform deployment and the endpoint are running, while 1 indicates
# that it failed at some point
retry_counter=0
max_retry=2
while [ $retry_counter -lt $max_retry ]; do
echo "Attempt $retry_counter"
deployment_failed=0
terraform apply -auto-approve \
-var="aws_region=${{ inputs.aws-region }}" \
-var="test_id=${{ env.TESTING_ID }}" \
-var="sample_app_jar=${{ env.SAMPLE_APP_FRONTEND_SERVICE_JAR }}" \
-var="sample_remote_app_jar=${{ env.SAMPLE_APP_REMOTE_SERVICE_JAR }}" \
-var="get_cw_agent_deb_command=${{ env.GET_CW_AGENT_DEB_COMMAND }}" \
-var="get_adot_jar_command=${{ env.GET_ADOT_JAR_COMMAND }}" \
-var="language_version=${{ env.JAVA_VERSION }}" \
-var="cpu_architecture=${{ env.CPU_ARCHITECTURE }}" \
|| deployment_failed=$?
if [ $deployment_failed -eq 1 ]; then
echo "Terraform deployment was unsuccessful. Will attempt to retry deployment."
fi
# If the success is 1 then either the terraform deployment or the endpoint connection failed, so first destroy the
# resources created from terraform and try again.
if [ $deployment_failed -eq 1 ]; then
echo "Destroying terraform"
terraform destroy -auto-approve \
-var="test_id=${{ env.TESTING_ID }}"
retry_counter=$(($retry_counter+1))
else
# If deployment succeeded, then exit the loop
break
fi
if [ $retry_counter -eq $max_retry ]; then
echo "Max retry reached, failed to deploy terraform and connect to the endpoint. Exiting code"
exit 1
fi
done
- name: Get the ec2 instance ami id
working-directory: terraform/java/ec2/ubuntu
run: |
echo "EC2_INSTANCE_AMI=$(terraform output ec2_instance_ami)" >> $GITHUB_ENV
- name: Get the sample app and EC2 instance information
working-directory: terraform/java/ec2/ubuntu
run: |
echo "MAIN_SERVICE_ENDPOINT=localhost:8080" >> $GITHUB_ENV
echo "REMOTE_SERVICE_IP=$(terraform output sample_app_remote_service_private_ip)" >> $GITHUB_ENV
echo "MAIN_SERVICE_INSTANCE_ID=$(terraform output main_service_instance_id)" >> $GITHUB_ENV
- 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 java/ec2/ubuntu/log-validation.yml
--testing-id ${{ env.TESTING_ID }}
--endpoint http://${{ env.MAIN_SERVICE_ENDPOINT }}
--remote-service-deployment-name ${{ env.REMOTE_SERVICE_IP }}:8080
--region ${{ inputs.aws-region }}
--account-id ${{ env.ACCOUNT_ID }}
--metric-namespace ${{ env.METRIC_NAMESPACE }}
--log-group ${{ env.LOG_GROUP_NAME }}
--service-name sample-application-${{ env.TESTING_ID }}
--remote-service-name sample-remote-application-${{ env.TESTING_ID }}
--query-string ip=${{ env.REMOTE_SERVICE_IP }}&testingId=${{ env.TESTING_ID }}
--instance-ami ${{ env.EC2_INSTANCE_AMI }}
--instance-id ${{ env.MAIN_SERVICE_INSTANCE_ID }}
--rollup'

- name: Validate generated metrics
id: metric-validation
if: (success() || steps.log-validation.outcome == 'failure') && !cancelled()
run: ./gradlew validator:run --args='-c java/ec2/ubuntu/metric-validation.yml
--testing-id ${{ env.TESTING_ID }}
--endpoint http://${{ env.MAIN_SERVICE_ENDPOINT }}
--remote-service-deployment-name ${{ env.REMOTE_SERVICE_IP }}:8080
--region ${{ inputs.aws-region }}
--account-id ${{ env.ACCOUNT_ID }}
--metric-namespace ${{ env.METRIC_NAMESPACE }}
--log-group ${{ env.LOG_GROUP_NAME }}
--service-name sample-application-${{ env.TESTING_ID }}
--remote-service-name sample-remote-application-${{ env.TESTING_ID }}
--query-string ip=${{ env.REMOTE_SERVICE_IP }}&testingId=${{ env.TESTING_ID }}
--instance-ami ${{ env.EC2_INSTANCE_AMI }}
--instance-id ${{ env.MAIN_SERVICE_INSTANCE_ID }}
--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 java/ec2/ubuntu/trace-validation.yml
--testing-id ${{ env.TESTING_ID }}
--endpoint http://${{ env.MAIN_SERVICE_ENDPOINT }}
--remote-service-deployment-name ${{ env.REMOTE_SERVICE_IP }}:8080
--region ${{ inputs.aws-region }}
--account-id ${{ env.ACCOUNT_ID }}
--metric-namespace ${{ env.METRIC_NAMESPACE }}
--log-group ${{ env.LOG_GROUP_NAME }}
--service-name sample-application-${{ env.TESTING_ID }}
--remote-service-name sample-remote-application-${{ env.TESTING_ID }}
--query-string ip=${{ env.REMOTE_SERVICE_IP }}&testingId=${{ env.TESTING_ID }}
--instance-ami ${{ env.EC2_INSTANCE_AMI }}
--instance-id ${{ env.MAIN_SERVICE_INSTANCE_ID }}
--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
working-directory: terraform/java/ec2/default
run: |
terraform destroy -auto-approve \
-var="test_id=${{ env.TESTING_ID }}"
4 changes: 4 additions & 0 deletions terraform/java/ec2/default/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ resource "null_resource" "main_service_setup" {
provisioner "remote-exec" {
inline = [
<<-EOF
#!/bin/bash
# Make the Terraform fail if any step throws an error
set -o errexit
# Install wget
Expand Down Expand Up @@ -206,11 +207,13 @@ resource "null_resource" "remote_service_setup" {
provisioner "remote-exec" {
inline = [
<<-EOF
#!/bin/bash
# Make the Terraform fail if any step throws an error
set -o errexit
# Install wget
sudo yum install wget -y
# Install Java
echo
if [[ "${var.language_version}" == "8" ]]; then
sudo yum install java-1.8.0-amazon-corretto -y
else
Expand Down Expand Up @@ -282,6 +285,7 @@ resource "null_resource" "traffic_generator_setup" {
provisioner "remote-exec" {
inline = [
<<-EOF
#!/bin/bash
sudo yum install nodejs aws-cli unzip tmux -y

# Bring in the traffic generator files to EC2 Instance
Expand Down
16 changes: 16 additions & 0 deletions terraform/java/ec2/ubuntu/amazon-cloudwatch-agent.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"agent": {
"debug": true,
"region": "$REGION"
},
"traces": {
"traces_collected": {
"application_signals": {}
}
},
"logs": {
"metrics_collected": {
"application_signals": {}
}
}
}
Loading
Loading