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