github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/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) 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.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) (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 }) 126 diags = diags.Append(beDiags) 127 if beDiags.HasErrors() { 128 return nil, diags 129 } 130 131 return be, diags 132 } 133 134 func (c *RefreshCommand) OperationRequest(be backend.Enhanced, view views.Refresh, args *arguments.Operation, 135 ) (*backend.Operation, tfdiags.Diagnostics) { 136 var diags tfdiags.Diagnostics 137 138 // Build the operation 139 opReq := c.Operation(be) 140 opReq.ConfigDir = "." 141 opReq.Hooks = view.Hooks() 142 opReq.Targets = args.Targets 143 opReq.Type = backend.OperationTypeRefresh 144 opReq.View = view.Operation() 145 146 var err error 147 opReq.ConfigLoader, err = c.initConfigLoader() 148 if err != nil { 149 diags = diags.Append(fmt.Errorf("Failed to initialize config loader: %s", err)) 150 return nil, diags 151 } 152 153 return opReq, diags 154 } 155 156 func (c *RefreshCommand) GatherVariables(opReq *backend.Operation, args *arguments.Vars) tfdiags.Diagnostics { 157 var diags tfdiags.Diagnostics 158 159 // FIXME the arguments package currently trivially gathers variable related 160 // arguments in a heterogenous slice, in order to minimize the number of 161 // code paths gathering variables during the transition to this structure. 162 // Once all commands that gather variables have been converted to this 163 // structure, we could move the variable gathering code to the arguments 164 // package directly, removing this shim layer. 165 166 varArgs := args.All() 167 items := make([]rawFlag, len(varArgs)) 168 for i := range varArgs { 169 items[i].Name = varArgs[i].Name 170 items[i].Value = varArgs[i].Value 171 } 172 c.Meta.variableArgs = rawFlags{items: &items} 173 opReq.Variables, diags = c.collectVariableValues() 174 175 return diags 176 } 177 178 func (c *RefreshCommand) Help() string { 179 helpText := ` 180 Usage: terraform [global options] refresh [options] 181 182 Update the state file of your infrastructure with metadata that matches 183 the physical resources they are tracking. 184 185 This will not modify your infrastructure, but it can modify your 186 state file to update metadata. This metadata might cause new changes 187 to occur when you generate a plan or call apply next. 188 189 Options: 190 191 -compact-warnings If Terraform produces any warnings that are not 192 accompanied by errors, show them in a more compact form 193 that includes only the summary messages. 194 195 -input=true Ask for input for variables if not directly set. 196 197 -lock=false Don't hold a state lock during the operation. This is 198 dangerous if others might concurrently run commands 199 against the same workspace. 200 201 -lock-timeout=0s Duration to retry a state lock. 202 203 -no-color If specified, output won't contain any color. 204 205 -parallelism=n Limit the number of concurrent operations. Defaults to 10. 206 207 -target=resource Resource to target. Operation will be limited to this 208 resource and its dependencies. This flag can be used 209 multiple times. 210 211 -var 'foo=bar' Set a variable in the Terraform configuration. This 212 flag can be set multiple times. 213 214 -var-file=foo Set variables in the Terraform configuration from 215 a file. If "terraform.tfvars" or any ".auto.tfvars" 216 files are present, they will be automatically loaded. 217 218 -state, state-out, and -backup are legacy options supported for the local 219 backend only. For more information, see the local backend's documentation. 220 ` 221 return strings.TrimSpace(helpText) 222 } 223 224 func (c *RefreshCommand) Synopsis() string { 225 return "Update the state to match remote systems" 226 }