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  }