@ -8,6 +8,7 @@ import (
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/tfdiags"
)
// Provider represents a "provider" block in a module or file. A provider
@ -107,28 +108,82 @@ func (p *Provider) moduleUniqueKey() string {
return p . Name
}
// ProviderRequirement represents a declaration of a dependency on a particular
// provider version without actually configuring that provider. This is used in
// child modules that expect a provider to be passed in from their parent.
type ProviderRequirement struct {
Name string
Requirement VersionConstraint
// ParseProviderConfigCompact parses the given absolute traversal as a relative
// provider address in compact form. The following are examples of traversals
// that can be successfully parsed as compact relative provider configuration
// addresses:
//
// aws
// aws.foo
//
// This function will panic if given a relative traversal.
//
// If the returned diagnostics contains errors then the result value is invalid
// and must not be used.
func ParseProviderConfigCompact ( traversal hcl . Traversal ) ( addrs . ProviderConfig , tfdiags . Diagnostics ) {
var diags tfdiags . Diagnostics
ret := addrs . ProviderConfig {
Type : addrs . NewLegacyProvider ( traversal . RootName ( ) ) ,
}
if len ( traversal ) < 2 {
// Just a type 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
}
func decodeRequiredProvidersBlock ( block * hcl . Block ) ( [ ] * ProviderRequirement , hcl . Diagnostics ) {
attrs , diags := block . Body . JustAttributes ( )
var reqs [ ] * ProviderRequirement
for name , attr := range attrs {
req , reqDiags := decodeVersionConstraint ( attr )
diags = append ( diags , reqDiags ... )
if ! diags . HasErrors ( ) {
reqs = append ( reqs , & ProviderRequirement {
Name : name ,
Requirement : req ,
} )
}
// ParseProviderConfigCompactStr is a helper wrapper around ParseProviderConfigCompact
// that takes a string and parses it with the HCL native syntax traversal parser
// before interpreting it.
//
// This should be used only in specialized situations since it will cause the
// created references to not have any meaningful source location information.
// If a reference string is coming from a source that should be identified in
// error messages then the caller should instead parse it directly using a
// suitable function from the HCL API and pass the traversal itself to
// ParseProviderConfigCompact.
//
// Error diagnostics are returned if either the parsing fails or the analysis
// of the traversal fails. There is no way for the caller to distinguish the
// two kinds of diagnostics programmatically. If error diagnostics are returned
// then the returned address is invalid.
func ParseProviderConfigCompactStr ( str string ) ( addrs . ProviderConfig , tfdiags . Diagnostics ) {
var diags tfdiags . Diagnostics
traversal , parseDiags := hclsyntax . ParseTraversalAbs ( [ ] byte ( str ) , "" , hcl . Pos { Line : 1 , Column : 1 } )
diags = diags . Append ( parseDiags )
if parseDiags . HasErrors ( ) {
return addrs . ProviderConfig { } , diags
}
return reqs , diags
addr , addrDiags := ParseProviderConfigCompact ( traversal )
diags = diags . Append ( addrDiags )
return addr , diags
}
var providerBlockSchema = & hcl . BodySchema {