github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/refresh.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/hashicorp/terraform/internal/backend" 8 "github.com/hashicorp/terraform/internal/command/arguments" 9 "github.com/hashicorp/terraform/internal/command/views" 10 "github.com/hashicorp/terraform/internal/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 }