mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-28 01:41:48 -06:00
e5f52e56f8
As the comment notes, this hostname is the default for provide source addresses. We'll shortly be adding some address types to represent module source addresses too, and so we'll also have DefaultModuleRegistryHost for that situation. (They'll actually both contain the the same hostname, but that's a coincidence rather than a requirement.)
350 lines
9.0 KiB
Go
350 lines
9.0 KiB
Go
package configs
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
|
version "github.com/hashicorp/go-version"
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/hashicorp/hcl/v2/hcltest"
|
|
"github.com/hashicorp/terraform/internal/addrs"
|
|
"github.com/zclconf/go-cty/cty"
|
|
)
|
|
|
|
var (
|
|
ignoreUnexported = cmpopts.IgnoreUnexported(version.Constraint{})
|
|
comparer = cmp.Comparer(func(x, y RequiredProvider) bool {
|
|
if x.Name != y.Name {
|
|
return false
|
|
}
|
|
if x.Type != y.Type {
|
|
return false
|
|
}
|
|
if x.Source != y.Source {
|
|
return false
|
|
}
|
|
if x.Requirement.Required.String() != y.Requirement.Required.String() {
|
|
return false
|
|
}
|
|
if x.DeclRange != y.DeclRange {
|
|
return false
|
|
}
|
|
return true
|
|
})
|
|
blockRange = hcl.Range{
|
|
Filename: "mock.tf",
|
|
Start: hcl.Pos{Line: 3, Column: 12, Byte: 27},
|
|
End: hcl.Pos{Line: 3, Column: 19, Byte: 34},
|
|
}
|
|
mockRange = hcl.Range{
|
|
Filename: "MockExprLiteral",
|
|
}
|
|
)
|
|
|
|
func TestDecodeRequiredProvidersBlock(t *testing.T) {
|
|
tests := map[string]struct {
|
|
Block *hcl.Block
|
|
Want *RequiredProviders
|
|
Error string
|
|
}{
|
|
"legacy": {
|
|
Block: &hcl.Block{
|
|
Type: "required_providers",
|
|
Body: hcltest.MockBody(&hcl.BodyContent{
|
|
Attributes: hcl.Attributes{
|
|
"default": {
|
|
Name: "default",
|
|
Expr: hcltest.MockExprLiteral(cty.StringVal("1.0.0")),
|
|
},
|
|
},
|
|
}),
|
|
DefRange: blockRange,
|
|
},
|
|
Want: &RequiredProviders{
|
|
RequiredProviders: map[string]*RequiredProvider{
|
|
"default": {
|
|
Name: "default",
|
|
Type: addrs.NewDefaultProvider("default"),
|
|
Requirement: testVC("1.0.0"),
|
|
DeclRange: mockRange,
|
|
},
|
|
},
|
|
DeclRange: blockRange,
|
|
},
|
|
},
|
|
"provider source": {
|
|
Block: &hcl.Block{
|
|
Type: "required_providers",
|
|
Body: hcltest.MockBody(&hcl.BodyContent{
|
|
Attributes: hcl.Attributes{
|
|
"my-test": {
|
|
Name: "my-test",
|
|
Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{
|
|
"source": cty.StringVal("mycloud/test"),
|
|
"version": cty.StringVal("2.0.0"),
|
|
})),
|
|
},
|
|
},
|
|
}),
|
|
DefRange: blockRange,
|
|
},
|
|
Want: &RequiredProviders{
|
|
RequiredProviders: map[string]*RequiredProvider{
|
|
"my-test": {
|
|
Name: "my-test",
|
|
Source: "mycloud/test",
|
|
Type: addrs.NewProvider(addrs.DefaultProviderRegistryHost, "mycloud", "test"),
|
|
Requirement: testVC("2.0.0"),
|
|
DeclRange: mockRange,
|
|
},
|
|
},
|
|
DeclRange: blockRange,
|
|
},
|
|
},
|
|
"mixed": {
|
|
Block: &hcl.Block{
|
|
Type: "required_providers",
|
|
Body: hcltest.MockBody(&hcl.BodyContent{
|
|
Attributes: hcl.Attributes{
|
|
"legacy": {
|
|
Name: "legacy",
|
|
Expr: hcltest.MockExprLiteral(cty.StringVal("1.0.0")),
|
|
},
|
|
"my-test": {
|
|
Name: "my-test",
|
|
Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{
|
|
"source": cty.StringVal("mycloud/test"),
|
|
"version": cty.StringVal("2.0.0"),
|
|
})),
|
|
},
|
|
},
|
|
}),
|
|
DefRange: blockRange,
|
|
},
|
|
Want: &RequiredProviders{
|
|
RequiredProviders: map[string]*RequiredProvider{
|
|
"legacy": {
|
|
Name: "legacy",
|
|
Type: addrs.NewDefaultProvider("legacy"),
|
|
Requirement: testVC("1.0.0"),
|
|
DeclRange: mockRange,
|
|
},
|
|
"my-test": {
|
|
Name: "my-test",
|
|
Source: "mycloud/test",
|
|
Type: addrs.NewProvider(addrs.DefaultProviderRegistryHost, "mycloud", "test"),
|
|
Requirement: testVC("2.0.0"),
|
|
DeclRange: mockRange,
|
|
},
|
|
},
|
|
DeclRange: blockRange,
|
|
},
|
|
},
|
|
"version-only block": {
|
|
Block: &hcl.Block{
|
|
Type: "required_providers",
|
|
Body: hcltest.MockBody(&hcl.BodyContent{
|
|
Attributes: hcl.Attributes{
|
|
"test": {
|
|
Name: "test",
|
|
Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{
|
|
"version": cty.StringVal("~>2.0.0"),
|
|
})),
|
|
},
|
|
},
|
|
}),
|
|
DefRange: blockRange,
|
|
},
|
|
Want: &RequiredProviders{
|
|
RequiredProviders: map[string]*RequiredProvider{
|
|
"test": {
|
|
Name: "test",
|
|
Type: addrs.NewDefaultProvider("test"),
|
|
Requirement: testVC("~>2.0.0"),
|
|
DeclRange: mockRange,
|
|
},
|
|
},
|
|
DeclRange: blockRange,
|
|
},
|
|
},
|
|
"invalid source": {
|
|
Block: &hcl.Block{
|
|
Type: "required_providers",
|
|
Body: hcltest.MockBody(&hcl.BodyContent{
|
|
Attributes: hcl.Attributes{
|
|
"my-test": {
|
|
Name: "my-test",
|
|
Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{
|
|
"source": cty.StringVal("some/invalid/provider/source/test"),
|
|
"version": cty.StringVal("~>2.0.0"),
|
|
})),
|
|
},
|
|
},
|
|
}),
|
|
DefRange: blockRange,
|
|
},
|
|
Want: &RequiredProviders{
|
|
RequiredProviders: map[string]*RequiredProvider{},
|
|
DeclRange: blockRange,
|
|
},
|
|
Error: "Invalid provider source string",
|
|
},
|
|
"invalid localname": {
|
|
Block: &hcl.Block{
|
|
Type: "required_providers",
|
|
Body: hcltest.MockBody(&hcl.BodyContent{
|
|
Attributes: hcl.Attributes{
|
|
"my_test": {
|
|
Name: "my_test",
|
|
Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{
|
|
"version": cty.StringVal("~>2.0.0"),
|
|
})),
|
|
},
|
|
},
|
|
}),
|
|
DefRange: blockRange,
|
|
},
|
|
Want: &RequiredProviders{
|
|
RequiredProviders: map[string]*RequiredProvider{},
|
|
DeclRange: blockRange,
|
|
},
|
|
Error: "Invalid provider local name",
|
|
},
|
|
"invalid localname caps": {
|
|
Block: &hcl.Block{
|
|
Type: "required_providers",
|
|
Body: hcltest.MockBody(&hcl.BodyContent{
|
|
Attributes: hcl.Attributes{
|
|
"MYTEST": {
|
|
Name: "MYTEST",
|
|
Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{
|
|
"version": cty.StringVal("~>2.0.0"),
|
|
})),
|
|
},
|
|
},
|
|
}),
|
|
DefRange: blockRange,
|
|
},
|
|
Want: &RequiredProviders{
|
|
RequiredProviders: map[string]*RequiredProvider{},
|
|
DeclRange: blockRange,
|
|
},
|
|
Error: "Invalid provider local name",
|
|
},
|
|
"version constraint error": {
|
|
Block: &hcl.Block{
|
|
Type: "required_providers",
|
|
Body: hcltest.MockBody(&hcl.BodyContent{
|
|
Attributes: hcl.Attributes{
|
|
"my-test": {
|
|
Name: "my-test",
|
|
Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{
|
|
"source": cty.StringVal("mycloud/test"),
|
|
"version": cty.StringVal("invalid"),
|
|
})),
|
|
},
|
|
},
|
|
}),
|
|
DefRange: blockRange,
|
|
},
|
|
Want: &RequiredProviders{
|
|
RequiredProviders: map[string]*RequiredProvider{},
|
|
DeclRange: blockRange,
|
|
},
|
|
Error: "Invalid version constraint",
|
|
},
|
|
"invalid required_providers attribute value": {
|
|
Block: &hcl.Block{
|
|
Type: "required_providers",
|
|
Body: hcltest.MockBody(&hcl.BodyContent{
|
|
Attributes: hcl.Attributes{
|
|
"test": {
|
|
Name: "test",
|
|
Expr: hcltest.MockExprLiteral(cty.ListVal([]cty.Value{cty.StringVal("2.0.0")})),
|
|
},
|
|
},
|
|
}),
|
|
DefRange: blockRange,
|
|
},
|
|
Want: &RequiredProviders{
|
|
RequiredProviders: map[string]*RequiredProvider{},
|
|
DeclRange: blockRange,
|
|
},
|
|
Error: "Invalid required_providers object",
|
|
},
|
|
"invalid source attribute type": {
|
|
Block: &hcl.Block{
|
|
Type: "required_providers",
|
|
Body: hcltest.MockBody(&hcl.BodyContent{
|
|
Attributes: hcl.Attributes{
|
|
"my-test": {
|
|
Name: "my-test",
|
|
Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{
|
|
"source": cty.DynamicVal,
|
|
})),
|
|
},
|
|
},
|
|
}),
|
|
DefRange: blockRange,
|
|
},
|
|
Want: &RequiredProviders{
|
|
RequiredProviders: map[string]*RequiredProvider{},
|
|
DeclRange: blockRange,
|
|
},
|
|
Error: "Invalid source",
|
|
},
|
|
"additional attributes": {
|
|
Block: &hcl.Block{
|
|
Type: "required_providers",
|
|
Body: hcltest.MockBody(&hcl.BodyContent{
|
|
Attributes: hcl.Attributes{
|
|
"my-test": {
|
|
Name: "my-test",
|
|
Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{
|
|
"source": cty.StringVal("mycloud/test"),
|
|
"version": cty.StringVal("2.0.0"),
|
|
"invalid": cty.BoolVal(true),
|
|
})),
|
|
},
|
|
},
|
|
}),
|
|
DefRange: blockRange,
|
|
},
|
|
Want: &RequiredProviders{
|
|
RequiredProviders: map[string]*RequiredProvider{},
|
|
DeclRange: blockRange,
|
|
},
|
|
Error: "Invalid required_providers object",
|
|
},
|
|
}
|
|
|
|
for name, test := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
got, diags := decodeRequiredProvidersBlock(test.Block)
|
|
if diags.HasErrors() {
|
|
if test.Error == "" {
|
|
t.Fatalf("unexpected error: %v", diags)
|
|
}
|
|
if gotErr := diags[0].Summary; gotErr != test.Error {
|
|
t.Errorf("wrong error, got %q, want %q", gotErr, test.Error)
|
|
}
|
|
} else if test.Error != "" {
|
|
t.Fatalf("expected error")
|
|
}
|
|
|
|
if !cmp.Equal(got, test.Want, ignoreUnexported, comparer) {
|
|
t.Fatalf("wrong result:\n %s", cmp.Diff(got, test.Want, ignoreUnexported, comparer))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func testVC(ver string) VersionConstraint {
|
|
constraint, _ := version.NewConstraint(ver)
|
|
return VersionConstraint{
|
|
Required: constraint,
|
|
DeclRange: hcl.Range{},
|
|
}
|
|
}
|