mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-24 16:10:46 -06:00
main: Honor explicit provider_installation CLI config when present
If the CLI configuration contains a provider_installation block then we'll use the source configuration it describes instead of the implied one we'd build otherwise.
This commit is contained in:
parent
c5bd783eba
commit
5af1e6234a
18
main.go
18
main.go
@ -127,6 +127,7 @@ func wrappedMain() int {
|
||||
log.Printf("[INFO] CLI args: %#v", os.Args)
|
||||
|
||||
config, diags := cliconfig.LoadConfig()
|
||||
|
||||
if len(diags) > 0 {
|
||||
// Since we haven't instantiated a command.Meta yet, we need to do
|
||||
// some things manually here and use some "safe" defaults for things
|
||||
@ -168,7 +169,22 @@ func wrappedMain() int {
|
||||
// direct from a registry. In future there should be a mechanism to
|
||||
// configure providers sources from the CLI config, which will then
|
||||
// change how we construct this object.
|
||||
providerSrc := providerSource(services)
|
||||
providerSrc, diags := providerSource(config.ProviderInstallation, services)
|
||||
if len(diags) > 0 {
|
||||
Ui.Error("There are some problems with the provider_installation configuration:")
|
||||
for _, diag := range diags {
|
||||
earlyColor := &colorstring.Colorize{
|
||||
Colors: colorstring.DefaultColors,
|
||||
Disable: true, // Disable color to be conservative until we know better
|
||||
Reset: true,
|
||||
}
|
||||
Ui.Error(format.Diagnostic(diag, nil, earlyColor, 78))
|
||||
}
|
||||
if diags.HasErrors() {
|
||||
Ui.Error("As a result of the above problems, Terraform's provider installer may not behave as intended.\n\n")
|
||||
// We continue to run anyway, because most commands don't do provider installation.
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the backends.
|
||||
backendInit.Init(services)
|
||||
|
@ -1,28 +1,76 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/apparentlymart/go-userdirs/userdirs"
|
||||
svchost "github.com/hashicorp/terraform-svchost"
|
||||
"github.com/hashicorp/terraform-svchost/disco"
|
||||
|
||||
"github.com/hashicorp/terraform/addrs"
|
||||
"github.com/hashicorp/terraform/command/cliconfig"
|
||||
"github.com/hashicorp/terraform/internal/getproviders"
|
||||
"github.com/hashicorp/terraform/tfdiags"
|
||||
)
|
||||
|
||||
// providerSource constructs a provider source based on a combination of the
|
||||
// CLI configuration and some default search locations. This will be the
|
||||
// provider source used for provider installation in the "terraform init"
|
||||
// command, unless overridden by the special -plugin-dir option.
|
||||
func providerSource(services *disco.Disco) getproviders.Source {
|
||||
// We're not yet using the CLI config here because we've not implemented
|
||||
// yet the new configuration constructs to customize provider search
|
||||
// locations. That'll come later. For now, we just always use the
|
||||
// implicit default provider source.
|
||||
return implicitProviderSource(services)
|
||||
func providerSource(configs []*cliconfig.ProviderInstallation, services *disco.Disco) (getproviders.Source, tfdiags.Diagnostics) {
|
||||
if len(configs) == 0 {
|
||||
// If there's no explicit installation configuration then we'll build
|
||||
// up an implicit one with direct registry installation along with
|
||||
// some automatically-selected local filesystem mirrors.
|
||||
return implicitProviderSource(services), nil
|
||||
}
|
||||
|
||||
// There should only be zero or one configurations, which is checked by
|
||||
// the validation logic in the cliconfig package. Therefore we'll just
|
||||
// ignore any additional configurations in here.
|
||||
config := configs[0]
|
||||
return explicitProviderSource(config, services)
|
||||
}
|
||||
|
||||
func explicitProviderSource(config *cliconfig.ProviderInstallation, services *disco.Disco) (getproviders.Source, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
var searchRules []getproviders.MultiSourceSelector
|
||||
|
||||
for _, sourceConfig := range config.Sources {
|
||||
source, moreDiags := providerSourceForCLIConfigLocation(sourceConfig.Location, services)
|
||||
diags = diags.Append(moreDiags)
|
||||
if moreDiags.HasErrors() {
|
||||
continue
|
||||
}
|
||||
|
||||
include, err := getproviders.ParseMultiSourceMatchingPatterns(sourceConfig.Include)
|
||||
if err != nil {
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Error,
|
||||
"Invalid provider source inclusion patterns",
|
||||
fmt.Sprintf("CLI config specifies invalid provider inclusion patterns: %s.", err),
|
||||
))
|
||||
}
|
||||
exclude, err := getproviders.ParseMultiSourceMatchingPatterns(sourceConfig.Include)
|
||||
if err != nil {
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Error,
|
||||
"Invalid provider source exclusion patterns",
|
||||
fmt.Sprintf("CLI config specifies invalid provider exclusion patterns: %s.", err),
|
||||
))
|
||||
}
|
||||
|
||||
searchRules = append(searchRules, getproviders.MultiSourceSelector{
|
||||
Source: source,
|
||||
Include: include,
|
||||
Exclude: exclude,
|
||||
})
|
||||
}
|
||||
|
||||
return getproviders.MultiSource(searchRules), diags
|
||||
}
|
||||
|
||||
// implicitProviderSource builds a default provider source to use if there's
|
||||
@ -130,3 +178,36 @@ func implicitProviderSource(services *disco.Disco) getproviders.Source {
|
||||
|
||||
return getproviders.MultiSource(searchRules)
|
||||
}
|
||||
|
||||
func providerSourceForCLIConfigLocation(loc cliconfig.ProviderInstallationSourceLocation, services *disco.Disco) (getproviders.Source, tfdiags.Diagnostics) {
|
||||
if loc == cliconfig.ProviderInstallationDirect {
|
||||
return getproviders.NewMemoizeSource(
|
||||
getproviders.NewRegistrySource(services),
|
||||
), nil
|
||||
}
|
||||
|
||||
switch loc := loc.(type) {
|
||||
|
||||
case cliconfig.ProviderInstallationFilesystemMirror:
|
||||
return getproviders.NewFilesystemMirrorSource(string(loc)), nil
|
||||
|
||||
case cliconfig.ProviderInstallationNetworkMirror:
|
||||
host, err := svchost.ForComparison(string(loc))
|
||||
if err != nil {
|
||||
var diags tfdiags.Diagnostics
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Error,
|
||||
"Invalid hostname for provider installation source",
|
||||
fmt.Sprintf("Cannot parse %q as a hostname for a network provider mirror: %s.", string(loc), err),
|
||||
))
|
||||
return nil, diags
|
||||
}
|
||||
return getproviders.NewNetworkMirrorSource(host), nil
|
||||
|
||||
default:
|
||||
// We should not get here because the set of cases above should
|
||||
// be comprehensive for all of the
|
||||
// cliconfig.ProviderInstallationLocation implementations.
|
||||
panic(fmt.Sprintf("unexpected provider source location type %T", loc))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user