github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/builtin/providers/terraform/resource_data_test.go (about) 1 package terraform 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/hashicorp/terraform/internal/providers" 8 "github.com/zclconf/go-cty/cty" 9 ctyjson "github.com/zclconf/go-cty/cty/json" 10 ) 11 12 func TestManagedDataValidate(t *testing.T) { 13 cfg := map[string]cty.Value{ 14 "input": cty.NullVal(cty.DynamicPseudoType), 15 "output": cty.NullVal(cty.DynamicPseudoType), 16 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 17 "id": cty.NullVal(cty.String), 18 } 19 20 // empty 21 req := providers.ValidateResourceConfigRequest{ 22 TypeName: "terraform_data", 23 Config: cty.ObjectVal(cfg), 24 } 25 26 resp := validateDataStoreResourceConfig(req) 27 if resp.Diagnostics.HasErrors() { 28 t.Error("empty config error:", resp.Diagnostics.ErrWithWarnings()) 29 } 30 31 // invalid computed values 32 cfg["output"] = cty.StringVal("oops") 33 req.Config = cty.ObjectVal(cfg) 34 35 resp = validateDataStoreResourceConfig(req) 36 if !resp.Diagnostics.HasErrors() { 37 t.Error("expected error") 38 } 39 40 msg := resp.Diagnostics.Err().Error() 41 if !strings.Contains(msg, "attribute is read-only") { 42 t.Error("unexpected error", msg) 43 } 44 } 45 46 func TestManagedDataUpgradeState(t *testing.T) { 47 schema := dataStoreResourceSchema() 48 ty := schema.Block.ImpliedType() 49 50 state := cty.ObjectVal(map[string]cty.Value{ 51 "input": cty.StringVal("input"), 52 "output": cty.StringVal("input"), 53 "triggers_replace": cty.ListVal([]cty.Value{ 54 cty.StringVal("a"), cty.StringVal("b"), 55 }), 56 "id": cty.StringVal("not-quite-unique"), 57 }) 58 59 jsState, err := ctyjson.Marshal(state, ty) 60 if err != nil { 61 t.Fatal(err) 62 } 63 64 // empty 65 req := providers.UpgradeResourceStateRequest{ 66 TypeName: "terraform_data", 67 RawStateJSON: jsState, 68 } 69 70 resp := upgradeDataStoreResourceState(req) 71 if resp.Diagnostics.HasErrors() { 72 t.Error("upgrade state error:", resp.Diagnostics.ErrWithWarnings()) 73 } 74 75 if !resp.UpgradedState.RawEquals(state) { 76 t.Errorf("prior state was:\n%#v\nupgraded state is:\n%#v\n", state, resp.UpgradedState) 77 } 78 } 79 80 func TestManagedDataRead(t *testing.T) { 81 req := providers.ReadResourceRequest{ 82 TypeName: "terraform_data", 83 PriorState: cty.ObjectVal(map[string]cty.Value{ 84 "input": cty.StringVal("input"), 85 "output": cty.StringVal("input"), 86 "triggers_replace": cty.ListVal([]cty.Value{ 87 cty.StringVal("a"), cty.StringVal("b"), 88 }), 89 "id": cty.StringVal("not-quite-unique"), 90 }), 91 } 92 93 resp := readDataStoreResourceState(req) 94 if resp.Diagnostics.HasErrors() { 95 t.Fatal("unexpected error", resp.Diagnostics.ErrWithWarnings()) 96 } 97 98 if !resp.NewState.RawEquals(req.PriorState) { 99 t.Errorf("prior state was:\n%#v\nnew state is:\n%#v\n", req.PriorState, resp.NewState) 100 } 101 } 102 103 func TestManagedDataPlan(t *testing.T) { 104 schema := dataStoreResourceSchema().Block 105 ty := schema.ImpliedType() 106 107 for name, tc := range map[string]struct { 108 prior cty.Value 109 proposed cty.Value 110 planned cty.Value 111 }{ 112 "create": { 113 prior: cty.NullVal(ty), 114 proposed: cty.ObjectVal(map[string]cty.Value{ 115 "input": cty.NullVal(cty.DynamicPseudoType), 116 "output": cty.NullVal(cty.DynamicPseudoType), 117 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 118 "id": cty.NullVal(cty.String), 119 }), 120 planned: cty.ObjectVal(map[string]cty.Value{ 121 "input": cty.NullVal(cty.DynamicPseudoType), 122 "output": cty.NullVal(cty.DynamicPseudoType), 123 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 124 "id": cty.UnknownVal(cty.String), 125 }), 126 }, 127 128 "create-typed-null-input": { 129 prior: cty.NullVal(ty), 130 proposed: cty.ObjectVal(map[string]cty.Value{ 131 "input": cty.NullVal(cty.String), 132 "output": cty.NullVal(cty.DynamicPseudoType), 133 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 134 "id": cty.NullVal(cty.String), 135 }), 136 planned: cty.ObjectVal(map[string]cty.Value{ 137 "input": cty.NullVal(cty.String), 138 "output": cty.NullVal(cty.String), 139 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 140 "id": cty.UnknownVal(cty.String), 141 }), 142 }, 143 144 "create-output": { 145 prior: cty.NullVal(ty), 146 proposed: cty.ObjectVal(map[string]cty.Value{ 147 "input": cty.StringVal("input"), 148 "output": cty.NullVal(cty.DynamicPseudoType), 149 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 150 "id": cty.NullVal(cty.String), 151 }), 152 planned: cty.ObjectVal(map[string]cty.Value{ 153 "input": cty.StringVal("input"), 154 "output": cty.UnknownVal(cty.String), 155 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 156 "id": cty.UnknownVal(cty.String), 157 }), 158 }, 159 160 "update-input": { 161 prior: cty.ObjectVal(map[string]cty.Value{ 162 "input": cty.StringVal("input"), 163 "output": cty.StringVal("input"), 164 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 165 "id": cty.StringVal("not-quite-unique"), 166 }), 167 proposed: cty.ObjectVal(map[string]cty.Value{ 168 "input": cty.UnknownVal(cty.List(cty.String)), 169 "output": cty.StringVal("input"), 170 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 171 "id": cty.StringVal("not-quite-unique"), 172 }), 173 planned: cty.ObjectVal(map[string]cty.Value{ 174 "input": cty.UnknownVal(cty.List(cty.String)), 175 "output": cty.UnknownVal(cty.List(cty.String)), 176 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 177 "id": cty.StringVal("not-quite-unique"), 178 }), 179 }, 180 181 "update-trigger": { 182 prior: cty.ObjectVal(map[string]cty.Value{ 183 "input": cty.StringVal("input"), 184 "output": cty.StringVal("input"), 185 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 186 "id": cty.StringVal("not-quite-unique"), 187 }), 188 proposed: cty.ObjectVal(map[string]cty.Value{ 189 "input": cty.StringVal("input"), 190 "output": cty.StringVal("input"), 191 "triggers_replace": cty.StringVal("new-value"), 192 "id": cty.StringVal("not-quite-unique"), 193 }), 194 planned: cty.ObjectVal(map[string]cty.Value{ 195 "input": cty.StringVal("input"), 196 "output": cty.UnknownVal(cty.String), 197 "triggers_replace": cty.StringVal("new-value"), 198 "id": cty.UnknownVal(cty.String), 199 }), 200 }, 201 202 "update-input-trigger": { 203 prior: cty.ObjectVal(map[string]cty.Value{ 204 "input": cty.StringVal("input"), 205 "output": cty.StringVal("input"), 206 "triggers_replace": cty.MapVal(map[string]cty.Value{ 207 "key": cty.StringVal("value"), 208 }), 209 "id": cty.StringVal("not-quite-unique"), 210 }), 211 proposed: cty.ObjectVal(map[string]cty.Value{ 212 "input": cty.ListVal([]cty.Value{cty.StringVal("new-input")}), 213 "output": cty.StringVal("input"), 214 "triggers_replace": cty.MapVal(map[string]cty.Value{ 215 "key": cty.StringVal("new value"), 216 }), 217 "id": cty.StringVal("not-quite-unique"), 218 }), 219 planned: cty.ObjectVal(map[string]cty.Value{ 220 "input": cty.ListVal([]cty.Value{cty.StringVal("new-input")}), 221 "output": cty.UnknownVal(cty.List(cty.String)), 222 "triggers_replace": cty.MapVal(map[string]cty.Value{ 223 "key": cty.StringVal("new value"), 224 }), 225 "id": cty.UnknownVal(cty.String), 226 }), 227 }, 228 } { 229 t.Run("plan-"+name, func(t *testing.T) { 230 req := providers.PlanResourceChangeRequest{ 231 TypeName: "terraform_data", 232 PriorState: tc.prior, 233 ProposedNewState: tc.proposed, 234 } 235 236 resp := planDataStoreResourceChange(req) 237 if resp.Diagnostics.HasErrors() { 238 t.Fatal(resp.Diagnostics.ErrWithWarnings()) 239 } 240 241 if !resp.PlannedState.RawEquals(tc.planned) { 242 t.Errorf("expected:\n%#v\ngot:\n%#v\n", tc.planned, resp.PlannedState) 243 } 244 }) 245 } 246 } 247 248 func TestManagedDataApply(t *testing.T) { 249 testUUIDHook = func() string { 250 return "not-quite-unique" 251 } 252 defer func() { 253 testUUIDHook = nil 254 }() 255 256 schema := dataStoreResourceSchema().Block 257 ty := schema.ImpliedType() 258 259 for name, tc := range map[string]struct { 260 prior cty.Value 261 planned cty.Value 262 state cty.Value 263 }{ 264 "create": { 265 prior: cty.NullVal(ty), 266 planned: cty.ObjectVal(map[string]cty.Value{ 267 "input": cty.NullVal(cty.DynamicPseudoType), 268 "output": cty.NullVal(cty.DynamicPseudoType), 269 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 270 "id": cty.UnknownVal(cty.String), 271 }), 272 state: cty.ObjectVal(map[string]cty.Value{ 273 "input": cty.NullVal(cty.DynamicPseudoType), 274 "output": cty.NullVal(cty.DynamicPseudoType), 275 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 276 "id": cty.StringVal("not-quite-unique"), 277 }), 278 }, 279 280 "create-output": { 281 prior: cty.NullVal(ty), 282 planned: cty.ObjectVal(map[string]cty.Value{ 283 "input": cty.StringVal("input"), 284 "output": cty.UnknownVal(cty.String), 285 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 286 "id": cty.UnknownVal(cty.String), 287 }), 288 state: cty.ObjectVal(map[string]cty.Value{ 289 "input": cty.StringVal("input"), 290 "output": cty.StringVal("input"), 291 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 292 "id": cty.StringVal("not-quite-unique"), 293 }), 294 }, 295 296 "update-input": { 297 prior: cty.ObjectVal(map[string]cty.Value{ 298 "input": cty.StringVal("input"), 299 "output": cty.StringVal("input"), 300 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 301 "id": cty.StringVal("not-quite-unique"), 302 }), 303 planned: cty.ObjectVal(map[string]cty.Value{ 304 "input": cty.ListVal([]cty.Value{cty.StringVal("new-input")}), 305 "output": cty.UnknownVal(cty.List(cty.String)), 306 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 307 "id": cty.StringVal("not-quite-unique"), 308 }), 309 state: cty.ObjectVal(map[string]cty.Value{ 310 "input": cty.ListVal([]cty.Value{cty.StringVal("new-input")}), 311 "output": cty.ListVal([]cty.Value{cty.StringVal("new-input")}), 312 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 313 "id": cty.StringVal("not-quite-unique"), 314 }), 315 }, 316 317 "update-trigger": { 318 prior: cty.ObjectVal(map[string]cty.Value{ 319 "input": cty.StringVal("input"), 320 "output": cty.StringVal("input"), 321 "triggers_replace": cty.NullVal(cty.DynamicPseudoType), 322 "id": cty.StringVal("not-quite-unique"), 323 }), 324 planned: cty.ObjectVal(map[string]cty.Value{ 325 "input": cty.StringVal("input"), 326 "output": cty.UnknownVal(cty.String), 327 "triggers_replace": cty.StringVal("new-value"), 328 "id": cty.UnknownVal(cty.String), 329 }), 330 state: cty.ObjectVal(map[string]cty.Value{ 331 "input": cty.StringVal("input"), 332 "output": cty.StringVal("input"), 333 "triggers_replace": cty.StringVal("new-value"), 334 "id": cty.StringVal("not-quite-unique"), 335 }), 336 }, 337 338 "update-input-trigger": { 339 prior: cty.ObjectVal(map[string]cty.Value{ 340 "input": cty.StringVal("input"), 341 "output": cty.StringVal("input"), 342 "triggers_replace": cty.MapVal(map[string]cty.Value{ 343 "key": cty.StringVal("value"), 344 }), 345 "id": cty.StringVal("not-quite-unique"), 346 }), 347 planned: cty.ObjectVal(map[string]cty.Value{ 348 "input": cty.ListVal([]cty.Value{cty.StringVal("new-input")}), 349 "output": cty.UnknownVal(cty.List(cty.String)), 350 "triggers_replace": cty.MapVal(map[string]cty.Value{ 351 "key": cty.StringVal("new value"), 352 }), 353 "id": cty.UnknownVal(cty.String), 354 }), 355 state: cty.ObjectVal(map[string]cty.Value{ 356 "input": cty.ListVal([]cty.Value{cty.StringVal("new-input")}), 357 "output": cty.ListVal([]cty.Value{cty.StringVal("new-input")}), 358 "triggers_replace": cty.MapVal(map[string]cty.Value{ 359 "key": cty.StringVal("new value"), 360 }), 361 "id": cty.StringVal("not-quite-unique"), 362 }), 363 }, 364 } { 365 t.Run("apply-"+name, func(t *testing.T) { 366 req := providers.ApplyResourceChangeRequest{ 367 TypeName: "terraform_data", 368 PriorState: tc.prior, 369 PlannedState: tc.planned, 370 } 371 372 resp := applyDataStoreResourceChange(req) 373 if resp.Diagnostics.HasErrors() { 374 t.Fatal(resp.Diagnostics.ErrWithWarnings()) 375 } 376 377 if !resp.NewState.RawEquals(tc.state) { 378 t.Errorf("expected:\n%#v\ngot:\n%#v\n", tc.state, resp.NewState) 379 } 380 }) 381 } 382 }