github.com/paultyng/terraform@v0.6.11-0.20180227224804-66ff8f8bed40/configs/configload/loader.go (about) 1 package configload 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/terraform/configs" 7 "github.com/hashicorp/terraform/registry" 8 "github.com/hashicorp/terraform/svchost/auth" 9 "github.com/hashicorp/terraform/svchost/disco" 10 "github.com/spf13/afero" 11 ) 12 13 // A Loader instance is the main entry-point for loading configurations via 14 // this package. 15 // 16 // It extends the general config-loading functionality in the parent package 17 // "configs" to support installation of modules from remote sources and 18 // loading full configurations using modules that were previously installed. 19 type Loader struct { 20 // parser is used to read configuration 21 parser *configs.Parser 22 23 // modules is used to install and locate descendent modules that are 24 // referenced (directly or indirectly) from the root module. 25 modules moduleMgr 26 } 27 28 // Config is used with NewLoader to specify configuration arguments for the 29 // loader. 30 type Config struct { 31 // ModulesDir is a path to a directory where descendent modules are 32 // (or should be) installed. (This is usually the 33 // .terraform/modules directory, in the common case where this package 34 // is being loaded from the main Terraform CLI package.) 35 ModulesDir string 36 37 // Services is the service discovery client to use when locating remote 38 // module registry endpoints. If this is nil then registry sources are 39 // not supported, which should be true only in specialized circumstances 40 // such as in tests. 41 Services *disco.Disco 42 43 // Creds is a credentials store for communicating with remote module 44 // registry endpoints. If this is nil then no credentials will be used. 45 Creds auth.CredentialsSource 46 } 47 48 // NewLoader creates and returns a loader that reads configuration from the 49 // real OS filesystem. 50 // 51 // The loader has some internal state about the modules that are currently 52 // installed, which is read from disk as part of this function. If that 53 // manifest cannot be read then an error will be returned. 54 func NewLoader(config *Config) (*Loader, error) { 55 fs := afero.NewOsFs() 56 parser := configs.NewParser(fs) 57 reg := registry.NewClient(config.Services, config.Creds, nil) 58 59 ret := &Loader{ 60 parser: parser, 61 modules: moduleMgr{ 62 FS: afero.Afero{Fs: fs}, 63 CanInstall: true, 64 Dir: config.ModulesDir, 65 Services: config.Services, 66 Creds: config.Creds, 67 Registry: reg, 68 }, 69 } 70 71 err := ret.modules.readModuleManifestSnapshot() 72 if err != nil { 73 return nil, fmt.Errorf("failed to read module manifest: %s", err) 74 } 75 76 return ret, nil 77 } 78 79 // Parser returns the underlying parser for this loader. 80 // 81 // This is useful for loading other sorts of files than the module directories 82 // that a loader deals with, since then they will share the source code cache 83 // for this loader and can thus be shown as snippets in diagnostic messages. 84 func (l *Loader) Parser() *configs.Parser { 85 return l.parser 86 } 87 88 // Sources returns the source code cache for the underlying parser of this 89 // loader. This is a shorthand for l.Parser().Sources(). 90 func (l *Loader) Sources() map[string][]byte { 91 return l.parser.Sources() 92 }