Skip to content
Open
Show file tree
Hide file tree
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
6 changes: 6 additions & 0 deletions src/terraform/structure/terraform_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ type TerraformBlock struct {

var ProviderToTagAttribute = map[string]string{"aws": "tags", "azurerm": "tags", "google": "labels", "oci": "freeform_tags", "alicloud": "tags"}

// ResourceTypeToTagAttribute overrides ProviderToTagAttribute for specific resource types
// whose tag attribute differs from their provider's default.
var ResourceTypeToTagAttribute = map[string]string{
"google_container_cluster": "resource_labels",
}

const ResourceBlockType = "resource"
const ModuleBlockType = "module"
const DataBlockType = "data"
Expand Down
19 changes: 19 additions & 0 deletions src/terraform/structure/terraform_block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,23 @@ func TestTerraformBlock(t *testing.T) {

assert.True(t, gcpBlock.IsGCPBlock())
})

t.Run("is_gcp_block_google_container_cluster", func(t *testing.T) {
gkeBlock := &TerraformBlock{
HclSyntaxBlock: &hclsyntax.Block{Labels: []string{"google_container_cluster", "primary"}},
Block: structure.Block{TagsAttributeName: "resource_labels"},
}

assert.True(t, gkeBlock.IsGCPBlock(), "google_container_cluster should be identified as a GCP block")
})

t.Run("resource_type_to_tag_attribute_override", func(t *testing.T) {
// Verify that google_container_cluster maps to resource_labels, not labels
attr, ok := ResourceTypeToTagAttribute["google_container_cluster"]
assert.True(t, ok, "google_container_cluster should have an entry in ResourceTypeToTagAttribute")
assert.Equal(t, "resource_labels", attr)

// Verify that the provider-level default for google is still labels
assert.Equal(t, "labels", ProviderToTagAttribute["google"])
})
}
5 changes: 5 additions & 0 deletions src/terraform/structure/terraform_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,11 @@ func getProviderFromResourceType(resourceType string) string {
}

func getTagAttributeByResourceType(resourceType string) (string, error) {
// Check for resource-type-specific override first
if attr, ok := ResourceTypeToTagAttribute[resourceType]; ok {
return attr, nil
}
// Fall back to provider-level default
prefix := ProviderToTagAttribute[getProviderFromResourceType(resourceType)]
if prefix == "" {
return "", fmt.Errorf("failed to find tags attribute name for resource type %s", resourceType)
Expand Down
40 changes: 40 additions & 0 deletions src/terraform/structure/terraform_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,46 @@ func TestTerraformParser_ParseFile(t *testing.T) {
assert.NotNil(t, err)
})

t.Run("parse gcp gke file with resource_labels", func(t *testing.T) {
p := &TerraformParser{}
p.Init("../../../tests/terraform/resources/gke", nil)
defer p.Close()
filePath := "../../../tests/terraform/resources/gke/main.tf"
parsedBlocks, err := p.ParseFile(filePath)
if err != nil {
t.Errorf("failed to read hcl file because %s", err)
}
assert.Equal(t, 2, len(parsedBlocks))

for _, block := range parsedBlocks {
hclBlock := block.GetRawBlock().(*hclwrite.Block)
assert.Equal(t, ResourceBlockType, hclBlock.Type())
assert.Equal(t, "google_container_cluster", hclBlock.Labels()[0])
assert.True(t, block.IsBlockTaggable(), fmt.Sprintf("expected block %s to be taggable", hclBlock.Labels()))

tfBlock := block.(*TerraformBlock)
assert.Equal(t, "resource_labels", tfBlock.TagsAttributeName,
"google_container_cluster should use resource_labels, not labels")
assert.True(t, tfBlock.IsGCPBlock(), "google_container_cluster should be identified as a GCP block")

resourceName := hclBlock.Labels()[1]
if resourceName == "primary" {
// The tagged resource should have existing tags
existingTags := block.GetExistingTags()
assert.Equal(t, 2, len(existingTags))
tagMap := make(map[string]string)
for _, tag := range existingTags {
tagMap[tag.GetKey()] = tag.GetValue()
}
assert.Equal(t, "test", tagMap["env"])
assert.Equal(t, "devops", tagMap["team"])
} else if resourceName == "untagged" {
// The untagged resource should have no existing tags
assert.Equal(t, 0, len(block.GetExistingTags()))
}
}
})

t.Run("Do not crash if getting malformed file", func(t *testing.T) {
p := &TerraformParser{}
p.Init("../../../tests/terraform/malformed_file_in_dir", nil)
Expand Down
1 change: 1 addition & 0 deletions src/terraform/structure/tf_taggable.go
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,7 @@ var TfTaggableResourceTypes = []string{
"google_cloud_identity_group",
"google_cloudfunctions_function",
"google_composer_environment",
"google_container_cluster",
"google_compute_disk",
"google_compute_image",
"google_compute_instance",
Expand Down
14 changes: 14 additions & 0 deletions tests/terraform/resources/gke/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
resource "google_container_cluster" "primary" {
name = "my-gke-cluster"
location = "us-central1"

resource_labels = {
env = "test"
team = "devops"
}
}

resource "google_container_cluster" "untagged" {
name = "my-gke-cluster-untagged"
location = "us-central1"
}
Loading