mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
terraform show -json
: Add Errored field to output for plan (#33372)
* Add Errored field to JSON output * Fix test error message
This commit is contained in:
parent
66e3c20b18
commit
49f99db1c2
@ -63,6 +63,7 @@ type plan struct {
|
||||
RelevantAttributes []ResourceAttr `json:"relevant_attributes,omitempty"`
|
||||
Checks json.RawMessage `json:"checks,omitempty"`
|
||||
Timestamp string `json:"timestamp,omitempty"`
|
||||
Errored bool `json:"errored"`
|
||||
}
|
||||
|
||||
func newPlan() *plan {
|
||||
@ -221,6 +222,7 @@ func Marshal(
|
||||
output := newPlan()
|
||||
output.TerraformVersion = version.String()
|
||||
output.Timestamp = p.Timestamp.Format(time.RFC3339)
|
||||
output.Errored = p.Errored
|
||||
|
||||
err := output.marshalPlanVariables(p.VariableValues, config.Module.Variables)
|
||||
if err != nil {
|
||||
|
@ -421,7 +421,43 @@ func TestShow_planWithForceReplaceChange(t *testing.T) {
|
||||
if !strings.Contains(got, want) {
|
||||
t.Fatalf("unexpected output\ngot: %s\nwant: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShow_planErrored(t *testing.T) {
|
||||
_, snap := testModuleWithSnapshot(t, "show")
|
||||
plan := testPlan(t)
|
||||
plan.Errored = true
|
||||
planFilePath := testPlanFile(
|
||||
t,
|
||||
snap,
|
||||
states.NewState(),
|
||||
plan,
|
||||
)
|
||||
|
||||
view, done := testView(t)
|
||||
c := &ShowCommand{
|
||||
Meta: Meta{
|
||||
testingOverrides: metaOverridesForProvider(showFixtureProvider()),
|
||||
View: view,
|
||||
},
|
||||
}
|
||||
|
||||
args := []string{
|
||||
planFilePath,
|
||||
"-no-color",
|
||||
}
|
||||
code := c.Run(args)
|
||||
output := done(t)
|
||||
|
||||
if code != 0 {
|
||||
t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, output.Stderr())
|
||||
}
|
||||
|
||||
got := output.Stdout()
|
||||
want := `Planning failed. Terraform encountered an error while generating this plan.`
|
||||
if !strings.Contains(got, want) {
|
||||
t.Fatalf("unexpected output\ngot: %s\nwant: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShow_plan_json(t *testing.T) {
|
||||
@ -525,6 +561,20 @@ func TestShow_json_output(t *testing.T) {
|
||||
t.Fatalf("init failed\n%s", ui.ErrorWriter)
|
||||
}
|
||||
|
||||
// read expected output
|
||||
wantFile, err := os.Open("output.json")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %s", err)
|
||||
}
|
||||
defer wantFile.Close()
|
||||
byteValue, err := ioutil.ReadAll(wantFile)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %s", err)
|
||||
}
|
||||
|
||||
var want plan
|
||||
json.Unmarshal([]byte(byteValue), &want)
|
||||
|
||||
// plan
|
||||
planView, planDone := testView(t)
|
||||
pc := &PlanCommand{
|
||||
@ -542,8 +592,15 @@ func TestShow_json_output(t *testing.T) {
|
||||
code := pc.Run(args)
|
||||
planOutput := planDone(t)
|
||||
|
||||
if code != 0 {
|
||||
t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, planOutput.Stderr())
|
||||
var wantedCode int
|
||||
if want.Errored {
|
||||
wantedCode = 1
|
||||
} else {
|
||||
wantedCode = 0
|
||||
}
|
||||
|
||||
if code != wantedCode {
|
||||
t.Fatalf("unexpected exit status %d; want %d\ngot: %s", code, wantedCode, planOutput.Stderr())
|
||||
}
|
||||
|
||||
// show
|
||||
@ -569,22 +626,11 @@ func TestShow_json_output(t *testing.T) {
|
||||
}
|
||||
|
||||
// compare view output to wanted output
|
||||
var got, want plan
|
||||
var got plan
|
||||
|
||||
gotString := showOutput.Stdout()
|
||||
json.Unmarshal([]byte(gotString), &got)
|
||||
|
||||
wantFile, err := os.Open("output.json")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %s", err)
|
||||
}
|
||||
defer wantFile.Close()
|
||||
byteValue, err := ioutil.ReadAll(wantFile)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %s", err)
|
||||
}
|
||||
json.Unmarshal([]byte(byteValue), &want)
|
||||
|
||||
// Disregard format version to reduce needless test fixture churn
|
||||
want.FormatVersion = got.FormatVersion
|
||||
|
||||
@ -1150,6 +1196,7 @@ type plan struct {
|
||||
OutputChanges map[string]interface{} `json:"output_changes,omitempty"`
|
||||
PriorState priorState `json:"prior_state,omitempty"`
|
||||
Config map[string]interface{} `json:"configuration,omitempty"`
|
||||
Errored bool `json:"errored"`
|
||||
}
|
||||
|
||||
type priorState struct {
|
||||
|
15
internal/command/testdata/show-json/plan-error/main.tf
vendored
Normal file
15
internal/command/testdata/show-json/plan-error/main.tf
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
locals {
|
||||
ami = "bar"
|
||||
}
|
||||
|
||||
resource "test_instance" "test" {
|
||||
ami = local.ami
|
||||
|
||||
lifecycle {
|
||||
precondition {
|
||||
// failing condition
|
||||
condition = local.ami != "bar"
|
||||
error_message = "ami is bar"
|
||||
}
|
||||
}
|
||||
}
|
35
internal/command/testdata/show-json/plan-error/output.json
vendored
Normal file
35
internal/command/testdata/show-json/plan-error/output.json
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"format_version": "1.2",
|
||||
"planned_values": {
|
||||
"root_module": {}
|
||||
},
|
||||
"prior_state": {},
|
||||
"configuration": {
|
||||
"provider_config": {
|
||||
"test": {
|
||||
"full_name": "registry.terraform.io/hashicorp/test",
|
||||
"name": "test"
|
||||
}
|
||||
},
|
||||
"root_module": {
|
||||
"resources": [
|
||||
{
|
||||
"address": "test_instance.test",
|
||||
"expressions": {
|
||||
"ami": {
|
||||
"references": [
|
||||
"local.ami"
|
||||
]
|
||||
}
|
||||
},
|
||||
"mode": "managed",
|
||||
"name": "test",
|
||||
"provider_config_key": "test",
|
||||
"schema_version": 0,
|
||||
"type": "test_instance"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"errored": true
|
||||
}
|
@ -229,7 +229,11 @@ For ease of consumption by callers, the plan representation includes a partial r
|
||||
// resources with postconditions, with as much information as Terraform can
|
||||
// recognize at plan time. Some objects will have status "unknown" to
|
||||
// indicate that their status will only be determined after applying the plan.
|
||||
"checks" <checks-representation>
|
||||
"checks" <checks-representation>,
|
||||
|
||||
// "errored" indicates whether planning failed. An errored plan cannot be applied,
|
||||
// but the actions planned before failure may help to understand the error.
|
||||
"errored": false
|
||||
}
|
||||
```
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user