github.com/paultyng/terraform@v0.6.11-0.20180227224804-66ff8f8bed40/command/meta_new.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "log" 6 "os" 7 "path/filepath" 8 "strconv" 9 10 "github.com/hashicorp/errwrap" 11 "github.com/hashicorp/terraform/config" 12 "github.com/hashicorp/terraform/config/module" 13 "github.com/hashicorp/terraform/terraform" 14 "github.com/hashicorp/terraform/tfdiags" 15 ) 16 17 // NOTE: Temporary file until this branch is cleaned up. 18 19 // Input returns whether or not input asking is enabled. 20 func (m *Meta) Input() bool { 21 if test || !m.input { 22 return false 23 } 24 25 if envVar := os.Getenv(InputModeEnvVar); envVar != "" { 26 if v, err := strconv.ParseBool(envVar); err == nil && !v { 27 return false 28 } 29 } 30 31 return true 32 } 33 34 // Module loads the module tree for the given root path. 35 // 36 // It expects the modules to already be downloaded. This will never 37 // download any modules. 38 // 39 // The configuration is validated before returning, so the returned diagnostics 40 // may contain warnings and/or errors. If the diagnostics contains only 41 // warnings, the caller may treat the returned module.Tree as valid after 42 // presenting the warnings to the user. 43 func (m *Meta) Module(path string) (*module.Tree, tfdiags.Diagnostics) { 44 var diags tfdiags.Diagnostics 45 46 mod, err := module.NewTreeModule("", path) 47 if err != nil { 48 // Check for the error where we have no config files 49 if errwrap.ContainsType(err, new(config.ErrNoConfigsFound)) { 50 return nil, nil 51 } 52 53 diags = diags.Append(err) 54 return nil, diags 55 } 56 57 err = mod.Load(m.moduleStorage(m.DataDir(), module.GetModeNone)) 58 if err != nil { 59 diags = diags.Append(errwrap.Wrapf("Error loading modules: {{err}}", err)) 60 return nil, diags 61 } 62 63 diags = diags.Append(mod.Validate()) 64 65 return mod, diags 66 } 67 68 // Config loads the root config for the path specified. Path may be a directory 69 // or file. The absence of configuration is not an error and returns a nil Config. 70 func (m *Meta) Config(path string) (*config.Config, error) { 71 // If no explicit path was given then it is okay for there to be 72 // no backend configuration found. 73 emptyOk := path == "" 74 75 // If we had no path set, it is an error. We can't initialize unset 76 if path == "" { 77 path = "." 78 } 79 80 // Expand the path 81 if !filepath.IsAbs(path) { 82 var err error 83 path, err = filepath.Abs(path) 84 if err != nil { 85 return nil, fmt.Errorf( 86 "Error expanding path to backend config %q: %s", path, err) 87 } 88 } 89 90 log.Printf("[DEBUG] command: loading backend config file: %s", path) 91 92 // We first need to determine if we're loading a file or a directory. 93 fi, err := os.Stat(path) 94 if err != nil { 95 if os.IsNotExist(err) && emptyOk { 96 log.Printf( 97 "[INFO] command: backend config not found, returning nil: %s", 98 path) 99 return nil, nil 100 } 101 102 return nil, err 103 } 104 105 var f func(string) (*config.Config, error) = config.LoadFile 106 if fi.IsDir() { 107 f = config.LoadDir 108 } 109 110 // Load the configuration 111 c, err := f(path) 112 if err != nil { 113 // Check for the error where we have no config files and return nil 114 // as the configuration type. 115 if errwrap.ContainsType(err, new(config.ErrNoConfigsFound)) { 116 log.Printf( 117 "[INFO] command: backend config not found, returning nil: %s", 118 path) 119 return nil, nil 120 } 121 122 return nil, err 123 } 124 125 return c, nil 126 } 127 128 // Plan returns the plan for the given path. 129 // 130 // This only has an effect if the path itself looks like a plan. 131 // If error is nil and the plan is nil, then the path didn't look like 132 // a plan. 133 // 134 // Error will be non-nil if path looks like a plan and loading the plan 135 // failed. 136 func (m *Meta) Plan(path string) (*terraform.Plan, error) { 137 // Open the path no matter if its a directory or file 138 f, err := os.Open(path) 139 defer f.Close() 140 if err != nil { 141 return nil, fmt.Errorf( 142 "Failed to load Terraform configuration or plan: %s", err) 143 } 144 145 // Stat it so we can check if its a directory 146 fi, err := f.Stat() 147 if err != nil { 148 return nil, fmt.Errorf( 149 "Failed to load Terraform configuration or plan: %s", err) 150 } 151 152 // If this path is a directory, then it can't be a plan. Not an error. 153 if fi.IsDir() { 154 return nil, nil 155 } 156 157 // Read the plan 158 p, err := terraform.ReadPlan(f) 159 if err != nil { 160 return nil, err 161 } 162 163 // We do a validation here that seems odd but if any plan is given, 164 // we must not have set any extra variables. The plan itself contains 165 // the variables and those aren't overwritten. 166 if len(m.variables) > 0 { 167 return nil, fmt.Errorf( 168 "You can't set variables with the '-var' or '-var-file' flag\n" + 169 "when you're applying a plan file. The variables used when\n" + 170 "the plan was created will be used. If you wish to use different\n" + 171 "variable values, create a new plan file.") 172 } 173 174 return p, nil 175 }