Skip to content

Commit

Permalink
Deploy Traffic Generator
Browse files Browse the repository at this point in the history
  • Loading branch information
harrryr committed Jul 26, 2024
1 parent 8cdc51d commit c3a2adf
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 0 deletions.
97 changes: 97 additions & 0 deletions .github/workflows/traffic-generator-image-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# This workflow will build and the traffic generator image to each region whenever there is an update made to the traffic-generator folder.
# This image will be used by EKS and K8s test to call sample app endpoints
name: Create and Push Traffic Generator Image

on:
workflow_dispatch:
push:
# branches:
# - main
# paths:
# - 'traffic-generator/**'

permissions:
id-token: write
contents: read

env:
E2E_TEST_ACCOUNT_ID: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ACCOUNT_ID }}
E2E_TEST_ROLE_NAME: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ROLE_NAME }}

jobs:
build-and-push-image:
runs-on: ubuntu-latest
strategy:
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']
steps:
- name: Checkout repository
uses: actions/checkout@v4

- 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/${{ matrix.aws-region }}
- name: Configure AWS Credentials
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: ${{ matrix.aws-region }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2

- name: Build, tag, and push image to Amazon ECR
working-directory: traffic-generator
env:
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
REPOSITORY: e2e-test-resource
IMAGE_TAG: traffic-generator
run: |
docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG .
docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG
upload-files:
runs-on: ubuntu-latest
strategy:
matrix:
aws-region: [ 'us-east-1' ]
steps:
- name: Checkout repository
uses: actions/checkout@v4

- 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/${{ matrix.aws-region }}
- name: Configure AWS Credentials
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: ${{ matrix.aws-region }}

- name: Upload traffic generator files
working-directory: traffic-generator
run: |
zip traffic-generator.zip ./index.js ./package.json
aws s3 cp traffic-generator.zip s3://aws-appsignals-sample-app-prod-${{ matrix.aws-region }}/traffic-generator.zip
21 changes: 21 additions & 0 deletions traffic-generator/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Use the official lightweight Node.js 16 image.
# https://hub.docker.com/_/node
# FROM node:16-slim
FROM public.ecr.aws/eks-distro-build-tooling/nodejs:16

# Create and change to the app directory
WORKDIR /usr/src/app

# Copy application dependency manifests to the container image.
# A wildcard is used to ensure copying both package.json AND package-lock.json (if available).
# Copying this first prevents re-running npm install on every code change.
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy local code to the container image.
COPY . .

# Run the web service on container startup.
CMD [ "npm", "start" ]
73 changes: 73 additions & 0 deletions traffic-generator/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const axios = require('axios');

// Send API requests to the sample app
const sendRequests = async (urls) => {
try {
const fetchPromises = urls.map(url => axios.get(url));
const responses = await Promise.all(fetchPromises);

// Handle the responses
responses.forEach((response, index) => {
if (response.status === 200) {
const data = response.data;
console.log(`Response from ${urls[index]}:`, data);
} else {
console.error(`Failed to fetch ${urls[index]}:`, response.statusText);
}
});
} catch (error) {
console.error('Error sending GET requests:', error);
}
}

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

// This loop will run until the environment variables are available
const waitForEnvVariables = async () => {
while (!process.env.MAIN_ENDPOINT || !process.env.REMOTE_ENDPOINT || !process.env.ID || !process.env.CANARY_TYPE) {
console.log('Environment variables not set. Waiting for 10 seconds...');
await sleep(10000); // Wait for 10 seconds
}
};

// Traffic generator that sends traffic every specified interval. Send request immediately then every 2 minutes afterwords
const trafficGenerator = async (interval) => {
await waitForEnvVariables();

const mainEndpoint = process.env.MAIN_ENDPOINT;
const remoteEndpoint = process.env.REMOTE_ENDPOINT;
const id = process.env.ID;
const canaryType = process.env.CANARY_TYPE

let urls = [
`http://${mainEndpoint}/outgoing-http-call`,
`http://${mainEndpoint}/aws-sdk-call?ip=${remoteEndpoint}&testingId=${id}`,
`http://${mainEndpoint}/remote-service?ip=${remoteEndpoint}&testingId=${id}`,
`http://${mainEndpoint}/client-call`
];

if (canaryType === 'java-eks' || canaryType === 'python-eks') {
urls.push(`http://${mainEndpoint}/mysql`)
}

// Need to call some APIs so that it exceeds the metric limiter threshold and make the test
// APIs generate AllOtherOperations metric. Sleep for a minute to let cloudwatch service process the API call
// Calling it here before calling the remote sample app endpoint because the API generated by it is validated
// for AllOtherRemoteOperations in the metric validation step
if (canaryType === 'java-metric-limiter'){
const fakeUrls = [
`http://${mainEndpoint}`,
`http://${mainEndpoint}/fake-endpoint`
]
// Send the fake requests and wait a minute
await sendRequests(fakeUrls);
await sleep(60000);
}

await sendRequests(urls);
setInterval(() => sendRequests(urls), interval);
}

const interval = 60 * 1000;
// Start sending GET requests every minute (60,000 milliseconds)
trafficGenerator(interval);
12 changes: 12 additions & 0 deletions traffic-generator/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "traffic-generator",
"version": "1.0.0",
"description": "A simple traffic generator that sends GET requests to a list of URLs every 2 minutes",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"axios": "^1.4.0"
}
}

0 comments on commit c3a2adf

Please sign in to comment.