Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cloudformation stacks End to End tests - test suite structure #13

Merged
merged 25 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
33a1f75
added lambda trigger script and some common stack script to validate …
ahegdeNR Dec 19, 2024
de62b23
added cloudwatch trigger script
ahegdeNR Dec 24, 2024
c80e547
added ci/cd automation to run tests during merge
ahegdeNR Dec 30, 2024
22cd0a9
fixed missing permission to fetch secrets from github secrets
ahegdeNR Dec 30, 2024
dd18908
fixed constants for scripts
ahegdeNR Dec 30, 2024
e5e49c3
moved license key to github secrets
ahegdeNR Dec 31, 2024
4349ebb
fixed filter pattern json format in template parameters
ahegdeNR Dec 31, 2024
93f5be7
fixes
ahegdeNR Dec 31, 2024
9514269
modified bucket name and log group name, build all templates
ahegdeNR Dec 31, 2024
b03fcc9
code refactoring and fixes
ahegdeNR Jan 7, 2025
1b398af
fixes
ahegdeNR Jan 7, 2025
3925822
fixes
ahegdeNR Jan 7, 2025
c9ce5aa
updated permissions for common script
ahegdeNR Jan 7, 2025
f9a6d38
removed other templates from getting packaged and published as part o…
ahegdeNR Jan 7, 2025
e2f6a1c
modified parameters file name in triggers
ahegdeNR Jan 7, 2025
ef69275
removed parallelization of script
ahegdeNR Jan 7, 2025
41fd962
removed parallelization of script
ahegdeNR Jan 7, 2025
20adcf8
fixes
ahegdeNR Jan 7, 2025
5f7c392
fixes
ahegdeNR Jan 7, 2025
7c44eb6
fixes
ahegdeNR Jan 7, 2025
0def76a
add parallelization to running scripts
ahegdeNR Jan 7, 2025
94720fc
modified e2e tests to run during push workflow
ahegdeNR Jan 7, 2025
6114fe8
review fixes, comments and retries
ahegdeNR Jan 8, 2025
bd7278c
Merge branch 'develop' into NR-334397-e2e-testing-automation-part-1-test
ahegdeNR Jan 10, 2025
2397044
review fixes, comments and retries
ahegdeNR Jan 10, 2025
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
1 change: 1 addition & 0 deletions .github/workflows/pull_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: Pull Request Workflow
on:
pull_request:
branches:
- develop
- main

jobs:
Expand Down
60 changes: 60 additions & 0 deletions .github/workflows/run-e2e-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: E2E Test Workflow

on:
pull_request:
branches:
- develop
- main
ahegdeNR marked this conversation as resolved.
Show resolved Hide resolved

jobs:
run-e2e-tests:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.22'

- name: Install AWS SAM CLI
run: |
pip install aws-sam-cli

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v3
with:
role-to-assume: ${{ secrets.AWS_E2E_ROLE }}
aws-region: us-east-1

- name: Run e2e tests
ahegdeNR marked this conversation as resolved.
Show resolved Hide resolved
env:
NEW_RELIC_USER_KEY: ${{ secrets.NEW_RELIC_USER_KEY }}
NEW_RELIC_LICENSE_KEY: ${{ secrets.NEW_RELIC_LICENSE_KEY }}
S3_BUCKET: unified-lambda-e2e-test-templates
run: |
cd e2e-tests/
./build-templates.sh
ahegdeNR marked this conversation as resolved.
Show resolved Hide resolved

echo "Running s3 and cloudwatch trigger tests parallely"
./lambda-cloudwatch-trigger.sh &
hrai-nr marked this conversation as resolved.
Show resolved Hide resolved
pid1=$!
echo "Testing setting up cloudwatch trigger with PID: $pid1"

./lambda-s3-trigger.sh &
pid2=$!
echo "Testing setting up s3 trigger with PID: $pid2"

wait $pid1
wait $pid2

- name: Delete Resources
env:
S3_BUCKET: unified-lambda-e2e-test-templates
run:
aws s3 rm "s3://$S3_BUCKET" --recursive
17 changes: 17 additions & 0 deletions e2e-tests/build-templates.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

# add all templates for subsequent test cases
# make packaging and publishing of templates more efficient so every time new al2 env is not spun up
TEMPLATES=("lambda-template.yaml")

source config-file.cfg

for TEMPLATE_FILE in "${TEMPLATES[@]}"; do

BASE_NAME=$(basename "$TEMPLATE_FILE" .yaml)
BUILD_DIR="$BUILD_DIR_BASE/$BASE_NAME"

sam build -u --template-file "../$TEMPLATE_FILE" --build-dir "$BUILD_DIR"
sam package --s3-bucket "$S3_BUCKET" --template-file "$BUILD_DIR/template.yaml" --output-template-file "$BUILD_DIR/$TEMPLATE_FILE"
ahegdeNR marked this conversation as resolved.
Show resolved Hide resolved

done
74 changes: 74 additions & 0 deletions e2e-tests/common-scripts.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/bin/bash

source config-file.cfg

validate_stack_deployment_status() {
stack_name=$1

echo "Validating stack deployment status for stack name: $stack_name"

stack_status=$(aws cloudformation describe-stacks --stack-name "$stack_name" --query "Stacks[0].StackStatus" --output text)
if [[ "$stack_status" == "ROLLBACK_COMPLETE" || "$stack_status" == "ROLLBACK_FAILED" || "$stack_status" == "CREATE_FAILED" || "$stack_status" == "UPDATE_FAILED" ]]; then
echo "Stack $stack_name failed to be created and rolled back."
failure_reason=$(aws cloudformation describe-stack-events --stack-name "$stack_name" --query "StackEvents[?ResourceStatus==\`$stack_status\`].ResourceStatusReason" --output text)
exit_with_error "Stack $stack_name failed to be created. Failure reason: $failure_reason"
else
echo "Stack $stack_name was created successfully."
fi
}

delete_stack() {
stack_name=$1

aws cloudformation delete-stack --stack-name "$stack_name"

echo "Initiated deletion of stack: $stack_name"

stack_status=$(aws cloudformation describe-stacks --stack-name "$stack_name" --query 'Stacks[0].StackStatus' --output text)

# delete stack with exponential back off retires
max_sleep_time=300 # Cap sleep time to 5 minutes
sleep_time=30

while [[ $stack_status == "DELETE_IN_PROGRESS" ]]; do
echo "Stack $stack_name is still being deleted..."

sleep $sleep_time
if (( sleep_time < max_sleep_time )); then
sleep_time=$(( sleep_time * 2 ))
fi

stack_status=$(aws cloudformation describe-stacks --stack-name "$stack_name" --query 'Stacks[0].StackStatus' --output text 2>/dev/null || true)
done

if [ -z "$stack_status" ]; then
echo "Stack $stack_name has been successfully deleted."
elif [ "$stack_status" == "DELETE_FAILED" ]; then
echo "Failed to delete stack $stack_name."
else
echo "Unexpected stack status: $stack_status."
fi
}

exit_with_error() {
echo "Error: $1"
exit 1
}

get_lambda_function_arn() {
stack_name=$1

lambda_physical_id=$(aws cloudformation describe-stack-resources \
--stack-name "$stack_name" \
--logical-resource-id "$LAMBDA_LOGICAL_RESOURCE_ID" \
--query "StackResources[0].PhysicalResourceId" \
--output text
)

lambda_function_arn=$(aws lambda get-function --function-name "$lambda_physical_id" \
--query "Configuration.FunctionArn" \
--output text
)

echo "$lambda_function_arn"
}
18 changes: 18 additions & 0 deletions e2e-tests/config-file.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# test resources
NEW_RELIC_REGION=US
NEW_RELIC_ACCOUNT_ID=2813435

# build constants
BUILD_DIR_BASE=.aws-sam/build

# template constants
LAMBDA_TEMPLATE=lambda-template.yaml
LAMBDA_TEMPLATE_BUILD_DIR=.aws-sam/build/lambda-template
LAMBDA_LOGICAL_RESOURCE_ID=NewRelicLogsServerlessLogForwarder

# deployment constants
S3_BUCKET_NAME=aws-unified-lambda-e2e-test-bucket
S3_BUCKET_PREFIX=LogFolder
LOG_GROUP_NAME=aws-unified-lambda-e2e-test-log-group
LOG_GROUP_FILTER_PATTERN=ERROR

65 changes: 65 additions & 0 deletions e2e-tests/lambda-cloudwatch-trigger.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/bin/bash

source common-scripts.sh
source config-file.cfg

# test case constants
CLOUDWATCH_TRIGGER_CASE=e2e-cloudwatch-trigger-stack

deploy_cloudwatch_trigger_stack() {
template_file=$1
stack_name=$2
license_key=$3
new_relic_region=$4
new_relic_account_id=$5
secret_license_key=$6
log_group_config=$7
common_attributes=$8

echo "Deploying cloudwatch trigger stack with name: $stack_name"

sam deploy \
--template-file "$template_file" \
--stack-name "$stack_name" \
--parameter-overrides \
LicenseKey="$license_key" \
NewRelicRegion="$new_relic_region" \
NewRelicAccountId="$new_relic_account_id" \
StoreNRLicenseKeyInSecretManager="$secret_license_key" \
S3BucketNames="''" \
LogGroupConfig="$log_group_config" \
CommonAttributes="$common_attributes" \
--capabilities CAPABILITY_IAM
}

validate_lambda_subscription_created() {
# this function fetches cloudwatch subscriptions and
# validates if lambda subscription filter is configured
stack_name=$1
log_group_name=$2
log_group_filter=$3

echo "Validating cloudwatch lambda subscription for stack name: $stack_name, log group name: $log_group_name, and log group filter: $log_group_filter"

lambda_function_arn=$(get_lambda_function_arn "$stack_name")

subscriptions=$(aws logs describe-subscription-filters --log-group-name "$log_group_name" --query 'subscriptionFilters[*].[destinationArn, filterPattern]' --output text)

if echo "$subscriptions" | grep -q "$lambda_function_arn" && echo "$subscriptions" | grep -q "$log_group_filter"; then
echo "Lambda function $lambda_function_arn is subscribed to log group: $log_group_name with filter: $log_group_filter"
else
exit_with_error "Lambda function $lambda_function_arn is not subscribed to log group: $log_group_name"
fi

}

cat <<EOF > cloudwatch-parameter.json
'[{"LogGroupName":"$LOG_GROUP_NAME","FilterPattern":"$LOG_GROUP_FILTER_PATTERN"}]'
EOF
LOG_GROUP_NAMES=$(<cloudwatch-parameter.json)
echo "Testing for log group configuration JSON: $(<cloudwatch-parameter.json)"

ahegdeNR marked this conversation as resolved.
Show resolved Hide resolved
deploy_cloudwatch_trigger_stack "$LAMBDA_TEMPLATE_BUILD_DIR/$LAMBDA_TEMPLATE" "$CLOUDWATCH_TRIGGER_CASE" "$NEW_RELIC_LICENSE_KEY" "$NEW_RELIC_REGION" "$NEW_RELIC_ACCOUNT_ID" "false" "$LOG_GROUP_NAMES" "''"
hrai-nr marked this conversation as resolved.
Show resolved Hide resolved
validate_stack_deployment_status "$CLOUDWATCH_TRIGGER_CASE"
ahegdeNR marked this conversation as resolved.
Show resolved Hide resolved
validate_lambda_subscription_created "$CLOUDWATCH_TRIGGER_CASE" "$LOG_GROUP_NAME" "$LOG_GROUP_FILTER_PATTERN"
delete_stack "$CLOUDWATCH_TRIGGER_CASE"
70 changes: 70 additions & 0 deletions e2e-tests/lambda-s3-trigger.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/bin/bash

source common-scripts.sh
source config-file.cfg

# test case constants
S3_TRIGGER_CASE=e2e-s3-trigger-stack
hrai-nr marked this conversation as resolved.
Show resolved Hide resolved

deploy_s3_trigger_stack() {
template_file=$1
stack_name=$2
license_key=$3
new_relic_region=$4
new_relic_account_id=$5
secret_license_key=$6
s3_bucket_names=$7
common_attributes=$8

echo "Deploying s3 trigger stack with name: $stack_name"

sam deploy \
--template-file "$template_file" \
--stack-name "$stack_name" \
--parameter-overrides \
LicenseKey="$license_key" \
NewRelicRegion="$new_relic_region" \
NewRelicAccountId="$new_relic_account_id" \
StoreNRLicenseKeyInSecretManager="$secret_license_key" \
S3BucketNames="$s3_bucket_names" \
LogGroupConfig="''" \
CommonAttributes="$common_attributes" \
--capabilities CAPABILITY_IAM
}

validate_lambda_s3_trigger_created() {
# this function fetches bucket configurations and
# validates if lambda event notification is configured
stack_name=$1
bucket_name=$2
bucket_prefix=$3

echo "Validating s3 lambda trigger event for stack name: $stack_name, bucket name: $bucket_name, and prefix: $bucket_prefix"

lambda_function_arn=$(get_lambda_function_arn "$stack_name")

notification_configuration=$(aws s3api get-bucket-notification-configuration --bucket "$bucket_name")

lambda_configurations=$(echo "$notification_configuration" |
ahegdeNR marked this conversation as resolved.
Show resolved Hide resolved
jq --arg lambda "$lambda_function_arn" --arg prefix "$bucket_prefix" '
.LambdaFunctionConfigurations[] |
select(.LambdaFunctionArn == $lambda and (.Filter.Key.FilterRules[]? | select(.Name == "Prefix" and .Value == $prefix)?))')

if [ -n "$lambda_configurations" ]; then
echo "S3 triggers with prefix '$bucket_prefix' found for Lambda function $lambda_function_arn on bucket $bucket_name:"
echo "$lambda_configurations" | jq '.'
else
exit_with_error "No S3 triggers with prefix '$bucket_prefix' found for Lambda function $lambda_function_arn on bucket $bucket_name."
fi
}

cat <<EOF > s3-parameter.json
'[{"bucket":"$S3_BUCKET_NAME","prefix":"$S3_BUCKET_PREFIX"}]'
EOF
S3_BUCKET_NAMES=$(<s3-parameter.json)
echo "Testing for s3 bucket configuration JSON: $(<s3-parameter.json)"

deploy_s3_trigger_stack "$LAMBDA_TEMPLATE_BUILD_DIR/$LAMBDA_TEMPLATE" "$S3_TRIGGER_CASE" "$NEW_RELIC_LICENSE_KEY" "$NEW_RELIC_REGION" "$NEW_RELIC_ACCOUNT_ID" "false" "$S3_BUCKET_NAMES" "''"
ahegdeNR marked this conversation as resolved.
Show resolved Hide resolved
validate_stack_deployment_status "$S3_TRIGGER_CASE"
validate_lambda_s3_trigger_created "$S3_TRIGGER_CASE" "$S3_BUCKET_NAME" "$S3_BUCKET_PREFIX"
delete_stack "$S3_TRIGGER_CASE"
maya-jha marked this conversation as resolved.
Show resolved Hide resolved
Loading