have Meta.Backend use a Config rather than loading

Instead of providing the a path in BackendOpts, provide a loaded
*config.Config instead. This reduces the number of places where
configuration is loaded.
This commit is contained in:
James Bardin 2017-05-01 17:47:53 -04:00 committed by Martin Atkins
parent d7d8ea9543
commit 718ede0636
17 changed files with 184 additions and 75 deletions

View File

@ -132,10 +132,15 @@ func (c *ApplyCommand) Run(args []string) int {
} }
*/ */
var conf *config.Config
if mod != nil {
conf = mod.Config()
}
// Load the backend // Load the backend
b, err := c.Backend(&BackendOpts{ b, err := c.Backend(&BackendOpts{
ConfigPath: configPath, Config: conf,
Plan: plan, Plan: plan,
}) })
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))

View File

@ -6,6 +6,7 @@ import (
"strings" "strings"
"github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/helper/wrappedstreams" "github.com/hashicorp/terraform/helper/wrappedstreams"
"github.com/hashicorp/terraform/repl" "github.com/hashicorp/terraform/repl"
@ -43,8 +44,16 @@ func (c *ConsoleCommand) Run(args []string) int {
return 1 return 1
} }
var conf *config.Config
if mod != nil {
conf = mod.Config()
}
// Load the backend // Load the backend
b, err := c.Backend(&BackendOpts{ConfigPath: configPath}) b, err := c.Backend(&BackendOpts{
Config: conf,
})
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))
return 1 return 1

View File

@ -43,8 +43,17 @@ func (c *EnvDeleteCommand) Run(args []string) int {
return 1 return 1
} }
cfg, err := c.Config(configPath)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load root config module: %s", err))
return 1
}
// Load the backend // Load the backend
b, err := c.Backend(&BackendOpts{ConfigPath: configPath}) b, err := c.Backend(&BackendOpts{
Config: cfg,
})
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))
return 1 return 1

View File

@ -26,8 +26,17 @@ func (c *EnvListCommand) Run(args []string) int {
return 1 return 1
} }
cfg, err := c.Config(configPath)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load root config module: %s", err))
return 1
}
// Load the backend // Load the backend
b, err := c.Backend(&BackendOpts{ConfigPath: configPath}) b, err := c.Backend(&BackendOpts{
Config: cfg,
})
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))
return 1 return 1

View File

@ -46,8 +46,16 @@ func (c *EnvNewCommand) Run(args []string) int {
return 1 return 1
} }
conf, err := c.Config(configPath)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load root config module: %s", err))
}
// Load the backend // Load the backend
b, err := c.Backend(&BackendOpts{ConfigPath: configPath}) b, err := c.Backend(&BackendOpts{
Config: conf,
})
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))
return 1 return 1

View File

@ -31,8 +31,17 @@ func (c *EnvSelectCommand) Run(args []string) int {
return 1 return 1
} }
conf, err := c.Config(configPath)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load root config module: %s", err))
return 1
}
// Load the backend // Load the backend
b, err := c.Backend(&BackendOpts{ConfigPath: configPath}) b, err := c.Backend(&BackendOpts{
Config: conf,
})
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))
return 1 return 1

View File

@ -6,6 +6,7 @@ import (
"strings" "strings"
"github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/config/module" "github.com/hashicorp/terraform/config/module"
"github.com/hashicorp/terraform/dag" "github.com/hashicorp/terraform/dag"
"github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/terraform"
@ -62,10 +63,15 @@ func (c *GraphCommand) Run(args []string) int {
} }
} }
var conf *config.Config
if mod != nil {
conf = mod.Config()
}
// Load the backend // Load the backend
b, err := c.Backend(&BackendOpts{ b, err := c.Backend(&BackendOpts{
ConfigPath: configPath, Config: conf,
Plan: plan, Plan: plan,
}) })
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))

View File

@ -7,6 +7,7 @@ import (
"strings" "strings"
"github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/config/module" "github.com/hashicorp/terraform/config/module"
"github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/terraform"
) )
@ -60,8 +61,15 @@ func (c *ImportCommand) Run(args []string) int {
} }
} }
var conf *config.Config
if mod != nil {
conf = mod.Config()
}
// Load the backend // Load the backend
b, err := c.Backend(&BackendOpts{ConfigPath: configPath}) b, err := c.Backend(&BackendOpts{
Config: conf,
})
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))
return 1 return 1

View File

@ -106,11 +106,7 @@ func (c *InitCommand) Run(args []string) int {
// If we're performing a get or loading the backend, then we perform // If we're performing a get or loading the backend, then we perform
// some extra tasks. // some extra tasks.
if flagGet || flagBackend { if flagGet || flagBackend {
// Load the configuration in this directory so that we can know conf, err := c.Config(path)
// if we have anything to get or any backend to configure. We do
// this to improve the UX. Practically, we could call the functions
// below without checking this to the same effect.
conf, err := config.LoadDir(path)
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf( c.Ui.Error(fmt.Sprintf(
"Error loading configuration: %s", err)) "Error loading configuration: %s", err))
@ -145,7 +141,7 @@ func (c *InitCommand) Run(args []string) int {
} }
opts := &BackendOpts{ opts := &BackendOpts{
ConfigPath: path, Config: conf,
ConfigExtra: flagConfigExtra, ConfigExtra: flagConfigExtra,
Init: true, Init: true,
} }

View File

@ -9,11 +9,9 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"os"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/go-multierror" "github.com/hashicorp/go-multierror"
"github.com/hashicorp/hcl" "github.com/hashicorp/hcl"
"github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/backend"
@ -29,9 +27,9 @@ import (
// BackendOpts are the options used to initialize a backend.Backend. // BackendOpts are the options used to initialize a backend.Backend.
type BackendOpts struct { type BackendOpts struct {
// ConfigPath is a path to a file or directory containing the backend // Module is the root module from which we will extract the terraform and
// configuration (declaration). // backend configuration.
ConfigPath string Config *config.Config
// ConfigFile is a path to a file that contains configuration that // ConfigFile is a path to a file that contains configuration that
// is merged directly into the backend configuration when loaded // is merged directly into the backend configuration when loaded
@ -178,71 +176,34 @@ func (m *Meta) Operation() *backend.Operation {
// backendConfig returns the local configuration for the backend // backendConfig returns the local configuration for the backend
func (m *Meta) backendConfig(opts *BackendOpts) (*config.Backend, error) { func (m *Meta) backendConfig(opts *BackendOpts) (*config.Backend, error) {
// If no explicit path was given then it is okay for there to be if opts.Config == nil {
// no backend configuration found. // check if the config was missing, or just not required
emptyOk := opts.ConfigPath == "" conf, err := m.Config(".")
// Determine the path to the configuration.
path := opts.ConfigPath
// If we had no path set, it is an error. We can't initialize unset
if path == "" {
path = "."
}
// Expand the path
if !filepath.IsAbs(path) {
var err error
path, err = filepath.Abs(path)
if err != nil { if err != nil {
return nil, fmt.Errorf( return nil, err
"Error expanding path to backend config %q: %s", path, err)
} }
}
log.Printf("[DEBUG] command: loading backend config file: %s", path) if conf == nil {
log.Println("[INFO] command: no config, returning nil")
// We first need to determine if we're loading a file or a directory.
fi, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) && emptyOk {
log.Printf(
"[INFO] command: backend config not found, returning nil: %s",
path)
return nil, nil return nil, nil
} }
return nil, err log.Println("[WARNING] BackendOpts.Config not set, but config found")
opts.Config = conf
} }
var f func(string) (*config.Config, error) = config.LoadFile c := opts.Config
if fi.IsDir() {
f = config.LoadDir
}
// Load the configuration
c, err := f(path)
if err != nil {
// Check for the error where we have no config files and return nil
// as the configuration type.
if errwrap.ContainsType(err, new(config.ErrNoConfigsFound)) {
log.Printf(
"[INFO] command: backend config not found, returning nil: %s",
path)
return nil, nil
}
return nil, err
}
// If there is no Terraform configuration block, no backend config // If there is no Terraform configuration block, no backend config
if c.Terraform == nil { if c.Terraform == nil {
log.Println("[INFO] command: empty terraform config, returning nil")
return nil, nil return nil, nil
} }
// Get the configuration for the backend itself. // Get the configuration for the backend itself.
backend := c.Terraform.Backend backend := c.Terraform.Backend
if backend == nil { if backend == nil {
log.Println("[INFO] command: empty backend config, returning nil")
return nil, nil return nil, nil
} }

View File

@ -2,7 +2,9 @@ package command
import ( import (
"fmt" "fmt"
"log"
"os" "os"
"path/filepath"
"strconv" "strconv"
"github.com/hashicorp/errwrap" "github.com/hashicorp/errwrap"
@ -51,6 +53,66 @@ func (m *Meta) Module(path string) (*module.Tree, error) {
return mod, nil return mod, nil
} }
// Config loads the root config for the path specified. Path may be a directory
// or file. The absence of configuration is not an error and returns a nil Config.
func (m *Meta) Config(path string) (*config.Config, error) {
// If no explicit path was given then it is okay for there to be
// no backend configuration found.
emptyOk := path == ""
// If we had no path set, it is an error. We can't initialize unset
if path == "" {
path = "."
}
// Expand the path
if !filepath.IsAbs(path) {
var err error
path, err = filepath.Abs(path)
if err != nil {
return nil, fmt.Errorf(
"Error expanding path to backend config %q: %s", path, err)
}
}
log.Printf("[DEBUG] command: loading backend config file: %s", path)
// We first need to determine if we're loading a file or a directory.
fi, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) && emptyOk {
log.Printf(
"[INFO] command: backend config not found, returning nil: %s",
path)
return nil, nil
}
return nil, err
}
var f func(string) (*config.Config, error) = config.LoadFile
if fi.IsDir() {
f = config.LoadDir
}
// Load the configuration
c, err := f(path)
if err != nil {
// Check for the error where we have no config files and return nil
// as the configuration type.
if errwrap.ContainsType(err, new(config.ErrNoConfigsFound)) {
log.Printf(
"[INFO] command: backend config not found, returning nil: %s",
path)
return nil, nil
}
return nil, err
}
return c, nil
}
// Plan returns the plan for the given path. // Plan returns the plan for the given path.
// //
// This only has an effect if the path itself looks like a plan. // This only has an effect if the path itself looks like a plan.

View File

@ -6,6 +6,7 @@ import (
"strings" "strings"
"github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/config/module" "github.com/hashicorp/terraform/config/module"
) )
@ -68,10 +69,14 @@ func (c *PlanCommand) Run(args []string) int {
} }
} }
var conf *config.Config
if mod != nil {
conf = mod.Config()
}
// Load the backend // Load the backend
b, err := c.Backend(&BackendOpts{ b, err := c.Backend(&BackendOpts{
ConfigPath: configPath, Config: conf,
Plan: plan, Plan: plan,
}) })
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))

View File

@ -52,7 +52,9 @@ func (c *ProvidersCommand) Run(args []string) int {
} }
// Load the backend // Load the backend
b, err := c.Backend(&BackendOpts{ConfigPath: configPath}) b, err := c.Backend(&BackendOpts{
Config: root.Config(),
})
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))
return 1 return 1

View File

@ -11,6 +11,7 @@ import (
"github.com/hashicorp/atlas-go/archive" "github.com/hashicorp/atlas-go/archive"
"github.com/hashicorp/atlas-go/v1" "github.com/hashicorp/atlas-go/v1"
"github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/terraform"
) )
@ -98,9 +99,14 @@ func (c *PushCommand) Run(args []string) int {
return 1 return 1
} }
var conf *config.Config
if mod != nil {
conf = mod.Config()
}
// Load the backend // Load the backend
b, err := c.Backend(&BackendOpts{ b, err := c.Backend(&BackendOpts{
ConfigPath: configPath, Config: conf,
}) })
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))

View File

@ -6,6 +6,7 @@ import (
"strings" "strings"
"github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/terraform"
) )
@ -43,8 +44,15 @@ func (c *RefreshCommand) Run(args []string) int {
return 1 return 1
} }
var conf *config.Config
if mod != nil {
conf = mod.Config()
}
// Load the backend // Load the backend
b, err := c.Backend(&BackendOpts{ConfigPath: configPath}) b, err := c.Backend(&BackendOpts{
Config: conf,
})
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))
return 1 return 1

View File

@ -43,9 +43,15 @@ func (c *UnlockCommand) Run(args []string) int {
return 1 return 1
} }
conf, err := c.Config(configPath)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load root config module: %s", err))
return 1
}
// Load the backend // Load the backend
b, err := c.Backend(&BackendOpts{ b, err := c.Backend(&BackendOpts{
ConfigPath: configPath, Config: conf,
}) })
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))

0
plugin/getter/get.go Normal file
View File