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)
|
log.Printf("[INFO] CLI args: %#v", os.Args)
|
||||||
|
|
||||||
config, diags := cliconfig.LoadConfig()
|
config, diags := cliconfig.LoadConfig()
|
||||||
|
|
||||||
if len(diags) > 0 {
|
if len(diags) > 0 {
|
||||||
// Since we haven't instantiated a command.Meta yet, we need to do
|
// Since we haven't instantiated a command.Meta yet, we need to do
|
||||||
// some things manually here and use some "safe" defaults for things
|
// 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
|
// direct from a registry. In future there should be a mechanism to
|
||||||
// configure providers sources from the CLI config, which will then
|
// configure providers sources from the CLI config, which will then
|
||||||
// change how we construct this object.
|
// 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.
|
// Initialize the backends.
|
||||||
backendInit.Init(services)
|
backendInit.Init(services)
|
||||||
|
|
|
@ -1,28 +1,76 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/apparentlymart/go-userdirs/userdirs"
|
"github.com/apparentlymart/go-userdirs/userdirs"
|
||||||
|
svchost "github.com/hashicorp/terraform-svchost"
|
||||||
"github.com/hashicorp/terraform-svchost/disco"
|
"github.com/hashicorp/terraform-svchost/disco"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/addrs"
|
"github.com/hashicorp/terraform/addrs"
|
||||||
"github.com/hashicorp/terraform/command/cliconfig"
|
"github.com/hashicorp/terraform/command/cliconfig"
|
||||||
"github.com/hashicorp/terraform/internal/getproviders"
|
"github.com/hashicorp/terraform/internal/getproviders"
|
||||||
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
)
|
)
|
||||||
|
|
||||||
// providerSource constructs a provider source based on a combination of the
|
// providerSource constructs a provider source based on a combination of the
|
||||||
// CLI configuration and some default search locations. This will be the
|
// CLI configuration and some default search locations. This will be the
|
||||||
// provider source used for provider installation in the "terraform init"
|
// provider source used for provider installation in the "terraform init"
|
||||||
// command, unless overridden by the special -plugin-dir option.
|
// command, unless overridden by the special -plugin-dir option.
|
||||||
func providerSource(services *disco.Disco) getproviders.Source {
|
func providerSource(configs []*cliconfig.ProviderInstallation, services *disco.Disco) (getproviders.Source, tfdiags.Diagnostics) {
|
||||||
// We're not yet using the CLI config here because we've not implemented
|
if len(configs) == 0 {
|
||||||
// yet the new configuration constructs to customize provider search
|
// If there's no explicit installation configuration then we'll build
|
||||||
// locations. That'll come later. For now, we just always use the
|
// up an implicit one with direct registry installation along with
|
||||||
// implicit default provider source.
|
// some automatically-selected local filesystem mirrors.
|
||||||
return implicitProviderSource(services)
|
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
|
// 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)
|
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