Skip to content

Commit ea4b962

Browse files
authored
state/plan: Add output type and relevant_attributes (#53)
* state: Add output 'type' * plan: Add RelevantAttributes * testdata: add tests for 1.2.0 (based on rc1 output)
1 parent 064a365 commit ea4b962

File tree

16 files changed

+257
-2
lines changed

16 files changed

+257
-2
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ require (
99
github.com/mitchellh/copystructure v1.2.0
1010
github.com/sebdah/goldie v1.0.0
1111
github.com/zclconf/go-cty v1.10.0
12+
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b
1213
)

go.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
12
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
23
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
34
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
45
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6+
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
57
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
68
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
79
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -12,6 +14,7 @@ github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09
1214
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
1315
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
1416
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
17+
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
1518
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
1619
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
1720
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
@@ -23,18 +26,25 @@ github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdk
2326
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
2427
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
2528
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
29+
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
2630
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
2731
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
32+
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
2833
github.com/zclconf/go-cty v1.10.0 h1:mp9ZXQeIcN8kAwuqorjH+Q+njbJKjLrvB2yIh4q7U+0=
2934
github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
35+
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI=
36+
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
3037
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
38+
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
3139
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
3240
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
41+
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
3342
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
3443
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
3544
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
3645
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
3746
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
3847
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
48+
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
3949
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
4050
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

parse_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ func testParse(t *testing.T, filename string, typ reflect.Type) {
5252
// Add a newline at the end
5353
actual = append(actual, byte('\n'))
5454

55+
// TODO: Compare the actual struct instead of byte slice
56+
// because JSON does not guarantee consistent key ordering
57+
5558
if diff := cmp.Diff(expected, actual); diff != "" {
5659
t.Fatalf("unexpected: %s", diff)
5760
}

plan.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,19 @@ type Plan struct {
5555

5656
// The Terraform configuration used to make the plan.
5757
Config *Config `json:"configuration,omitempty"`
58+
59+
// RelevantAttributes represents any resource instances and their
60+
// attributes which may have contributed to the planned changes
61+
RelevantAttributes []ResourceAttribute `json:"relevant_attributes,omitempty"`
62+
}
63+
64+
// ResourceAttribute describes a full path to a resource attribute
65+
type ResourceAttribute struct {
66+
// Resource describes resource instance address (e.g. null_resource.foo)
67+
Resource string `json:"resource"`
68+
// Attribute describes the attribute path using a lossy representation
69+
// of cty.Path. (e.g. ["id"] or ["objects", 0, "val"]).
70+
Attribute []json.RawMessage `json:"attribute"`
5871
}
5972

6073
// Validate checks to ensure that the plan is present, and the

sanitize/sanitize_state_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/google/go-cmp/cmp"
77
tfjson "github.com/hashicorp/terraform-json"
8+
"github.com/zclconf/go-cty-debug/ctydebug"
89
)
910

1011
type testStateCase struct {
@@ -245,11 +246,11 @@ func TestSanitizeStateOutputs(t *testing.T) {
245246
t.Fatal(err)
246247
}
247248

248-
if diff := cmp.Diff(tc.expected, actual); diff != "" {
249+
if diff := cmp.Diff(tc.expected, actual, ctydebug.CmpOptions); diff != "" {
249250
t.Errorf("SanitizeStateOutputs() mismatch (-expected +actual):\n%s", diff)
250251
}
251252

252-
if diff := cmp.Diff(outputCases()[i].old, tc.old); diff != "" {
253+
if diff := cmp.Diff(outputCases()[i].old, tc.old, ctydebug.CmpOptions); diff != "" {
253254
t.Errorf("SanitizeStateOutputs() altered original (-expected +actual):\n%s", diff)
254255
}
255256
})

schemas.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,13 @@ type SchemaAttribute struct {
223223
Sensitive bool `json:"sensitive,omitempty"`
224224
}
225225

226+
// jsonSchemaAttribute describes an attribute within a schema block
227+
// in a middle-step internal representation before marshalled into
228+
// a more useful SchemaAttribute with cty.Type.
229+
//
230+
// This avoid panic on marshalling cty.NilType (from cty upstream)
231+
// which the default Go marshaller cannot ignore because it's a
232+
// not nil-able struct.
226233
type jsonSchemaAttribute struct {
227234
AttributeType json.RawMessage `json:"type,omitempty"`
228235
AttributeNestedType *SchemaNestedAttributeType `json:"nested_type,omitempty"`

state.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88

99
"github.com/hashicorp/go-version"
10+
"github.com/zclconf/go-cty/cty"
1011
)
1112

1213
// StateFormatVersionConstraints defines the versions of the JSON state format
@@ -175,4 +176,31 @@ type StateOutput struct {
175176

176177
// The value of the output.
177178
Value interface{} `json:"value,omitempty"`
179+
180+
// The type of the output.
181+
Type cty.Type `json:"type,omitempty"`
182+
}
183+
184+
// jsonStateOutput describes an output value in a middle-step internal
185+
// representation before marshalled into a more useful StateOutput with cty.Type.
186+
//
187+
// This avoid panic on marshalling cty.NilType (from cty upstream)
188+
// which the default Go marshaller cannot ignore because it's a
189+
// not nil-able struct.
190+
type jsonStateOutput struct {
191+
Sensitive bool `json:"sensitive"`
192+
Value interface{} `json:"value,omitempty"`
193+
Type json.RawMessage `json:"type,omitempty"`
194+
}
195+
196+
func (so *StateOutput) MarshalJSON() ([]byte, error) {
197+
jsonSa := &jsonStateOutput{
198+
Sensitive: so.Sensitive,
199+
Value: so.Value,
200+
}
201+
if so.Type != cty.NilType {
202+
outputType, _ := so.Type.MarshalJSON()
203+
jsonSa.Type = outputType
204+
}
205+
return json.Marshal(jsonSa)
178206
}

testdata/120_basic/.terraform.lock.hcl

Lines changed: 40 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

testdata/120_basic/foo/main.tf

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
terraform {
2+
required_providers {
3+
null = {
4+
source = "hashicorp/null"
5+
configuration_aliases = [null.aliased]
6+
}
7+
}
8+
}
9+
10+
variable "bar" {
11+
type = string
12+
}
13+
14+
variable "one" {
15+
type = string
16+
}
17+
18+
resource "null_resource" "foo" {
19+
triggers = {
20+
foo = "bar"
21+
}
22+
}
23+
24+
resource "null_resource" "aliased" {
25+
provider = null.aliased
26+
}
27+
28+
output "foo" {
29+
value = "bar"
30+
}

testdata/120_basic/module.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module "foo" {
2+
source = "./foo"
3+
4+
bar = "baz"
5+
one = "two"
6+
7+
providers = {
8+
null.aliased = null
9+
}
10+
}

0 commit comments

Comments
 (0)