github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/command/views/plan_test.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package views 5 6 import ( 7 "testing" 8 9 "github.com/terramate-io/tf/addrs" 10 "github.com/terramate-io/tf/command/arguments" 11 "github.com/terramate-io/tf/configs/configschema" 12 "github.com/terramate-io/tf/plans" 13 "github.com/terramate-io/tf/providers" 14 "github.com/terramate-io/tf/terminal" 15 "github.com/terramate-io/tf/terraform" 16 "github.com/zclconf/go-cty/cty" 17 ) 18 19 // Ensure that the correct view type and in-automation settings propagate to the 20 // Operation view. 21 func TestPlanHuman_operation(t *testing.T) { 22 streams, done := terminal.StreamsForTesting(t) 23 defer done(t) 24 v := NewPlan(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true)).Operation() 25 if hv, ok := v.(*OperationHuman); !ok { 26 t.Fatalf("unexpected return type %t", v) 27 } else if hv.inAutomation != true { 28 t.Fatalf("unexpected inAutomation value on Operation view") 29 } 30 } 31 32 // Verify that Hooks includes a UI hook 33 func TestPlanHuman_hooks(t *testing.T) { 34 streams, done := terminal.StreamsForTesting(t) 35 defer done(t) 36 v := NewPlan(arguments.ViewHuman, NewView(streams).SetRunningInAutomation((true))) 37 hooks := v.Hooks() 38 39 var uiHook *UiHook 40 for _, hook := range hooks { 41 if ch, ok := hook.(*UiHook); ok { 42 uiHook = ch 43 } 44 } 45 if uiHook == nil { 46 t.Fatalf("expected Hooks to include a UiHook: %#v", hooks) 47 } 48 } 49 50 // Helper functions to build a trivial test plan, to exercise the plan 51 // renderer. 52 func testPlan(t *testing.T) *plans.Plan { 53 t.Helper() 54 55 plannedVal := cty.ObjectVal(map[string]cty.Value{ 56 "id": cty.UnknownVal(cty.String), 57 "foo": cty.StringVal("bar"), 58 }) 59 priorValRaw, err := plans.NewDynamicValue(cty.NullVal(plannedVal.Type()), plannedVal.Type()) 60 if err != nil { 61 t.Fatal(err) 62 } 63 plannedValRaw, err := plans.NewDynamicValue(plannedVal, plannedVal.Type()) 64 if err != nil { 65 t.Fatal(err) 66 } 67 68 changes := plans.NewChanges() 69 addr := addrs.Resource{ 70 Mode: addrs.ManagedResourceMode, 71 Type: "test_resource", 72 Name: "foo", 73 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance) 74 75 changes.SyncWrapper().AppendResourceInstanceChange(&plans.ResourceInstanceChangeSrc{ 76 Addr: addr, 77 PrevRunAddr: addr, 78 ProviderAddr: addrs.AbsProviderConfig{ 79 Provider: addrs.NewDefaultProvider("test"), 80 Module: addrs.RootModule, 81 }, 82 ChangeSrc: plans.ChangeSrc{ 83 Action: plans.Create, 84 Before: priorValRaw, 85 After: plannedValRaw, 86 }, 87 }) 88 89 return &plans.Plan{ 90 Changes: changes, 91 } 92 } 93 94 func testPlanWithDatasource(t *testing.T) *plans.Plan { 95 plan := testPlan(t) 96 97 addr := addrs.Resource{ 98 Mode: addrs.DataResourceMode, 99 Type: "test_data_source", 100 Name: "bar", 101 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance) 102 103 dataVal := cty.ObjectVal(map[string]cty.Value{ 104 "id": cty.StringVal("C6743020-40BD-4591-81E6-CD08494341D3"), 105 "bar": cty.StringVal("foo"), 106 }) 107 priorValRaw, err := plans.NewDynamicValue(cty.NullVal(dataVal.Type()), dataVal.Type()) 108 if err != nil { 109 t.Fatal(err) 110 } 111 plannedValRaw, err := plans.NewDynamicValue(dataVal, dataVal.Type()) 112 if err != nil { 113 t.Fatal(err) 114 } 115 116 plan.Changes.SyncWrapper().AppendResourceInstanceChange(&plans.ResourceInstanceChangeSrc{ 117 Addr: addr, 118 PrevRunAddr: addr, 119 ProviderAddr: addrs.AbsProviderConfig{ 120 Provider: addrs.NewDefaultProvider("test"), 121 Module: addrs.RootModule, 122 }, 123 ChangeSrc: plans.ChangeSrc{ 124 Action: plans.Read, 125 Before: priorValRaw, 126 After: plannedValRaw, 127 }, 128 }) 129 130 return plan 131 } 132 133 func testSchemas() *terraform.Schemas { 134 provider := testProvider() 135 return &terraform.Schemas{ 136 Providers: map[addrs.Provider]providers.ProviderSchema{ 137 addrs.NewDefaultProvider("test"): provider.GetProviderSchema(), 138 }, 139 } 140 } 141 142 func testProvider() *terraform.MockProvider { 143 p := new(terraform.MockProvider) 144 p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse { 145 return providers.ReadResourceResponse{NewState: req.PriorState} 146 } 147 148 p.GetProviderSchemaResponse = testProviderSchema() 149 150 return p 151 } 152 153 func testProviderSchema() *providers.GetProviderSchemaResponse { 154 return &providers.GetProviderSchemaResponse{ 155 Provider: providers.Schema{ 156 Block: &configschema.Block{}, 157 }, 158 ResourceTypes: map[string]providers.Schema{ 159 "test_resource": { 160 Block: &configschema.Block{ 161 Attributes: map[string]*configschema.Attribute{ 162 "id": {Type: cty.String, Computed: true}, 163 "foo": {Type: cty.String, Optional: true}, 164 }, 165 }, 166 }, 167 }, 168 DataSources: map[string]providers.Schema{ 169 "test_data_source": { 170 Block: &configschema.Block{ 171 Attributes: map[string]*configschema.Attribute{ 172 "id": {Type: cty.String, Required: true}, 173 "bar": {Type: cty.String, Optional: true}, 174 }, 175 }, 176 }, 177 }, 178 } 179 }