github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/internal/terraform/variables_test.go (about) 1 package terraform 2 3 import ( 4 "testing" 5 6 "github.com/hashicorp/terraform/internal/configs" 7 "github.com/zclconf/go-cty/cty" 8 ) 9 10 func TestCheckInputVariables(t *testing.T) { 11 c := testModule(t, "input-variables") 12 13 t.Run("No variables set", func(t *testing.T) { 14 // No variables set 15 diags := checkInputVariables(c.Module.Variables, nil) 16 if !diags.HasErrors() { 17 t.Fatal("check succeeded, but want errors") 18 } 19 20 // Required variables set, optional variables unset 21 // This is still an error at this layer, since it's the caller's 22 // responsibility to have already merged in any default values. 23 diags = checkInputVariables(c.Module.Variables, InputValues{ 24 "foo": &InputValue{ 25 Value: cty.StringVal("bar"), 26 SourceType: ValueFromCLIArg, 27 }, 28 }) 29 if !diags.HasErrors() { 30 t.Fatal("check succeeded, but want errors") 31 } 32 }) 33 34 t.Run("All variables set", func(t *testing.T) { 35 diags := checkInputVariables(c.Module.Variables, InputValues{ 36 "foo": &InputValue{ 37 Value: cty.StringVal("bar"), 38 SourceType: ValueFromCLIArg, 39 }, 40 "bar": &InputValue{ 41 Value: cty.StringVal("baz"), 42 SourceType: ValueFromCLIArg, 43 }, 44 "map": &InputValue{ 45 Value: cty.StringVal("baz"), // okay because config has no type constraint 46 SourceType: ValueFromCLIArg, 47 }, 48 "object_map": &InputValue{ 49 Value: cty.MapVal(map[string]cty.Value{ 50 "uno": cty.ObjectVal(map[string]cty.Value{ 51 "foo": cty.StringVal("baz"), 52 "bar": cty.NumberIntVal(2), // type = any 53 }), 54 "dos": cty.ObjectVal(map[string]cty.Value{ 55 "foo": cty.StringVal("bat"), 56 "bar": cty.NumberIntVal(99), // type = any 57 }), 58 }), 59 SourceType: ValueFromCLIArg, 60 }, 61 "object_list": &InputValue{ 62 Value: cty.ListVal([]cty.Value{ 63 cty.ObjectVal(map[string]cty.Value{ 64 "foo": cty.StringVal("baz"), 65 "bar": cty.NumberIntVal(2), // type = any 66 }), 67 cty.ObjectVal(map[string]cty.Value{ 68 "foo": cty.StringVal("bang"), 69 "bar": cty.NumberIntVal(42), // type = any 70 }), 71 }), 72 SourceType: ValueFromCLIArg, 73 }, 74 }) 75 if diags.HasErrors() { 76 t.Fatalf("unexpected errors: %s", diags.Err()) 77 } 78 }) 79 80 t.Run("Invalid Complex Types", func(t *testing.T) { 81 diags := checkInputVariables(c.Module.Variables, InputValues{ 82 "foo": &InputValue{ 83 Value: cty.StringVal("bar"), 84 SourceType: ValueFromCLIArg, 85 }, 86 "bar": &InputValue{ 87 Value: cty.StringVal("baz"), 88 SourceType: ValueFromCLIArg, 89 }, 90 "map": &InputValue{ 91 Value: cty.StringVal("baz"), // okay because config has no type constraint 92 SourceType: ValueFromCLIArg, 93 }, 94 "object_map": &InputValue{ 95 Value: cty.MapVal(map[string]cty.Value{ 96 "uno": cty.ObjectVal(map[string]cty.Value{ 97 "foo": cty.StringVal("baz"), 98 "bar": cty.NumberIntVal(2), // type = any 99 }), 100 "dos": cty.ObjectVal(map[string]cty.Value{ 101 "foo": cty.StringVal("bat"), 102 "bar": cty.NumberIntVal(99), // type = any 103 }), 104 }), 105 SourceType: ValueFromCLIArg, 106 }, 107 "object_list": &InputValue{ 108 Value: cty.TupleVal([]cty.Value{ 109 cty.ObjectVal(map[string]cty.Value{ 110 "foo": cty.StringVal("baz"), 111 "bar": cty.NumberIntVal(2), // type = any 112 }), 113 cty.ObjectVal(map[string]cty.Value{ 114 "foo": cty.StringVal("bang"), 115 "bar": cty.StringVal("42"), // type = any, but mismatch with the first list item 116 }), 117 }), 118 SourceType: ValueFromCLIArg, 119 }, 120 }) 121 122 if diags.HasErrors() { 123 t.Fatalf("unexpected errors: %s", diags.Err()) 124 } 125 }) 126 } 127 128 // testInputValuesUnset is a helper for constructing InputValues values for 129 // situations where all of the root module variables are optional and a 130 // test case intends to just use those default values and not override them 131 // at all. 132 // 133 // In other words, this constructs an InputValues with one entry per given 134 // input variable declaration where all of them are declared as unset. 135 func testInputValuesUnset(decls map[string]*configs.Variable) InputValues { 136 if len(decls) == 0 { 137 return nil 138 } 139 140 ret := make(InputValues, len(decls)) 141 for name := range decls { 142 ret[name] = &InputValue{ 143 Value: cty.NilVal, 144 SourceType: ValueFromUnknown, 145 } 146 } 147 return ret 148 }