github.com/paultyng/terraform@v0.6.11-0.20180227224804-66ff8f8bed40/configs/configload/loader_load.go (about) 1 package configload 2 3 import ( 4 "fmt" 5 6 version "github.com/hashicorp/go-version" 7 "github.com/hashicorp/hcl2/hcl" 8 "github.com/hashicorp/terraform/configs" 9 ) 10 11 // LoadConfig reads the Terraform module in the given directory and uses it as the 12 // root module to build the static module tree that represents a configuration, 13 // assuming that all required descendent modules have already been installed. 14 // 15 // If error diagnostics are returned, the returned configuration may be either 16 // nil or incomplete. In the latter case, cautious static analysis is possible 17 // in spite of the errors. 18 // 19 // LoadConfig performs the basic syntax and uniqueness validations that are 20 // required to process the individual modules, and also detects 21 func (l *Loader) LoadConfig(rootDir string) (*configs.Config, hcl.Diagnostics) { 22 rootMod, diags := l.parser.LoadConfigDir(rootDir) 23 if rootMod == nil { 24 return nil, diags 25 } 26 27 cfg, cDiags := configs.BuildConfig(rootMod, configs.ModuleWalkerFunc(l.moduleWalkerLoad)) 28 diags = append(diags, cDiags...) 29 30 return cfg, diags 31 } 32 33 // moduleWalkerLoad is a configs.ModuleWalkerFunc for loading modules that 34 // are presumed to have already been installed. A different function 35 // (moduleWalkerInstall) is used for installation. 36 func (l *Loader) moduleWalkerLoad(req *configs.ModuleRequest) (*configs.Module, *version.Version, hcl.Diagnostics) { 37 // Since we're just loading here, we expect that all referenced modules 38 // will be already installed and described in our manifest. However, we 39 // do verify that the manifest and the configuration are in agreement 40 // so that we can prompt the user to run "terraform init" if not. 41 42 key := manifestKey(req.Path) 43 record, exists := l.modules.manifest[key] 44 45 if !exists { 46 return nil, nil, hcl.Diagnostics{ 47 { 48 Severity: hcl.DiagError, 49 Summary: "Module not installed", 50 Detail: "This module is not yet installed. Run \"terraform init\" to install all modules required by this configuration.", 51 Subject: &req.CallRange, 52 }, 53 } 54 } 55 56 var diags hcl.Diagnostics 57 58 // Check for inconsistencies between manifest and config 59 if req.SourceAddr != record.SourceAddr { 60 diags = append(diags, &hcl.Diagnostic{ 61 Severity: hcl.DiagError, 62 Summary: "Module source has changed", 63 Detail: "The source address was changed since this module was installed. Run \"terraform init\" to install all modules required by this configuration.", 64 Subject: &req.SourceAddrRange, 65 }) 66 } 67 if !req.VersionConstraint.Required.Check(record.Version) { 68 diags = append(diags, &hcl.Diagnostic{ 69 Severity: hcl.DiagError, 70 Summary: "Module version requirements have changed", 71 Detail: fmt.Sprintf( 72 "The version requirements have changed since this module was installed and the installed version (%s) is no longer acceptable. Run \"terraform init\" to install all modules required by this configuration.", 73 record.Version, 74 ), 75 Subject: &req.SourceAddrRange, 76 }) 77 } 78 79 mod, mDiags := l.parser.LoadConfigDir(record.Dir) 80 diags = append(diags, mDiags...) 81 if mod == nil { 82 // nil specifically indicates that the directory does not exist or 83 // cannot be read, so in this case we'll discard any generic diagnostics 84 // returned from LoadConfigDir and produce our own context-sensitive 85 // error message. 86 return nil, nil, hcl.Diagnostics{ 87 { 88 Severity: hcl.DiagError, 89 Summary: "Module not installed", 90 Detail: fmt.Sprintf("This module's local cache directory %s could not be read. Run \"terraform init\" to install all modules required by this configuration.", record.Dir), 91 Subject: &req.CallRange, 92 }, 93 } 94 } 95 96 return mod, record.Version, diags 97 }