Skip to content

Commit

Permalink
add --skip to exclude resources (#155)
Browse files Browse the repository at this point in the history
* add --invertFilter to reverse the filter function

* remove duplicate snippet

* change inverFilter to skip

* fix formatting

* only evaluate skip if it is set

Co-authored-by: Duncan Bakker <[email protected]>
  • Loading branch information
duncan485 and Duncan Bakker authored Sep 15, 2022
1 parent 0342c0b commit b45c746
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 10 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Maintaining tags across your application is hard, especially when done manually.
- `-tags` - tags, as valid JSON (NOT HCL) or a comma seperated list of key=value.
- `-skipTerratagFiles` - optional. Default to `true`. Skips any previously tagged - (files with `terratag.tf` suffix)
- `-filter` - optional. Only apply tags to the selected resource types (regex)
- `-skip` - optional. Skip applying tags to the selected resource types (regex)

### Example Output
#### Before Terratag
Expand Down
2 changes: 2 additions & 0 deletions cli/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Args struct {
Tags string
Dir string
Filter string
Skip string
Type string
IsSkipTerratagFiles bool
Verbose bool
Expand Down Expand Up @@ -41,6 +42,7 @@ func InitArgs() (Args, error) {
fs.StringVar(&args.Dir, "dir", ".", "Directory to recursively search for .tf files and terratag them")
fs.BoolVar(&args.IsSkipTerratagFiles, "skipTerratagFiles", true, "Skips any previously tagged files")
fs.StringVar(&args.Filter, "filter", ".*", "Only apply tags to the selected resource types (regex)")
fs.StringVar(&args.Skip, "skip", "", "Exclude the selected resource types from tagging (regex)")
fs.BoolVar(&args.Verbose, "verbose", false, "Enable verbose logging")
fs.BoolVar(&args.Rename, "rename", true, "Keep the original filename or replace it with <basename>.terratag.tf")
fs.StringVar(&args.Type, "type", string(common.Terraform), "The IAC type. Valid values: terraform or terragrunt")
Expand Down
1 change: 1 addition & 0 deletions internal/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type Version struct {

type TaggingArgs struct {
Filter string
Skip string
Dir string
Tags string
Matches []string
Expand Down
13 changes: 13 additions & 0 deletions terratag.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func Terratag(args cli.Args) error {

taggingArgs := &common.TaggingArgs{
Filter: args.Filter,
Skip: args.Skip,
Dir: args.Dir,
Tags: args.Tags,
Matches: matches,
Expand Down Expand Up @@ -144,11 +145,23 @@ func tagFileResources(path string, args *common.TaggingArgs) (*counters, error)
if err != nil {
return nil, err
}

if !matched {
log.Print("[INFO] Resource excluded by filter, skipping.", resource.Labels())
continue
}

if args.Skip != "" {
matched, err = regexp.MatchString(args.Skip, resource.Labels()[0])
if err != nil {
return nil, err
}
if matched {
log.Print("[INFO] Resource excluded by skip, skipping.", resource.Labels())
continue
}
}

isTaggable, err := tfschema.IsTaggable(args.Dir, args.IACType, *resource)
if err != nil {
return nil, err
Expand Down
28 changes: 18 additions & 10 deletions terratag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,23 +67,27 @@ func TestTerraform1o0(t *testing.T) {
}

func TestTerraform1o0WithFilter(t *testing.T) {
testTerraformWithFilter(t, "15_1.0_filter", "azurerm_resource_group|aws_s3_bucket")
testTerraformWithFilter(t, "15_1.0_filter", "azurerm_resource_group|aws_s3_bucket", "")
}

func TestTerraform1o1(t *testing.T) {
testTerraform(t, "15_1.1")
}

func TestTerraform1o1WithFilter(t *testing.T) {
testTerraformWithFilter(t, "15_1.1_filter", "azurerm_resource_group|aws_s3_bucket")
testTerraformWithFilter(t, "15_1.1_filter", "azurerm_resource_group|aws_s3_bucket", "")
}

func TestTerraform1o2(t *testing.T) {
testTerraform(t, "15_1.2")
}

func TestTerraform1o2WithFilter(t *testing.T) {
testTerraformWithFilter(t, "15_1.2_filter", "azurerm_resource_group|aws_s3_bucket")
testTerraformWithFilter(t, "15_1.2_filter", "azurerm_resource_group|aws_s3_bucket", "")
}

func TestTerraform1o2WithSkip(t *testing.T) {
testTerraformWithFilter(t, "15_1.2_skip", ".*", "azurerm_resource_group")
}

func TestTerragruntWithCache(t *testing.T) {
Expand Down Expand Up @@ -128,14 +132,14 @@ func testTerraform(t *testing.T, version string) {
t.Parallel() // marks each test case as capable of running in parallel with each other
g := NewWithT(t)
itShouldTerraformInit(tt.entryDir, g)
itShouldRunTerratag(tt.entryDir, "", g)
itShouldRunTerratag(tt.entryDir, "", "", g)
itShouldRunTerraformValidate(tt.entryDir, g)
itShouldGenerateExpectedTerratagFiles(tt.suiteDir, g)
})
}
}

func testTerraformWithFilter(t *testing.T, version string, filter string) {
func testTerraformWithFilter(t *testing.T, version string, filter string, skip string) {
if _, skip := os.LookupEnv("SKIP_INTEGRATION_TESTS"); skip {
t.Skip("skipping integration test")
}
Expand All @@ -146,7 +150,7 @@ func testTerraformWithFilter(t *testing.T, version string, filter string) {
t.Parallel() // marks each test case as capable of running in parallel with each other
g := NewWithT(t)
itShouldTerraformInit(tt.entryDir, g)
itShouldRunTerratag(tt.entryDir, filter, g)
itShouldRunTerratag(tt.entryDir, filter, skip, g)
itShouldRunTerraformValidate(tt.entryDir, g)
itShouldGenerateExpectedTerratagFiles(tt.suiteDir, g)
})
Expand Down Expand Up @@ -217,13 +221,13 @@ func itShouldRunTerraformValidate(entryDir string, g *GomegaWithT) {
g.Expect(err).To(BeNil(), "terraform validate failed")
}

func itShouldRunTerratag(entryDir string, filter string, g *GomegaWithT) {
err := run_terratag(entryDir, filter, false)
func itShouldRunTerratag(entryDir string, filter string, skip string, g *GomegaWithT) {
err := run_terratag(entryDir, filter, skip, false)
g.Expect(err).To(BeNil(), "terratag failed")
}

func itShouldRunTerratagTerragruntMode(entryDir string, g *GomegaWithT) {
err := run_terratag(entryDir, "", true)
err := run_terratag(entryDir, "", "", true)
g.Expect(err).To(BeNil(), "terratag terragrunt mode failed")
}

Expand Down Expand Up @@ -310,7 +314,7 @@ func cloneOutput(inputDirs []string, terraformDir string) {
}
}

func run_terratag(entryDir string, filter string, terragrunt bool) (err interface{}) {
func run_terratag(entryDir string, filter string, skip string, terragrunt bool) (err interface{}) {
defer func() {
if innerErr := recover(); innerErr != nil {
fmt.Println(innerErr)
Expand All @@ -325,6 +329,10 @@ func run_terratag(entryDir string, filter string, terragrunt bool) (err interfac
os.Args = append(os.Args, "-filter="+filter)
}

if skip != "" {
os.Args = append(os.Args, "-skip="+skip)
}

if terragrunt {
os.Args = append(os.Args, "-type=terragrunt", "-rename=false")
}
Expand Down
2 changes: 2 additions & 0 deletions test/fixture/terraform_15_1.2_skip/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
suites:
- azurerm_skip
50 changes: 50 additions & 0 deletions test/tests/azurerm_skip/expected/main.terratag.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "West Europe"
}

resource "azurerm_virtual_network" "example" {
name = "example-network"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
address_space = ["10.254.0.0/16"]
tags = local.terratag_added_main
}

resource "azurerm_subnet" "frontend" {
name = "frontend"
resource_group_name = azurerm_resource_group.example.name
virtual_network_name = azurerm_virtual_network.example.name
address_prefixes = ["10.254.0.0/24"]
}

resource "azurerm_subnet" "backend" {
name = "backend"
resource_group_name = azurerm_resource_group.example.name
virtual_network_name = azurerm_virtual_network.example.name
address_prefixes = ["10.254.2.0/24"]
}

resource "azurerm_public_ip" "example" {
name = "example-pip"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
allocation_method = "Dynamic"
tags = local.terratag_added_main
}

#&nbsp;since these variables are re-used - a locals block makes this more maintainable
locals {
backend_address_pool_name = "${azurerm_virtual_network.example.name}-beap"
frontend_port_name = "${azurerm_virtual_network.example.name}-feport"
frontend_ip_configuration_name = "${azurerm_virtual_network.example.name}-feip"
http_setting_name = "${azurerm_virtual_network.example.name}-be-htst"
listener_name = "${azurerm_virtual_network.example.name}-httplstn"
request_routing_rule_name = "${azurerm_virtual_network.example.name}-rqrt"
redirect_configuration_name = "${azurerm_virtual_network.example.name}-rdrcfg"
}

locals {
terratag_added_main = {"env0_environment_id"="40907eff-cf7c-419a-8694-e1c6bf1d1168","env0_project_id"="43fd4ff1-8d37-4d9d-ac97-295bd850bf94"}
}

44 changes: 44 additions & 0 deletions test/tests/azurerm_skip/expected/main.tf.bak
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "West Europe"
}

resource "azurerm_virtual_network" "example" {
name = "example-network"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
address_space = ["10.254.0.0/16"]
}

resource "azurerm_subnet" "frontend" {
name = "frontend"
resource_group_name = azurerm_resource_group.example.name
virtual_network_name = azurerm_virtual_network.example.name
address_prefixes = ["10.254.0.0/24"]
}

resource "azurerm_subnet" "backend" {
name = "backend"
resource_group_name = azurerm_resource_group.example.name
virtual_network_name = azurerm_virtual_network.example.name
address_prefixes = ["10.254.2.0/24"]
}

resource "azurerm_public_ip" "example" {
name = "example-pip"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
allocation_method = "Dynamic"
}

#&nbsp;since these variables are re-used - a locals block makes this more maintainable
locals {
backend_address_pool_name = "${azurerm_virtual_network.example.name}-beap"
frontend_port_name = "${azurerm_virtual_network.example.name}-feport"
frontend_ip_configuration_name = "${azurerm_virtual_network.example.name}-feip"
http_setting_name = "${azurerm_virtual_network.example.name}-be-htst"
listener_name = "${azurerm_virtual_network.example.name}-httplstn"
request_routing_rule_name = "${azurerm_virtual_network.example.name}-rqrt"
redirect_configuration_name = "${azurerm_virtual_network.example.name}-rdrcfg"
}
43 changes: 43 additions & 0 deletions test/tests/azurerm_skip/input/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "West Europe"
}

resource "azurerm_virtual_network" "example" {
name = "example-network"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
address_space = ["10.254.0.0/16"]
}

resource "azurerm_subnet" "frontend" {
name = "frontend"
resource_group_name = azurerm_resource_group.example.name
virtual_network_name = azurerm_virtual_network.example.name
address_prefixes = ["10.254.0.0/24"]
}

resource "azurerm_subnet" "backend" {
name = "backend"
resource_group_name = azurerm_resource_group.example.name
virtual_network_name = azurerm_virtual_network.example.name
address_prefixes = ["10.254.2.0/24"]
}

resource "azurerm_public_ip" "example" {
name = "example-pip"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
allocation_method = "Dynamic"
}

#&nbsp;since these variables are re-used - a locals block makes this more maintainable
locals {
backend_address_pool_name = "${azurerm_virtual_network.example.name}-beap"
frontend_port_name = "${azurerm_virtual_network.example.name}-feport"
frontend_ip_configuration_name = "${azurerm_virtual_network.example.name}-feip"
http_setting_name = "${azurerm_virtual_network.example.name}-be-htst"
listener_name = "${azurerm_virtual_network.example.name}-httplstn"
request_routing_rule_name = "${azurerm_virtual_network.example.name}-rqrt"
redirect_configuration_name = "${azurerm_virtual_network.example.name}-rdrcfg"
}

0 comments on commit b45c746

Please sign in to comment.