github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/terraform/node_output_test.go (about) 1 package terraform 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/hashicorp/hcl/v2" 8 "github.com/muratcelep/terraform/not-internal/addrs" 9 "github.com/muratcelep/terraform/not-internal/configs" 10 "github.com/muratcelep/terraform/not-internal/lang/marks" 11 "github.com/muratcelep/terraform/not-internal/states" 12 "github.com/zclconf/go-cty/cty" 13 ) 14 15 func TestNodeApplyableOutputExecute_knownValue(t *testing.T) { 16 ctx := new(MockEvalContext) 17 ctx.StateState = states.NewState().SyncWrapper() 18 ctx.RefreshStateState = states.NewState().SyncWrapper() 19 20 config := &configs.Output{Name: "map-output"} 21 addr := addrs.OutputValue{Name: config.Name}.Absolute(addrs.RootModuleInstance) 22 node := &NodeApplyableOutput{Config: config, Addr: addr} 23 val := cty.MapVal(map[string]cty.Value{ 24 "a": cty.StringVal("b"), 25 }) 26 ctx.EvaluateExprResult = val 27 28 err := node.Execute(ctx, walkApply) 29 if err != nil { 30 t.Fatalf("unexpected execute error: %s", err) 31 } 32 33 outputVal := ctx.StateState.OutputValue(addr) 34 if got, want := outputVal.Value, val; !got.RawEquals(want) { 35 t.Errorf("wrong output value in state\n got: %#v\nwant: %#v", got, want) 36 } 37 38 if !ctx.RefreshStateCalled { 39 t.Fatal("should have called RefreshState, but didn't") 40 } 41 refreshOutputVal := ctx.RefreshStateState.OutputValue(addr) 42 if got, want := refreshOutputVal.Value, val; !got.RawEquals(want) { 43 t.Fatalf("wrong output value in refresh state\n got: %#v\nwant: %#v", got, want) 44 } 45 } 46 47 func TestNodeApplyableOutputExecute_noState(t *testing.T) { 48 ctx := new(MockEvalContext) 49 50 config := &configs.Output{Name: "map-output"} 51 addr := addrs.OutputValue{Name: config.Name}.Absolute(addrs.RootModuleInstance) 52 node := &NodeApplyableOutput{Config: config, Addr: addr} 53 val := cty.MapVal(map[string]cty.Value{ 54 "a": cty.StringVal("b"), 55 }) 56 ctx.EvaluateExprResult = val 57 58 err := node.Execute(ctx, walkApply) 59 if err != nil { 60 t.Fatalf("unexpected execute error: %s", err) 61 } 62 } 63 64 func TestNodeApplyableOutputExecute_invalidDependsOn(t *testing.T) { 65 ctx := new(MockEvalContext) 66 ctx.StateState = states.NewState().SyncWrapper() 67 68 config := &configs.Output{ 69 Name: "map-output", 70 DependsOn: []hcl.Traversal{ 71 { 72 hcl.TraverseRoot{Name: "test_instance"}, 73 hcl.TraverseAttr{Name: "foo"}, 74 hcl.TraverseAttr{Name: "bar"}, 75 }, 76 }, 77 } 78 addr := addrs.OutputValue{Name: config.Name}.Absolute(addrs.RootModuleInstance) 79 node := &NodeApplyableOutput{Config: config, Addr: addr} 80 val := cty.MapVal(map[string]cty.Value{ 81 "a": cty.StringVal("b"), 82 }) 83 ctx.EvaluateExprResult = val 84 85 diags := node.Execute(ctx, walkApply) 86 if !diags.HasErrors() { 87 t.Fatal("expected execute error, but there was none") 88 } 89 if got, want := diags.Err().Error(), "Invalid depends_on reference"; !strings.Contains(got, want) { 90 t.Errorf("expected error to include %q, but was: %s", want, got) 91 } 92 } 93 94 func TestNodeApplyableOutputExecute_sensitiveValueNotOutput(t *testing.T) { 95 ctx := new(MockEvalContext) 96 ctx.StateState = states.NewState().SyncWrapper() 97 98 config := &configs.Output{Name: "map-output"} 99 addr := addrs.OutputValue{Name: config.Name}.Absolute(addrs.RootModuleInstance) 100 node := &NodeApplyableOutput{Config: config, Addr: addr} 101 val := cty.MapVal(map[string]cty.Value{ 102 "a": cty.StringVal("b").Mark(marks.Sensitive), 103 }) 104 ctx.EvaluateExprResult = val 105 106 diags := node.Execute(ctx, walkApply) 107 if !diags.HasErrors() { 108 t.Fatal("expected execute error, but there was none") 109 } 110 if got, want := diags.Err().Error(), "Output refers to sensitive values"; !strings.Contains(got, want) { 111 t.Errorf("expected error to include %q, but was: %s", want, got) 112 } 113 } 114 115 func TestNodeApplyableOutputExecute_sensitiveValueAndOutput(t *testing.T) { 116 ctx := new(MockEvalContext) 117 ctx.StateState = states.NewState().SyncWrapper() 118 119 config := &configs.Output{ 120 Name: "map-output", 121 Sensitive: true, 122 } 123 addr := addrs.OutputValue{Name: config.Name}.Absolute(addrs.RootModuleInstance) 124 node := &NodeApplyableOutput{Config: config, Addr: addr} 125 val := cty.MapVal(map[string]cty.Value{ 126 "a": cty.StringVal("b").Mark(marks.Sensitive), 127 }) 128 ctx.EvaluateExprResult = val 129 130 err := node.Execute(ctx, walkApply) 131 if err != nil { 132 t.Fatalf("unexpected execute error: %s", err) 133 } 134 135 // Unmarked value should be stored in state 136 outputVal := ctx.StateState.OutputValue(addr) 137 want, _ := val.UnmarkDeep() 138 if got := outputVal.Value; !got.RawEquals(want) { 139 t.Errorf("wrong output value in state\n got: %#v\nwant: %#v", got, want) 140 } 141 } 142 143 func TestNodeDestroyableOutputExecute(t *testing.T) { 144 outputAddr := addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance) 145 146 state := states.NewState() 147 state.Module(addrs.RootModuleInstance).SetOutputValue("foo", cty.StringVal("bar"), false) 148 state.OutputValue(outputAddr) 149 150 ctx := &MockEvalContext{ 151 StateState: state.SyncWrapper(), 152 } 153 node := NodeDestroyableOutput{Addr: outputAddr} 154 155 diags := node.Execute(ctx, walkApply) 156 if diags.HasErrors() { 157 t.Fatalf("Unexpected error: %s", diags.Err()) 158 } 159 if state.OutputValue(outputAddr) != nil { 160 t.Fatal("Unexpected outputs in state after removal") 161 } 162 }