github.com/jrasell/terraform@v0.6.17-0.20160523115548-2652f5232949/command/refresh.go (about)

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