github.com/ezbercih/terraform@v0.1.1-0.20140729011846-3c33865e0839/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) 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 extention 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(configPath, statePath) 88 if err != nil { 89 c.Ui.Error(err.Error()) 90 return 1 91 } 92 if !validateContext(ctx, c.Ui) { 93 return 1 94 } 95 96 // Create a backup of the state before updating 97 if backupPath != "-" && c.state != nil { 98 log.Printf("[INFO] Writing backup state to: %s", backupPath) 99 f, err := os.Create(backupPath) 100 if err == nil { 101 err = terraform.WriteState(c.state, f) 102 f.Close() 103 } 104 if err != nil { 105 c.Ui.Error(fmt.Sprintf("Error writing backup state file: %s", err)) 106 return 1 107 } 108 } 109 110 state, err := ctx.Refresh() 111 if err != nil { 112 c.Ui.Error(fmt.Sprintf("Error refreshing state: %s", err)) 113 return 1 114 } 115 116 log.Printf("[INFO] Writing state output to: %s", stateOutPath) 117 f, err := os.Create(stateOutPath) 118 if err == nil { 119 defer f.Close() 120 err = terraform.WriteState(state, f) 121 } 122 if err != nil { 123 c.Ui.Error(fmt.Sprintf("Error writing state file: %s", err)) 124 return 1 125 } 126 127 return 0 128 } 129 130 func (c *RefreshCommand) Help() string { 131 helpText := ` 132 Usage: terraform refresh [options] [dir] 133 134 Update the state file of your infrastructure with metadata that matches 135 the physical resources they are tracking. 136 137 This will not modify your infrastructure, but it can modify your 138 state file to update metadata. This metadata might cause new changes 139 to occur when you generate a plan or call apply next. 140 141 Options: 142 143 -backup=path Path to backup the existing state file before 144 modifying. Defaults to the "-state-out" path with 145 ".backup" extention. Set to "-" to disable backup. 146 147 -no-color If specified, output won't contain any color. 148 149 -state=path Path to read and save state (unless state-out 150 is specified). Defaults to "terraform.tfstate". 151 152 -state-out=path Path to write updated state file. By default, the 153 "-state" path will be used. 154 155 -var 'foo=bar' Set a variable in the Terraform configuration. This 156 flag can be set multiple times. 157 158 -var-file=foo Set variables in the Terraform configuration from 159 a file. If "terraform.tfvars" is present, it will be 160 automatically loaded if this flag is not specified. 161 162 ` 163 return strings.TrimSpace(helpText) 164 } 165 166 func (c *RefreshCommand) Synopsis() string { 167 return "Update local state file against real resources" 168 }