diff --git a/config/module/get_test.go b/config/module/get_test.go index e01312b18..c468653c2 100644 --- a/config/module/get_test.go +++ b/config/module/get_test.go @@ -16,7 +16,6 @@ import ( version "github.com/hashicorp/go-version" "github.com/hashicorp/terraform/registry/regsrc" "github.com/hashicorp/terraform/registry/response" - "github.com/hashicorp/terraform/svchost/disco" ) // Map of module names and location of test modules. @@ -162,7 +161,7 @@ func mockRegHandler() http.Handler { mux.HandleFunc("/.well-known/terraform.json", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") - io.WriteString(w, `{"modules.v1":"/v1/modules/"}`) + io.WriteString(w, `{"modules.v1":"http://localhost/v1/modules/"}`) }) return mux } @@ -174,26 +173,16 @@ func mockRegistry() *httptest.Server { return server } -func mockTLSRegistry() *httptest.Server { - server := httptest.NewTLSServer(mockRegHandler()) - return server -} - // GitHub archives always contain the module source in a single subdirectory, // so the registry will return a path with with a `//*` suffix. We need to make // sure this doesn't intefere with our internal handling of `//` subdir. func TestRegistryGitHubArchive(t *testing.T) { - server := mockTLSRegistry() + server := mockRegistry() defer server.Close() - d := regDisco - regDisco = disco.NewDisco() - regDisco.Transport = mockTransport(server) - defer func() { - regDisco = d - }() + disco := testDisco(server) + storage := testStorage(t, disco) - storage := testStorage(t) tree := NewTree("", testConfig(t, "registry-tar-subdir")) storage.Mode = GetModeGet @@ -232,17 +221,11 @@ func TestRegistryGitHubArchive(t *testing.T) { // Test that the //subdir notation can be used with registry modules func TestRegisryModuleSubdir(t *testing.T) { - server := mockTLSRegistry() + server := mockRegistry() defer server.Close() - d := regDisco - regDisco = disco.NewDisco() - regDisco.Transport = mockTransport(server) - defer func() { - regDisco = d - }() - - storage := testStorage(t) + disco := testDisco(server) + storage := testStorage(t, disco) tree := NewTree("", testConfig(t, "registry-subdir")) storage.Mode = GetModeGet @@ -277,7 +260,8 @@ func TestAccRegistryDiscover(t *testing.T) { t.Fatal(err) } - loc, err := lookupModuleLocation(nil, module, "") + s := NewStorage("/tmp", nil, nil) + loc, err := s.lookupModuleLocation(module, "") if err != nil { t.Fatal(err) } @@ -301,7 +285,7 @@ func TestAccRegistryLoad(t *testing.T) { t.Skip("skipping ACC test") } - storage := testStorage(t) + storage := testStorage(t, nil) tree := NewTree("", testConfig(t, "registry-load")) storage.Mode = GetModeGet diff --git a/config/module/module_test.go b/config/module/module_test.go index 13614736c..9685f7fee 100644 --- a/config/module/module_test.go +++ b/config/module/module_test.go @@ -1,13 +1,17 @@ package module import ( + "fmt" "io/ioutil" "log" + "net/http/httptest" "os" "path/filepath" "testing" "github.com/hashicorp/terraform/config" + "github.com/hashicorp/terraform/svchost" + "github.com/hashicorp/terraform/svchost/disco" ) func init() { @@ -41,7 +45,22 @@ func testConfig(t *testing.T, n string) *config.Config { return c } -func testStorage(t *testing.T) *Storage { +func testStorage(t *testing.T, d *disco.Disco) *Storage { t.Helper() - return &Storage{StorageDir: tempDir(t)} + return NewStorage(tempDir(t), d, nil) +} + +// test discovery maps registry.terraform.io, localhost, localhost.localdomain, +// and example.com to the test server. +func testDisco(s *httptest.Server) *disco.Disco { + services := map[string]interface{}{ + "modules.v1": fmt.Sprintf("%s/v1/modules/", s.URL), + } + d := disco.NewDisco() + + d.ForceHostServices(svchost.Hostname("registry.terraform.io"), services) + d.ForceHostServices(svchost.Hostname("localhost"), services) + d.ForceHostServices(svchost.Hostname("localhost.localdomain"), services) + d.ForceHostServices(svchost.Hostname("example.com"), services) + return d } diff --git a/config/module/registry.go b/config/module/registry.go index b9ca08c8d..eb236cc0e 100644 --- a/config/module/registry.go +++ b/config/module/registry.go @@ -16,7 +16,6 @@ import ( "github.com/hashicorp/terraform/registry/regsrc" "github.com/hashicorp/terraform/registry/response" "github.com/hashicorp/terraform/svchost" - "github.com/hashicorp/terraform/svchost/disco" "github.com/hashicorp/terraform/version" ) @@ -33,7 +32,6 @@ const ( var ( httpClient *http.Client tfVersion = version.String() - regDisco = disco.NewDisco() ) func init() { @@ -47,16 +45,8 @@ func (e errModuleNotFound) Error() string { return `module "` + string(e) + `" not found` } -func discoverRegURL(d *disco.Disco, module *regsrc.Module) *url.URL { - if d == nil { - d = regDisco - } - - if module.RawHost == nil { - module.RawHost = regsrc.NewFriendlyHost(defaultRegistry) - } - - regURL := d.DiscoverServiceURL(svchost.Hostname(module.RawHost.Normalized()), serviceID) +func (s *Storage) discoverRegURL(module *regsrc.Module) *url.URL { + regURL := s.Services.DiscoverServiceURL(svchost.Hostname(module.RawHost.Normalized()), serviceID) if regURL == nil { regURL = &url.URL{ Scheme: "https", @@ -72,9 +62,29 @@ func discoverRegURL(d *disco.Disco, module *regsrc.Module) *url.URL { return regURL } +func (s *Storage) addRequestCreds(host svchost.Hostname, req *http.Request) { + if s.Creds == nil { + return + } + + creds, err := s.Creds.ForHost(host) + if err != nil { + log.Printf("[WARNING] Failed to get credentials for %s: %s (ignoring)", host, err) + return + } + + if creds != nil { + creds.PrepareRequest(req) + } +} + // Lookup module versions in the registry. -func lookupModuleVersions(d *disco.Disco, module *regsrc.Module) (*response.ModuleVersions, error) { - service := discoverRegURL(d, module) +func (s *Storage) lookupModuleVersions(module *regsrc.Module) (*response.ModuleVersions, error) { + if module.RawHost == nil { + module.RawHost = regsrc.NewFriendlyHost(defaultRegistry) + } + + service := s.discoverRegURL(module) p, err := url.Parse(path.Join(module.Module(), "versions")) if err != nil { @@ -90,22 +100,10 @@ func lookupModuleVersions(d *disco.Disco, module *regsrc.Module) (*response.Modu return nil, err } + s.addRequestCreds(svchost.Hostname(module.RawHost.Normalized()), req) req.Header.Set(xTerraformVersion, tfVersion) - if d == nil { - d = regDisco - } - - // if discovery required a custom transport, then we should use that too - client := httpClient - if d.Transport != nil { - client = &http.Client{ - Transport: d.Transport, - Timeout: requestTimeout, - } - } - - resp, err := client.Do(req) + resp, err := httpClient.Do(req) if err != nil { return nil, err } @@ -131,8 +129,12 @@ func lookupModuleVersions(d *disco.Disco, module *regsrc.Module) (*response.Modu } // lookup the location of a specific module version in the registry -func lookupModuleLocation(d *disco.Disco, module *regsrc.Module, version string) (string, error) { - service := discoverRegURL(d, module) +func (s *Storage) lookupModuleLocation(module *regsrc.Module, version string) (string, error) { + if module.RawHost == nil { + module.RawHost = regsrc.NewFriendlyHost(defaultRegistry) + } + + service := s.discoverRegURL(module) var p *url.URL var err error @@ -155,16 +157,7 @@ func lookupModuleLocation(d *disco.Disco, module *regsrc.Module, version string) req.Header.Set(xTerraformVersion, tfVersion) - // if discovery required a custom transport, then we should use that too - client := httpClient - if regDisco.Transport != nil { - client = &http.Client{ - Transport: regDisco.Transport, - Timeout: requestTimeout, - } - } - - resp, err := client.Do(req) + resp, err := httpClient.Do(req) if err != nil { return "", err } diff --git a/config/module/registry_test.go b/config/module/registry_test.go index 6387c1812..ec2ae77a5 100644 --- a/config/module/registry_test.go +++ b/config/module/registry_test.go @@ -1,75 +1,19 @@ package module import ( - "context" - "net" - "net/http" - "net/http/httptest" - "net/url" "os" "testing" - "time" - cleanhttp "github.com/hashicorp/go-cleanhttp" version "github.com/hashicorp/go-version" "github.com/hashicorp/terraform/registry/regsrc" "github.com/hashicorp/terraform/svchost/disco" ) -// Return a transport to use for this test server. -// This not only loads the tls.Config from the test server for proper cert -// validation, but also inserts a Dialer that resolves localhost and -// example.com to 127.0.0.1 with the correct port, since 127.0.0.1 on its own -// isn't a valid registry hostname. -// TODO: cert validation not working here, so we use don't verify for now. -func mockTransport(server *httptest.Server) *http.Transport { - u, _ := url.Parse(server.URL) - _, port, _ := net.SplitHostPort(u.Host) - - transport := cleanhttp.DefaultTransport() - transport.TLSClientConfig = server.TLS - transport.TLSClientConfig.InsecureSkipVerify = true - transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { - host, _, _ := net.SplitHostPort(addr) - switch host { - case "example.com", "localhost", "localhost.localdomain", "registry.terraform.io": - addr = "127.0.0.1" - if port != "" { - addr += ":" + port - } - } - return (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - DualStack: true, - }).DialContext(ctx, network, addr) - } - return transport -} - -func TestMockDiscovery(t *testing.T) { - server := mockTLSRegistry() - defer server.Close() - - regDisco := disco.NewDisco() - regDisco.Transport = mockTransport(server) - - regURL := regDisco.DiscoverServiceURL("example.com", serviceID) - - if regURL == nil { - t.Fatal("no registry service discovered") - } - - if regURL.Host != "example.com" { - t.Fatal("expected registry host example.com, got:", regURL.Host) - } -} - func TestLookupModuleVersions(t *testing.T) { - server := mockTLSRegistry() + server := mockRegistry() defer server.Close() - regDisco := disco.NewDisco() - regDisco.Transport = mockTransport(server) + + regDisco := testDisco(server) // test with and without a hostname for _, src := range []string{ @@ -81,7 +25,8 @@ func TestLookupModuleVersions(t *testing.T) { t.Fatal(err) } - resp, err := lookupModuleVersions(regDisco, modsrc) + s := &Storage{Services: regDisco} + resp, err := s.lookupModuleVersions(modsrc) if err != nil { t.Fatal(err) } @@ -125,7 +70,10 @@ func TestAccLookupModuleVersions(t *testing.T) { t.Fatal(err) } - resp, err := lookupModuleVersions(regDisco, modsrc) + s := &Storage{ + Services: regDisco, + } + resp, err := s.lookupModuleVersions(modsrc) if err != nil { t.Fatal(err) } diff --git a/config/module/storage.go b/config/module/storage.go index 6bec91be9..318c5d36a 100644 --- a/config/module/storage.go +++ b/config/module/storage.go @@ -10,6 +10,7 @@ import ( getter "github.com/hashicorp/go-getter" "github.com/hashicorp/terraform/registry/regsrc" + "github.com/hashicorp/terraform/svchost/auth" "github.com/hashicorp/terraform/svchost/disco" "github.com/mitchellh/cli" ) @@ -55,26 +56,44 @@ type moduleRecord struct { registry bool } -// Storage implements methods to record and fetch metadata about the -// modules that have been fetched and stored locally. The getter.Storgae -// abstraction doesn't provide the information needed to know which versions of -// a module have been stored, or their location. +// Storage implements methods to manage the storage of modules. +// This is used by Tree.Load to query registries, authenticate requests, and +// store modules locally. type Storage struct { - // StorageDir is the directory where all modules will be stored. + // StorageDir is the full path to the directory where all modules will be + // stored. StorageDir string - // Services is a *Disco which ay have services and credentials pre-loaded. + // 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 } +func NewStorage(dir string, services *disco.Disco, creds auth.CredentialsSource) *Storage { + s := &Storage{ + StorageDir: dir, + Services: services, + Creds: creds, + } + + // make sure this isn't nil + if s.Services == nil { + s.Services = disco.NewDisco() + } + return s +} + // loadManifest returns the moduleManifest file from the parent directory. -func (m Storage) loadManifest() (moduleManifest, error) { +func (s Storage) loadManifest() (moduleManifest, error) { manifest := moduleManifest{} - manifestPath := filepath.Join(m.StorageDir, manifestName) + manifestPath := filepath.Join(s.StorageDir, manifestName) data, err := ioutil.ReadFile(manifestPath) if err != nil && !os.IsNotExist(err) { return manifest, err @@ -94,8 +113,8 @@ func (m Storage) loadManifest() (moduleManifest, error) { // root directory. The storage method loads the entire file and rewrites it // each time. This is only done a few times during init, so efficiency is // not a concern. -func (m Storage) recordModule(rec moduleRecord) error { - manifest, err := m.loadManifest() +func (s Storage) recordModule(rec moduleRecord) error { + manifest, err := s.loadManifest() if err != nil { // if there was a problem with the file, we will attempt to write a new // one. Any non-data related error should surface there. @@ -124,15 +143,15 @@ func (m Storage) recordModule(rec moduleRecord) error { panic(err) } - manifestPath := filepath.Join(m.StorageDir, manifestName) + manifestPath := filepath.Join(s.StorageDir, manifestName) return ioutil.WriteFile(manifestPath, js, 0644) } // load the manifest from dir, and return all module versions matching the // provided source. Records with no version info will be skipped, as they need // to be uniquely identified by other means. -func (m Storage) moduleVersions(source string) ([]moduleRecord, error) { - manifest, err := m.loadManifest() +func (s Storage) moduleVersions(source string) ([]moduleRecord, error) { + manifest, err := s.loadManifest() if err != nil { return manifest.Modules, err } @@ -148,8 +167,8 @@ func (m Storage) moduleVersions(source string) ([]moduleRecord, error) { return matching, nil } -func (m Storage) moduleDir(key string) (string, error) { - manifest, err := m.loadManifest() +func (s Storage) moduleDir(key string) (string, error) { + manifest, err := s.loadManifest() if err != nil { return "", err } @@ -164,8 +183,8 @@ func (m Storage) moduleDir(key string) (string, error) { } // return only the root directory of the module stored in dir. -func (m Storage) getModuleRoot(dir string) (string, error) { - manifest, err := m.loadManifest() +func (s Storage) getModuleRoot(dir string) (string, error) { + manifest, err := s.loadManifest() if err != nil { return "", err } @@ -179,33 +198,32 @@ func (m Storage) getModuleRoot(dir string) (string, error) { } // record only the Root directory for the module stored at dir. -// TODO: remove this compatibility function to store the full moduleRecord. -func (m Storage) recordModuleRoot(dir, root string) error { +func (s Storage) recordModuleRoot(dir, root string) error { rec := moduleRecord{ Dir: dir, Root: root, } - return m.recordModule(rec) + return s.recordModule(rec) } -func (m Storage) getStorage(key string, src string) (string, bool, error) { +func (s Storage) getStorage(key string, src string) (string, bool, error) { storage := &getter.FolderStorage{ - StorageDir: m.StorageDir, + StorageDir: s.StorageDir, } - if m.Ui != nil { + if s.Ui != nil { update := "" - if m.Mode == GetModeUpdate { + if s.Mode == GetModeUpdate { update = " (update)" } - m.Ui.Output(fmt.Sprintf("Get: %s%s", src, update)) + s.Ui.Output(fmt.Sprintf("Get: %s%s", src, update)) } // Get the module with the level specified if we were told to. - if m.Mode > GetModeNone { + if s.Mode > GetModeNone { log.Printf("[DEBUG] fetching %q with key %q", src, key) - if err := storage.Get(key, src, m.Mode == GetModeUpdate); err != nil { + if err := storage.Get(key, src, s.Mode == GetModeUpdate); err != nil { return "", false, err } } @@ -217,16 +235,16 @@ func (m Storage) getStorage(key string, src string) (string, bool, error) { } // find a stored module that's not from a registry -func (m Storage) findModule(key string) (string, error) { - if m.Mode == GetModeUpdate { +func (s Storage) findModule(key string) (string, error) { + if s.Mode == GetModeUpdate { return "", nil } - return m.moduleDir(key) + return s.moduleDir(key) } // find a registry module -func (m Storage) findRegistryModule(mSource, constraint string) (moduleRecord, error) { +func (s Storage) findRegistryModule(mSource, constraint string) (moduleRecord, error) { rec := moduleRecord{ Source: mSource, } @@ -244,7 +262,7 @@ func (m Storage) findRegistryModule(mSource, constraint string) (moduleRecord, e log.Printf("[TRACE] %q is a registry module", mod.Module()) - versions, err := m.moduleVersions(mod.String()) + versions, err := s.moduleVersions(mod.String()) if err != nil { log.Printf("[ERROR] error looking up versions for %q: %s", mod.Module(), err) return rec, err @@ -252,7 +270,6 @@ func (m Storage) findRegistryModule(mSource, constraint string) (moduleRecord, e match, err := newestRecord(versions, constraint) if err != nil { - // TODO: does this allow previously unversioned modules? log.Printf("[INFO] no matching version for %q<%s>, %s", mod.Module(), constraint, err) } @@ -262,8 +279,8 @@ func (m Storage) findRegistryModule(mSource, constraint string) (moduleRecord, e // we need to lookup available versions // Only on Get if it's not found, on unconditionally on Update - if (m.Mode == GetModeGet && !found) || (m.Mode == GetModeUpdate) { - resp, err := lookupModuleVersions(nil, mod) + if (s.Mode == GetModeGet && !found) || (s.Mode == GetModeUpdate) { + resp, err := s.lookupModuleVersions(mod) if err != nil { return rec, err } @@ -283,7 +300,7 @@ func (m Storage) findRegistryModule(mSource, constraint string) (moduleRecord, e rec.Version = match.Version - rec.url, err = lookupModuleLocation(nil, mod, rec.Version) + rec.url, err = s.lookupModuleLocation(mod, rec.Version) if err != nil { return rec, err } diff --git a/config/module/tree_gob_test.go b/config/module/tree_gob_test.go index ad0ab4ecd..1d2d7d5b5 100644 --- a/config/module/tree_gob_test.go +++ b/config/module/tree_gob_test.go @@ -8,7 +8,7 @@ import ( ) func TestTreeEncodeDecodeGob(t *testing.T) { - storage := testStorage(t) + storage := testStorage(t, nil) tree := NewTree("", testConfig(t, "basic")) // This should get things diff --git a/config/module/tree_test.go b/config/module/tree_test.go index 780023b7d..2e23f1aad 100644 --- a/config/module/tree_test.go +++ b/config/module/tree_test.go @@ -20,7 +20,7 @@ func TestTreeChild(t *testing.T) { t.Fatal("child should be nil") } - storage := testStorage(t) + storage := testStorage(t, nil) storage.Mode = GetModeGet tree := NewTree("", testConfig(t, "child")) if err := tree.Load(storage); err != nil { @@ -65,7 +65,7 @@ func TestTreeChild(t *testing.T) { } func TestTreeLoad(t *testing.T) { - storage := testStorage(t) + storage := testStorage(t, nil) tree := NewTree("", testConfig(t, "basic")) if tree.Loaded() { @@ -105,7 +105,7 @@ func TestTreeLoad(t *testing.T) { } func TestTreeLoad_duplicate(t *testing.T) { - storage := testStorage(t) + storage := testStorage(t, nil) tree := NewTree("", testConfig(t, "dup")) if tree.Loaded() { @@ -184,7 +184,7 @@ func TestTreeLoad_copyable(t *testing.T) { } func TestTreeLoad_parentRef(t *testing.T) { - storage := testStorage(t) + storage := testStorage(t, nil) tree := NewTree("", testConfig(t, "basic-parent")) if tree.Loaded() { @@ -228,17 +228,12 @@ func TestTreeLoad_subdir(t *testing.T) { fixtures := []string{ "basic-subdir", "basic-tar-subdir", - - // Passing a subpath to go getter extracts only this subpath. The old - // internal code would keep the entire directory structure, allowing a - // top-level module to reference others through its parent directory. - // TODO: this can be removed as a breaking change in a major release. "tar-subdir-to-parent", } for _, tc := range fixtures { t.Run(tc, func(t *testing.T) { - storage := testStorage(t) + storage := testStorage(t, nil) tree := NewTree("", testConfig(t, tc)) if tree.Loaded() { @@ -404,7 +399,7 @@ func TestTreeValidate_table(t *testing.T) { for i, tc := range cases { t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) { tree := NewTree("", testConfig(t, tc.Fixture)) - storage := testStorage(t) + storage := testStorage(t, nil) storage.Mode = GetModeGet if err := tree.Load(storage); err != nil { t.Fatalf("err: %s", err) @@ -427,7 +422,7 @@ func TestTreeValidate_table(t *testing.T) { func TestTreeValidate_badChild(t *testing.T) { tree := NewTree("", testConfig(t, "validate-child-bad")) - storage := testStorage(t) + storage := testStorage(t, nil) storage.Mode = GetModeGet if err := tree.Load(storage); err != nil { t.Fatalf("err: %s", err) @@ -441,7 +436,7 @@ func TestTreeValidate_badChild(t *testing.T) { func TestTreeValidate_badChildOutput(t *testing.T) { tree := NewTree("", testConfig(t, "validate-bad-output")) - storage := testStorage(t) + storage := testStorage(t, nil) storage.Mode = GetModeGet if err := tree.Load(storage); err != nil { t.Fatalf("err: %s", err) @@ -455,7 +450,7 @@ func TestTreeValidate_badChildOutput(t *testing.T) { func TestTreeValidate_badChildOutputToModule(t *testing.T) { tree := NewTree("", testConfig(t, "validate-bad-output-to-module")) - storage := testStorage(t) + storage := testStorage(t, nil) storage.Mode = GetModeGet if err := tree.Load(storage); err != nil { t.Fatalf("err: %s", err) @@ -469,7 +464,7 @@ func TestTreeValidate_badChildOutputToModule(t *testing.T) { func TestTreeValidate_badChildVar(t *testing.T) { tree := NewTree("", testConfig(t, "validate-bad-var")) - storage := testStorage(t) + storage := testStorage(t, nil) storage.Mode = GetModeGet if err := tree.Load(storage); err != nil { t.Fatalf("err: %s", err) @@ -483,7 +478,7 @@ func TestTreeValidate_badChildVar(t *testing.T) { func TestTreeValidate_badRoot(t *testing.T) { tree := NewTree("", testConfig(t, "validate-root-bad")) - storage := testStorage(t) + storage := testStorage(t, nil) storage.Mode = GetModeGet if err := tree.Load(storage); err != nil { t.Fatalf("err: %s", err) @@ -497,7 +492,7 @@ func TestTreeValidate_badRoot(t *testing.T) { func TestTreeValidate_good(t *testing.T) { tree := NewTree("", testConfig(t, "validate-child-good")) - storage := testStorage(t) + storage := testStorage(t, nil) storage.Mode = GetModeGet if err := tree.Load(storage); err != nil { t.Fatalf("err: %s", err) @@ -519,7 +514,7 @@ func TestTreeValidate_notLoaded(t *testing.T) { func TestTreeValidate_requiredChildVar(t *testing.T) { tree := NewTree("", testConfig(t, "validate-required-var")) - storage := testStorage(t) + storage := testStorage(t, nil) storage.Mode = GetModeGet if err := tree.Load(storage); err != nil { t.Fatalf("err: %s", err) @@ -542,7 +537,7 @@ func TestTreeValidate_requiredChildVar(t *testing.T) { func TestTreeValidate_unknownModule(t *testing.T) { tree := NewTree("", testConfig(t, "validate-module-unknown")) - storage := testStorage(t) + storage := testStorage(t, nil) storage.Mode = GetModeNone if err := tree.Load(storage); err != nil { t.Fatalf("err: %s", err) @@ -554,7 +549,7 @@ func TestTreeValidate_unknownModule(t *testing.T) { } func TestTreeProviders_basic(t *testing.T) { - storage := testStorage(t) + storage := testStorage(t, nil) tree := NewTree("", testConfig(t, "basic-parent-providers")) storage.Mode = GetModeGet @@ -617,7 +612,7 @@ func TestTreeProviders_basic(t *testing.T) { } func TestTreeProviders_implicit(t *testing.T) { - storage := testStorage(t) + storage := testStorage(t, nil) tree := NewTree("", testConfig(t, "implicit-parent-providers")) storage.Mode = GetModeGet @@ -658,7 +653,7 @@ func TestTreeProviders_implicit(t *testing.T) { } func TestTreeProviders_implicitMultiLevel(t *testing.T) { - storage := testStorage(t) + storage := testStorage(t, nil) tree := NewTree("", testConfig(t, "implicit-grandparent-providers")) storage.Mode = GetModeGet @@ -728,7 +723,7 @@ func TestTreeProviders_implicitMultiLevel(t *testing.T) { } func TestTreeLoad_conflictingSubmoduleNames(t *testing.T) { - storage := testStorage(t) + storage := testStorage(t, nil) tree := NewTree("", testConfig(t, "conficting-submodule-names")) storage.Mode = GetModeGet