kubeform.dev/terraform-backend-sdk@v0.0.0-20220310143633-45f07fe731c5/configs/provider_requirements_test.go (about) 1 package configs 2 3 import ( 4 "testing" 5 6 "github.com/google/go-cmp/cmp" 7 "github.com/google/go-cmp/cmp/cmpopts" 8 version "github.com/hashicorp/go-version" 9 "github.com/hashicorp/hcl/v2" 10 "github.com/hashicorp/hcl/v2/hcltest" 11 "kubeform.dev/terraform-backend-sdk/addrs" 12 "github.com/zclconf/go-cty/cty" 13 ) 14 15 var ( 16 ignoreUnexported = cmpopts.IgnoreUnexported(version.Constraint{}) 17 comparer = cmp.Comparer(func(x, y RequiredProvider) bool { 18 if x.Name != y.Name { 19 return false 20 } 21 if x.Type != y.Type { 22 return false 23 } 24 if x.Source != y.Source { 25 return false 26 } 27 if x.Requirement.Required.String() != y.Requirement.Required.String() { 28 return false 29 } 30 if x.DeclRange != y.DeclRange { 31 return false 32 } 33 return true 34 }) 35 blockRange = hcl.Range{ 36 Filename: "mock.tf", 37 Start: hcl.Pos{Line: 3, Column: 12, Byte: 27}, 38 End: hcl.Pos{Line: 3, Column: 19, Byte: 34}, 39 } 40 mockRange = hcl.Range{ 41 Filename: "MockExprLiteral", 42 } 43 ) 44 45 func TestDecodeRequiredProvidersBlock(t *testing.T) { 46 tests := map[string]struct { 47 Block *hcl.Block 48 Want *RequiredProviders 49 Error string 50 }{ 51 "legacy": { 52 Block: &hcl.Block{ 53 Type: "required_providers", 54 Body: hcltest.MockBody(&hcl.BodyContent{ 55 Attributes: hcl.Attributes{ 56 "default": { 57 Name: "default", 58 Expr: hcltest.MockExprLiteral(cty.StringVal("1.0.0")), 59 }, 60 }, 61 }), 62 DefRange: blockRange, 63 }, 64 Want: &RequiredProviders{ 65 RequiredProviders: map[string]*RequiredProvider{ 66 "default": { 67 Name: "default", 68 Type: addrs.NewDefaultProvider("default"), 69 Requirement: testVC("1.0.0"), 70 DeclRange: mockRange, 71 }, 72 }, 73 DeclRange: blockRange, 74 }, 75 }, 76 "provider source": { 77 Block: &hcl.Block{ 78 Type: "required_providers", 79 Body: hcltest.MockBody(&hcl.BodyContent{ 80 Attributes: hcl.Attributes{ 81 "my-test": { 82 Name: "my-test", 83 Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{ 84 "source": cty.StringVal("mycloud/test"), 85 "version": cty.StringVal("2.0.0"), 86 })), 87 }, 88 }, 89 }), 90 DefRange: blockRange, 91 }, 92 Want: &RequiredProviders{ 93 RequiredProviders: map[string]*RequiredProvider{ 94 "my-test": { 95 Name: "my-test", 96 Source: "mycloud/test", 97 Type: addrs.NewProvider(addrs.DefaultProviderRegistryHost, "mycloud", "test"), 98 Requirement: testVC("2.0.0"), 99 DeclRange: mockRange, 100 }, 101 }, 102 DeclRange: blockRange, 103 }, 104 }, 105 "mixed": { 106 Block: &hcl.Block{ 107 Type: "required_providers", 108 Body: hcltest.MockBody(&hcl.BodyContent{ 109 Attributes: hcl.Attributes{ 110 "legacy": { 111 Name: "legacy", 112 Expr: hcltest.MockExprLiteral(cty.StringVal("1.0.0")), 113 }, 114 "my-test": { 115 Name: "my-test", 116 Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{ 117 "source": cty.StringVal("mycloud/test"), 118 "version": cty.StringVal("2.0.0"), 119 })), 120 }, 121 }, 122 }), 123 DefRange: blockRange, 124 }, 125 Want: &RequiredProviders{ 126 RequiredProviders: map[string]*RequiredProvider{ 127 "legacy": { 128 Name: "legacy", 129 Type: addrs.NewDefaultProvider("legacy"), 130 Requirement: testVC("1.0.0"), 131 DeclRange: mockRange, 132 }, 133 "my-test": { 134 Name: "my-test", 135 Source: "mycloud/test", 136 Type: addrs.NewProvider(addrs.DefaultProviderRegistryHost, "mycloud", "test"), 137 Requirement: testVC("2.0.0"), 138 DeclRange: mockRange, 139 }, 140 }, 141 DeclRange: blockRange, 142 }, 143 }, 144 "version-only block": { 145 Block: &hcl.Block{ 146 Type: "required_providers", 147 Body: hcltest.MockBody(&hcl.BodyContent{ 148 Attributes: hcl.Attributes{ 149 "test": { 150 Name: "test", 151 Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{ 152 "version": cty.StringVal("~>2.0.0"), 153 })), 154 }, 155 }, 156 }), 157 DefRange: blockRange, 158 }, 159 Want: &RequiredProviders{ 160 RequiredProviders: map[string]*RequiredProvider{ 161 "test": { 162 Name: "test", 163 Type: addrs.NewDefaultProvider("test"), 164 Requirement: testVC("~>2.0.0"), 165 DeclRange: mockRange, 166 }, 167 }, 168 DeclRange: blockRange, 169 }, 170 }, 171 "invalid source": { 172 Block: &hcl.Block{ 173 Type: "required_providers", 174 Body: hcltest.MockBody(&hcl.BodyContent{ 175 Attributes: hcl.Attributes{ 176 "my-test": { 177 Name: "my-test", 178 Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{ 179 "source": cty.StringVal("some/invalid/provider/source/test"), 180 "version": cty.StringVal("~>2.0.0"), 181 })), 182 }, 183 }, 184 }), 185 DefRange: blockRange, 186 }, 187 Want: &RequiredProviders{ 188 RequiredProviders: map[string]*RequiredProvider{}, 189 DeclRange: blockRange, 190 }, 191 Error: "Invalid provider source string", 192 }, 193 "invalid localname": { 194 Block: &hcl.Block{ 195 Type: "required_providers", 196 Body: hcltest.MockBody(&hcl.BodyContent{ 197 Attributes: hcl.Attributes{ 198 "my_test": { 199 Name: "my_test", 200 Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{ 201 "version": cty.StringVal("~>2.0.0"), 202 })), 203 }, 204 }, 205 }), 206 DefRange: blockRange, 207 }, 208 Want: &RequiredProviders{ 209 RequiredProviders: map[string]*RequiredProvider{}, 210 DeclRange: blockRange, 211 }, 212 Error: "Invalid provider local name", 213 }, 214 "invalid localname caps": { 215 Block: &hcl.Block{ 216 Type: "required_providers", 217 Body: hcltest.MockBody(&hcl.BodyContent{ 218 Attributes: hcl.Attributes{ 219 "MYTEST": { 220 Name: "MYTEST", 221 Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{ 222 "version": cty.StringVal("~>2.0.0"), 223 })), 224 }, 225 }, 226 }), 227 DefRange: blockRange, 228 }, 229 Want: &RequiredProviders{ 230 RequiredProviders: map[string]*RequiredProvider{}, 231 DeclRange: blockRange, 232 }, 233 Error: "Invalid provider local name", 234 }, 235 "version constraint error": { 236 Block: &hcl.Block{ 237 Type: "required_providers", 238 Body: hcltest.MockBody(&hcl.BodyContent{ 239 Attributes: hcl.Attributes{ 240 "my-test": { 241 Name: "my-test", 242 Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{ 243 "source": cty.StringVal("mycloud/test"), 244 "version": cty.StringVal("invalid"), 245 })), 246 }, 247 }, 248 }), 249 DefRange: blockRange, 250 }, 251 Want: &RequiredProviders{ 252 RequiredProviders: map[string]*RequiredProvider{}, 253 DeclRange: blockRange, 254 }, 255 Error: "Invalid version constraint", 256 }, 257 "invalid required_providers attribute value": { 258 Block: &hcl.Block{ 259 Type: "required_providers", 260 Body: hcltest.MockBody(&hcl.BodyContent{ 261 Attributes: hcl.Attributes{ 262 "test": { 263 Name: "test", 264 Expr: hcltest.MockExprLiteral(cty.ListVal([]cty.Value{cty.StringVal("2.0.0")})), 265 }, 266 }, 267 }), 268 DefRange: blockRange, 269 }, 270 Want: &RequiredProviders{ 271 RequiredProviders: map[string]*RequiredProvider{}, 272 DeclRange: blockRange, 273 }, 274 Error: "Invalid required_providers object", 275 }, 276 "invalid source attribute type": { 277 Block: &hcl.Block{ 278 Type: "required_providers", 279 Body: hcltest.MockBody(&hcl.BodyContent{ 280 Attributes: hcl.Attributes{ 281 "my-test": { 282 Name: "my-test", 283 Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{ 284 "source": cty.DynamicVal, 285 })), 286 }, 287 }, 288 }), 289 DefRange: blockRange, 290 }, 291 Want: &RequiredProviders{ 292 RequiredProviders: map[string]*RequiredProvider{}, 293 DeclRange: blockRange, 294 }, 295 Error: "Invalid source", 296 }, 297 "additional attributes": { 298 Block: &hcl.Block{ 299 Type: "required_providers", 300 Body: hcltest.MockBody(&hcl.BodyContent{ 301 Attributes: hcl.Attributes{ 302 "my-test": { 303 Name: "my-test", 304 Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{ 305 "source": cty.StringVal("mycloud/test"), 306 "version": cty.StringVal("2.0.0"), 307 "invalid": cty.BoolVal(true), 308 })), 309 }, 310 }, 311 }), 312 DefRange: blockRange, 313 }, 314 Want: &RequiredProviders{ 315 RequiredProviders: map[string]*RequiredProvider{}, 316 DeclRange: blockRange, 317 }, 318 Error: "Invalid required_providers object", 319 }, 320 } 321 322 for name, test := range tests { 323 t.Run(name, func(t *testing.T) { 324 got, diags := decodeRequiredProvidersBlock(test.Block) 325 if diags.HasErrors() { 326 if test.Error == "" { 327 t.Fatalf("unexpected error: %v", diags) 328 } 329 if gotErr := diags[0].Summary; gotErr != test.Error { 330 t.Errorf("wrong error, got %q, want %q", gotErr, test.Error) 331 } 332 } else if test.Error != "" { 333 t.Fatalf("expected error") 334 } 335 336 if !cmp.Equal(got, test.Want, ignoreUnexported, comparer) { 337 t.Fatalf("wrong result:\n %s", cmp.Diff(got, test.Want, ignoreUnexported, comparer)) 338 } 339 }) 340 } 341 } 342 343 func testVC(ver string) VersionConstraint { 344 constraint, _ := version.NewConstraint(ver) 345 return VersionConstraint{ 346 Required: constraint, 347 DeclRange: hcl.Range{}, 348 } 349 }