github.com/opentofu/opentofu@v1.7.1/internal/cloud/cloud_variables_test.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package cloud 7 8 import ( 9 "testing" 10 11 "github.com/google/go-cmp/cmp" 12 "github.com/hashicorp/hcl/v2" 13 "github.com/opentofu/opentofu/internal/backend" 14 "github.com/opentofu/opentofu/internal/configs" 15 "github.com/opentofu/opentofu/internal/tfdiags" 16 "github.com/opentofu/opentofu/internal/tofu" 17 "github.com/zclconf/go-cty/cty" 18 ) 19 20 func TestParseCloudRunVariables(t *testing.T) { 21 t.Run("populates variables from allowed sources", func(t *testing.T) { 22 vv := map[string]backend.UnparsedVariableValue{ 23 "undeclared": testUnparsedVariableValue{source: tofu.ValueFromCLIArg, value: cty.StringVal("0")}, 24 "declaredFromConfig": testUnparsedVariableValue{source: tofu.ValueFromConfig, value: cty.StringVal("1")}, 25 "declaredFromNamedFileMapString": testUnparsedVariableValue{source: tofu.ValueFromNamedFile, value: cty.MapVal(map[string]cty.Value{"foo": cty.StringVal("bar")})}, 26 "declaredFromNamedFileBool": testUnparsedVariableValue{source: tofu.ValueFromNamedFile, value: cty.BoolVal(true)}, 27 "declaredFromNamedFileNumber": testUnparsedVariableValue{source: tofu.ValueFromNamedFile, value: cty.NumberIntVal(2)}, 28 "declaredFromNamedFileListString": testUnparsedVariableValue{source: tofu.ValueFromNamedFile, value: cty.ListVal([]cty.Value{cty.StringVal("2a"), cty.StringVal("2b")})}, 29 "declaredFromNamedFileNull": testUnparsedVariableValue{source: tofu.ValueFromNamedFile, value: cty.NullVal(cty.String)}, 30 "declaredFromNamedMapComplex": testUnparsedVariableValue{source: tofu.ValueFromNamedFile, value: cty.MapVal(map[string]cty.Value{"foo": cty.ObjectVal(map[string]cty.Value{"qux": cty.ListVal([]cty.Value{cty.BoolVal(true), cty.BoolVal(false)})})})}, 31 "declaredFromCLIArg": testUnparsedVariableValue{source: tofu.ValueFromCLIArg, value: cty.StringVal("3")}, 32 "declaredFromEnvVar": testUnparsedVariableValue{source: tofu.ValueFromEnvVar, value: cty.StringVal("4")}, 33 } 34 35 decls := map[string]*configs.Variable{ 36 "declaredFromConfig": { 37 Name: "declaredFromConfig", 38 Type: cty.String, 39 ConstraintType: cty.String, 40 ParsingMode: configs.VariableParseLiteral, 41 DeclRange: hcl.Range{ 42 Filename: "fake.tf", 43 Start: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 44 End: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 45 }, 46 }, 47 "declaredFromNamedFileMapString": { 48 Name: "declaredFromNamedFileMapString", 49 Type: cty.Map(cty.String), 50 ConstraintType: cty.Map(cty.String), 51 ParsingMode: configs.VariableParseHCL, 52 DeclRange: hcl.Range{ 53 Filename: "fake.tf", 54 Start: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 55 End: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 56 }, 57 }, 58 "declaredFromNamedFileBool": { 59 Name: "declaredFromNamedFileBool", 60 Type: cty.Bool, 61 ConstraintType: cty.Bool, 62 ParsingMode: configs.VariableParseLiteral, 63 DeclRange: hcl.Range{ 64 Filename: "fake.tf", 65 Start: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 66 End: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 67 }, 68 }, 69 "declaredFromNamedFileNumber": { 70 Name: "declaredFromNamedFileNumber", 71 Type: cty.Number, 72 ConstraintType: cty.Number, 73 ParsingMode: configs.VariableParseLiteral, 74 DeclRange: hcl.Range{ 75 Filename: "fake.tf", 76 Start: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 77 End: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 78 }, 79 }, 80 "declaredFromNamedFileListString": { 81 Name: "declaredFromNamedFileListString", 82 Type: cty.List(cty.String), 83 ConstraintType: cty.List(cty.String), 84 ParsingMode: configs.VariableParseHCL, 85 DeclRange: hcl.Range{ 86 Filename: "fake.tf", 87 Start: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 88 End: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 89 }, 90 }, 91 "declaredFromNamedFileNull": { 92 Name: "declaredFromNamedFileNull", 93 Type: cty.String, 94 ConstraintType: cty.String, 95 ParsingMode: configs.VariableParseHCL, 96 DeclRange: hcl.Range{ 97 Filename: "fake.tf", 98 Start: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 99 End: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 100 }, 101 }, 102 "declaredFromNamedMapComplex": { 103 Name: "declaredFromNamedMapComplex", 104 Type: cty.DynamicPseudoType, 105 ConstraintType: cty.DynamicPseudoType, 106 ParsingMode: configs.VariableParseHCL, 107 DeclRange: hcl.Range{ 108 Filename: "fake.tf", 109 Start: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 110 End: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 111 }, 112 }, 113 "declaredFromCLIArg": { 114 Name: "declaredFromCLIArg", 115 Type: cty.String, 116 ConstraintType: cty.String, 117 ParsingMode: configs.VariableParseLiteral, 118 DeclRange: hcl.Range{ 119 Filename: "fake.tf", 120 Start: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 121 End: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 122 }, 123 }, 124 "declaredFromEnvVar": { 125 Name: "declaredFromEnvVar", 126 Type: cty.String, 127 ConstraintType: cty.String, 128 ParsingMode: configs.VariableParseLiteral, 129 DeclRange: hcl.Range{ 130 Filename: "fake.tf", 131 Start: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 132 End: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 133 }, 134 }, 135 "missing": { 136 Name: "missing", 137 Type: cty.String, 138 ConstraintType: cty.String, 139 Default: cty.StringVal("2"), 140 ParsingMode: configs.VariableParseLiteral, 141 DeclRange: hcl.Range{ 142 Filename: "fake.tf", 143 Start: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 144 End: hcl.Pos{Line: 2, Column: 1, Byte: 0}, 145 }, 146 }, 147 } 148 wantVals := make(map[string]string) 149 wantVals["declaredFromNamedFileBool"] = "true" 150 wantVals["declaredFromNamedFileNumber"] = "2" 151 wantVals["declaredFromNamedFileListString"] = `["2a", "2b"]` 152 wantVals["declaredFromNamedFileNull"] = "null" 153 wantVals["declaredFromNamedFileMapString"] = "{\n foo = \"bar\"\n}" 154 wantVals["declaredFromNamedMapComplex"] = "{\n foo = {\n qux = [true, false]\n }\n}" 155 wantVals["declaredFromCLIArg"] = `"3"` 156 wantVals["declaredFromEnvVar"] = `"4"` 157 158 gotVals, diags := ParseCloudRunVariables(vv, decls) 159 if diff := cmp.Diff(wantVals, gotVals, cmp.Comparer(cty.Value.RawEquals)); diff != "" { 160 t.Errorf("wrong result\n%s", diff) 161 } 162 163 if got, want := len(diags), 1; got != want { 164 t.Fatalf("expected 1 variable error: %v, got %v", diags.Err(), want) 165 } 166 167 if got, want := diags[0].Description().Summary, "Value for undeclared variable"; got != want { 168 t.Errorf("wrong summary for diagnostic 0\ngot: %s\nwant: %s", got, want) 169 } 170 }) 171 } 172 173 type testUnparsedVariableValue struct { 174 source tofu.ValueSourceType 175 value cty.Value 176 } 177 178 func (v testUnparsedVariableValue) ParseVariableValue(mode configs.VariableParsingMode) (*tofu.InputValue, tfdiags.Diagnostics) { 179 return &tofu.InputValue{ 180 Value: v.value, 181 SourceType: v.source, 182 SourceRange: tfdiags.SourceRange{ 183 Filename: "fake.tfvars", 184 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 185 End: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 186 }, 187 }, nil 188 }