Skip to content

Commit

Permalink
Adding aws creation timestamp to resources
Browse files Browse the repository at this point in the history
  • Loading branch information
willdavsmith committed Sep 13, 2023
1 parent 677aa29 commit adea799
Show file tree
Hide file tree
Showing 15 changed files with 200 additions and 35 deletions.
99 changes: 99 additions & 0 deletions .github/scripts/delete-aws-resources.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/bin/bash

# ------------------------------------------------------------
# Copyright 2023 The Radius Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License 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.
# ------------------------------------------------------------

# Comma-separated list of AWS resource types
RESOURCE_TYPES=$1

# Label on AWS resources
LABEL='RadiusCreationTimestamp'

# File to store the list of deleted resources
DELETED_RESOURCES_FILE='deleted-resources.txt'

# Number of retries
MAX_RETRIES=5

# Retry delay in seconds
RETRY_DELAY=300 # 5 minutes

# Maximum age of resources in seconds
MAX_AGE=21600

# Current time in seconds
CURRENT_TIME=$(date +%s)

function delete_old_aws_resources() {
# Empty the file
truncate -s 0 $DELETED_RESOURCES_FILE

for resource_type in ${RESOURCE_TYPES//,/ }
do
aws cloudcontrol list-resources --type-name "$resource_type" --query "ResourceDescriptions[].Identifier" --output text | tr '\t' '\n' | while read identifier
do
aws cloudcontrol get-resource --type-name "$resource_type" --identifier "$identifier" --query "ResourceDescription.Properties" --output text | while read resource
do
resource_tags=$(jq -c -r .Tags <<< "$resource")
for tag in $(jq -c -r '.[]' <<< "$resource_tags")
do
key=$(jq -r '.Key' <<< "$tag")
value=$(jq -r '.Value' <<< "$tag")
if [[ "$key" == "$LABEL" && $((CURRENT_TIME - value)) -gt $MAX_AGE]]
then
echo "Deleting resource of type: $resource_type with identifier: $identifier"
echo "$identifier\n" >> $DELETED_RESOURCES_FILE
aws cloudcontrol delete-resource --type-name "$resource_type" --identifier "$identifier"
fi
done
done
done
done

if [ -s $DELETED_RESOURCES_FILE ]; then
return 1
else
return 0
fi
}

RETRY_COUNT=0
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
# Trigger the function to delete the resources
delete_old_aws_resources

# If the function returned 0, then no resources needed to be deleted
# on this run. This means that all resources have been deleted.
if [ $? -eq 0 ]; then
echo "All resources deleted successfully"
break
fi

# Still have resources to delete, increase the retry count
RETRY_COUNT=$((RETRY_COUNT + 1))

# Check if there are more retries left
if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then
# Retry after delay
echo "Retrying in $RETRY_DELAY seconds..."
sleep $RETRY_DELAY
fi
done

# Check if the maximum number of retries exceeded
if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
echo "Maximum number of retries exceeded"
fi
18 changes: 5 additions & 13 deletions .github/workflows/purge-aws-test-resources.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ on:

env:
AWS_REGION: us-west-2
AWS_RESOURCE_TYPES: 'AWS::Kinesis::Stream,AWS::S3::Bucket,AWS::RDS::DBInstance,AWS::RDS::DBSubnetGroup,AWS::MemoryDB::Cluster,AWS::MemoryDB::SubnetGroup'
AWS_RESOURCE_TYPES: 'AWS::RDS::DBSubnetGroup,AWS::RDS::DBInstance,AWS::S3::Bucket,AWS::Logs::MetricFilter,AWS::Logs::LogGroup'

jobs:
purge_aws_resources:
name: Delete all AWS resources created by tests
name: Delete old AWS resources created by tests
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
Expand All @@ -35,15 +36,6 @@ jobs:
aws-access-key-id: ${{ secrets.FUNCTEST_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.FUNCTEST_AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Filter and delete resources
- name: Delete old AWS resources
run: |
RESOURCE_TYPES=${{env.AWS_RESOURCE_TYPES}}
for resource_type in ${RESOURCE_TYPES//,/ }
do
echo "Deleting resources of type $resource_type"
aws cloudcontrol list-resources --type-name "$resource_type" --query "ResourceDescriptions[].Identifier" --output text | tr '\t' '\n' | while read identifier
do
echo "Deleting resource $identifier of type $resource_type"
aws cloudcontrol delete-resource --type-name "$resource_type" --identifier "$identifier"
done
done
./.github/scripts/delete_aws_resources.sh ${{ env.AWS_RESOURCE_TYPES }}
11 changes: 7 additions & 4 deletions test/functional/shared/mechanics/aws_mechanics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"testing"

"github.com/google/uuid"
"github.com/radius-project/radius/test/functional"
"github.com/radius-project/radius/test/functional/shared"
"github.com/radius-project/radius/test/step"
"github.com/radius-project/radius/test/validation"
Expand All @@ -29,10 +30,11 @@ import (
func Test_AWSRedeployWithUpdatedResourceUpdatesResource(t *testing.T) {
templateFmt := "testdata/aws-mechanics-redeploy-withupdatedresource.step%d.bicep"
name := "radiusfunctionaltestbucket-" + uuid.New().String()
creationTimestamp := functional.GetCreationTimestamp()

test := shared.NewRPTest(t, name, []shared.TestStep{
{
Executor: step.NewDeployExecutor(fmt.Sprintf(templateFmt, 1), "bucketName="+name),
Executor: step.NewDeployExecutor(fmt.Sprintf(templateFmt, 1), "bucketName="+name, "creationTimestamp="+creationTimestamp),
SkipKubernetesOutputResourceValidation: true,
SkipObjectValidation: true,
SkipResourceDeletion: true,
Expand All @@ -56,7 +58,7 @@ func Test_AWSRedeployWithUpdatedResourceUpdatesResource(t *testing.T) {
},
},
{
Executor: step.NewDeployExecutor(fmt.Sprintf(templateFmt, 2), "bucketName="+name),
Executor: step.NewDeployExecutor(fmt.Sprintf(templateFmt, 2), "bucketName="+name, "creationTimestamp="+creationTimestamp),
SkipKubernetesOutputResourceValidation: true,
SkipObjectValidation: true,
AWSResources: &validation.AWSResourceSet{
Expand Down Expand Up @@ -86,10 +88,11 @@ func Test_AWSRedeployWithCreateAndWriteOnlyPropertyUpdate(t *testing.T) {
t.Skip("This test will fail because step 2 is updating a create-and-write-only property.")
name := "my-db"
templateFmt := "testdata/aws-mechanics-redeploy-withcreateandwriteonlypropertyupdate.step%d.bicep"
creationTimestamp := functional.GetCreationTimestamp()

test := shared.NewRPTest(t, name, []shared.TestStep{
{
Executor: step.NewDeployExecutor(fmt.Sprintf(templateFmt, 1)),
Executor: step.NewDeployExecutor(fmt.Sprintf(templateFmt, 1), "creationTimestamp="+creationTimestamp),
SkipKubernetesOutputResourceValidation: true,
SkipObjectValidation: true,
SkipResourceDeletion: true,
Expand All @@ -109,7 +112,7 @@ func Test_AWSRedeployWithCreateAndWriteOnlyPropertyUpdate(t *testing.T) {
},
},
{
Executor: step.NewDeployExecutor(fmt.Sprintf(templateFmt, 2)),
Executor: step.NewDeployExecutor(fmt.Sprintf(templateFmt, 2), "creationTimestamp="+creationTimestamp),
SkipKubernetesOutputResourceValidation: true,
SkipObjectValidation: true,
AWSResources: &validation.AWSResourceSet{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import aws as aws

param dbSubnetGroupName string = 'willsmith-rds-mssql-subnet-group-3'
param creationTimestamp string
param dbSubnetGroupName string
param dbName string

resource subnetGroup 'AWS.RDS/DBSubnetGroup@default' = {
alias: dbSubnetGroupName
properties: {
DBSubnetGroupDescription: dbSubnetGroupName
SubnetIds: ['']
Tags: [
{
Key: 'RadiusCreationTimestamp'
Value: creationTimestamp
}
]
}
}

param dbName string = 'willsmith-rds-mssql-3'
resource db 'AWS.RDS/DBInstance@default' = {
alias: dbName
properties: {
Expand All @@ -30,5 +38,11 @@ resource db 'AWS.RDS/DBInstance@default' = {
LicenseModel: 'license-included'
Timezone: 'GMT Standard Time'
CharacterSetName: 'Latin1_General_CI_AS'
Tags: [
{
Key: 'RadiusCreationTimestamp'
Value: creationTimestamp
}
]
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import aws as aws

param dbSubnetGroupName string = 'willsmith-rds-mssql-subnet-group-3'
param creationTimestamp string
param dbSubnetGroupName string
param dbName string

resource subnetGroup 'AWS.RDS/DBSubnetGroup@default' = {
alias: dbSubnetGroupName
properties: {
DBSubnetGroupDescription: dbSubnetGroupName
SubnetIds: ['']
Tags: [
{
Key: 'RadiusCreationTimestamp'
Value: creationTimestamp
}
]
}
}

param dbName string = 'willsmith-rds-mssql-3'
resource db 'AWS.RDS/DBInstance@default' = {
alias: dbName
properties: {
Expand All @@ -30,5 +38,11 @@ resource db 'AWS.RDS/DBInstance@default' = {
LicenseModel: 'license-included'
Timezone: 'GMT Standard Time'
CharacterSetName: 'Latin1_General_CI_AS'
Tags: [
{
Key: 'RadiusCreationTimestamp'
Value: creationTimestamp
}
]
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import aws as aws

param creationTimestamp string
param bucketName string

resource bucket 'AWS.S3/Bucket@default' = {
Expand All @@ -11,6 +12,10 @@ resource bucket 'AWS.S3/Bucket@default' = {
Key: 'testKey'
Value: 'testValue'
}
{
Key: 'RadiusCreationTimestamp'
Value: creationTimestamp
}
]
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import aws as aws

param creationTimestamp string
param bucketName string

resource bucket 'AWS.S3/Bucket@default' = {
Expand All @@ -11,6 +12,10 @@ resource bucket 'AWS.S3/Bucket@default' = {
Key: 'testKey'
Value: 'testValue2'
}
{
Key: 'RadiusCreationTimestamp'
Value: creationTimestamp
}
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ limitations under the License.
package resource_test

import (
"fmt"
"testing"
"time"

"github.com/google/uuid"
"github.com/radius-project/radius/test/functional/shared"
Expand All @@ -30,10 +32,11 @@ func Test_AWS_MultiIdentifier_Resource(t *testing.T) {
filterName := "ms" + uuid.New().String()
logGroupName := "ms" + uuid.New().String()
testName := "ms" + uuid.New().String()
creationTimestamp := fmt.Sprintf("%d", time.Now().Unix())

test := shared.NewRPTest(t, testName, []shared.TestStep{
{
Executor: step.NewDeployExecutor(template, "filterName="+filterName, "logGroupName="+logGroupName),
Executor: step.NewDeployExecutor(template, "filterName="+filterName, "logGroupName="+logGroupName, "creationTimestamp="+creationTimestamp),
SkipKubernetesOutputResourceValidation: true,
SkipObjectValidation: true,
AWSResources: &validation.AWSResourceSet{
Expand Down
16 changes: 7 additions & 9 deletions test/functional/shared/resources/aws_s3_bucket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,20 @@ package resource_test
import (
"testing"

"github.com/google/uuid"
"github.com/radius-project/radius/test/functional"
"github.com/radius-project/radius/test/functional/shared"
"github.com/radius-project/radius/test/step"
"github.com/radius-project/radius/test/validation"
)

func Test_AWS_S3Bucket(t *testing.T) {
template := "testdata/aws-s3-bucket.bicep"
name := generateS3BucketName()
name := functional.GenerateS3BucketName()
creationTimestamp := functional.GetCreationTimestamp()

test := shared.NewRPTest(t, name, []shared.TestStep{
{
Executor: step.NewDeployExecutor(template, "bucketName="+name),
Executor: step.NewDeployExecutor(template, "bucketName="+name, "creationTimestamp="+creationTimestamp),
SkipKubernetesOutputResourceValidation: true,
SkipObjectValidation: true,
AWSResources: &validation.AWSResourceSet{
Expand Down Expand Up @@ -61,11 +62,12 @@ func Test_AWS_S3Bucket(t *testing.T) {
func Test_AWS_S3Bucket_Existing(t *testing.T) {
template := "testdata/aws-s3-bucket.bicep"
templateExisting := "testdata/aws-s3-bucket-existing.bicep"
name := generateS3BucketName()
name := functional.GenerateS3BucketName()
creationTimestamp := functional.GetCreationTimestamp()

test := shared.NewRPTest(t, name, []shared.TestStep{
{
Executor: step.NewDeployExecutor(template, "bucketName="+name),
Executor: step.NewDeployExecutor(template, "bucketName="+name, "creationTimestamp="+creationTimestamp),
SkipKubernetesOutputResourceValidation: true,
SkipObjectValidation: true,
SkipResourceDeletion: true,
Expand Down Expand Up @@ -117,7 +119,3 @@ func Test_AWS_S3Bucket_Existing(t *testing.T) {

test.Test(t)
}

func generateS3BucketName() string {
return "radiusfunctionaltestbucket-" + uuid.New().String()
}
6 changes: 4 additions & 2 deletions test/functional/shared/resources/extender_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,16 @@ func Test_Extender_RecipeAWS(t *testing.T) {
template := "testdata/corerp-resources-extender-aws-s3-recipe.bicep"
name := "corerp-resources-extenders-aws-s3-recipe"
appName := "corerp-resources-extenders-aws-s3-recipe-app"
bucketName := generateS3BucketName()
bucketName := functional.GenerateS3BucketName()
bucketID := fmt.Sprintf("/planes/aws/aws/accounts/%s/regions/%s/providers/AWS.S3/Bucket/%s", awsAccountID, awsRegion, bucketName)
creationTimestamp := functional.GetCreationTimestamp()

test := shared.NewRPTest(t, name, []shared.TestStep{
{
Executor: step.NewDeployExecutor(
template,
fmt.Sprintf("bucketName=%s", bucketName),
"bucketName="+bucketName,
"creationTimestamp="+creationTimestamp,
functional.GetAWSAccountId(),
functional.GetAWSRegion(),
functional.GetBicepRecipeRegistry(),
Expand Down
Loading

0 comments on commit adea799

Please sign in to comment.