Skip to content
Merged
Changes from all commits
Commits
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
96 changes: 93 additions & 3 deletions pkg/destroy/aws/aws.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package aws

import (
"context"
"fmt"
"strings"
"time"
Expand Down Expand Up @@ -149,12 +150,13 @@ func (o *ClusterUninstaller) Run() error {
return err
}

tagClientStack := append([]*resourcegroupstaggingapi.ResourceGroupsTaggingAPI(nil), tagClients...)
err = wait.PollImmediateInfinite(
time.Second*10,
func() (done bool, err error) {
var loopError error
nextTagClients := tagClients[:0]
for _, tagClient := range tagClients {
for _, tagClient := range tagClientStack {
matched := false
for _, filter := range o.Filters {
o.Logger.Debugf("search for and delete matching resources by tag in %s matching %#+v", tagClientNames[tagClient], filter)
Expand Down Expand Up @@ -206,7 +208,7 @@ func (o *ClusterUninstaller) Run() error {
o.Logger.Debugf("no deletions from %s, removing client", tagClientNames[tagClient])
}
}
tagClients = nextTagClients
tagClientStack = nextTagClients

o.Logger.Debug("search for IAM roles")
arns, err := iamRoleSearch.arns()
Expand Down Expand Up @@ -247,7 +249,7 @@ func (o *ClusterUninstaller) Run() error {
}
}

return len(tagClients) == 0 && loopError == nil, nil
return len(tagClientStack) == 0 && loopError == nil, nil
},
)
if err != nil {
Expand All @@ -259,6 +261,12 @@ func (o *ClusterUninstaller) Run() error {
o.Logger.Debug(err)
return err
}

err = removeSharedTags(context.TODO(), tagClients, tagClientNames, o.Filters, o.Logger)
Comment thread
wking marked this conversation as resolved.
Outdated
if err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -1832,3 +1840,85 @@ func isBucketNotFound(err interface{}) bool {
}
return false
}

func removeSharedTags(ctx context.Context, tagClients []*resourcegroupstaggingapi.ResourceGroupsTaggingAPI, tagClientNames map[*resourcegroupstaggingapi.ResourceGroupsTaggingAPI]string, filters []Filter, logger logrus.FieldLogger) error {
for _, filter := range filters {
for key, value := range filter {
if strings.HasPrefix(key, "kubernetes.io/cluster/") {
if value == "owned" {
if err := removeSharedTag(ctx, tagClients, tagClientNames, key, logger); err != nil {
return err
}
} else {
logger.Warnf("Ignoring non-owned cluster key %s: %s for shared-tag removal", key, value)
}
}
}
}

return nil
}

func removeSharedTag(ctx context.Context, tagClients []*resourcegroupstaggingapi.ResourceGroupsTaggingAPI, tagClientNames map[*resourcegroupstaggingapi.ResourceGroupsTaggingAPI]string, key string, logger logrus.FieldLogger) error {
request := &resourcegroupstaggingapi.UntagResourcesInput{
TagKeys: []*string{aws.String(key)},
}

removed := map[string]struct{}{}
tagClients = append([]*resourcegroupstaggingapi.ResourceGroupsTaggingAPI(nil), tagClients...)
for len(tagClients) > 0 {
nextTagClients := tagClients[:0]
for _, tagClient := range tagClients {
logger.Debugf("Search for and remove tags in %s matching %s: shared", tagClientNames[tagClient], key)
arns := []string{}
err := tagClient.GetResourcesPages(
&resourcegroupstaggingapi.GetResourcesInput{TagFilters: []*resourcegroupstaggingapi.TagFilter{{
Key: aws.String(key),
Values: []*string{aws.String("shared")},
}}},
func(results *resourcegroupstaggingapi.GetResourcesOutput, lastPage bool) bool {
for _, resource := range results.ResourceTagMappingList {
arn := *resource.ResourceARN
if _, ok := removed[arn]; !ok {
arns = append(arns, arn)
}
}

return !lastPage
},
)
if err != nil {
err = errors.Wrap(err, "get tagged resources")
logger.Info(err)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we make this ERROR ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we make this ERROR ?

We're ignoring it, so I don't think so. I'm ok with warnings though, although if we did that this package has a few other infos we'd need to bump as well.

nextTagClients = append(nextTagClients, tagClient)
continue
}
if len(arns) == 0 {
logger.Debugf("No matches in %s for %s: shared, removing client", tagClientNames[tagClient], key)
continue
}
nextTagClients = append(nextTagClients, tagClient)

for i := 0; i < len(arns); i += 20 {
request.ResourceARNList = make([]*string, 0, 20)
for j := 0; i+j < len(arns) && j < 20; j++ {
request.ResourceARNList = append(request.ResourceARNList, aws.String(arns[i+j]))
}
_, err = tagClient.UntagResourcesWithContext(ctx, request)
if err != nil {
err = errors.Wrap(err, "untag shared resources")
logger.Info(err)
continue
}
for j := 0; i+j < len(arns) && j < 20; j++ {
arn := arns[i+j]
logger.WithField("arn", arn).Infof("Removed tag %s: shared", key)
removed[arn] = exists
}
}
}
tagClients = nextTagClients
}

return nil
}