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  }