diff --git a/config/module/storage.go b/config/module/storage.go index 318c5d36a4..730376c62e 100644 --- a/config/module/storage.go +++ b/config/module/storage.go @@ -243,6 +243,41 @@ func (s Storage) findModule(key string) (string, error) { return s.moduleDir(key) } +// GetModule fetches a module source into the specified directory. This is used +// as a convenience function by the CLI to initialize a configuration. +func (s Storage) GetModule(dst, src string) error { + // reset this in case the caller was going to re-use it + mode := s.Mode + s.Mode = GetModeUpdate + defer func() { + s.Mode = mode + }() + + rec, err := s.findRegistryModule(src, anyVersion) + if err != nil { + return err + } + + pwd, err := os.Getwd() + if err != nil { + return err + } + + source := rec.url + if source == "" { + source, err = getter.Detect(src, pwd, getter.Detectors) + if err != nil { + return fmt.Errorf("module %s: %s", src, err) + } + } + + if source == "" { + return fmt.Errorf("module %q not found", src) + } + + return GetCopy(dst, source) +} + // find a registry module func (s Storage) findRegistryModule(mSource, constraint string) (moduleRecord, error) { rec := moduleRecord{ diff --git a/config/module/storage_test.go b/config/module/storage_test.go new file mode 100644 index 0000000000..6fa1212f8a --- /dev/null +++ b/config/module/storage_test.go @@ -0,0 +1,49 @@ +package module + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" +) + +func TestGetModule(t *testing.T) { + server := mockRegistry() + defer server.Close() + disco := testDisco(server) + + td, err := ioutil.TempDir("", "tf") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(td) + storage := NewStorage(td, disco, nil) + + // this module exists in a test fixture, and is known by the mockRegistry + // relative to our cwd. + err = storage.GetModule(filepath.Join(td, "foo"), "registry/local/sub") + if err != nil { + t.Fatal(err) + } + + // list everything to make sure nothing else got unpacked in here + ls, err := ioutil.ReadDir(td) + if err != nil { + t.Fatal(err) + } + + var names []string + for _, info := range ls { + names = append(names, info.Name()) + } + + if !(len(names) == 1 && names[0] == "foo") { + t.Fatalf("expected only directory 'foo', found entries %q", names) + } + + _, err = os.Stat(filepath.Join(td, "foo", "main.tf")) + if err != nil { + t.Fatal(err) + } + +}