terraform/command/refresh.go

230 lines
7.1 KiB
Go
Raw Normal View History

2014-06-27 20:09:01 +02:00
package command
import (
"fmt"
"strings"
2017-01-19 05:50:45 +01:00
"github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/command/arguments"
"github.com/hashicorp/terraform/command/views"
"github.com/hashicorp/terraform/tfdiags"
2014-06-27 20:09:01 +02:00
)
// RefreshCommand is a cli.Command implementation that refreshes the state
// file.
type RefreshCommand struct {
Meta
2014-06-27 20:09:01 +02:00
}
2021-02-22 17:38:39 +01:00
func (c *RefreshCommand) Run(rawArgs []string) int {
// Parse and apply global view arguments
common, rawArgs := arguments.ParseView(rawArgs)
c.View.Configure(common)
// Parse and validate flags
args, diags := arguments.ParseRefresh(rawArgs)
// Instantiate the view, even if there are flag errors, so that we render
// diagnostics according to the desired view
var view views.Refresh
view = views.NewRefresh(args.ViewType, c.RunningInAutomation, c.View)
if diags.HasErrors() {
2021-02-22 17:38:39 +01:00
view.Diagnostics(diags)
view.HelpPrompt("refresh")
2014-06-27 20:09:01 +02:00
return 1
}
2021-02-22 17:38:39 +01:00
// Check for user-supplied plugin path
var err error
if c.pluginPath, err = c.loadPluginPath(); err != nil {
diags = diags.Append(err)
view.Diagnostics(diags)
2014-06-27 20:09:01 +02:00
return 1
}
2021-02-22 17:38:39 +01:00
// FIXME: the -input flag value is needed to initialize the backend and the
// operation, but there is no clear path to pass this value down, so we
// continue to mutate the Meta object state for now.
c.Meta.input = args.InputEnabled
// FIXME: the -parallelism flag is used to control the concurrency of
// Terraform operations. At the moment, this value is used both to
// initialize the backend via the ContextOpts field inside CLIOpts, and to
// set a largely unused field on the Operation request. Again, there is no
// clear path to pass this value down, so we continue to mutate the Meta
// object state for now.
c.Meta.parallelism = args.Operation.Parallelism
// Prepare the backend with the backend-specific arguments
be, beDiags := c.PrepareBackend(args.State)
diags = diags.Append(beDiags)
if diags.HasErrors() {
view.Diagnostics(diags)
return 1
}
2021-02-22 17:38:39 +01:00
// Build the operation request
opReq, opDiags := c.OperationRequest(be, view, args.Operation)
diags = diags.Append(opDiags)
if diags.HasErrors() {
view.Diagnostics(diags)
return 1
}
2021-02-22 17:38:39 +01:00
// Collect variable value and add them to the operation request
diags = diags.Append(c.GatherVariables(opReq, args.Vars))
if diags.HasErrors() {
view.Diagnostics(diags)
2014-06-27 20:09:01 +02:00
return 1
}
// Before we delegate to the backend, we'll print any warning diagnostics
// we've accumulated here, since the backend will start fresh with its own
// diagnostics.
2021-02-22 17:38:39 +01:00
view.Diagnostics(diags)
diags = nil
2021-02-22 17:38:39 +01:00
// Perform the operation
op, err := c.RunOperation(be, opReq)
2014-06-27 20:09:01 +02:00
if err != nil {
2021-02-22 17:38:39 +01:00
diags = diags.Append(err)
view.Diagnostics(diags)
return 1
}
2021-02-22 17:38:39 +01:00
if op.State != nil {
view.Outputs(op.State.RootModule().OutputValues)
}
2021-02-22 17:38:39 +01:00
return op.Result.ExitStatus()
}
func (c *RefreshCommand) PrepareBackend(args *arguments.State) (backend.Enhanced, tfdiags.Diagnostics) {
// FIXME: we need to apply the state arguments to the meta object here
// because they are later used when initializing the backend. Carving a
// path to pass these arguments to the functions that need them is
// difficult but would make their use easier to understand.
c.Meta.applyStateArguments(args)
backendConfig, diags := c.loadBackendConfig(".")
if diags.HasErrors() {
return nil, diags
2014-06-27 20:09:01 +02:00
}
2021-02-22 17:38:39 +01:00
// Load the backend
be, beDiags := c.Backend(&BackendOpts{
Config: backendConfig,
})
diags = diags.Append(beDiags)
if beDiags.HasErrors() {
return nil, diags
}
2021-02-22 17:38:39 +01:00
return be, diags
}
func (c *RefreshCommand) OperationRequest(be backend.Enhanced, view views.Refresh, args *arguments.Operation,
) (*backend.Operation, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
// Build the operation
opReq := c.Operation(be)
opReq.ConfigDir = "."
opReq.Hooks = view.Hooks()
opReq.Targets = args.Targets
opReq.Type = backend.OperationTypeRefresh
opReq.View = view.Operation()
// FIXME: this shim is needed until the remote backend is migrated to views
opReq.ShowDiagnostics = func(vals ...interface{}) {
var diags tfdiags.Diagnostics
diags = diags.Append(vals...)
view.Diagnostics(diags)
}
2021-02-22 17:38:39 +01:00
var err error
opReq.ConfigLoader, err = c.initConfigLoader()
if err != nil {
diags = diags.Append(fmt.Errorf("Failed to initialize config loader: %s", err))
return nil, diags
}
return opReq, diags
}
func (c *RefreshCommand) GatherVariables(opReq *backend.Operation, args *arguments.Vars) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
// FIXME the arguments package currently trivially gathers variable related
// arguments in a heterogenous slice, in order to minimize the number of
// code paths gathering variables during the transition to this structure.
// Once all commands that gather variables have been converted to this
// structure, we could move the variable gathering code to the arguments
// package directly, removing this shim layer.
varArgs := args.All()
items := make([]rawFlag, len(varArgs))
for i := range varArgs {
items[i].Name = varArgs[i].Name
items[i].Value = varArgs[i].Value
}
c.Meta.variableArgs = rawFlags{items: &items}
opReq.Variables, diags = c.collectVariableValues()
return diags
2014-06-27 20:09:01 +02:00
}
func (c *RefreshCommand) Help() string {
helpText := `
Usage: terraform refresh [options]
Update the state file of your infrastructure with metadata that matches
the physical resources they are tracking.
2014-06-27 20:09:01 +02:00
This will not modify your infrastructure, but it can modify your
state file to update metadata. This metadata might cause new changes
to occur when you generate a plan or call apply next.
2014-06-27 20:09:01 +02:00
Options:
2014-07-28 00:09:04 +02:00
-backup=path Path to backup the existing state file before
modifying. Defaults to the "-state-out" path with
".backup" extension. Set to "-" to disable backup.
2014-07-28 00:09:04 +02:00
-compact-warnings If Terraform produces any warnings that are not
accompanied by errors, show them in a more compact form
that includes only the summary messages.
-input=true Ask for input for variables if not directly set.
2017-02-06 16:07:32 +01:00
-lock=true Lock the state file when locking is supported.
-lock-timeout=0s Duration to retry a state lock.
-no-color If specified, output won't contain any color.
-state=path Path to read and save state (unless state-out
is specified). Defaults to "terraform.tfstate".
-state-out=path Path to write updated state file. By default, the
"-state" path will be used.
2014-06-27 20:09:01 +02:00
-target=resource Resource to target. Operation will be limited to this
resource and its dependencies. This flag can be used
multiple times.
2014-07-18 20:37:27 +02:00
-var 'foo=bar' Set a variable in the Terraform configuration. This
flag can be set multiple times.
-var-file=foo Set variables in the Terraform configuration from
2017-06-22 03:22:07 +02:00
a file. If "terraform.tfvars" or any ".auto.tfvars"
files are present, they will be automatically loaded.
2014-07-18 20:37:27 +02:00
2014-06-27 20:09:01 +02:00
`
return strings.TrimSpace(helpText)
}
func (c *RefreshCommand) Synopsis() string {
return "Update the state to match remote systems"
2014-06-27 20:09:01 +02:00
}