From 829e689e255ab2bf8f577849e47e61d399d73f75 Mon Sep 17 00:00:00 2001 From: Amanuel Engeda <74629455+engedaam@users.noreply.github.com> Date: Thu, 30 Nov 2023 10:44:10 -0800 Subject: [PATCH] ci: Add Resource count to Timestream (#5098) --- .github/actions/e2e/cleanup/action.yaml | 6 +- .github/workflows/resource-count.yaml | 30 +++++++++ .github/workflows/sweeper.yaml | 6 +- test/cloudformation/README.md | 4 +- test/cloudformation/iam_cloudformation.yaml | 4 ++ .../timestream_cloudformation.yaml | 14 ++++ test/hack/{cleanup => resource/clean}/main.go | 7 +- test/hack/resource/count/main.go | 67 +++++++++++++++++++ test/hack/{cleanup => resource}/go.mod | 2 +- test/hack/{cleanup => resource}/go.sum | 0 .../pkg}/metrics/metrics.go | 11 ++- .../pkg}/resourcetypes/eni.go | 20 ++++++ .../pkg}/resourcetypes/instance.go | 37 +++++++++- .../pkg}/resourcetypes/instanceprofile.go | 9 +++ .../pkg}/resourcetypes/launchtemplate.go | 20 ++++++ .../pkg}/resourcetypes/oidc.go | 9 +++ .../pkg}/resourcetypes/resourcetypes.go | 2 + .../pkg}/resourcetypes/securitygroup.go | 20 ++++++ .../pkg}/resourcetypes/stack.go | 20 ++++++ .../pkg}/resourcetypes/vpc_endpoint.go | 20 ++++++ 20 files changed, 289 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/resource-count.yaml rename test/hack/{cleanup => resource/clean}/main.go (88%) create mode 100644 test/hack/resource/count/main.go rename test/hack/{cleanup => resource}/go.mod (96%) rename test/hack/{cleanup => resource}/go.sum (100%) rename test/hack/{cleanup => resource/pkg}/metrics/metrics.go (82%) rename test/hack/{cleanup => resource/pkg}/resourcetypes/eni.go (88%) rename test/hack/{cleanup => resource/pkg}/resourcetypes/instance.go (77%) rename test/hack/{cleanup => resource/pkg}/resourcetypes/instanceprofile.go (93%) rename test/hack/{cleanup => resource/pkg}/resourcetypes/launchtemplate.go (88%) rename test/hack/{cleanup => resource/pkg}/resourcetypes/oidc.go (90%) rename test/hack/{cleanup => resource/pkg}/resourcetypes/resourcetypes.go (93%) rename test/hack/{cleanup => resource/pkg}/resourcetypes/securitygroup.go (88%) rename test/hack/{cleanup => resource/pkg}/resourcetypes/stack.go (89%) rename test/hack/{cleanup => resource/pkg}/resourcetypes/vpc_endpoint.go (86%) diff --git a/.github/actions/e2e/cleanup/action.yaml b/.github/actions/e2e/cleanup/action.yaml index da0c14984b1a..8db0b5f83dc3 100644 --- a/.github/actions/e2e/cleanup/action.yaml +++ b/.github/actions/e2e/cleanup/action.yaml @@ -33,12 +33,12 @@ runs: eksctl delete cluster --name ${{ inputs.cluster_name }} --timeout 60m --wait || true - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4 with: - go-version-file: test/hack/cleanup/go.mod - cache-dependency-path: test/hack/cleanup/go.sum + go-version-file: test/hack/resource/go.mod + cache-dependency-path: test/hack/resource/go.sum check-latest: true cache: false - name: "Run cleanup script" run: | go run main.go ${{ inputs.cluster_name }} - working-directory: ./test/hack/cleanup + working-directory: ./test/hack/resource/clean shell: bash diff --git a/.github/workflows/resource-count.yaml b/.github/workflows/resource-count.yaml new file mode 100644 index 000000000000..18e7d19e0658 --- /dev/null +++ b/.github/workflows/resource-count.yaml @@ -0,0 +1,30 @@ +name: ResourceCount +on: + schedule: + - cron: '3 */1 * * *' # every hour + workflow_dispatch: +permissions: + id-token: write # aws-actions/configure-aws-credentials@v4.0.1 +jobs: + counter: + if: vars.ACCOUNT_ID != '' || github.event_name == 'workflow_dispatch' + strategy: + fail-fast: false + matrix: + region: [us-east-2, us-west-2, eu-west-1] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: configure aws credentials + uses: aws-actions/configure-aws-credentials@v4.0.1 + with: + role-to-assume: arn:aws:iam::${{ vars.ACCOUNT_ID }}:role/${{ vars.ROLE_NAME }} + aws-region: ${{ matrix.region }} + - uses: actions/setup-go@v4 + with: + go-version-file: test/hack/resource/go.mod + check-latest: true + cache-dependency-path: "test/hack/resource/go.sum" + - run: go run main.go + working-directory: ./test/hack/resource/count + name: "Run resource count script" diff --git a/.github/workflows/sweeper.yaml b/.github/workflows/sweeper.yaml index c17f9b7a99f3..cc441413eaad 100644 --- a/.github/workflows/sweeper.yaml +++ b/.github/workflows/sweeper.yaml @@ -22,9 +22,9 @@ jobs: aws-region: ${{ matrix.region }} - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4 with: - go-version-file: test/hack/cleanup/go.mod + go-version-file: test/hack/resource/go.mod check-latest: true - cache-dependency-path: "test/hack/cleanup/go.sum" + cache-dependency-path: "test/hack/resource/go.sum" - run: go run main.go - working-directory: ./test/hack/cleanup + working-directory: ./test/hack/resource/clean name: "Run cleanup script" diff --git a/test/cloudformation/README.md b/test/cloudformation/README.md index 4012cb0dc858..69df60d47854 100644 --- a/test/cloudformation/README.md +++ b/test/cloudformation/README.md @@ -13,7 +13,7 @@ aws cloudformation deploy \ aws cloudformation deploy \ --stack-name GithubActionsTimestream \ --template-file timestream_cloudformation.yaml \ - --parameter-overrides "DatabaseName=karpenterTesting" "TableName=scaleTestDurations" "SweeperTableName=sweeperCleanedResources" + --parameter-overrides "DatabaseName=karpenterTesting" "TableName=scaleTestDurations" "SweeperTableName=sweeperCleanedResources" "ResourceCountTableName=resourceCount" ``` ### [Optional] Deploying ManagedGrafana and its Policy @@ -30,7 +30,7 @@ aws cloudformation deploy \ ```console aws cloudformation deploy --stack-name GithubActionsIAM \ --template-file iam_cloudformation.yaml \ - --parameter-overrides "DatabaseName=karpenterTesting" "TableName=scaleTestDurations" "SweeperTableName=sweeperCleanedResources" "Repository=" Branches="*" "PrometheusWorkspaceID=" Regions="us-east-2,us-west-2,..." \ + --parameter-overrides "DatabaseName=karpenterTesting" "TableName=scaleTestDurations" "SweeperTableName=sweeperCleanedResources" "ResourceCountTableName=resourceCount" "Repository=" Branches="*" "PrometheusWorkspaceID=" Regions="us-east-2,us-west-2,..." \ --capabilities CAPABILITY_NAMED_IAM ``` diff --git a/test/cloudformation/iam_cloudformation.yaml b/test/cloudformation/iam_cloudformation.yaml index d1ab91eb9384..6184121f41dc 100644 --- a/test/cloudformation/iam_cloudformation.yaml +++ b/test/cloudformation/iam_cloudformation.yaml @@ -22,6 +22,9 @@ Parameters: SweeperTableName: Type: String Description: "Timestream table to forward leaked resources to" + ResourceCountTableName: + Type: String + Description: "Timestream table to count number of resources to" Resources: GithubOIDCProvider: Type: AWS::IAM::OIDCProvider @@ -138,6 +141,7 @@ Resources: Resource: - !Sub "arn:${AWS::Partition}:timestream:${AWS::Region}:${AWS::AccountId}:database/${DatabaseName}/table/${TableName}" - !Sub "arn:${AWS::Partition}:timestream:${AWS::Region}:${AWS::AccountId}:database/${DatabaseName}/table/${SweeperTableName}" + - !Sub "arn:${AWS::Partition}:timestream:${AWS::Region}:${AWS::AccountId}:database/${DatabaseName}/table/${ResourceCountTableName}" - Effect: Allow Action: timestream:DescribeEndpoints Resource: "*" diff --git a/test/cloudformation/timestream_cloudformation.yaml b/test/cloudformation/timestream_cloudformation.yaml index 1f937ce24733..9de4adb6f5a8 100644 --- a/test/cloudformation/timestream_cloudformation.yaml +++ b/test/cloudformation/timestream_cloudformation.yaml @@ -10,6 +10,9 @@ Parameters: SweeperTableName: Type: String Description: "Timestream table to forward leaked resources to" + ResourceCountTableName: + Type: String + Description: "Timestream table to count number of resources to" BackupDisasterRecoveryRegion: Type: String Default: "us-east-1" @@ -39,6 +42,16 @@ Resources: RetentionProperties: MemoryStoreRetentionPeriodInHours: "2160" # Three months of memory store retention MagneticStoreRetentionPeriodInDays: "1825" # 5 years of magnetic store retention + ResourceCountTimestreamTable: + Type: "AWS::Timestream::Table" + Properties: + DatabaseName: !Ref "TimestreamDatabase" + TableName: !Sub "${ResourceCountTableName}" + MagneticStoreWriteProperties: + EnableMagneticStoreWrites: true + RetentionProperties: + MemoryStoreRetentionPeriodInHours: "2160" # Three months of memory store retention + MagneticStoreRetentionPeriodInDays: "1825" # 5 years of magnetic store retention TimestreamBackupPlan: Type: "AWS::Backup::BackupPlan" Properties: @@ -65,6 +78,7 @@ Resources: Resources: - !GetAtt "TimestreamTable.Arn" - !GetAtt "SweeperTimestreamTable.Arn" + - !GetAtt "ResourceCountTimestreamTable.Arn" BackupPlanId: !Ref "TimestreamBackupPlan" Outputs: ScaleTimestreamTable: diff --git a/test/hack/cleanup/main.go b/test/hack/resource/clean/main.go similarity index 88% rename from test/hack/cleanup/main.go rename to test/hack/resource/clean/main.go index a281d04a1c3f..c5c6b32854c0 100644 --- a/test/hack/cleanup/main.go +++ b/test/hack/resource/clean/main.go @@ -27,11 +27,12 @@ import ( "github.com/samber/lo" "go.uber.org/zap" - "github.com/aws/karpenter/test/hack/cleanup/metrics" - "github.com/aws/karpenter/test/hack/cleanup/resourcetypes" + "github.com/aws/karpenter/test/hack/resource/pkg/metrics" + "github.com/aws/karpenter/test/hack/resource/pkg/resourcetypes" ) const expirationTTL = time.Hour * 12 +const sweeperCleanedResourcesTableName = "sweeperCleanedResources" func main() { var clusterName string @@ -86,7 +87,7 @@ func main() { if err != nil { resourceLogger.Errorf("%v", err) } - if err = metricsClient.FireMetric(ctx, fmt.Sprintf("%sDeleted", resourceTypes[i].String()), float64(len(cleaned)), cfg.Region); err != nil { + if err = metricsClient.FireMetric(ctx, sweeperCleanedResourcesTableName, fmt.Sprintf("%sDeleted", resourceTypes[i].String()), float64(len(cleaned)), cfg.Region); err != nil { resourceLogger.Errorf("%v", err) } resourceLogger.With("ids", cleaned, "count", len(cleaned)).Infof("deleted resourceTypes") diff --git a/test/hack/resource/count/main.go b/test/hack/resource/count/main.go new file mode 100644 index 000000000000..1213a81c8b64 --- /dev/null +++ b/test/hack/resource/count/main.go @@ -0,0 +1,67 @@ +/* +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. +*/ + +package main + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/cloudformation" + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/iam" + "github.com/samber/lo" + "go.uber.org/zap" + + "github.com/aws/karpenter/test/hack/resource/pkg/metrics" + "github.com/aws/karpenter/test/hack/resource/pkg/resourcetypes" +) + +const resourceCountTableName = "resourceCount" + +func main() { + ctx := context.Background() + cfg := lo.Must(config.LoadDefaultConfig(ctx)) + + logger := lo.Must(zap.NewProduction()).Sugar() + + ec2Client := ec2.NewFromConfig(cfg) + cloudFormationClient := cloudformation.NewFromConfig(cfg) + iamClient := iam.NewFromConfig(cfg) + metricsClient := metrics.Client(metrics.NewTimeStream(cfg)) + + resourceTypes := []resourcetypes.Type{ + resourcetypes.NewInstance(ec2Client), + resourcetypes.NewVPCEndpoint(ec2Client), + resourcetypes.NewENI(ec2Client), + resourcetypes.NewSecurityGroup(ec2Client), + resourcetypes.NewLaunchTemplate(ec2Client), + resourcetypes.NewOIDC(iamClient), + resourcetypes.NewInstanceProfile(iamClient), + resourcetypes.NewStack(cloudFormationClient), + } + + for i := range resourceTypes { + resourceLogger := logger.With("type", resourceTypes[i].String()) + resourceCount, err := resourceTypes[i].CountAll(ctx) + if err != nil { + resourceLogger.Errorf("%v", err) + } + + if err = metricsClient.FireMetric(ctx, resourceCountTableName, resourceTypes[i].String(), float64(resourceCount), cfg.Region); err != nil { + resourceLogger.Errorf("%v", err) + } + resourceLogger.With("count", resourceCount).Infof("counted resourceTypes") + } +} diff --git a/test/hack/cleanup/go.mod b/test/hack/resource/go.mod similarity index 96% rename from test/hack/cleanup/go.mod rename to test/hack/resource/go.mod index 957d62666071..83dd3a60bd8f 100644 --- a/test/hack/cleanup/go.mod +++ b/test/hack/resource/go.mod @@ -1,4 +1,4 @@ -module github.com/aws/karpenter/test/hack/cleanup +module github.com/aws/karpenter/test/hack/resource go 1.21 diff --git a/test/hack/cleanup/go.sum b/test/hack/resource/go.sum similarity index 100% rename from test/hack/cleanup/go.sum rename to test/hack/resource/go.sum diff --git a/test/hack/cleanup/metrics/metrics.go b/test/hack/resource/pkg/metrics/metrics.go similarity index 82% rename from test/hack/cleanup/metrics/metrics.go rename to test/hack/resource/pkg/metrics/metrics.go index 9eff9dc43bd6..69f3ffb068dc 100644 --- a/test/hack/cleanup/metrics/metrics.go +++ b/test/hack/resource/pkg/metrics/metrics.go @@ -25,13 +25,12 @@ import ( ) const ( - karpenterMetricRegion = "us-east-2" - karpenterMetricDatabase = "karpenterTesting" - karpenterMetricTableName = "sweeperCleanedResources" + karpenterMetricRegion = "us-east-2" + karpenterMetricDatabase = "karpenterTesting" ) type Client interface { - FireMetric(context.Context, string, float64, string) error + FireMetric(ctx context.Context, tableName string, metricName string, metricValue float64, region string) error } type TimeStream struct { @@ -42,10 +41,10 @@ func NewTimeStream(cfg aws.Config) *TimeStream { return &TimeStream{timestreamClient: timestreamwrite.NewFromConfig(cfg, WithRegion(karpenterMetricRegion))} } -func (t *TimeStream) FireMetric(ctx context.Context, name string, value float64, region string) error { +func (t *TimeStream) FireMetric(ctx context.Context, tableName string, name string, value float64, region string) error { _, err := t.timestreamClient.WriteRecords(ctx, ×treamwrite.WriteRecordsInput{ DatabaseName: aws.String(karpenterMetricDatabase), - TableName: aws.String(karpenterMetricTableName), + TableName: aws.String(tableName), Records: []timestreamtypes.Record{ { MeasureName: aws.String(name), diff --git a/test/hack/cleanup/resourcetypes/eni.go b/test/hack/resource/pkg/resourcetypes/eni.go similarity index 88% rename from test/hack/cleanup/resourcetypes/eni.go rename to test/hack/resource/pkg/resourcetypes/eni.go index 1562f179243e..a81450b0facf 100644 --- a/test/hack/cleanup/resourcetypes/eni.go +++ b/test/hack/resource/pkg/resourcetypes/eni.go @@ -77,6 +77,26 @@ func (e *ENI) GetExpired(ctx context.Context, expirationTime time.Time) (ids []s return ids, err } +func (e *ENI) CountAll(ctx context.Context) (count int, err error) { + var nextToken *string + for { + out, err := e.ec2Client.DescribeNetworkInterfaces(ctx, &ec2.DescribeNetworkInterfacesInput{ + NextToken: nextToken, + }) + if err != nil { + return count, err + } + + count += len(out.NetworkInterfaces) + + nextToken = out.NextToken + if nextToken == nil { + break + } + } + return count, err +} + func (e *ENI) Get(ctx context.Context, clusterName string) (ids []string, err error) { var nextToken *string for { diff --git a/test/hack/cleanup/resourcetypes/instance.go b/test/hack/resource/pkg/resourcetypes/instance.go similarity index 77% rename from test/hack/cleanup/resourcetypes/instance.go rename to test/hack/resource/pkg/resourcetypes/instance.go index d1a8404e4006..d869d71c3dd6 100644 --- a/test/hack/cleanup/resourcetypes/instance.go +++ b/test/hack/resource/pkg/resourcetypes/instance.go @@ -71,6 +71,41 @@ func (i *Instance) GetExpired(ctx context.Context, expirationTime time.Time) (id return ids, err } +func (i *Instance) CountAll(ctx context.Context) (count int, err error) { + var nextToken *string + + for { + out, err := i.ec2Client.DescribeInstances(ctx, &ec2.DescribeInstancesInput{ + Filters: []ec2types.Filter{ + { + Name: lo.ToPtr("instance-state-name"), + Values: []string{ + string(ec2types.InstanceStateNameRunning), + string(ec2types.InstanceStateNamePending), + string(ec2types.InstanceStateNameShuttingDown), + string(ec2types.InstanceStateNameStopped), + string(ec2types.InstanceStateNameStopping), + }, + }, + }, + NextToken: nextToken, + }) + if err != nil { + return count, err + } + + for _, res := range out.Reservations { + count += len(res.Instances) + } + + nextToken = out.NextToken + if nextToken == nil { + break + } + } + return count, err +} + func (i *Instance) Get(ctx context.Context, clusterName string) (ids []string, err error) { var nextToken *string @@ -78,7 +113,7 @@ func (i *Instance) Get(ctx context.Context, clusterName string) (ids []string, e out, err := i.ec2Client.DescribeInstances(ctx, &ec2.DescribeInstancesInput{ Filters: []ec2types.Filter{ { - Name: lo.ToPtr("Instance-state-name"), + Name: lo.ToPtr("instance-state-name"), Values: []string{string(ec2types.InstanceStateNameRunning)}, }, { diff --git a/test/hack/cleanup/resourcetypes/instanceprofile.go b/test/hack/resource/pkg/resourcetypes/instanceprofile.go similarity index 93% rename from test/hack/cleanup/resourcetypes/instanceprofile.go rename to test/hack/resource/pkg/resourcetypes/instanceprofile.go index dbfd79297305..23fff1a5a4f3 100644 --- a/test/hack/cleanup/resourcetypes/instanceprofile.go +++ b/test/hack/resource/pkg/resourcetypes/instanceprofile.go @@ -64,6 +64,15 @@ func (ip *InstanceProfile) GetExpired(ctx context.Context, expirationTime time.T return names, multierr.Combine(errs...) } +func (ip *InstanceProfile) CountAll(ctx context.Context) (count int, err error) { + out, err := ip.iamClient.ListInstanceProfiles(ctx, &iam.ListInstanceProfilesInput{}) + if err != nil { + return count, err + } + + return len(out.InstanceProfiles), nil +} + func (ip *InstanceProfile) Get(ctx context.Context, clusterName string) (names []string, err error) { out, err := ip.iamClient.ListInstanceProfiles(ctx, &iam.ListInstanceProfilesInput{}) if err != nil { diff --git a/test/hack/cleanup/resourcetypes/launchtemplate.go b/test/hack/resource/pkg/resourcetypes/launchtemplate.go similarity index 88% rename from test/hack/cleanup/resourcetypes/launchtemplate.go rename to test/hack/resource/pkg/resourcetypes/launchtemplate.go index d6a915243ad1..38dc681eef4f 100644 --- a/test/hack/cleanup/resourcetypes/launchtemplate.go +++ b/test/hack/resource/pkg/resourcetypes/launchtemplate.go @@ -66,6 +66,26 @@ func (lt *LaunchTemplate) GetExpired(ctx context.Context, expirationTime time.Ti return names, err } +func (lt *LaunchTemplate) CountAll(ctx context.Context) (count int, err error) { + var nextToken *string + for { + out, err := lt.ec2Client.DescribeLaunchTemplates(ctx, &ec2.DescribeLaunchTemplatesInput{ + NextToken: nextToken, + }) + if err != nil { + return count, err + } + + count += len(out.LaunchTemplates) + + nextToken = out.NextToken + if nextToken == nil { + break + } + } + return count, err +} + func (lt *LaunchTemplate) Get(ctx context.Context, clusterName string) (names []string, err error) { var nextToken *string for { diff --git a/test/hack/cleanup/resourcetypes/oidc.go b/test/hack/resource/pkg/resourcetypes/oidc.go similarity index 90% rename from test/hack/cleanup/resourcetypes/oidc.go rename to test/hack/resource/pkg/resourcetypes/oidc.go index cba7dddd3234..def8e163db84 100644 --- a/test/hack/cleanup/resourcetypes/oidc.go +++ b/test/hack/resource/pkg/resourcetypes/oidc.go @@ -61,6 +61,15 @@ func (o *OIDC) GetExpired(ctx context.Context, expirationTime time.Time) (names return names, multierr.Combine(errs...) } +func (o *OIDC) CountAll(ctx context.Context) (count int, err error) { + out, err := o.iamClient.ListOpenIDConnectProviders(ctx, &iam.ListOpenIDConnectProvidersInput{}) + if err != nil { + return count, err + } + + return len(out.OpenIDConnectProviderList), nil +} + func (o *OIDC) Get(ctx context.Context, clusterName string) (names []string, err error) { return names, err } diff --git a/test/hack/cleanup/resourcetypes/resourcetypes.go b/test/hack/resource/pkg/resourcetypes/resourcetypes.go similarity index 93% rename from test/hack/cleanup/resourcetypes/resourcetypes.go rename to test/hack/resource/pkg/resourcetypes/resourcetypes.go index 1d0e773059ee..58b47e3c61dc 100644 --- a/test/hack/cleanup/resourcetypes/resourcetypes.go +++ b/test/hack/resource/pkg/resourcetypes/resourcetypes.go @@ -42,4 +42,6 @@ type Type interface { // In general, if all resources can't be deleted by id with a single API call (like with DeleteInstances) // you should call the requests synchronously to avoid rate limiting against the number of requests made Cleanup(ctx context.Context, ids []string) (cleaned []string, err error) + // CountAll returns the number of all resource of the type in the account + CountAll(ctx context.Context) (count int, err error) } diff --git a/test/hack/cleanup/resourcetypes/securitygroup.go b/test/hack/resource/pkg/resourcetypes/securitygroup.go similarity index 88% rename from test/hack/cleanup/resourcetypes/securitygroup.go rename to test/hack/resource/pkg/resourcetypes/securitygroup.go index 377577dbf1e5..eac9c902b88a 100644 --- a/test/hack/cleanup/resourcetypes/securitygroup.go +++ b/test/hack/resource/pkg/resourcetypes/securitygroup.go @@ -77,6 +77,26 @@ func (sg *SecurityGroup) GetExpired(ctx context.Context, expirationTime time.Tim return ids, err } +func (sg *SecurityGroup) CountAll(ctx context.Context) (count int, err error) { + var nextToken *string + for { + out, err := sg.ec2Client.DescribeSecurityGroups(ctx, &ec2.DescribeSecurityGroupsInput{ + NextToken: nextToken, + }) + if err != nil { + return count, err + } + + count += len(out.SecurityGroups) + + nextToken = out.NextToken + if nextToken == nil { + break + } + } + return count, err +} + func (sg *SecurityGroup) Get(ctx context.Context, clusterName string) (ids []string, err error) { var nextToken *string for { diff --git a/test/hack/cleanup/resourcetypes/stack.go b/test/hack/resource/pkg/resourcetypes/stack.go similarity index 89% rename from test/hack/cleanup/resourcetypes/stack.go rename to test/hack/resource/pkg/resourcetypes/stack.go index 44500a17b3b3..2aad555913a4 100644 --- a/test/hack/cleanup/resourcetypes/stack.go +++ b/test/hack/resource/pkg/resourcetypes/stack.go @@ -66,6 +66,26 @@ func (s *Stack) GetExpired(ctx context.Context, expirationTime time.Time) (names return names, err } +func (s *Stack) CountAll(ctx context.Context) (count int, err error) { + var nextToken *string + for { + out, err := s.cloudFormationClient.DescribeStacks(ctx, &cloudformation.DescribeStacksInput{ + NextToken: nextToken, + }) + if err != nil { + return count, err + } + + count += len(out.Stacks) + + nextToken = out.NextToken + if nextToken == nil { + break + } + } + return count, nil +} + func (s *Stack) Get(ctx context.Context, clusterName string) (names []string, err error) { var nextToken *string for { diff --git a/test/hack/cleanup/resourcetypes/vpc_endpoint.go b/test/hack/resource/pkg/resourcetypes/vpc_endpoint.go similarity index 86% rename from test/hack/cleanup/resourcetypes/vpc_endpoint.go rename to test/hack/resource/pkg/resourcetypes/vpc_endpoint.go index b75ed9f94103..380eba791996 100644 --- a/test/hack/cleanup/resourcetypes/vpc_endpoint.go +++ b/test/hack/resource/pkg/resourcetypes/vpc_endpoint.go @@ -61,6 +61,26 @@ func (v *VPCEndpoint) Get(ctx context.Context, clusterName string) (ids []string return ids, err } +func (v *VPCEndpoint) CountAll(ctx context.Context) (count int, err error) { + var nextToken *string + for { + out, err := v.ec2Client.DescribeVpcEndpoints(ctx, &ec2.DescribeVpcEndpointsInput{ + NextToken: nextToken, + }) + if err != nil { + return count, err + } + + count += len(out.VpcEndpoints) + + nextToken = out.NextToken + if nextToken == nil { + break + } + } + return count, err +} + func (v *VPCEndpoint) GetExpired(ctx context.Context, expirationTime time.Time) (ids []string, err error) { var nextToken *string for {