Skip to content

Commit

Permalink
change the behaviour of excluding resources to allow specifying the t…
Browse files Browse the repository at this point in the history
…ag value using a regular expression, fix #822
  • Loading branch information
wakeful committed Dec 27, 2024
1 parent a244989 commit da874fc
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 12 deletions.
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -527,14 +527,21 @@ s3:

#### Tag Filter

You can also exclude resources by tags. The following config will exclude all s3 buckets that have a tag with key `foo`
if the specified tag has a value, it must be set to `true` (case-insensitive),
if the tag value is not set, cloud-nuke will only check for the tag name.
You can also exclude resources by tags. The following configuration will exclude all S3 buckets that have a tag with the key `foo`.
By default, we will check if the tag's value is set to `true` (case-insensitive).

```yaml
s3:
exclude:
tag: 'foo' # exclude if tag foo exists with empty value or 'true'
tag: 'foo' # exclude if tag foo exists with value of 'true'
```

You can also overwrite the expected value by specifying `tag_value` (you can use regular expressions).
```yaml
s3:
exclude:
tag: 'foo'
tag_value: 'dev-.*'
```
#### Timeout
You have the flexibility to set individual timeout options for specific resources. The execution will pause until the designated timeout is reached for each resource.
Expand Down
21 changes: 16 additions & 5 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import (
)

const (
DefaultAwsResourceExclusionTagKey = "cloud-nuke-excluded"
CloudNukeAfterExclusionTagKey = "cloud-nuke-after"
CloudNukeAfterTimeFormat = time.RFC3339
CloudNukeAfterTimeFormatLegacy = time.DateTime
DefaultAwsResourceExclusionTagKey = "cloud-nuke-excluded"
DefaultAwsResourceExclusionTagValue = "true"
CloudNukeAfterExclusionTagKey = "cloud-nuke-after"
CloudNukeAfterTimeFormat = time.RFC3339
CloudNukeAfterTimeFormatLegacy = time.DateTime
)

// Config - the config object we pass around
Expand Down Expand Up @@ -272,6 +273,7 @@ type FilterRule struct {
TimeAfter *time.Time `yaml:"time_after"`
TimeBefore *time.Time `yaml:"time_before"`
Tag *string `yaml:"tag"` // A tag to filter resources by. (e.g., If set under ExcludedRule, resources with this tag will be excluded).
TagValue *Expression `yaml:"tag_value"`
}

type Expression struct {
Expand Down Expand Up @@ -377,6 +379,14 @@ func (r ResourceType) getExclusionTag() string {
return DefaultAwsResourceExclusionTagKey
}

func (r ResourceType) getExclusionTagValue() *Expression {
if r.ExcludeRule.TagValue != nil {
return r.ExcludeRule.TagValue
}

return &Expression{RE: *regexp.MustCompile(DefaultAwsResourceExclusionTagValue)}
}

func ParseTimestamp(timestamp string) (*time.Time, error) {
parsed, err := time.Parse(CloudNukeAfterTimeFormat, timestamp)
if err != nil {
Expand All @@ -394,8 +404,9 @@ func ParseTimestamp(timestamp string) (*time.Time, error) {
func (r ResourceType) ShouldIncludeBasedOnTag(tags map[string]string) bool {
// Handle exclude rule first
exclusionTag := r.getExclusionTag()
exclusionTagValue := r.getExclusionTagValue()
if value, ok := tags[exclusionTag]; ok {
if strings.ToLower(value) == "true" || value == "" {
if matches(strings.ToLower(value), []Expression{*exclusionTagValue}) {
return false
}
}
Expand Down
31 changes: 28 additions & 3 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,16 +378,41 @@ func TestShouldIncludeBasedOnTag(t *testing.T) {
given: arg{
ExcludeRule: FilterRule{
Tag: aws.String("my-custom-skip-tag"),
TagValue: &Expression{
RE: *regexp.MustCompile(""),
},
},
ProtectUntilExpire: false,
},
when: map[string]string{"my-custom-skip-tag": ""},
expect: false,
},
{
name: "should include resource with empty default exclude tag value",
given: arg{},
when: map[string]string{DefaultAwsResourceExclusionTagKey: ""},
name: "should include resource with custom exclude tag and empty value (using regular expression)",
given: arg{
ExcludeRule: FilterRule{
Tag: aws.String("my-custom-skip-tag"),
TagValue: &Expression{
RE: *regexp.MustCompile(".*"),
},
},
ProtectUntilExpire: false,
},
when: map[string]string{"my-custom-skip-tag": ""},
expect: false,
},
{
name: "should include resource with custom exclude tag and prefix value (using regular expression)",
given: arg{
ExcludeRule: FilterRule{
Tag: aws.String("my-custom-skip-tag"),
TagValue: &Expression{
RE: *regexp.MustCompile("protected-.*"),
},
},
ProtectUntilExpire: false,
},
when: map[string]string{"my-custom-skip-tag": "protected-database"},
expect: false,
},
{
Expand Down

0 comments on commit da874fc

Please sign in to comment.