github.com/pulumi/terraform@v1.4.0/pkg/command/refresh.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/pulumi/terraform/pkg/backend"
     8  	"github.com/pulumi/terraform/pkg/command/arguments"
     9  	"github.com/pulumi/terraform/pkg/command/views"
    10  	"github.com/pulumi/terraform/pkg/tfdiags"
    11  )
    12  
    13  // RefreshCommand is a cli.Command implementation that refreshes the state
    14  // file.
    15  type RefreshCommand struct {
    16  	Meta
    17  }
    18  
    19  func (c *RefreshCommand) Run(rawArgs []string) int {
    20  	var diags tfdiags.Diagnostics
    21  
    22  	// Parse and apply global view arguments
    23  	common, rawArgs := arguments.ParseView(rawArgs)
    24  	c.View.Configure(common)
    25  
    26  	// Propagate -no-color for legacy use of Ui.  The remote backend and
    27  	// cloud package use this; it should be removed when/if they are
    28  	// migrated to views.
    29  	c.Meta.color = !common.NoColor
    30  	c.Meta.Color = c.Meta.color
    31  
    32  	// Parse and validate flags
    33  	args, diags := arguments.ParseRefresh(rawArgs)
    34  
    35  	// Instantiate the view, even if there are flag errors, so that we render
    36  	// diagnostics according to the desired view
    37  	view := views.NewRefresh(args.ViewType, c.View)
    38  
    39  	if diags.HasErrors() {
    40  		view.Diagnostics(diags)
    41  		view.HelpPrompt()
    42  		return 1
    43  	}
    44  
    45  	// Check for user-supplied plugin path
    46  	var err error
    47  	if c.pluginPath, err = c.loadPluginPath(); err != nil {
    48  		diags = diags.Append(err)
    49  		view.Diagnostics(diags)
    50  		return 1
    51  	}
    52  
    53  	// FIXME: the -input flag value is needed to initialize the backend and the
    54  	// operation, but there is no clear path to pass this value down, so we
    55  	// continue to mutate the Meta object state for now.
    56  	c.Meta.input = args.InputEnabled
    57  
    58  	// FIXME: the -parallelism flag is used to control the concurrency of
    59  	// Terraform operations. At the moment, this value is used both to
    60  	// initialize the backend via the ContextOpts field inside CLIOpts, and to
    61  	// set a largely unused field on the Operation request. Again, there is no
    62  	// clear path to pass this value down, so we continue to mutate the Meta
    63  	// object state for now.
    64  	c.Meta.parallelism = args.Operation.Parallelism
    65  
    66  	// Prepare the backend with the backend-specific arguments
    67  	be, beDiags := c.PrepareBackend(args.State, args.ViewType)
    68  	diags = diags.Append(beDiags)
    69  	if diags.HasErrors() {
    70  		view.Diagnostics(diags)
    71  		return 1
    72  	}
    73  
    74  	// Build the operation request
    75  	opReq, opDiags := c.OperationRequest(be, view, args.ViewType, args.Operation)
    76  	diags = diags.Append(opDiags)
    77  	if diags.HasErrors() {
    78  		view.Diagnostics(diags)
    79  		return 1
    80  	}
    81  
    82  	// Collect variable value and add them to the operation request
    83  	diags = diags.Append(c.GatherVariables(opReq, args.Vars))
    84  	if diags.HasErrors() {
    85  		view.Diagnostics(diags)
    86  		return 1
    87  	}
    88  
    89  	// Before we delegate to the backend, we'll print any warning diagnostics
    90  	// we've accumulated here, since the backend will start fresh with its own
    91  	// diagnostics.
    92  	view.Diagnostics(diags)
    93  	diags = nil
    94  
    95  	// Perform the operation
    96  	op, err := c.RunOperation(be, opReq)
    97  	if err != nil {
    98  		diags = diags.Append(err)
    99  		view.Diagnostics(diags)
   100  		return 1
   101  	}
   102  
   103  	if op.State != nil {
   104  		view.Outputs(op.State.RootModule().OutputValues)
   105  	}
   106  
   107  	return op.Result.ExitStatus()
   108  }
   109  
   110  func (c *RefreshCommand) PrepareBackend(args *arguments.State, viewType arguments.ViewType) (backend.Enhanced, tfdiags.Diagnostics) {
   111  	// FIXME: we need to apply the state arguments to the meta object here
   112  	// because they are later used when initializing the backend. Carving a
   113  	// path to pass these arguments to the functions that need them is
   114  	// difficult but would make their use easier to understand.
   115  	c.Meta.applyStateArguments(args)
   116  
   117  	backendConfig, diags := c.loadBackendConfig(".")
   118  	if diags.HasErrors() {
   119  		return nil, diags
   120  	}
   121  
   122  	// Load the backend
   123  	be, beDiags := c.Backend(&BackendOpts{
   124  		Config:   backendConfig,
   125  		ViewType: viewType,
   126  	})
   127  	diags = diags.Append(beDiags)
   128  	if beDiags.HasErrors() {
   129  		return nil, diags
   130  	}
   131  
   132  	return be, diags
   133  }
   134  
   135  func (c *RefreshCommand) OperationRequest(be backend.Enhanced, view views.Refresh, viewType arguments.ViewType, args *arguments.Operation,
   136  ) (*backend.Operation, tfdiags.Diagnostics) {
   137  	var diags tfdiags.Diagnostics
   138  
   139  	// Build the operation
   140  	opReq := c.Operation(be, viewType)
   141  	opReq.ConfigDir = "."
   142  	opReq.Hooks = view.Hooks()
   143  	opReq.Targets = args.Targets
   144  	opReq.Type = backend.OperationTypeRefresh
   145  	opReq.View = view.Operation()
   146  
   147  	var err error
   148  	opReq.ConfigLoader, err = c.initConfigLoader()
   149  	if err != nil {
   150  		diags = diags.Append(fmt.Errorf("Failed to initialize config loader: %s", err))
   151  		return nil, diags
   152  	}
   153  
   154  	return opReq, diags
   155  }
   156  
   157  func (c *RefreshCommand) GatherVariables(opReq *backend.Operation, args *arguments.Vars) tfdiags.Diagnostics {
   158  	var diags tfdiags.Diagnostics
   159  
   160  	// FIXME the arguments package currently trivially gathers variable related
   161  	// arguments in a heterogenous slice, in order to minimize the number of
   162  	// code paths gathering variables during the transition to this structure.
   163  	// Once all commands that gather variables have been converted to this
   164  	// structure, we could move the variable gathering code to the arguments
   165  	// package directly, removing this shim layer.
   166  
   167  	varArgs := args.All()
   168  	items := make([]rawFlag, len(varArgs))
   169  	for i := range varArgs {
   170  		items[i].Name = varArgs[i].Name
   171  		items[i].Value = varArgs[i].Value
   172  	}
   173  	c.Meta.variableArgs = rawFlags{items: &items}
   174  	opReq.Variables, diags = c.collectVariableValues()
   175  
   176  	return diags
   177  }
   178  
   179  func (c *RefreshCommand) Help() string {
   180  	helpText := `
   181  Usage: terraform [global options] refresh [options]
   182  
   183    Update the state file of your infrastructure with metadata that matches
   184    the physical resources they are tracking.
   185  
   186    This will not modify your infrastructure, but it can modify your
   187    state file to update metadata. This metadata might cause new changes
   188    to occur when you generate a plan or call apply next.
   189  
   190  Options:
   191  
   192    -compact-warnings   If Terraform produces any warnings that are not
   193                        accompanied by errors, show them in a more compact form
   194                        that includes only the summary messages.
   195  
   196    -input=true         Ask for input for variables if not directly set.
   197  
   198    -lock=false         Don't hold a state lock during the operation. This is
   199                        dangerous if others might concurrently run commands
   200                        against the same workspace.
   201  
   202    -lock-timeout=0s    Duration to retry a state lock.
   203  
   204    -no-color           If specified, output won't contain any color.
   205  
   206    -parallelism=n      Limit the number of concurrent operations. Defaults to 10.
   207  
   208    -target=resource    Resource to target. Operation will be limited to this
   209                        resource and its dependencies. This flag can be used
   210                        multiple times.
   211  
   212    -var 'foo=bar'      Set a variable in the Terraform configuration. This
   213                        flag can be set multiple times.
   214  
   215    -var-file=foo       Set variables in the Terraform configuration from
   216                        a file. If "terraform.tfvars" or any ".auto.tfvars"
   217                        files are present, they will be automatically loaded.
   218  
   219    -state, state-out, and -backup are legacy options supported for the local
   220    backend only. For more information, see the local backend's documentation.
   221  `
   222  	return strings.TrimSpace(helpText)
   223  }
   224  
   225  func (c *RefreshCommand) Synopsis() string {
   226  	return "Update the state to match remote systems"
   227  }