github.com/richardbowden/terraform@v0.6.12-0.20160901200758-30ea22c25211/command/refresh.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "log" 6 "os" 7 "strings" 8 9 "github.com/hashicorp/terraform/terraform" 10 ) 11 12 // RefreshCommand is a cli.Command implementation that refreshes the state 13 // file. 14 type RefreshCommand struct { 15 Meta 16 } 17 18 func (c *RefreshCommand) Run(args []string) int { 19 args = c.Meta.process(args, true) 20 21 cmdFlags := c.Meta.flagSet("refresh") 22 cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path") 23 cmdFlags.IntVar(&c.Meta.parallelism, "parallelism", 0, "parallelism") 24 cmdFlags.StringVar(&c.Meta.stateOutPath, "state-out", "", "path") 25 cmdFlags.StringVar(&c.Meta.backupPath, "backup", "", "path") 26 cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } 27 if err := cmdFlags.Parse(args); err != nil { 28 return 1 29 } 30 31 var configPath string 32 args = cmdFlags.Args() 33 if len(args) > 1 { 34 c.Ui.Error("The refresh command expects at most one argument.") 35 cmdFlags.Usage() 36 return 1 37 } else if len(args) == 1 { 38 configPath = args[0] 39 } else { 40 var err error 41 configPath, err = os.Getwd() 42 if err != nil { 43 c.Ui.Error(fmt.Sprintf("Error getting pwd: %s", err)) 44 } 45 } 46 47 // Check if remote state is enabled 48 state, err := c.State() 49 if err != nil { 50 c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) 51 return 1 52 } 53 54 // Verify that the state path exists. The "ContextArg" function below 55 // will actually do this, but we want to provide a richer error message 56 // if possible. 57 if !state.State().IsRemote() { 58 if _, err := os.Stat(c.Meta.statePath); err != nil { 59 if os.IsNotExist(err) { 60 c.Ui.Error(fmt.Sprintf( 61 "The Terraform state file for your infrastructure does not\n"+ 62 "exist. The 'refresh' command only works and only makes sense\n"+ 63 "when there is existing state that Terraform is managing. Please\n"+ 64 "double-check the value given below and try again. If you\n"+ 65 "haven't created infrastructure with Terraform yet, use the\n"+ 66 "'terraform apply' command.\n\n"+ 67 "Path: %s", 68 c.Meta.statePath)) 69 return 1 70 } 71 72 c.Ui.Error(fmt.Sprintf( 73 "There was an error reading the Terraform state that is needed\n"+ 74 "for refreshing. The path and error are shown below.\n\n"+ 75 "Path: %s\n\nError: %s", 76 c.Meta.statePath, 77 err)) 78 return 1 79 } 80 } 81 82 // Build the context based on the arguments given 83 ctx, _, err := c.Context(contextOpts{ 84 Path: configPath, 85 StatePath: c.Meta.statePath, 86 Parallelism: c.Meta.parallelism, 87 }) 88 if err != nil { 89 c.Ui.Error(err.Error()) 90 return 1 91 } 92 93 if err := ctx.Input(c.InputMode()); err != nil { 94 c.Ui.Error(fmt.Sprintf("Error configuring: %s", err)) 95 return 1 96 } 97 98 if !validateContext(ctx, c.Ui) { 99 return 1 100 } 101 102 newState, err := ctx.Refresh() 103 if err != nil { 104 c.Ui.Error(fmt.Sprintf("Error refreshing state: %s", err)) 105 return 1 106 } 107 108 log.Printf("[INFO] Writing state output to: %s", c.Meta.StateOutPath()) 109 if err := c.Meta.PersistState(newState); err != nil { 110 c.Ui.Error(fmt.Sprintf("Error writing state file: %s", err)) 111 return 1 112 } 113 114 if outputs := outputsAsString(newState, terraform.RootModulePath, ctx.Module().Config().Outputs, true); outputs != "" { 115 c.Ui.Output(c.Colorize().Color(outputs)) 116 } 117 118 return 0 119 } 120 121 func (c *RefreshCommand) Help() string { 122 helpText := ` 123 Usage: terraform refresh [options] [dir] 124 125 Update the state file of your infrastructure with metadata that matches 126 the physical resources they are tracking. 127 128 This will not modify your infrastructure, but it can modify your 129 state file to update metadata. This metadata might cause new changes 130 to occur when you generate a plan or call apply next. 131 132 Options: 133 134 -backup=path Path to backup the existing state file before 135 modifying. Defaults to the "-state-out" path with 136 ".backup" extension. Set to "-" to disable backup. 137 138 -input=true Ask for input for variables if not directly set. 139 140 -no-color If specified, output won't contain any color. 141 142 -state=path Path to read and save state (unless state-out 143 is specified). Defaults to "terraform.tfstate". 144 145 -state-out=path Path to write updated state file. By default, the 146 "-state" path will be used. 147 148 -target=resource Resource to target. Operation will be limited to this 149 resource and its dependencies. This flag can be used 150 multiple times. 151 152 -var 'foo=bar' Set a variable in the Terraform configuration. This 153 flag can be set multiple times. 154 155 -var-file=foo Set variables in the Terraform configuration from 156 a file. If "terraform.tfvars" is present, it will be 157 automatically loaded if this flag is not specified. 158 159 ` 160 return strings.TrimSpace(helpText) 161 } 162 163 func (c *RefreshCommand) Synopsis() string { 164 return "Update local state file against real resources" 165 }