From 54a30542b4987142eef49867bc6f63d464a3bbab Mon Sep 17 00:00:00 2001 From: Lior Jacobian Date: Tue, 11 Jul 2023 15:52:29 +0300 Subject: [PATCH] fix(parser): support nameless tf resources --- pkg/parser/terraform/terraform.go | 38 ++++++++++++++++++++------ pkg/parser/terraform/terraform_test.go | 30 ++++++++++++++++++-- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/pkg/parser/terraform/terraform.go b/pkg/parser/terraform/terraform.go index 136f6db1382..01313eb1658 100644 --- a/pkg/parser/terraform/terraform.go +++ b/pkg/parser/terraform/terraform.go @@ -77,19 +77,39 @@ func processElements(elements model.Document, path string) { } } +func processResourcesElements(resourcesElements model.Document, path string) error { + for _, v2 := range resourcesElements { + switch t := v2.(type) { + case []interface{}: + return errors.New("failed to process resources") + case interface{}: + if elements, ok := t.(model.Document); ok { + processElements(elements, path) + } + } + } + return nil +} + func processResources(doc model.Document, path string) error { var resourcesElements model.Document - for _, resources := range doc { // iterate over resources - resourcesElements = resources.(model.Document) - for _, v2 := range resourcesElements { // resource name - switch t := v2.(type) { - case []interface{}: - return errors.New("failed to process resources") - case interface{}: - if elements, ok := t.(model.Document); ok { - processElements(elements, path) + for _, resources := range doc { + switch t := resources.(type) { + case []interface{}: // support the case of nameless resources - where we get a list of resources + for _, value := range t { + resourcesElements = value.(model.Document) + err := processResourcesElements(resourcesElements, path) + if err != nil { + return err } } + + case interface{}: + resourcesElements = t.(model.Document) + err := processResourcesElements(resourcesElements, path) + if err != nil { + return err + } } } return nil diff --git a/pkg/parser/terraform/terraform_test.go b/pkg/parser/terraform/terraform_test.go index 1d0512b5a82..e5d99332d39 100644 --- a/pkg/parser/terraform/terraform_test.go +++ b/pkg/parser/terraform/terraform_test.go @@ -52,10 +52,10 @@ variable "default" { type = "string" default = "default_var_file" } - + data "aws_ami" "example" { most_recent = true - + owners = ["self"] tags = { Name = "app-server" @@ -64,6 +64,22 @@ data "aws_ami" "example" { } } ` + namelessResource = `resource "aws_lb" { + name = "test-lb-tf" + internal = false + load_balancer_type = "network" + subnets = [for subnet in aws_subnet.public : subnet.id] + enable_deletion_protection = true +} + +resource "aws_lb" { + name = "test-lb-tf" + internal = false + load_balancer_type = "network" + subnets = [for subnet in aws_subnet.public : subnet.id] + enable_deletion_protection = true +} +` ) type fileTest struct { @@ -127,6 +143,16 @@ func Test_Parentheses_Expr(t *testing.T) { require.Contains(t, ami.(model.Document)["tags"], "Tag/default_var_file") } +// Test_Bla tests the case of the nameless resource where the resource name is not specified and model.Document resource is a list +func Test_namelessResource(t *testing.T) { + parser := NewDefault() + document, _, err := parser.Parse("namelessResource.tf", []byte(namelessResource)) + require.NoError(t, err) + require.Len(t, document, 1) + require.Contains(t, document[0], "resource") + require.Len(t, document[0]["resource"].(model.Document)["aws_lb"].([]interface{}), 2) +} + // Test_Resolve tests the functions [Resolve()] and all the methods called by them func Test_Resolve(t *testing.T) { parser := NewDefault()