Skip to content

Commit

Permalink
Add a CredentialsForHost method to disco.Disco
Browse files Browse the repository at this point in the history
By adding this method you now only have to pass a `*disco.Disco` object around in order to do discovery and use any configured credentials for the discovered hosts.

Of course you can also still pass around both a `*disco.Disco` and a `auth.CredentialsSource` object if there is a need or a reason for that!
  • Loading branch information
Sander van Harmelen committed Aug 3, 2018
1 parent 495d1ea commit 179b32d
Show file tree
Hide file tree
Showing 17 changed files with 80 additions and 94 deletions.
2 changes: 1 addition & 1 deletion command/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func testModule(t *testing.T, name string) *module.Tree {
t.Fatalf("err: %s", err)
}

s := module.NewStorage(tempDir(t), nil, nil)
s := module.NewStorage(tempDir(t), nil)
s.Mode = module.GetModeGet
if err := mod.Load(s); err != nil {
t.Fatalf("err: %s", err)
Expand Down
2 changes: 1 addition & 1 deletion command/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func (c *InitCommand) Run(args []string) int {
)))
header = true

s := module.NewStorage("", c.Services, c.Credentials)
s := module.NewStorage("", c.Services)
if err := s.GetModule(path, src); err != nil {
c.Ui.Error(fmt.Sprintf("Error copying source module: %s", err))
return 1
Expand Down
7 changes: 1 addition & 6 deletions command/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"github.com/hashicorp/terraform/helper/experiment"
"github.com/hashicorp/terraform/helper/variables"
"github.com/hashicorp/terraform/helper/wrappedstreams"
"github.com/hashicorp/terraform/svchost/auth"
"github.com/hashicorp/terraform/svchost/disco"
"github.com/hashicorp/terraform/terraform"
"github.com/hashicorp/terraform/tfdiags"
Expand All @@ -51,10 +50,6 @@ type Meta struct {
// "terraform-native' services running at a specific user-facing hostname.
Services *disco.Disco

// Credentials provides access to credentials for "terraform-native"
// services, which are accessed by a service hostname.
Credentials auth.CredentialsSource

// RunningInAutomation indicates that commands are being run by an
// automated system rather than directly at a command prompt.
//
Expand Down Expand Up @@ -410,7 +405,7 @@ func (m *Meta) flagSet(n string) *flag.FlagSet {
// moduleStorage returns the module.Storage implementation used to store
// modules for commands.
func (m *Meta) moduleStorage(root string, mode module.GetMode) *module.Storage {
s := module.NewStorage(filepath.Join(root, "modules"), m.Services, m.Credentials)
s := module.NewStorage(filepath.Join(root, "modules"), m.Services)
s.Ui = m.Ui
s.Mode = mode
return s
Expand Down
8 changes: 2 additions & 6 deletions commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,12 @@ const (
OutputPrefix = "o:"
)

func initCommands(config *Config) {
func initCommands(config *Config, services *disco.Disco) {
var inAutomation bool
if v := os.Getenv(runningInAutomationEnvName); v != "" {
inAutomation = true
}

credsSrc := credentialsSource(config)
services := disco.NewDisco()
services.SetCredentialsSource(credsSrc)
for userHost, hostConfig := range config.Hosts {
host, err := svchost.ForComparison(userHost)
if err != nil {
Expand All @@ -57,8 +54,7 @@ func initCommands(config *Config) {
PluginOverrides: &PluginOverrides,
Ui: Ui,

Services: services,
Credentials: credsSrc,
Services: services,

RunningInAutomation: inAutomation,
PluginCacheDir: config.PluginCacheDir,
Expand Down
2 changes: 1 addition & 1 deletion config/module/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,5 @@ func testConfig(t *testing.T, n string) *config.Config {

func testStorage(t *testing.T, d *disco.Disco) *Storage {
t.Helper()
return NewStorage(tempDir(t), d, nil)
return NewStorage(tempDir(t), d)
}
13 changes: 4 additions & 9 deletions config/module/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
getter "github.com/hashicorp/go-getter"
"github.com/hashicorp/terraform/registry"
"github.com/hashicorp/terraform/registry/regsrc"
"github.com/hashicorp/terraform/svchost/auth"
"github.com/hashicorp/terraform/svchost/disco"
"github.com/mitchellh/cli"
)
Expand Down Expand Up @@ -64,23 +63,19 @@ type Storage struct {
// StorageDir is the full path to the directory where all modules will be
// stored.
StorageDir string
// Services is a required *disco.Disco, which may have services and
// credentials pre-loaded.
Services *disco.Disco
// Creds optionally provides credentials for communicating with service
// providers.
Creds auth.CredentialsSource

// Ui is an optional cli.Ui for user output
Ui cli.Ui

// Mode is the GetMode that will be used for various operations.
Mode GetMode

registry *registry.Client
}

// NewStorage returns a new initialized Storage object.
func NewStorage(dir string, services *disco.Disco, creds auth.CredentialsSource) *Storage {
regClient := registry.NewClient(services, creds, nil)
func NewStorage(dir string, services *disco.Disco) *Storage {
regClient := registry.NewClient(services, nil)

return &Storage{
StorageDir: dir,
Expand Down
4 changes: 2 additions & 2 deletions config/module/storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestGetModule(t *testing.T) {
t.Fatal(err)
}
defer os.RemoveAll(td)
storage := NewStorage(td, disco, nil)
storage := NewStorage(td, disco)

// this module exists in a test fixture, and is known by the test.Registry
// relative to our cwd.
Expand Down Expand Up @@ -139,7 +139,7 @@ func TestAccRegistryDiscover(t *testing.T) {
t.Fatal(err)
}

s := NewStorage("/tmp", nil, nil)
s := NewStorage("/tmp", nil)
loc, err := s.registry.Location(module, "")
if err != nil {
t.Fatal(err)
Expand Down
8 changes: 1 addition & 7 deletions configs/configload/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

"github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/registry"
"github.com/hashicorp/terraform/svchost/auth"
"github.com/hashicorp/terraform/svchost/disco"
"github.com/spf13/afero"
)
Expand Down Expand Up @@ -39,10 +38,6 @@ type Config struct {
// not supported, which should be true only in specialized circumstances
// such as in tests.
Services *disco.Disco

// Creds is a credentials store for communicating with remote module
// registry endpoints. If this is nil then no credentials will be used.
Creds auth.CredentialsSource
}

// NewLoader creates and returns a loader that reads configuration from the
Expand All @@ -54,7 +49,7 @@ type Config struct {
func NewLoader(config *Config) (*Loader, error) {
fs := afero.NewOsFs()
parser := configs.NewParser(fs)
reg := registry.NewClient(config.Services, config.Creds, nil)
reg := registry.NewClient(config.Services, nil)

ret := &Loader{
parser: parser,
Expand All @@ -63,7 +58,6 @@ func NewLoader(config *Config) (*Loader, error) {
CanInstall: true,
Dir: config.ModulesDir,
Services: config.Services,
Creds: config.Creds,
Registry: reg,
},
}
Expand Down
4 changes: 0 additions & 4 deletions configs/configload/module_mgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package configload

import (
"github.com/hashicorp/terraform/registry"
"github.com/hashicorp/terraform/svchost/auth"
"github.com/hashicorp/terraform/svchost/disco"
"github.com/spf13/afero"
)
Expand All @@ -25,9 +24,6 @@ type moduleMgr struct {
// cached discovery information.
Services *disco.Disco

// Creds provides optional credentials for communicating with service hosts.
Creds auth.CredentialsSource

// Registry is a client for the module registry protocol, which is used
// when a module is requested from a registry source.
Registry *registry.Client
Expand Down
5 changes: 4 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/terraform/command/format"
"github.com/hashicorp/terraform/helper/logging"
"github.com/hashicorp/terraform/svchost/disco"
"github.com/hashicorp/terraform/terraform"
"github.com/mattn/go-colorable"
"github.com/mattn/go-shellwords"
Expand Down Expand Up @@ -144,7 +145,9 @@ func wrappedMain() int {

// In tests, Commands may already be set to provide mock commands
if Commands == nil {
initCommands(config)
credsSrc := credentialsSource(config)
services := disco.NewWithCredentialsSource(credsSrc)
initCommands(config, services)
}

// Run checkpoint
Expand Down
18 changes: 3 additions & 15 deletions registry/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"github.com/hashicorp/terraform/registry/regsrc"
"github.com/hashicorp/terraform/registry/response"
"github.com/hashicorp/terraform/svchost"
"github.com/hashicorp/terraform/svchost/auth"
"github.com/hashicorp/terraform/svchost/disco"
"github.com/hashicorp/terraform/version"
)
Expand All @@ -37,20 +36,14 @@ type Client struct {
// services is a required *disco.Disco, which may have services and
// credentials pre-loaded.
services *disco.Disco

// Creds optionally provides credentials for communicating with service
// providers.
creds auth.CredentialsSource
}

// NewClient returns a new initialized registry client.
func NewClient(services *disco.Disco, creds auth.CredentialsSource, client *http.Client) *Client {
func NewClient(services *disco.Disco, client *http.Client) *Client {
if services == nil {
services = disco.NewDisco()
services = disco.New()
}

services.SetCredentialsSource(creds)

if client == nil {
client = httpclient.New()
client.Timeout = requestTimeout
Expand All @@ -61,7 +54,6 @@ func NewClient(services *disco.Disco, creds auth.CredentialsSource, client *http
return &Client{
client: client,
services: services,
creds: creds,
}
}

Expand Down Expand Up @@ -138,11 +130,7 @@ func (c *Client) Versions(module *regsrc.Module) (*response.ModuleVersions, erro
}

func (c *Client) addRequestCreds(host svchost.Hostname, req *http.Request) {
if c.creds == nil {
return
}

creds, err := c.creds.ForHost(host)
creds, err := c.services.CredentialsForHost(host)
if err != nil {
log.Printf("[WARN] Failed to get credentials for %s: %s (ignoring)", host, err)
return
Expand Down
35 changes: 18 additions & 17 deletions registry/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func TestLookupModuleVersions(t *testing.T) {
server := test.Registry()
defer server.Close()

client := NewClient(test.Disco(server), nil, nil)
client := NewClient(test.Disco(server), nil)

// test with and without a hostname
for _, src := range []string{
Expand Down Expand Up @@ -59,7 +59,7 @@ func TestInvalidRegistry(t *testing.T) {
server := test.Registry()
defer server.Close()

client := NewClient(test.Disco(server), nil, nil)
client := NewClient(test.Disco(server), nil)

src := "non-existent.localhost.localdomain/test-versions/name/provider"
modsrc, err := regsrc.ParseModuleSource(src)
Expand All @@ -76,41 +76,42 @@ func TestRegistryAuth(t *testing.T) {
server := test.Registry()
defer server.Close()

client := NewClient(test.Disco(server), nil, nil)
client := NewClient(test.Disco(server), nil)

src := "private/name/provider"
mod, err := regsrc.ParseModuleSource(src)
if err != nil {
t.Fatal(err)
}

// both should fail without auth
_, err = client.Versions(mod)
if err == nil {
t.Fatal("expected error")
if err != nil {
t.Fatal(err)
}
_, err = client.Location(mod, "1.0.0")
if err == nil {
t.Fatal("expected error")
if err != nil {
t.Fatal(err)
}

client = NewClient(test.Disco(server), test.Credentials, nil)
// Also test without a credentials source
client.services.SetCredentialsSource(nil)

// both should fail without auth
_, err = client.Versions(mod)
if err != nil {
t.Fatal(err)
if err == nil {
t.Fatal("expected error")
}
_, err = client.Location(mod, "1.0.0")
if err != nil {
t.Fatal(err)
if err == nil {
t.Fatal("expected error")
}
}

func TestLookupModuleLocationRelative(t *testing.T) {
server := test.Registry()
defer server.Close()

client := NewClient(test.Disco(server), nil, nil)
client := NewClient(test.Disco(server), nil)

src := "relative/foo/bar"
mod, err := regsrc.ParseModuleSource(src)
Expand All @@ -133,7 +134,7 @@ func TestAccLookupModuleVersions(t *testing.T) {
if os.Getenv("TF_ACC") == "" {
t.Skip()
}
regDisco := disco.NewDisco()
regDisco := disco.New()

// test with and without a hostname
for _, src := range []string{
Expand All @@ -145,7 +146,7 @@ func TestAccLookupModuleVersions(t *testing.T) {
t.Fatal(err)
}

s := NewClient(regDisco, nil, nil)
s := NewClient(regDisco, nil)
resp, err := s.Versions(modsrc)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -179,7 +180,7 @@ func TestLookupLookupModuleError(t *testing.T) {
server := test.Registry()
defer server.Close()

client := NewClient(test.Disco(server), nil, nil)
client := NewClient(test.Disco(server), nil)

// this should not be found in teh registry
src := "bad/local/path"
Expand Down
6 changes: 3 additions & 3 deletions registry/test/mock_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func Disco(s *httptest.Server) *disco.Disco {
// TODO: add specific tests to enumerate both possibilities.
"modules.v1": fmt.Sprintf("%s/v1/modules", s.URL),
}
d := disco.NewDisco()
d := disco.NewWithCredentialsSource(credsSrc)

d.ForceHostServices(svchost.Hostname("registry.terraform.io"), services)
d.ForceHostServices(svchost.Hostname("localhost"), services)
Expand All @@ -48,8 +48,8 @@ const (
)

var (
regHost = svchost.Hostname(regsrc.PublicRegistryHost.Normalized())
Credentials = auth.StaticCredentialsSource(map[svchost.Hostname]map[string]interface{}{
regHost = svchost.Hostname(regsrc.PublicRegistryHost.Normalized())
credsSrc = auth.StaticCredentialsSource(map[svchost.Hostname]map[string]interface{}{
regHost: {"token": testCred},
})
)
Expand Down
3 changes: 3 additions & 0 deletions svchost/auth/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ type HostCredentials interface {
// receiving credentials. The usual behavior of this method is to
// add some sort of Authorization header to the request.
PrepareRequest(req *http.Request)

// Token returns the authentication token.
Token() string
}

// ForHost iterates over the contained CredentialsSource objects and
Expand Down
5 changes: 5 additions & 0 deletions svchost/auth/token_credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ func (tc HostCredentialsToken) PrepareRequest(req *http.Request) {
}
req.Header.Set("Authorization", "Bearer "+string(tc))
}

// Token returns the authentication token.
func (tc HostCredentialsToken) Token() string {
return string(tc)
}
Loading

0 comments on commit 179b32d

Please sign in to comment.