github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/builtin/providers/terraform/data_source_state_test.go (about) 1 package terraform 2 3 import ( 4 "testing" 5 6 "github.com/hashicorp/terraform/tfdiags" 7 8 "github.com/apparentlymart/go-dump/dump" 9 "github.com/hashicorp/terraform/backend" 10 "github.com/zclconf/go-cty/cty" 11 ) 12 13 func TestResource(t *testing.T) { 14 if err := dataSourceRemoteStateGetSchema().Block.InternalValidate(); err != nil { 15 t.Fatalf("err: %s", err) 16 } 17 } 18 19 func TestState_basic(t *testing.T) { 20 var tests = map[string]struct { 21 Config cty.Value 22 Want cty.Value 23 Err bool 24 }{ 25 "basic": { 26 cty.ObjectVal(map[string]cty.Value{ 27 "backend": cty.StringVal("local"), 28 "config": cty.ObjectVal(map[string]cty.Value{ 29 "path": cty.StringVal("./testdata/basic.tfstate"), 30 }), 31 }), 32 cty.ObjectVal(map[string]cty.Value{ 33 "backend": cty.StringVal("local"), 34 "config": cty.ObjectVal(map[string]cty.Value{ 35 "path": cty.StringVal("./testdata/basic.tfstate"), 36 }), 37 "outputs": cty.ObjectVal(map[string]cty.Value{ 38 "foo": cty.StringVal("bar"), 39 }), 40 "workspace": cty.StringVal(backend.DefaultStateName), 41 "defaults": cty.NullVal(cty.DynamicPseudoType), 42 }), 43 false, 44 }, 45 "complex outputs": { 46 cty.ObjectVal(map[string]cty.Value{ 47 "backend": cty.StringVal("local"), 48 "config": cty.ObjectVal(map[string]cty.Value{ 49 "path": cty.StringVal("./testdata/complex_outputs.tfstate"), 50 }), 51 }), 52 cty.ObjectVal(map[string]cty.Value{ 53 "backend": cty.StringVal("local"), 54 "config": cty.ObjectVal(map[string]cty.Value{ 55 "path": cty.StringVal("./testdata/complex_outputs.tfstate"), 56 }), 57 "outputs": cty.ObjectVal(map[string]cty.Value{ 58 "computed_map": cty.MapVal(map[string]cty.Value{ 59 "key1": cty.StringVal("value1"), 60 }), 61 "computed_set": cty.ListVal([]cty.Value{ 62 cty.StringVal("setval1"), 63 cty.StringVal("setval2"), 64 }), 65 "map": cty.MapVal(map[string]cty.Value{ 66 "key": cty.StringVal("test"), 67 "test": cty.StringVal("test"), 68 }), 69 "set": cty.ListVal([]cty.Value{ 70 cty.StringVal("test1"), 71 cty.StringVal("test2"), 72 }), 73 }), 74 "workspace": cty.StringVal(backend.DefaultStateName), 75 "defaults": cty.NullVal(cty.DynamicPseudoType), 76 }), 77 false, 78 }, 79 "null outputs": { 80 cty.ObjectVal(map[string]cty.Value{ 81 "backend": cty.StringVal("local"), 82 "config": cty.ObjectVal(map[string]cty.Value{ 83 "path": cty.StringVal("./testdata/null_outputs.tfstate"), 84 }), 85 }), 86 cty.ObjectVal(map[string]cty.Value{ 87 "backend": cty.StringVal("local"), 88 "config": cty.ObjectVal(map[string]cty.Value{ 89 "path": cty.StringVal("./testdata/null_outputs.tfstate"), 90 }), 91 "outputs": cty.ObjectVal(map[string]cty.Value{ 92 "map": cty.NullVal(cty.DynamicPseudoType), 93 "list": cty.NullVal(cty.DynamicPseudoType), 94 }), 95 "workspace": cty.StringVal(backend.DefaultStateName), 96 "defaults": cty.NullVal(cty.DynamicPseudoType), 97 }), 98 false, 99 }, 100 "defaults": { 101 cty.ObjectVal(map[string]cty.Value{ 102 "backend": cty.StringVal("local"), 103 "config": cty.ObjectVal(map[string]cty.Value{ 104 "path": cty.StringVal("./testdata/empty.tfstate"), 105 }), 106 "defaults": cty.ObjectVal(map[string]cty.Value{ 107 "foo": cty.StringVal("bar"), 108 }), 109 }), 110 cty.ObjectVal(map[string]cty.Value{ 111 "backend": cty.StringVal("local"), 112 "config": cty.ObjectVal(map[string]cty.Value{ 113 "path": cty.StringVal("./testdata/empty.tfstate"), 114 }), 115 "defaults": cty.ObjectVal(map[string]cty.Value{ 116 "foo": cty.StringVal("bar"), 117 }), 118 "outputs": cty.ObjectVal(map[string]cty.Value{ 119 "foo": cty.StringVal("bar"), 120 }), 121 "workspace": cty.StringVal(backend.DefaultStateName), 122 }), 123 false, 124 }, 125 "future version": { 126 cty.ObjectVal(map[string]cty.Value{ 127 "backend": cty.StringVal("local"), 128 "config": cty.ObjectVal(map[string]cty.Value{ 129 "path": cty.StringVal("./testdata/future.tfstate"), 130 }), 131 }), 132 cty.ObjectVal(map[string]cty.Value{ 133 "backend": cty.StringVal("local"), 134 "config": cty.ObjectVal(map[string]cty.Value{ 135 "path": cty.StringVal("./testdata/future.tfstate"), 136 }), 137 "outputs": cty.ObjectVal(map[string]cty.Value{ 138 "foo": cty.StringVal("bar"), 139 }), 140 "defaults": cty.NullVal(cty.DynamicPseudoType), 141 "workspace": cty.StringVal(backend.DefaultStateName), 142 }), 143 false, 144 }, 145 "missing": { 146 cty.ObjectVal(map[string]cty.Value{ 147 "backend": cty.StringVal("local"), 148 "config": cty.ObjectVal(map[string]cty.Value{ 149 "path": cty.StringVal("./testdata/missing.tfstate"), // intentionally not present on disk 150 }), 151 }), 152 cty.ObjectVal(map[string]cty.Value{ 153 "backend": cty.StringVal("local"), 154 "config": cty.ObjectVal(map[string]cty.Value{ 155 "path": cty.StringVal("./testdata/missing.tfstate"), 156 }), 157 "defaults": cty.NullVal(cty.DynamicPseudoType), 158 "outputs": cty.EmptyObjectVal, 159 "workspace": cty.StringVal(backend.DefaultStateName), 160 }), 161 true, 162 }, 163 "wrong type for config": { 164 cty.ObjectVal(map[string]cty.Value{ 165 "backend": cty.StringVal("local"), 166 "config": cty.StringVal("nope"), 167 }), 168 cty.NilVal, 169 true, 170 }, 171 "wrong type for config with unknown backend": { 172 cty.ObjectVal(map[string]cty.Value{ 173 "backend": cty.UnknownVal(cty.String), 174 "config": cty.StringVal("nope"), 175 }), 176 cty.NilVal, 177 true, 178 }, 179 "wrong type for config with unknown config": { 180 cty.ObjectVal(map[string]cty.Value{ 181 "backend": cty.StringVal("local"), 182 "config": cty.UnknownVal(cty.String), 183 }), 184 cty.NilVal, 185 true, 186 }, 187 "wrong type for defaults": { 188 cty.ObjectVal(map[string]cty.Value{ 189 "backend": cty.StringVal("local"), 190 "config": cty.ObjectVal(map[string]cty.Value{ 191 "path": cty.StringVal("./testdata/basic.tfstate"), 192 }), 193 "defaults": cty.StringVal("nope"), 194 }), 195 cty.NilVal, 196 true, 197 }, 198 "config as map": { 199 cty.ObjectVal(map[string]cty.Value{ 200 "backend": cty.StringVal("local"), 201 "config": cty.MapVal(map[string]cty.Value{ 202 "path": cty.StringVal("./testdata/empty.tfstate"), 203 }), 204 }), 205 cty.ObjectVal(map[string]cty.Value{ 206 "backend": cty.StringVal("local"), 207 "config": cty.MapVal(map[string]cty.Value{ 208 "path": cty.StringVal("./testdata/empty.tfstate"), 209 }), 210 "defaults": cty.NullVal(cty.DynamicPseudoType), 211 "outputs": cty.EmptyObjectVal, 212 "workspace": cty.StringVal(backend.DefaultStateName), 213 }), 214 false, 215 }, 216 "defaults as map": { 217 cty.ObjectVal(map[string]cty.Value{ 218 "backend": cty.StringVal("local"), 219 "config": cty.ObjectVal(map[string]cty.Value{ 220 "path": cty.StringVal("./testdata/basic.tfstate"), 221 }), 222 "defaults": cty.MapValEmpty(cty.String), 223 }), 224 cty.ObjectVal(map[string]cty.Value{ 225 "backend": cty.StringVal("local"), 226 "config": cty.ObjectVal(map[string]cty.Value{ 227 "path": cty.StringVal("./testdata/basic.tfstate"), 228 }), 229 "defaults": cty.MapValEmpty(cty.String), 230 "outputs": cty.ObjectVal(map[string]cty.Value{ 231 "foo": cty.StringVal("bar"), 232 }), 233 "workspace": cty.StringVal(backend.DefaultStateName), 234 }), 235 false, 236 }, 237 } 238 for name, test := range tests { 239 t.Run(name, func(t *testing.T) { 240 schema := dataSourceRemoteStateGetSchema().Block 241 config, err := schema.CoerceValue(test.Config) 242 if err != nil { 243 t.Fatalf("unexpected error: %s", err) 244 } 245 246 diags := dataSourceRemoteStateValidate(config) 247 248 var got cty.Value 249 if !diags.HasErrors() && config.IsWhollyKnown() { 250 var moreDiags tfdiags.Diagnostics 251 got, moreDiags = dataSourceRemoteStateRead(config) 252 diags = diags.Append(moreDiags) 253 } 254 255 if test.Err { 256 if !diags.HasErrors() { 257 t.Fatal("succeeded; want error") 258 } 259 } else if diags.HasErrors() { 260 t.Fatalf("unexpected errors: %s", diags.Err()) 261 } 262 263 if test.Want != cty.NilVal && !test.Want.RawEquals(got) { 264 t.Errorf("wrong result\nconfig: %sgot: %swant: %s", dump.Value(config), dump.Value(got), dump.Value(test.Want)) 265 } 266 }) 267 } 268 }