| package jsonchecks |
| |
| import ( |
| "encoding/json" |
| "testing" |
| |
| "github.com/google/go-cmp/cmp" |
| "github.com/hashicorp/terraform/internal/addrs" |
| "github.com/hashicorp/terraform/internal/checks" |
| "github.com/hashicorp/terraform/internal/states" |
| ) |
| |
| func TestMarshalCheckStates(t *testing.T) { |
| resourceAAddr := addrs.ConfigCheckable(addrs.Resource{ |
| Mode: addrs.ManagedResourceMode, |
| Type: "test", |
| Name: "a", |
| }.InModule(addrs.RootModule)) |
| resourceAInstAddr := addrs.Checkable(addrs.Resource{ |
| Mode: addrs.ManagedResourceMode, |
| Type: "test", |
| Name: "a", |
| }.Instance(addrs.StringKey("foo")).Absolute(addrs.RootModuleInstance)) |
| moduleChildAddr := addrs.RootModuleInstance.Child("child", addrs.IntKey(0)) |
| resourceBAddr := addrs.ConfigCheckable(addrs.Resource{ |
| Mode: addrs.ManagedResourceMode, |
| Type: "test", |
| Name: "b", |
| }.InModule(moduleChildAddr.Module())) |
| resourceBInstAddr := addrs.Checkable(addrs.Resource{ |
| Mode: addrs.ManagedResourceMode, |
| Type: "test", |
| Name: "b", |
| }.Instance(addrs.NoKey).Absolute(moduleChildAddr)) |
| outputAAddr := addrs.ConfigCheckable(addrs.OutputValue{Name: "a"}.InModule(addrs.RootModule)) |
| outputAInstAddr := addrs.Checkable(addrs.OutputValue{Name: "a"}.Absolute(addrs.RootModuleInstance)) |
| outputBAddr := addrs.ConfigCheckable(addrs.OutputValue{Name: "b"}.InModule(moduleChildAddr.Module())) |
| outputBInstAddr := addrs.Checkable(addrs.OutputValue{Name: "b"}.Absolute(moduleChildAddr)) |
| |
| tests := map[string]struct { |
| Input *states.CheckResults |
| Want any |
| }{ |
| "empty": { |
| &states.CheckResults{}, |
| []any{}, |
| }, |
| "failures": { |
| &states.CheckResults{ |
| ConfigResults: addrs.MakeMap( |
| addrs.MakeMapElem(resourceAAddr, &states.CheckResultAggregate{ |
| Status: checks.StatusFail, |
| ObjectResults: addrs.MakeMap( |
| addrs.MakeMapElem(resourceAInstAddr, &states.CheckResultObject{ |
| Status: checks.StatusFail, |
| FailureMessages: []string{ |
| "Not enough boops.", |
| "Too many beeps.", |
| }, |
| }), |
| ), |
| }), |
| addrs.MakeMapElem(resourceBAddr, &states.CheckResultAggregate{ |
| Status: checks.StatusFail, |
| ObjectResults: addrs.MakeMap( |
| addrs.MakeMapElem(resourceBInstAddr, &states.CheckResultObject{ |
| Status: checks.StatusFail, |
| FailureMessages: []string{ |
| "Splines are too pointy.", |
| }, |
| }), |
| ), |
| }), |
| addrs.MakeMapElem(outputAAddr, &states.CheckResultAggregate{ |
| Status: checks.StatusFail, |
| ObjectResults: addrs.MakeMap( |
| addrs.MakeMapElem(outputAInstAddr, &states.CheckResultObject{ |
| Status: checks.StatusFail, |
| }), |
| ), |
| }), |
| addrs.MakeMapElem(outputBAddr, &states.CheckResultAggregate{ |
| Status: checks.StatusFail, |
| ObjectResults: addrs.MakeMap( |
| addrs.MakeMapElem(outputBInstAddr, &states.CheckResultObject{ |
| Status: checks.StatusFail, |
| FailureMessages: []string{ |
| "Not object-oriented enough.", |
| }, |
| }), |
| ), |
| }), |
| ), |
| }, |
| []any{ |
| map[string]any{ |
| "//": "EXPERIMENTAL: see docs for details", |
| "address": map[string]any{ |
| "kind": "output_value", |
| "module": "module.child", |
| "name": "b", |
| "to_display": "module.child.output.b", |
| }, |
| "instances": []any{ |
| map[string]any{ |
| "address": map[string]any{ |
| "module": "module.child[0]", |
| "to_display": "module.child[0].output.b", |
| }, |
| "problems": []any{ |
| map[string]any{ |
| "message": "Not object-oriented enough.", |
| }, |
| }, |
| "status": "fail", |
| }, |
| }, |
| "status": "fail", |
| }, |
| map[string]any{ |
| "//": "EXPERIMENTAL: see docs for details", |
| "address": map[string]any{ |
| "kind": "resource", |
| "mode": "managed", |
| "module": "module.child", |
| "name": "b", |
| "to_display": "module.child.test.b", |
| "type": "test", |
| }, |
| "instances": []any{ |
| map[string]any{ |
| "address": map[string]any{ |
| "module": "module.child[0]", |
| "to_display": "module.child[0].test.b", |
| }, |
| "problems": []any{ |
| map[string]any{ |
| "message": "Splines are too pointy.", |
| }, |
| }, |
| "status": "fail", |
| }, |
| }, |
| "status": "fail", |
| }, |
| map[string]any{ |
| "//": "EXPERIMENTAL: see docs for details", |
| "address": map[string]any{ |
| "kind": "output_value", |
| "name": "a", |
| "to_display": "output.a", |
| }, |
| "instances": []any{ |
| map[string]any{ |
| "address": map[string]any{ |
| "to_display": "output.a", |
| }, |
| "status": "fail", |
| }, |
| }, |
| "status": "fail", |
| }, |
| map[string]any{ |
| "//": "EXPERIMENTAL: see docs for details", |
| "address": map[string]any{ |
| "kind": "resource", |
| "mode": "managed", |
| "name": "a", |
| "to_display": "test.a", |
| "type": "test", |
| }, |
| "instances": []any{ |
| map[string]any{ |
| "address": map[string]any{ |
| "to_display": `test.a["foo"]`, |
| "instance_key": "foo", |
| }, |
| "problems": []any{ |
| map[string]any{ |
| "message": "Not enough boops.", |
| }, |
| map[string]any{ |
| "message": "Too many beeps.", |
| }, |
| }, |
| "status": "fail", |
| }, |
| }, |
| "status": "fail", |
| }, |
| }, |
| }, |
| } |
| |
| for name, test := range tests { |
| t.Run(name, func(t *testing.T) { |
| gotBytes := MarshalCheckStates(test.Input) |
| |
| var got any |
| err := json.Unmarshal(gotBytes, &got) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| if diff := cmp.Diff(test.Want, got); diff != "" { |
| t.Errorf("wrong result\n%s", diff) |
| } |
| }) |
| } |
| } |