Add identity fields to Plan struct (#158)
diff --git a/parse_test.go b/parse_test.go
index 79c9a66..725e281 100644
--- a/parse_test.go
+++ b/parse_test.go
@@ -6,7 +6,6 @@
import (
"bytes"
"encoding/json"
- "io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -21,7 +20,7 @@
const testGoldenSchemasFileName = "schemas.json"
func testParse(t *testing.T, filename string, typ reflect.Type) {
- entries, err := ioutil.ReadDir(testFixtureDir)
+ entries, err := os.ReadDir(testFixtureDir)
if err != nil {
t.Fatalf("err: %s", err)
}
@@ -32,7 +31,7 @@
}
t.Run(e.Name(), func(t *testing.T) {
- expected, err := ioutil.ReadFile(filepath.Join(testFixtureDir, e.Name(), filename))
+ expected, err := os.ReadFile(filepath.Join(testFixtureDir, e.Name(), filename))
if err != nil {
if os.IsNotExist(err) {
t.Skip(err.Error())
diff --git a/plan.go b/plan.go
index d861898..f60739c 100644
--- a/plan.go
+++ b/plan.go
@@ -266,6 +266,11 @@
// is either an integer pointing to a child of a set/list, or a string
// pointing to the child of a map, object, or block.
ReplacePaths []interface{} `json:"replace_paths,omitempty"`
+
+ // BeforeIdentity and AfterIdentity are representations of the resource
+ // identity value both before and after the action.
+ BeforeIdentity interface{} `json:"before_identity,omitempty"`
+ AfterIdentity interface{} `json:"after_identity,omitempty"`
}
// Importing is a nested object for the resource import metadata.
@@ -273,6 +278,16 @@
// The original ID of this resource used to target it as part of planned
// import operation.
ID string `json:"id,omitempty"`
+
+ // Unknown indicates the ID or identity was unknown at the time of
+ // planning. This would have led to the overall change being deferred, as
+ // such this should only be true when processing changes from the deferred
+ // changes list.
+ Unknown bool `json:"unknown,omitempty"`
+
+ // The identity can be used instead of the ID to target the resource as part
+ // of the planned import operation.
+ Identity interface{} `json:"identity,omitempty"`
}
// PlanVariable is a top-level variable in the Terraform plan.
diff --git a/plan_test.go b/plan_test.go
index 1f59fc1..c97f8f9 100644
--- a/plan_test.go
+++ b/plan_test.go
@@ -13,19 +13,34 @@
)
func TestPlanValidate(t *testing.T) {
- f, err := os.Open("testdata/basic/plan.json")
- if err != nil {
- t.Fatal(err)
- }
- defer f.Close()
-
- var plan *Plan
- if err := json.NewDecoder(f).Decode(&plan); err != nil {
- t.Fatal(err)
+ cases := map[string]struct {
+ planPath string
+ }{
+ "basic plan": {
+ planPath: "testdata/basic/plan.json",
+ },
+ "plan with identity": {
+ planPath: "testdata/identity/plan.json",
+ },
}
- if err := plan.Validate(); err != nil {
- t.Fatal(err)
+ for tn, tc := range cases {
+ t.Run(tn, func(t *testing.T) {
+ f, err := os.Open(tc.planPath)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+
+ var plan *Plan
+ if err := json.NewDecoder(f).Decode(&plan); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := plan.Validate(); err != nil {
+ t.Fatal(err)
+ }
+ })
}
}
diff --git a/testdata/identity/plan.json b/testdata/identity/plan.json
new file mode 100644
index 0000000..ba7b4b6
--- /dev/null
+++ b/testdata/identity/plan.json
@@ -0,0 +1 @@
+{"format_version":"1.2","terraform_version":"1.13.0-dev","planned_values":{"root_module":{"resources":[{"address":"corner_user_identity.user","mode":"managed","type":"corner_user_identity","name":"user","provider_name":"registry.terraform.io/hashicorp/corner","schema_version":0,"values":{"age":999,"email":"a@example.com","id":"a@example.com","name":"test"},"sensitive_values":{},"identity_schema_version":1,"identity":{"email":"a@example.com"}}]}},"resource_changes":[{"address":"corner_user_identity.user","mode":"managed","type":"corner_user_identity","name":"user","provider_name":"registry.terraform.io/hashicorp/corner","change":{"actions":["update"],"before":{"age":null,"email":"a@example.com","id":"a@example.com","name":null},"after":{"age":999,"email":"a@example.com","id":"a@example.com","name":"test"},"after_unknown":{},"before_sensitive":{},"after_sensitive":{},"importing":{"identity":{"email":"a@example.com"}},"before_identity":{"email":"a@example.com"},"after_identity":{"email":"a@example.com"}}}],"prior_state":{"format_version":"1.0","terraform_version":"1.13.0","values":{"root_module":{"resources":[{"address":"corner_user_identity.user","mode":"managed","type":"corner_user_identity","name":"user","provider_name":"registry.terraform.io/hashicorp/corner","schema_version":0,"values":{"age":null,"email":"a@example.com","id":"a@example.com","name":null},"sensitive_values":{},"identity_schema_version":1,"identity":{"email":"a@example.com"}}]}}},"configuration":{"provider_config":{"corner":{"name":"corner","full_name":"registry.terraform.io/hashicorp/corner"}},"root_module":{"resources":[{"address":"corner_user_identity.user","mode":"managed","type":"corner_user_identity","name":"user","provider_config_key":"corner","expressions":{"age":{"constant_value":999},"email":{"constant_value":"a@example.com"},"name":{"constant_value":"test"}},"schema_version":0}]}},"timestamp":"2025-04-30T11:34:17Z"}