Skip to content

Commit

Permalink
Expose configuration_aliases from required_providers (#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko authored Mar 18, 2021
1 parent 4fd17a0 commit 9a80970
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 5 deletions.
97 changes: 93 additions & 4 deletions tfconfig/provider_ref.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ type ProviderRef struct {
}

type ProviderRequirement struct {
Source string `json:"source,omitempty"`
VersionConstraints []string `json:"version_constraints,omitempty"`
Source string `json:"source,omitempty"`
VersionConstraints []string `json:"version_constraints,omitempty"`
ConfigurationAliases []ProviderRef `json:"aliases,omitempty"`
}

func decodeRequiredProvidersBlock(block *hcl.Block) (map[string]*ProviderRequirement, hcl.Diagnostics) {
Expand Down Expand Up @@ -85,8 +86,8 @@ func decodeRequiredProvidersBlock(block *hcl.Block) (map[string]*ProviderRequire
}

case "source":
source, err := kv.Value.Value(nil)
if err != nil || !source.Type().Equals(cty.String) {
source, valDiags := kv.Value.Value(nil)
if valDiags.HasErrors() || !source.Type().Equals(cty.String) {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Unsuitable value type",
Expand All @@ -99,6 +100,13 @@ func decodeRequiredProvidersBlock(block *hcl.Block) (map[string]*ProviderRequire
if !source.IsNull() {
pr.Source = source.AsString()
}
case "configuration_aliases":
aliases, valDiags := decodeConfigurationAliases(name, kv.Value)
if valDiags.HasErrors() {
diags = append(diags, valDiags...)
continue
}
pr.ConfigurationAliases = append(pr.ConfigurationAliases, aliases...)
}

reqs[name] = &pr
Expand All @@ -107,3 +115,84 @@ func decodeRequiredProvidersBlock(block *hcl.Block) (map[string]*ProviderRequire

return reqs, diags
}

func decodeConfigurationAliases(localName string, value hcl.Expression) ([]ProviderRef, hcl.Diagnostics) {
aliases := make([]ProviderRef, 0)
var diags hcl.Diagnostics

exprs, listDiags := hcl.ExprList(value)
if listDiags.HasErrors() {
diags = append(diags, listDiags...)
return aliases, diags
}

for _, expr := range exprs {
traversal, travDiags := hcl.AbsTraversalForExpr(expr)
if travDiags.HasErrors() {
diags = append(diags, travDiags...)
continue
}

ref, cfgDiags := parseProviderRef(traversal)
if cfgDiags.HasErrors() {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid configuration_aliases value",
Detail: `Configuration aliases can only contain references to local provider configuration names in the format of provider.alias`,
Subject: value.Range().Ptr(),
})
continue
}

if ref.Name != localName {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid configuration_aliases value",
Detail: fmt.Sprintf(`Configuration aliases must be prefixed with the provider name. Expected %q, but found %q.`, localName, ref.Name),
Subject: value.Range().Ptr(),
})
continue
}

aliases = append(aliases, ref)
}

return aliases, diags
}

func parseProviderRef(traversal hcl.Traversal) (ProviderRef, hcl.Diagnostics) {
var diags hcl.Diagnostics
ret := ProviderRef{
Name: traversal.RootName(),
}

if len(traversal) < 2 {
// Just a local name, then.
return ret, diags
}

aliasStep := traversal[1]
switch ts := aliasStep.(type) {
case hcl.TraverseAttr:
ret.Alias = ts.Name
return ret, diags
default:
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid provider configuration address",
Detail: "The provider type name must either stand alone or be followed by an alias name separated with a dot.",
Subject: aliasStep.SourceRange().Ptr(),
})
}

if len(traversal) > 2 {
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid provider configuration address",
Detail: "Extraneous extra operators after provider configuration address.",
Subject: traversal[2:].SourceRange().Ptr(),
})
}

return ret, diags
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"path": "testdata/provider-aliases-json",
"variables": {},
"outputs": {},
"required_providers": {
"bar": {},
"baz": {},
"bleep": {
"aliases": [
{"name": "bleep", "alias": "bloop"}
]
},
"empty": {},
"foo": {}
},
"provider_configs": {
"bar.yellow": {"name": "bar", "alias": "yellow"},
"baz": {"name": "baz"},
"empty": {"name": "empty"},
"bar": {"name": "bar"},
"foo.blue": {"name": "foo", "alias": "blue"},
"foo.red": {"name": "foo", "alias": "red"}
},
"managed_resources": {},
"data_resources": {},
"module_calls": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

# Module `testdata/provider-aliases-json`

Provider Requirements:
* **bar:** (any version)
* **baz:** (any version)
* **bleep:** (any version)
* **empty:** (any version)
* **foo:** (any version)

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"terraform": {
"required_providers": {
"bleep": {
"configuration_aliases": [
"bleep.bloop"
]
}
}
},
"provider": {
"foo": [
{
"alias": "blue"
},
{
"alias": "red"
}
],
"bar": [
{},
{
"alias": "yellow"
}
],
"baz": [
{}
],
"empty": [
{
"alias": ""
}
]
}
}
6 changes: 5 additions & 1 deletion tfconfig/testdata/provider-aliases/provider-aliases.out.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
"required_providers": {
"bar": {},
"baz": {},
"bleep": {},
"bleep": {
"aliases": [
{"name": "bleep", "alias": "bloop"}
]
},
"empty": {},
"foo": {}
},
Expand Down

0 comments on commit 9a80970

Please sign in to comment.