From e8ca1d926e508e85f4ef38c23e4c7eff3d76a2e0 Mon Sep 17 00:00:00 2001 From: Kyle Adams Date: Fri, 20 Mar 2026 09:55:01 -0700 Subject: [PATCH] add support for changes to computed arrays and maps --- array_attribute.go | 2 +- map_attribute.go | 2 +- parse_test.go | 65 ++++++++++++++++++++++++++++++++++++++ test/computedobject.stdout | 24 ++++++++++++++ 4 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 test/computedobject.stdout diff --git a/array_attribute.go b/array_attribute.go index 9751a0c..c8e9711 100644 --- a/array_attribute.go +++ b/array_attribute.go @@ -27,7 +27,7 @@ func IsArrayAttributeChangeLine(line string) bool { // IsArrayAttributeTerminator returns true if the line is "]" or "] -> null" func IsArrayAttributeTerminator(line string) bool { - return strings.TrimSuffix(strings.TrimSpace(line), " -> null") == "]" + return strings.TrimSuffix(strings.TrimSpace(line), " -> null") == "]" || strings.TrimSuffix(strings.TrimSpace(line), " -> (known after apply)") == "]" } // IsOneLineEmptyArrayAttribute returns true if the line ends with a "[]" diff --git a/map_attribute.go b/map_attribute.go index 7adc817..76fc14b 100644 --- a/map_attribute.go +++ b/map_attribute.go @@ -24,7 +24,7 @@ func IsMapAttributeChangeLine(line string) bool { // IsMapAttributeTerminator returns true if the line is a "}" or "}," func IsMapAttributeTerminator(line string) bool { - return strings.TrimSuffix(strings.TrimSuffix(strings.TrimSpace(line), ","), " -> null") == "}" + return strings.TrimSuffix(strings.TrimSuffix(strings.TrimSpace(line), ","), " -> null") == "}" || strings.TrimSuffix(strings.TrimSuffix(strings.TrimSpace(line), ","), " -> (known after apply)") == "}" } // IsOneLineEmptyMapAttribute returns true if the line ends with a "{}" diff --git a/parse_test.go b/parse_test.go index f42b1e1..15cf29f 100644 --- a/parse_test.go +++ b/parse_test.go @@ -242,6 +242,71 @@ func TestParse(t *testing.T) { }, }, }, + "computedmap": { + file: "test/computedobject.stdout", + expected: []*ResourceChange{ + &ResourceChange{ + Address: "module.my-project.google_project_services.gcp_enabled_services[0]", + ModuleAddress: "module.my-project", + Type: "google_project_services", + Name: "gcp_enabled_services", + Index: 0, + UpdateType: UpdateInPlaceResource, + AttributeChanges: []attributeChange{ + &AttributeChange{ + Name: "disable_on_destroy", + OldValue: false, + NewValue: true, + UpdateType: UpdateInPlaceResource, + }, + &AttributeChange{ + Name: "id", + OldValue: "my-project", + NewValue: "test", + UpdateType: UpdateInPlaceResource, + }, + &AttributeChange{ + Name: "project", + OldValue: "my-project", + NewValue: "test2", + UpdateType: UpdateInPlaceResource, + }, + &ArrayAttributeChange{ + Name: "computed_services", + AttributeChanges: []attributeChange{ + &AttributeChange{ + OldValue: "appengine.googleapis.com", + NewValue: nil, + UpdateType: DestroyResource, + }, + &AttributeChange{ + OldValue: "audit.googleapis.com", + NewValue: nil, + UpdateType: DestroyResource, + }, + }, + UpdateType: UpdateInPlaceResource, + }, + &MapAttributeChange{ + Name: "computed_tags", + AttributeChanges: []attributeChange{ + &AttributeChange{ + Name: "key1", + OldValue: "old", + NewValue: "new", + UpdateType: UpdateInPlaceResource, + }, + }, + UpdateType: UpdateInPlaceResource, + }, + &MapAttributeChange{ + Name: "timeouts", + UpdateType: UpdateInPlaceResource, + }, + }, + }, + }, + }, "nested map": { file: "test/nestedmap.stdout", expected: []*ResourceChange{ diff --git a/test/computedobject.stdout b/test/computedobject.stdout new file mode 100644 index 0000000..4c2f081 --- /dev/null +++ b/test/computedobject.stdout @@ -0,0 +1,24 @@ +------------------------------------------------------------------------ + +An execution plan has been generated and is shown below. +Resource actions are indicated with the following symbols: + ~ update in-place + +Terraform will perform the following actions: + + # module.my-project.google_project_services.gcp_enabled_services[0] will be updated in-place + ~ resource "google_project_services" "gcp_enabled_services" { + ~ disable_on_destroy = false -> true + ~ id = "my-project" -> "test" + ~ project = "my-project" -> "test2" + ~ computed_services = [ + - "appengine.googleapis.com", + - "audit.googleapis.com", + ] -> (known after apply) + ~ computed_tags = { + ~ key1 = "old" -> "new" + } -> (known after apply) + ~ timeouts {} + } + +Plan: 0 to add, 0 to change, 1 to destroy. \ No newline at end of file