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