diff --git a/.github/workflows/dotnet-ec2-canary.yml b/.github/workflows/dotnet-ec2-canary.yml index a90c489a1..ba5eecfc9 100644 --- a/.github/workflows/dotnet-ec2-canary.yml +++ b/.github/workflows/dotnet-ec2-canary.yml @@ -43,4 +43,15 @@ jobs: secrets: inherit with: aws-region: ${{ matrix.aws-region }} - caller-workflow-name: 'appsignals-dotnet-e2e-ec2-windows-canary-test' \ No newline at end of file + caller-workflow-name: 'appsignals-dotnet-e2e-ec2-windows-canary-test' + + nuget: + strategy: + fail-fast: false + matrix: + aws-region: [ 'us-east-1'] + uses: ./.github/workflows/dotnet-ec2-nuget-retry.yml + secrets: inherit + with: + aws-region: ${{ matrix.aws-region }} + caller-workflow-name: 'appsignals-dotnet-e2e-ec2-nuget-canary-test' \ No newline at end of file diff --git a/.github/workflows/dotnet-ec2-nuget-retry.yml b/.github/workflows/dotnet-ec2-nuget-retry.yml new file mode 100644 index 000000000..3db5e8b91 --- /dev/null +++ b/.github/workflows/dotnet-ec2-nuget-retry.yml @@ -0,0 +1,57 @@ +## 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: Dotnet EC2 default Retry +on: + workflow_call: + inputs: + aws-region: + required: true + type: string + caller-workflow-name: + required: true + type: string + +permissions: + id-token: write + contents: read + +jobs: + dotnet-ec2-nuget-attempt-1: + uses: ./.github/workflows/dotnet-ec2-nuget-test.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + + dotnet-ec2-nuget-attempt-2: + needs: [ dotnet-ec2-nuget-attempt-1 ] + if: ${{ needs.dotnet-ec2-nuget-attempt-1.outputs.job-started != 'true' }} + uses: ./.github/workflows/dotnet-ec2-nuget-test.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + + publish-metric-attempt-1: + needs: [ dotnet-ec2-nuget-attempt-1, dotnet-ec2-nuget-attempt-2 ] + if: always() + uses: ./.github/workflows/enablement-test-publish-result.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + validation-result: ${{ needs.dotnet-ec2-nuget-attempt-1.outputs.validation-result || needs.dotnet-ec2-nuget-attempt-2.outputs.validation-result }} + + publish-metric-attempt-2: + needs: [ dotnet-ec2-nuget-attempt-1, dotnet-ec2-nuget-attempt-2, publish-metric-attempt-1 ] + if: ${{ always() && needs.publish-metric-attempt-1.outputs.job-started != 'true' }} + uses: ./.github/workflows/enablement-test-publish-result.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + validation-result: ${{ needs.dotnet-ec2-nuget-attempt-1.outputs.validation-result || needs.dotnet-ec2-nuget-attempt-2.outputs.validation-result }} \ No newline at end of file diff --git a/.github/workflows/dotnet-ec2-nuget-test.yml b/.github/workflows/dotnet-ec2-nuget-test.yml new file mode 100644 index 000000000..54d843c9b --- /dev/null +++ b/.github/workflows/dotnet-ec2-nuget-test.yml @@ -0,0 +1,256 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +# This is a reusable workflow for running the DotNet E2E Canary test for Application 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: DotNet EC2 Nuget Use Case +on: + workflow_call: + inputs: + aws-region: + required: true + type: string + staging_distro_name: + required: false + default: 'aws-opentelemetry-distro' + type: string + caller-workflow-name: + required: true + type: string + outputs: + job-started: + value: ${{ jobs.dotnet-ec2-nuget.outputs.job-started }} + validation-result: + value: ${{ jobs.dotnet-ec2-nuget.outputs.validation-result }} + +permissions: + id-token: write + contents: read + +env: + E2E_TEST_AWS_REGION: ${{ inputs.aws-region }} + E2E_TEST_ACCOUNT_ID: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ACCOUNT_ID }} + E2E_TEST_ROLE_NAME: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ROLE_NAME }} + SAMPLE_APP_ZIP: s3://aws-appsignals-sample-app-prod-${{ inputs.aws-region }}/dotnet-sample-app.zip + METRIC_NAMESPACE: ApplicationSignals + LOG_GROUP_NAME: /aws/application-signals/data + ADOT_DISTRO_NAME: ${{ inputs.staging_distro_name }} + TEST_RESOURCES_FOLDER: ${GITHUB_WORKSPACE} + +jobs: + dotnet-ec2-nuget: + 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 + + - uses: actions/checkout@v4 + with: + repository: 'aws-observability/aws-application-signals-test-framework' + ref: ${{ inputs.caller-workflow-name == 'main-build' && 'main' || github.ref }} + fetch-depth: 0 + + - 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: Generate testing id + run: echo TESTING_ID="${{ github.job }}-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" >> $GITHUB_ENV + + - 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 }} + + - 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: ${{ env.E2E_TEST_AWS_REGION }} + + - name: Set Get CW Agent command environment variable + run: | + if [ "${{ github.event.repository.name }}" = "amazon-cloudwatch-agent" ]; then + # Get cloudwatch agent staging file if triggered by cw-a repo + echo GET_CW_AGENT_RPM_COMMAND= "aws s3 cp s3://${{ secrets.S3_INTEGRATION_BUCKET }}/integration-test/binary/${{ github.sha }}/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm ./cw-agent.rpm" >> $GITHUB_ENV + else + # Otherwise get latest release version + echo GET_CW_AGENT_RPM_COMMAND="wget -O cw-agent.rpm https://amazoncloudwatch-agent-${{ env.E2E_TEST_AWS_REGION }}.s3.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm" >> $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/dotnet/ec2/nuget && 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/dotnet/ec2/nuget + 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=${{ env.E2E_TEST_AWS_REGION }}" \ + -var="test_id=${{ env.TESTING_ID }}" \ + -var="sample_app_zip=${{ env.SAMPLE_APP_ZIP }}" \ + -var="get_cw_agent_rpm_command=${{ env.GET_CW_AGENT_RPM_COMMAND }}" \ + || 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 + run: | + echo "EC2_INSTANCE_AMI=$(terraform output ec2_instance_ami)" >> $GITHUB_ENV + working-directory: terraform/dotnet/ec2/nuget + + - name: Get the sample app endpoint + 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 + working-directory: terraform/dotnet/ec2/nuget + + - name: Initiate Gradlew Daemon + if: steps.initiate-gradlew == 'failure' + uses: ./.github/workflows/actions/execute_and_retry + continue-on-error: true + with: + command: "./gradlew" + 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 dotnet/ec2/default/log-validation.yml + --testing-id ${{ env.TESTING_ID }} + --endpoint http://${{ env.MAIN_SERVICE_ENDPOINT }} + --remote-service-deployment-name ${{ env.REMOTE_SERVICE_IP }}:8081 + --region ${{ env.E2E_TEST_AWS_REGION }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --service-name dotnet-sample-application-${{ env.TESTING_ID }} + --remote-service-name dotnet-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 dotnet/ec2/default/metric-validation.yml + --testing-id ${{ env.TESTING_ID }} + --endpoint http://${{ env.MAIN_SERVICE_ENDPOINT }} + --remote-service-deployment-name ${{ env.REMOTE_SERVICE_IP }}:8081 + --region ${{ env.E2E_TEST_AWS_REGION }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --service-name dotnet-sample-application-${{ env.TESTING_ID }} + --remote-service-name dotnet-sample-remote-application-${{ env.TESTING_ID }} + --query-string ip=${{ env.REMOTE_SERVICE_IP }} + --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 dotnet/ec2/default/trace-validation.yml + --testing-id ${{ env.TESTING_ID }} + --endpoint http://${{ env.MAIN_SERVICE_ENDPOINT }} + --remote-service-deployment-name ${{ env.REMOTE_SERVICE_IP }}:8081 + --region ${{ env.E2E_TEST_AWS_REGION }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --service-name dotnet-sample-application-${{ env.TESTING_ID }} + --remote-service-name dotnet-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/dotnet/ec2/nuget + run: | + terraform destroy -auto-approve \ + -var="test_id=${{ env.TESTING_ID }}" \ No newline at end of file diff --git a/terraform/dotnet/ec2/nuget/amazon-cloudwatch-agent.json b/terraform/dotnet/ec2/nuget/amazon-cloudwatch-agent.json new file mode 100644 index 000000000..a98a40d36 --- /dev/null +++ b/terraform/dotnet/ec2/nuget/amazon-cloudwatch-agent.json @@ -0,0 +1,16 @@ +{ + "agent": { + "debug": true, + "region": "$REGION" + }, + "traces": { + "traces_collected": { + "application_signals": {} + } + }, + "logs": { + "metrics_collected": { + "application_signals": {} + } + } +} \ No newline at end of file diff --git a/terraform/dotnet/ec2/nuget/main.tf b/terraform/dotnet/ec2/nuget/main.tf new file mode 100644 index 000000000..7fdebad8b --- /dev/null +++ b/terraform/dotnet/ec2/nuget/main.tf @@ -0,0 +1,289 @@ +# ------------------------------------------------------------------------ +# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# A copy of the License is located at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# or in the "license" file accompanying this file. This file is distributed +# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language governing +# permissions and limitations under the License. +# ------------------------------------------------------------------------- + +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + } + } +} + +# Define the provider for AWS +provider "aws" {} + +resource "aws_default_vpc" "default" {} + +resource "tls_private_key" "ssh_key" { + algorithm = "RSA" + rsa_bits = 4096 +} + +resource "aws_key_pair" "aws_ssh_key" { + key_name = "instance_key-${var.test_id}" + public_key = tls_private_key.ssh_key.public_key_openssh +} + +locals { + ssh_key_name = aws_key_pair.aws_ssh_key.key_name + private_key_content = tls_private_key.ssh_key.private_key_pem +} + +data "aws_ami" "ami" { + owners = ["amazon"] + most_recent = true + filter { + name = "name" + values = ["al20*-ami-minimal-*-x86_64"] + } + filter { + name = "state" + values = ["available"] + } + filter { + name = "architecture" + values = ["x86_64"] + } + filter { + name = "image-type" + values = ["machine"] + } + + filter { + name = "root-device-name" + values = ["/dev/xvda"] + } + + filter { + name = "root-device-type" + values = ["ebs"] + } + + filter { + name = "virtualization-type" + values = ["hvm"] + } +} + +resource "aws_instance" "main_service_instance" { + ami = data.aws_ami.ami.id # Amazon Linux 2 (free tier) + instance_type = "t3.small" + key_name = local.ssh_key_name + iam_instance_profile = "APP_SIGNALS_EC2_TEST_ROLE" + vpc_security_group_ids = [aws_default_vpc.default.default_security_group_id] + associate_public_ip_address = true + instance_initiated_shutdown_behavior = "terminate" + metadata_options { + http_tokens = "required" + } + + tags = { + Name = "main-service-${var.test_id}" + } +} + +resource "null_resource" "main_service_setup" { + connection { + type = "ssh" + user = var.user + private_key = local.private_key_content + host = aws_instance.main_service_instance.public_ip + } + + provisioner "remote-exec" { + inline = [ + <<-EOF + #!/bin/bash + + # Install DotNet and wget + sudo yum install -y wget + sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc + sudo wget -O /etc/yum.repos.d/microsoft-prod.repo https://packages.microsoft.com/config/fedora/37/prod.repo + sudo dnf install -y dotnet-sdk-8.0 + sudo yum install unzip -y + sudo yum install dos2unix -y + + # Copy in CW Agent configuration + agent_config='${replace(replace(file("./amazon-cloudwatch-agent.json"), "/\\s+/", ""), "$REGION", var.aws_region)}' + echo $agent_config > amazon-cloudwatch-agent.json + + # Get and run CW agent rpm + ${var.get_cw_agent_rpm_command} + sudo rpm -U ./cw-agent.rpm + sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:./amazon-cloudwatch-agent.json + + # Get and run the sample application with configuration + aws s3 cp ${var.sample_app_zip} ./dotnet-sample-app.zip + unzip -o dotnet-sample-app.zip + + # Get Absolute Path + current_dir=$(pwd) + echo $current_dir + + # Export environment variables for instrumentation + export ASPNETCORE_URLS=http://0.0.0.0:8080 + export OTEL_RESOURCE_ATTRIBUTES=service.name=dotnet-sample-application-${var.test_id} + + cd ./asp_frontend_service + dotnet add package AWS.Distro.OpenTelemetry.AutoInstrumentation --prerelease + dotnet build --runtime linux-x64 + dos2unix bin/Debug/netcoreapp8.0/linux-x64/adot-launch.sh + nohup sh bin/Debug/netcoreapp8.0/linux-x64/adot-launch.sh dotnet bin/Debug/netcoreapp8.0/linux-x64/asp_frontend_service.dll & + + # The application needs time to come up and reach a steady state, this should not take longer than 30 seconds + sleep 30 + + # Check if the application is up. If it is not up, then exit 1. + attempt_counter=0 + max_attempts=30 + until $(curl --output /dev/null --silent --fail $(echo "http://localhost:8080" | tr -d '"')); do + if [ $attempt_counter -eq $max_attempts ];then + echo "Failed to connect to endpoint. Will attempt to redeploy sample app." + deployment_failed=1 + break + fi + echo "Attempting to connect to the main endpoint. Tried $attempt_counter out of $max_attempts" + attempt_counter=$(($attempt_counter+1)) + sleep 10 + done + + EOF + ] + } + + depends_on = [aws_instance.main_service_instance] +} + +resource "aws_instance" "remote_service_instance" { + ami = data.aws_ami.ami.id # Amazon Linux 2 (free tier) + instance_type = "t3.small" + key_name = local.ssh_key_name + iam_instance_profile = "APP_SIGNALS_EC2_TEST_ROLE" + vpc_security_group_ids = [aws_default_vpc.default.default_security_group_id] + associate_public_ip_address = true + instance_initiated_shutdown_behavior = "terminate" + metadata_options { + http_tokens = "required" + } + + tags = { + Name = "remote-service-${var.test_id}" + } +} + +resource "null_resource" "remote_service_setup" { + connection { + type = "ssh" + user = var.user + private_key = local.private_key_content + host = aws_instance.remote_service_instance.public_ip + } + + provisioner "remote-exec" { + inline = [ + <<-EOF + #!/bin/bash + + # Install DotNet and wget + sudo yum install -y wget + sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc + sudo wget -O /etc/yum.repos.d/microsoft-prod.repo https://packages.microsoft.com/config/fedora/37/prod.repo + sudo dnf install -y dotnet-sdk-8.0 + sudo yum install unzip -y + sudo yum install dos2unix -y + + # Copy in CW Agent configuration + agent_config='${replace(replace(file("./amazon-cloudwatch-agent.json"), "/\\s+/", ""), "$REGION", var.aws_region)}' + echo $agent_config > amazon-cloudwatch-agent.json + + # Get and run CW agent rpm + ${var.get_cw_agent_rpm_command} + sudo rpm -U ./cw-agent.rpm + sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:./amazon-cloudwatch-agent.json + + # Get and run the sample application with configuration + aws s3 cp ${var.sample_app_zip} ./dotnet-sample-app.zip + unzip -o dotnet-sample-app.zip + + # Get Absolute Path + current_dir=$(pwd) + echo $current_dir + + # Export environment variables for instrumentation + cd ./asp_remote_service + export OTEL_RESOURCE_ATTRIBUTES=service.name=dotnet-sample-remote-application-${var.test_id} + export ASPNETCORE_URLS=http://0.0.0.0:8081 + + dotnet add package AWS.Distro.OpenTelemetry.AutoInstrumentation --prerelease + dotnet build --runtime linux-x64 + dos2unix bin/Debug/netcoreapp8.0/linux-x64/adot-launch.sh + nohup sh bin/Debug/netcoreapp8.0/linux-x64/adot-launch.sh dotnet bin/Debug/netcoreapp8.0/linux-x64/asp_remote_service.dll & + + # The application needs time to come up and reach a steady state, this should not take longer than 30 seconds + sleep 30 + + # Check if the application is up. If it is not up, then exit 1. + attempt_counter=0 + max_attempts=30 + until $(curl --output /dev/null --silent --fail $(echo "http://localhost:8081" | tr -d '"')); do + if [ $attempt_counter -eq $max_attempts ];then + echo "Failed to connect to endpoint. Will attempt to redeploy sample app." + deployment_failed=1 + break + fi + echo "Attempting to connect to the remote endpoint. Tried $attempt_counter out of $max_attempts" + attempt_counter=$(($attempt_counter+1)) + sleep 10 + done + + EOF + ] + } + + depends_on = [aws_instance.remote_service_instance] +} + +resource "null_resource" "traffic_generator_setup" { + connection { + type = "ssh" + user = var.user + private_key = local.private_key_content + host = aws_instance.main_service_instance.public_ip + } + + provisioner "remote-exec" { + inline = [ + <<-EOF + sudo yum install nodejs aws-cli unzip tmux -y + + # Bring in the traffic generator files to EC2 Instance + aws s3 cp s3://aws-appsignals-sample-app-prod-${var.aws_region}/traffic-generator.zip ./traffic-generator.zip + unzip ./traffic-generator.zip -d ./ + + # Install the traffic generator dependencies + npm install + + tmux new -s traffic-generator -d + tmux send-keys -t traffic-generator "export MAIN_ENDPOINT=\"localhost:8080\"" C-m + tmux send-keys -t traffic-generator "export REMOTE_ENDPOINT=\"${aws_instance.remote_service_instance.private_ip}\"" C-m + tmux send-keys -t traffic-generator "export ID=\"${var.test_id}\"" C-m + tmux send-keys -t traffic-generator "npm start" C-m + + EOF + ] + } + + depends_on = [null_resource.main_service_setup, null_resource.remote_service_setup] +} diff --git a/terraform/dotnet/ec2/nuget/output.tf b/terraform/dotnet/ec2/nuget/output.tf new file mode 100644 index 000000000..be572868a --- /dev/null +++ b/terraform/dotnet/ec2/nuget/output.tf @@ -0,0 +1,26 @@ +# ------------------------------------------------------------------------ +# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# A copy of the License is located at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# or in the "license" file accompanying this file. This file is distributed +# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language governing +# permissions and limitations under the License. +# ------------------------------------------------------------------------- + +output "sample_app_remote_service_private_ip" { + value = aws_instance.remote_service_instance.private_ip +} + +output "main_service_instance_id" { + value = aws_instance.main_service_instance.id +} + +output "ec2_instance_ami" { + value = data.aws_ami.ami.id +} \ No newline at end of file diff --git a/terraform/dotnet/ec2/nuget/variables.tf b/terraform/dotnet/ec2/nuget/variables.tf new file mode 100644 index 000000000..ba9c04cc3 --- /dev/null +++ b/terraform/dotnet/ec2/nuget/variables.tf @@ -0,0 +1,38 @@ +# ------------------------------------------------------------------------ +# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# A copy of the License is located at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# or in the "license" file accompanying this file. This file is distributed +# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language governing +# permissions and limitations under the License. +# ------------------------------------------------------------------------- + +variable "test_id" { + default = "dummy-123" +} + +variable "aws_region" { + default = "" +} + +variable "user" { + default = "ec2-user" +} + +variable "sample_app_zip" { + default = "s3:///" +} + +variable "get_cw_agent_rpm_command" { + default = " s3:///" +} + +variable "canary_type" { + default = "dotnet-ec2-default" +} \ No newline at end of file