func (s Storage) recordModule(rec moduleRecord) error {
	manifest, err := s.loadManifest()
	if err != nil {
		log.Printf("[WARN] error reading module manifest: %s", err)
	}
	for i, stored := range manifest.Modules {
		if rec == stored {
			return nil
		}
		if rec.Dir == stored.Dir {
			manifest.Modules[i] = manifest.Modules[len(manifest.Modules)-1]
			manifest.Modules = manifest.Modules[:len(manifest.Modules)-1]
			break
		}
	}
	manifest.Modules = append(manifest.Modules, rec)
	js, err := json.Marshal(manifest)
	if err != nil {
		panic(err)
	}
	manifestPath := filepath.Join(s.StorageDir, manifestName)
	return ioutil.WriteFile(manifestPath, js, 0644)
}
Store the location of the module, along with the version used and the module
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.
package module
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	getter "github.com/hashicorp/go-getter"
	"github.com/hashicorp/terraform/registry"
	"github.com/hashicorp/terraform/registry/regsrc"
	"github.com/hashicorp/terraform/svchost/disco"
	"github.com/mitchellh/cli"
)
const manifestName = "modules.json"
type moduleManifest struct {
	Modules []moduleRecord
}
type moduleRecord struct {
	Source string
	Key string
	Version string
	Dir string
	Root string
	url string
	registry bool
}
type Storage struct {
	StorageDir string
	Ui cli.Ui
	Mode GetMode
	registry *registry.Client
}
func NewStorage(dir string, services *disco.Disco) *Storage {
	regClient := registry.NewClient(services, nil)
	return &Storage{
		StorageDir: dir,
		registry:   regClient,
	}
}
func (s Storage) loadManifest() (moduleManifest, error) {
	manifest := moduleManifest{}
	manifestPath := filepath.Join(s.StorageDir, manifestName)
	data, err := ioutil.ReadFile(manifestPath)
	if err != nil && !os.IsNotExist(err) {
		return manifest, err
	}
	if len(data) == 0 {
		return manifest, nil
	}
	if err := json.Unmarshal(data, &manifest); err != nil {
		return manifest, err
	}
	return manifest, nil
}