mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 17:59:05 -05:00
depsrccfgs: Parse source address mapping rules
This is similar to the provider address mapping rules, but for source packages. (The rest of the system currently calls these "module packages" but this is a forward-looking name in anticipation of us using these packages for other non-module artifacts in future, since this is the first time we've explicitly named this kind of package in one of our input languages so an opportunity to establish more general terminology before it's too late.) Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This commit is contained in:
@@ -69,7 +69,7 @@ func ParseProviderAddrPattern(src string) (ProviderAddrPattern, error) {
|
||||
if err != nil {
|
||||
return ret, fmt.Errorf("invalid type name %q: %w", parts[2], err)
|
||||
}
|
||||
ret.Namespace = typeName
|
||||
ret.Type = typeName
|
||||
}
|
||||
|
||||
// TODO: Verify that all of the wildcard segments are collected at the
|
||||
@@ -118,6 +118,95 @@ func (p ProviderAddrPattern) Specificity() PatternSpecificity {
|
||||
// For example, "example.com/*/*/*" is valid but "*/foo/*/*" is not.
|
||||
type SourceAddrPattern addrs.ModuleRegistryPackage
|
||||
|
||||
func ParseSourceAddrPattern(src string) (SourceAddrPattern, error) {
|
||||
ret := SourceAddrPattern{}
|
||||
|
||||
// This is largely the same as the addrs.Provider parser but additionally
|
||||
// allows "*" to appear in all positions, as long as all of the wildcard
|
||||
// parts are consecutive at the end of the address.
|
||||
parts := strings.Split(src, "/")
|
||||
if len(parts) != 4 {
|
||||
if len(parts) == 3 {
|
||||
// We don't support the shorthand that omits the hostname here,
|
||||
// to keep things as explicit as possible.
|
||||
return ret, fmt.Errorf("not enough address parts; if you intend to match packages on registry.opentofu.org then specify that prefix explicitly")
|
||||
}
|
||||
return ret, fmt.Errorf("source address pattern must have four parts")
|
||||
}
|
||||
|
||||
if parts[0] == "*" {
|
||||
ret.Host = svchost.Hostname(Wildcard)
|
||||
} else {
|
||||
hostname, err := svchost.ForComparison(parts[0])
|
||||
if err != nil {
|
||||
return ret, fmt.Errorf("invalid hostname: %w", err)
|
||||
}
|
||||
ret.Host = hostname
|
||||
}
|
||||
if parts[1] == "*" {
|
||||
ret.Namespace = Wildcard
|
||||
} else {
|
||||
// FIXME: Shouldn't be using the provider part function for module
|
||||
// address parts, because the rules are a little different.
|
||||
namespace, err := addrs.ParseProviderPart(parts[1])
|
||||
if err != nil {
|
||||
return ret, fmt.Errorf("invalid namespace %q: %w", parts[1], err)
|
||||
}
|
||||
ret.Namespace = namespace
|
||||
}
|
||||
if parts[2] == "*" {
|
||||
ret.Name = Wildcard
|
||||
} else {
|
||||
// FIXME: Shouldn't be using the provider part function for module
|
||||
// address parts, because the rules are a little different.
|
||||
typeName, err := addrs.ParseProviderPart(parts[2])
|
||||
if err != nil {
|
||||
return ret, fmt.Errorf("invalid name %q: %w", parts[2], err)
|
||||
}
|
||||
ret.Name = typeName
|
||||
}
|
||||
if parts[3] == "*" {
|
||||
ret.TargetSystem = Wildcard
|
||||
} else {
|
||||
// FIXME: Shouldn't be using the provider part function for this
|
||||
// module address parts, because it has some very different rules
|
||||
// for annoying historical reasons.
|
||||
targetSystemName, err := addrs.ParseProviderPart(parts[3])
|
||||
if err != nil {
|
||||
return ret, fmt.Errorf("invalid target system name %q: %w", parts[2], err)
|
||||
}
|
||||
ret.TargetSystem = targetSystemName
|
||||
}
|
||||
|
||||
// TODO: Verify that all of the wildcard segments are collected at the
|
||||
// suffix of the path, and return an error if not. Currently we'll
|
||||
// just accept invalid patterns with the rest of the system exhibiting
|
||||
// unspecified behavior if they are present.
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (p SourceAddrPattern) Matches(addr addrs.ModuleRegistryPackage) bool {
|
||||
switch {
|
||||
case p.Host == svchost.Hostname(Wildcard):
|
||||
return true
|
||||
case p.Host != addr.Host:
|
||||
return false
|
||||
case p.Namespace == Wildcard:
|
||||
return true
|
||||
case p.Namespace != addr.Namespace:
|
||||
return false
|
||||
case p.Name == Wildcard:
|
||||
return true
|
||||
case p.Name != addr.Name:
|
||||
return false
|
||||
case p.TargetSystem == Wildcard:
|
||||
return true
|
||||
default:
|
||||
return p.TargetSystem == addr.TargetSystem
|
||||
}
|
||||
}
|
||||
|
||||
func (p SourceAddrPattern) Specificity() PatternSpecificity {
|
||||
if p.Host == svchost.Hostname(Wildcard) {
|
||||
return 0
|
||||
|
||||
@@ -6,15 +6,448 @@
|
||||
package depsrccfgs
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/apparentlymart/go-versions/versions"
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/convert"
|
||||
"github.com/zclconf/go-cty/cty/gocty"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
)
|
||||
|
||||
type SourcePackageRule struct {
|
||||
MatchPattern SourceAddrPattern
|
||||
Mapper SourcePackageMapper
|
||||
|
||||
DeclRange hcl.Range
|
||||
}
|
||||
|
||||
func decodeSourcePackageRuleBlock(block *hcl.Block) (*SourcePackageRule, tfdiags.Diagnostics) {
|
||||
panic("unimplemented")
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
pattern, err := ParseSourceAddrPattern(block.Labels[0])
|
||||
if err != nil {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid source address pattern",
|
||||
Detail: fmt.Sprintf("Cannot parse %q as a source address pattern: %s.", block.Labels[0], err),
|
||||
Subject: block.LabelRanges[0].Ptr(),
|
||||
})
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
ret := &SourcePackageRule{
|
||||
MatchPattern: pattern,
|
||||
DeclRange: block.DefRange,
|
||||
}
|
||||
|
||||
content, hclDiags := block.Body.Content(sourcePackageRuleSchema)
|
||||
diags = diags.Append(hclDiags)
|
||||
if hclDiags.HasErrors() {
|
||||
return ret, diags
|
||||
}
|
||||
|
||||
for _, block := range content.Blocks {
|
||||
if ret.Mapper != nil {
|
||||
// Only one nested block is expected in each rule, with the type
|
||||
// specifying which mapper to use.
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Too many address mapping blocks",
|
||||
Detail: fmt.Sprintf("The mapping for this provider address pattern was already defined at %s.", ret.Mapper.DeclRange().StartString()),
|
||||
Subject: block.DefRange.Ptr(),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
switch block.Type {
|
||||
case "oci_repository":
|
||||
mapper, moreDiags := decodeSourcePackageOCIMapperBlock(block)
|
||||
diags = diags.Append(moreDiags)
|
||||
ret.Mapper = mapper
|
||||
case "git_repository":
|
||||
mapper, moreDiags := decodeSourcePackageGitMapperBlock(block)
|
||||
diags = diags.Append(moreDiags)
|
||||
ret.Mapper = mapper
|
||||
case "static":
|
||||
mapper, moreDiags := decodeSourcePackageStaticMapperBlock(block)
|
||||
diags = diags.Append(moreDiags)
|
||||
ret.Mapper = mapper
|
||||
case "direct":
|
||||
mapper, moreDiags := decodeSourcePackageDirectMapperBlock(block)
|
||||
diags = diags.Append(moreDiags)
|
||||
ret.Mapper = mapper
|
||||
default:
|
||||
panic(fmt.Sprintf("unhandled block type %q", block.Type))
|
||||
}
|
||||
}
|
||||
|
||||
if ret.Mapper == nil && !diags.HasErrors() {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Missing address mapping configuration",
|
||||
Detail: "A provider mapping block must include one nested block describing how to map each provider address to an installation method.",
|
||||
Subject: block.Body.MissingItemRange().Ptr(),
|
||||
})
|
||||
}
|
||||
|
||||
return ret, diags
|
||||
}
|
||||
|
||||
type SourcePackageMapper interface {
|
||||
DeclRange() tfdiags.SourceRange
|
||||
sourcePackageMapper() // sealed interface; implementations in this package only
|
||||
}
|
||||
|
||||
// SourcePackageStaticMapper is a transitional [SourcePackageMapper] that
|
||||
// translates directly to traditional raw source addresses at the expense
|
||||
// of forcing the author to write a list of all of the available versions
|
||||
// inline in the configuration, since raw source addresses don't have any
|
||||
// concept of versions.
|
||||
//
|
||||
// If possible it's better to use one of the other mappers that translates
|
||||
// to a system that is able to determine a list of available versions by
|
||||
// querying a remote system.
|
||||
type SourcePackageStaticMapper struct {
|
||||
// AvailableVersions is the statically-configured set of available versions,
|
||||
// used to compensate for the fact that raw source addresses don't have
|
||||
// any "list available versions" operation.
|
||||
AvailableVersions versions.List
|
||||
|
||||
// SourceAddrFunc encapsulates the process of rendering the author's
|
||||
// address template based on the module address and selected version.
|
||||
SourceAddrFunc func(addr addrs.ModuleRegistryPackage, version versions.Version) (addrs.ModuleSourceRemote, error)
|
||||
|
||||
declRange hcl.Range
|
||||
}
|
||||
|
||||
func decodeSourcePackageStaticMapperBlock(block *hcl.Block) (SourcePackageMapper, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
content, hclDiags := block.Body.Content(&hcl.BodySchema{
|
||||
Attributes: []hcl.AttributeSchema{
|
||||
{Name: "versions", Required: true},
|
||||
{Name: "source_addr", Required: true},
|
||||
},
|
||||
})
|
||||
diags = diags.Append(hclDiags)
|
||||
if hclDiags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
sourceAddrExpr := content.Attributes["source_addr"].Expr
|
||||
versionsVal, hclDiags := content.Attributes["versions"].Expr.Value(nil)
|
||||
diags = diags.Append(hclDiags)
|
||||
if hclDiags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
versionsVal, err := convert.Convert(versionsVal, cty.List(cty.String))
|
||||
if err != nil {
|
||||
// TODO: a proper diagnostic
|
||||
diags = diags.Append(err)
|
||||
return nil, diags
|
||||
}
|
||||
var versionStrs []string
|
||||
err = gocty.FromCtyValue(versionsVal, &versionStrs)
|
||||
if err != nil {
|
||||
// TODO: a proper diagnostic
|
||||
diags = diags.Append(err)
|
||||
return nil, diags
|
||||
}
|
||||
availableVersions := make(versions.List, len(versionStrs))
|
||||
for i, versionStr := range versionStrs {
|
||||
version, err := versions.ParseVersion(versionStr)
|
||||
if err != nil {
|
||||
// TODO: a proper diagnostic, ideally highlighting the specific
|
||||
// item that caused the error.
|
||||
diags = diags.Append(err)
|
||||
return nil, diags
|
||||
}
|
||||
availableVersions[i] = version
|
||||
}
|
||||
|
||||
return &SourcePackageStaticMapper{
|
||||
AvailableVersions: availableVersions,
|
||||
SourceAddrFunc: func(addr addrs.ModuleRegistryPackage, version versions.Version) (addrs.ModuleSourceRemote, error) {
|
||||
// TODO: Before returning this we should validate that the
|
||||
// template has substitutions for all of the parts of the
|
||||
// module address pattern that were wildcarded, and for
|
||||
// the version number in particular.
|
||||
hclCtx := &hcl.EvalContext{
|
||||
Variables: map[string]cty.Value{
|
||||
"hostname": cty.StringVal(addr.Host.ForDisplay()),
|
||||
"namespace": cty.StringVal(addr.Namespace),
|
||||
"name": cty.StringVal(addr.Name),
|
||||
"target_system": cty.StringVal(addr.TargetSystem),
|
||||
"version": cty.StringVal(version.String()),
|
||||
},
|
||||
}
|
||||
val, hclDiags := sourceAddrExpr.Value(hclCtx)
|
||||
if hclDiags.HasErrors() {
|
||||
// Ideally we should precheck the expression so that there are
|
||||
// as few cases as possible where we end up having to stuff
|
||||
// diagnostics into an error here. Refer to the oci_mirror
|
||||
// handling in CLI configuration for how that's done there.
|
||||
var diags tfdiags.Diagnostics
|
||||
diags = diags.Append(hclDiags)
|
||||
return addrs.ModuleSourceRemote{}, diags.Err()
|
||||
}
|
||||
var sourceAddrStr string
|
||||
err = gocty.FromCtyValue(val, &sourceAddrStr)
|
||||
if err != nil {
|
||||
return addrs.ModuleSourceRemote{}, fmt.Errorf("invalid source address value: %w", err)
|
||||
}
|
||||
src, err := addrs.ParseModuleSource(sourceAddrStr)
|
||||
if err != nil {
|
||||
return addrs.ModuleSourceRemote{}, fmt.Errorf("invalid source address value: %w", err)
|
||||
}
|
||||
remoteSrc, ok := src.(addrs.ModuleSourceRemote)
|
||||
if !ok {
|
||||
return addrs.ModuleSourceRemote{}, fmt.Errorf("invalid source address value: must specify a remote source location")
|
||||
}
|
||||
return remoteSrc, nil
|
||||
},
|
||||
}, diags
|
||||
}
|
||||
|
||||
// DeclRange implements SourcePackageMapper.
|
||||
func (m *SourcePackageStaticMapper) DeclRange() tfdiags.SourceRange {
|
||||
return tfdiags.SourceRangeFromHCL(m.declRange)
|
||||
}
|
||||
|
||||
// sourcePackageMapper implements SourcePackageMapper.
|
||||
func (m *SourcePackageStaticMapper) sourcePackageMapper() {}
|
||||
|
||||
type SourcePackageOCIMapper struct {
|
||||
RepositoryAddrFunc func(addr addrs.ModuleRegistryPackage) (registryDomain string, repositoryName string, err error)
|
||||
declRange hcl.Range
|
||||
}
|
||||
|
||||
var _ SourcePackageMapper = (*SourcePackageOCIMapper)(nil)
|
||||
|
||||
func decodeSourcePackageOCIMapperBlock(block *hcl.Block) (SourcePackageMapper, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
content, hclDiags := block.Body.Content(&hcl.BodySchema{
|
||||
Attributes: []hcl.AttributeSchema{
|
||||
{Name: "repository_addr", Required: true},
|
||||
},
|
||||
})
|
||||
diags = diags.Append(hclDiags)
|
||||
if hclDiags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
repositoryAddrExpr := content.Attributes["repository_addr"].Expr
|
||||
return &SourcePackageOCIMapper{
|
||||
RepositoryAddrFunc: func(addr addrs.ModuleRegistryPackage) (registryDomain string, repositoryName string, err error) {
|
||||
// TODO: Before returning this we should validate that the
|
||||
// template has substitutions for all of the parts of the
|
||||
// module address pattern that were wildcarded, in a similar
|
||||
// way as we do for provider oci_mirror in the CLI configuration.
|
||||
// That then allows us to reject an invalid configuration earlier
|
||||
// and return a better error message.
|
||||
hclCtx := &hcl.EvalContext{
|
||||
Variables: map[string]cty.Value{
|
||||
"hostname": cty.StringVal(addr.Host.ForDisplay()),
|
||||
"namespace": cty.StringVal(addr.Namespace),
|
||||
"name": cty.StringVal(addr.Name),
|
||||
"target_system": cty.StringVal(addr.TargetSystem),
|
||||
},
|
||||
}
|
||||
val, hclDiags := repositoryAddrExpr.Value(hclCtx)
|
||||
if hclDiags.HasErrors() {
|
||||
// Ideally we should precheck the expression so that there are
|
||||
// as few cases as possible where we end up having to stuff
|
||||
// diagnostics into an error here. Refer to the oci_mirror
|
||||
// handling in CLI configuration for how that's done there.
|
||||
var diags tfdiags.Diagnostics
|
||||
diags = diags.Append(hclDiags)
|
||||
return "", "", diags.Err()
|
||||
}
|
||||
var fullAddr string
|
||||
err = gocty.FromCtyValue(val, &fullAddr)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("invalid repository address value: %w", err)
|
||||
}
|
||||
// FIXME: There's a better parser for this in the CLI configuration package.
|
||||
registryDomain, repositoryName, _ = strings.Cut(fullAddr, "/")
|
||||
return registryDomain, repositoryName, nil
|
||||
},
|
||||
declRange: block.DefRange,
|
||||
}, diags
|
||||
}
|
||||
|
||||
// DeclRange implements SourcePackageMapper.
|
||||
func (m *SourcePackageOCIMapper) DeclRange() tfdiags.SourceRange {
|
||||
return tfdiags.SourceRangeFromHCL(m.declRange)
|
||||
}
|
||||
|
||||
// sourcePackageMapper implements SourcePackageMapper.
|
||||
func (m *SourcePackageOCIMapper) sourcePackageMapper() {}
|
||||
|
||||
type SourcePackageGitMapper struct {
|
||||
RepositoryAddrFunc func(addr addrs.ModuleRegistryPackage) (repositoryURL string, err error)
|
||||
TagPrefixFunc func(addr addrs.ModuleRegistryPackage) (tagPrefix string, err error)
|
||||
SubdirFunc func(addr addrs.ModuleRegistryPackage) (subdir string, present bool, err error)
|
||||
declRange hcl.Range
|
||||
}
|
||||
|
||||
var _ SourcePackageMapper = (*SourcePackageGitMapper)(nil)
|
||||
|
||||
func decodeSourcePackageGitMapperBlock(block *hcl.Block) (SourcePackageMapper, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
content, hclDiags := block.Body.Content(&hcl.BodySchema{
|
||||
Attributes: []hcl.AttributeSchema{
|
||||
{Name: "repository_addr", Required: true},
|
||||
{Name: "tag_prefix"},
|
||||
{Name: "subdirectory"},
|
||||
},
|
||||
})
|
||||
diags = diags.Append(hclDiags)
|
||||
if hclDiags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
makeHCLCtx := func(addr addrs.ModuleRegistryPackage) *hcl.EvalContext {
|
||||
// TODO: Before returning from the parent function we should validate
|
||||
// that the templates both have substitutions for all of the parts of
|
||||
// the module address pattern that were wildcarded, in a similar
|
||||
// way as we do for provider oci_mirror in the CLI configuration.
|
||||
// That then allows us to reject an invalid configuration earlier
|
||||
// and return a better error message.
|
||||
return &hcl.EvalContext{
|
||||
Variables: map[string]cty.Value{
|
||||
"hostname": cty.StringVal(addr.Host.ForDisplay()),
|
||||
"namespace": cty.StringVal(addr.Namespace),
|
||||
"name": cty.StringVal(addr.Name),
|
||||
"target_system": cty.StringVal(addr.TargetSystem),
|
||||
},
|
||||
}
|
||||
}
|
||||
evalExpr := func(expr hcl.Expression, addr addrs.ModuleRegistryPackage) (string, bool, error) {
|
||||
hclCtx := makeHCLCtx(addr)
|
||||
val, hclDiags := expr.Value(hclCtx)
|
||||
if hclDiags.HasErrors() {
|
||||
// Ideally we should precheck the expression so that there are
|
||||
// as few cases as possible where we end up having to stuff
|
||||
// diagnostics into an error here. Refer to the oci_mirror
|
||||
// handling in CLI configuration for how that's done there.
|
||||
var diags tfdiags.Diagnostics
|
||||
diags = diags.Append(hclDiags)
|
||||
return "", false, diags.Err()
|
||||
}
|
||||
if val.IsNull() {
|
||||
return "", false, nil
|
||||
}
|
||||
var result string
|
||||
err := gocty.FromCtyValue(val, &result)
|
||||
if err != nil {
|
||||
return "", false, fmt.Errorf("invalid value: %w", err)
|
||||
}
|
||||
return result, true, nil
|
||||
}
|
||||
|
||||
// By default we search for tags whose names simply start with "v", and
|
||||
// assume that whatever comes afterwards is inteded to be a version number.
|
||||
// Authors can override this if, for example, they have multiple
|
||||
// independently-versioned modules in the same repository and so need
|
||||
// to include some sort of per-module identifier as part of the prefix.
|
||||
tagPrefixFunc := func(addr addrs.ModuleRegistryPackage) (tagPrefix string, err error) {
|
||||
return "v", nil
|
||||
}
|
||||
if attr := content.Attributes["tag_prefix"]; attr != nil {
|
||||
tagPrefixFunc = func(addr addrs.ModuleRegistryPackage) (tagPrefix string, err error) {
|
||||
ret, present, err := evalExpr(attr.Expr, addr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !present {
|
||||
return "v", nil
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
}
|
||||
|
||||
subdirFunc := func(addr addrs.ModuleRegistryPackage) (string, bool, error) {
|
||||
return "", false, nil
|
||||
}
|
||||
if attr := content.Attributes["subdirectory"]; attr != nil {
|
||||
subdirFunc = func(addr addrs.ModuleRegistryPackage) (tagPrefix string, present bool, err error) {
|
||||
return evalExpr(attr.Expr, addr)
|
||||
}
|
||||
}
|
||||
|
||||
repositoryAddrFunc := func(addr addrs.ModuleRegistryPackage) (tagPrefix string, err error) {
|
||||
ret, present, err := evalExpr(content.Attributes["repository_addr"].Expr, addr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !present {
|
||||
return "", fmt.Errorf("repository address is required")
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
return &SourcePackageGitMapper{
|
||||
RepositoryAddrFunc: repositoryAddrFunc,
|
||||
TagPrefixFunc: tagPrefixFunc,
|
||||
SubdirFunc: subdirFunc,
|
||||
declRange: block.DefRange,
|
||||
}, diags
|
||||
}
|
||||
|
||||
// DeclRange implements SourcePackageMapper.
|
||||
func (m *SourcePackageGitMapper) DeclRange() tfdiags.SourceRange {
|
||||
return tfdiags.SourceRangeFromHCL(m.declRange)
|
||||
}
|
||||
|
||||
// sourcePackageMapper implements SourcePackageMapper.
|
||||
func (m *SourcePackageGitMapper) sourcePackageMapper() {}
|
||||
|
||||
type SourcePackageDirectMapper struct {
|
||||
// This mapper takes no arguments at all, because all of the information
|
||||
// it needs comes from the module source address and ambient service
|
||||
// discovery configuration.
|
||||
declRange hcl.Range
|
||||
}
|
||||
|
||||
var _ ProviderPackageMapper = (*ProviderPackageDirectMapper)(nil)
|
||||
|
||||
func decodeSourcePackageDirectMapperBlock(block *hcl.Block) (SourcePackageMapper, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
_, hclDiags := block.Body.Content(&hcl.BodySchema{})
|
||||
diags = diags.Append(hclDiags)
|
||||
if hclDiags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
return &SourcePackageDirectMapper{
|
||||
declRange: block.DefRange,
|
||||
}, diags
|
||||
}
|
||||
|
||||
// DeclRange implements ProviderPackageMapper.
|
||||
func (p *SourcePackageDirectMapper) DeclRange() tfdiags.SourceRange {
|
||||
return tfdiags.SourceRangeFromHCL(p.declRange)
|
||||
}
|
||||
|
||||
// providerPackageMapper implements ProviderPackageMapper.
|
||||
func (p *SourcePackageDirectMapper) sourcePackageMapper() {}
|
||||
|
||||
var sourcePackageRuleSchema = &hcl.BodySchema{
|
||||
Blocks: []hcl.BlockHeaderSchema{
|
||||
// Exactly one of the following "mapper configuration" blocks is
|
||||
// required in each provider package rule.
|
||||
{Type: "oci_repository"},
|
||||
{Type: "git_repository"},
|
||||
{Type: "static"},
|
||||
{Type: "direct"},
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user