diff --git a/commands.go b/commands.go index 5adba2277e50..ad4bb180d21e 100644 --- a/commands.go +++ b/commands.go @@ -91,7 +91,7 @@ func initCommands( View: views.NewView(streams).SetRunningInAutomation(inAutomation), Color: true, - GlobalPluginDirs: globalPluginDirs(), + GlobalPluginDirs: cliconfig.GlobalPluginDirs(), Ui: Ui, Services: services, @@ -475,6 +475,6 @@ func makeShutdownCh() <-chan struct{} { } func credentialsSource(config *cliconfig.Config) (auth.CredentialsSource, error) { - helperPlugins := pluginDiscovery.FindPlugins("credentials", globalPluginDirs()) + helperPlugins := pluginDiscovery.FindPlugins("credentials", cliconfig.GlobalPluginDirs()) return config.CredentialsSource(helperPlugins) } diff --git a/plugins.go b/internal/command/cliconfig/plugins.go similarity index 79% rename from plugins.go rename to internal/command/cliconfig/plugins.go index 4e7415f676cc..ad4cab536c6d 100644 --- a/plugins.go +++ b/internal/command/cliconfig/plugins.go @@ -1,27 +1,25 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -package main +package cliconfig import ( "fmt" "log" "path/filepath" "runtime" - - "github.com/hashicorp/terraform/internal/command/cliconfig" ) -// globalPluginDirs returns directories that should be searched for +// GlobalPluginDirs returns directories that should be searched for // globally-installed plugins (not specific to the current configuration). // // Earlier entries in this slice get priority over later when multiple copies // of the same plugin version are found, but newer versions always override // older versions where both satisfy the provider version constraints. -func globalPluginDirs() []string { +func GlobalPluginDirs() []string { var ret []string // Look in ~/.terraform.d/plugins/ , or its equivalent on non-UNIX - dir, err := cliconfig.ConfigDir() + dir, err := ConfigDir() if err != nil { log.Printf("[ERROR] Error finding global config directory: %s", err) } else { diff --git a/internal/rpcapi/credentials_source.go b/internal/rpcapi/credentials_source.go deleted file mode 100644 index c57d07f4506b..000000000000 --- a/internal/rpcapi/credentials_source.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package rpcapi - -import ( - svchost "github.com/hashicorp/terraform-svchost" - "github.com/hashicorp/terraform-svchost/auth" - "github.com/zclconf/go-cty/cty" -) - -var _ auth.CredentialsSource = &credentialsSource{} - -type credentialsSource struct { - configured map[svchost.Hostname]cty.Value -} - -func newCredentialsSource() *credentialsSource { - return &credentialsSource{ - configured: map[svchost.Hostname]cty.Value{}, - } -} - -func (c *credentialsSource) ForHost(host svchost.Hostname) (auth.HostCredentials, error) { - v, ok := c.configured[host] - if ok { - return auth.HostCredentialsFromObject(v), nil - } - return nil, nil -} - -func (c *credentialsSource) StoreForHost(host svchost.Hostname, credentials auth.HostCredentialsWritable) error { - c.configured[host] = credentials.ToStore() - return nil -} - -func (c *credentialsSource) ForgetForHost(host svchost.Hostname) error { - delete(c.configured, host) - return nil -} diff --git a/internal/rpcapi/plugin.go b/internal/rpcapi/plugin.go index 3e236f1d1ffa..adfbfd3bb678 100644 --- a/internal/rpcapi/plugin.go +++ b/internal/rpcapi/plugin.go @@ -13,6 +13,8 @@ import ( "github.com/hashicorp/terraform-svchost/disco" "google.golang.org/grpc" + "github.com/hashicorp/terraform/internal/command/cliconfig" + pluginDiscovery "github.com/hashicorp/terraform/internal/plugin/discovery" "github.com/hashicorp/terraform/internal/rpcapi/dynrpcserver" "github.com/hashicorp/terraform/internal/rpcapi/terraform1/dependencies" "github.com/hashicorp/terraform/internal/rpcapi/terraform1/packages" @@ -101,9 +103,25 @@ type serviceOpts struct { } func newServiceDisco(config *setup.Config) (*disco.Disco, error) { - services := disco.New() - credSrc := newCredentialsSource() + // First, we'll try and load any credentials that might have been available + // to the UI. It's perfectly fine if there are none so any errors we find + // are from malformed credentials rather than missing ones. + file, diags := cliconfig.LoadConfig() + if diags.HasErrors() { + return nil, fmt.Errorf("problem loading CLI configuration: %w", diags.ErrWithWarnings()) + } + + helperPlugins := pluginDiscovery.FindPlugins("credentials", cliconfig.GlobalPluginDirs()) + src, err := file.CredentialsSource(helperPlugins) + if err != nil { + return nil, fmt.Errorf("problem creating credentials source: %w", err) + } + services := disco.NewWithCredentialsSource(src) + + // Second, we'll side-load any credentials that might have been passed in. + + credSrc := services.CredentialsSource() if config != nil { for host, cred := range config.GetCredentials() { if err := credSrc.StoreForHost(svchost.Hostname(host), auth.HostCredentialsToken(cred.Token)); err != nil {