github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/command/meta_backend.go (about)

     1  package command
     2  
     3  // This file contains all the Backend-related function calls on Meta,
     4  // exported and private.
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"log"
    11  	"os"
    12  	"path/filepath"
    13  	"strings"
    14  
    15  	"github.com/hashicorp/errwrap"
    16  	"github.com/hashicorp/go-multierror"
    17  	"github.com/hashicorp/hcl"
    18  	"github.com/hashicorp/terraform/backend"
    19  	backendinit "github.com/hashicorp/terraform/backend/init"
    20  	clistate "github.com/hashicorp/terraform/command/state"
    21  	"github.com/hashicorp/terraform/config"
    22  	"github.com/hashicorp/terraform/state"
    23  	"github.com/hashicorp/terraform/terraform"
    24  	"github.com/mitchellh/mapstructure"
    25  
    26  	backendlegacy "github.com/hashicorp/terraform/backend/legacy"
    27  	backendlocal "github.com/hashicorp/terraform/backend/local"
    28  )
    29  
    30  // BackendOpts are the options used to initialize a backend.Backend.
    31  type BackendOpts struct {
    32  	// ConfigPath is a path to a file or directory containing the backend
    33  	// configuration (declaration).
    34  	ConfigPath string
    35  
    36  	// ConfigFile is a path to a file that contains configuration that
    37  	// is merged directly into the backend configuration when loaded
    38  	// from a file.
    39  	ConfigFile string
    40  
    41  	// Plan is a plan that is being used. If this is set, the backend
    42  	// configuration and output configuration will come from this plan.
    43  	Plan *terraform.Plan
    44  
    45  	// Init should be set to true if initialization is allowed. If this is
    46  	// false, then any configuration that requires configuration will show
    47  	// an error asking the user to reinitialize.
    48  	Init bool
    49  
    50  	// ForceLocal will force a purely local backend, including state.
    51  	// You probably don't want to set this.
    52  	ForceLocal bool
    53  }
    54  
    55  // Backend initializes and returns the backend for this CLI session.
    56  //
    57  // The backend is used to perform the actual Terraform operations. This
    58  // abstraction enables easily sliding in new Terraform behavior such as
    59  // remote state storage, remote operations, etc. while allowing the CLI
    60  // to remain mostly identical.
    61  //
    62  // This will initialize a new backend for each call, which can carry some
    63  // overhead with it. Please reuse the returned value for optimal behavior.
    64  //
    65  // Only one backend should be used per Meta. This function is stateful
    66  // and is unsafe to create multiple backends used at once. This function
    67  // can be called multiple times with each backend being "live" (usable)
    68  // one at a time.
    69  func (m *Meta) Backend(opts *BackendOpts) (backend.Enhanced, error) {
    70  	// If no opts are set, then initialize
    71  	if opts == nil {
    72  		opts = &BackendOpts{}
    73  	}
    74  
    75  	// Initialize a backend from the config unless we're forcing a purely
    76  	// local operation.
    77  	var b backend.Backend
    78  	if !opts.ForceLocal {
    79  		var err error
    80  
    81  		// If we have a plan then, we get the the backend from there. Otherwise,
    82  		// the backend comes from the configuration.
    83  		if opts.Plan != nil {
    84  			b, err = m.backendFromPlan(opts)
    85  		} else {
    86  			b, err = m.backendFromConfig(opts)
    87  		}
    88  		if err != nil {
    89  			return nil, err
    90  		}
    91  
    92  		log.Printf("[INFO] command: backend initialized: %T", b)
    93  	}
    94  
    95  	// Setup the CLI opts we pass into backends that support it
    96  	cliOpts := &backend.CLIOpts{
    97  		CLI:             m.Ui,
    98  		CLIColor:        m.Colorize(),
    99  		StatePath:       m.statePath,
   100  		StateOutPath:    m.stateOutPath,
   101  		StateBackupPath: m.backupPath,
   102  		ContextOpts:     m.contextOpts(),
   103  		Input:           m.Input(),
   104  		Validation:      true,
   105  	}
   106  
   107  	// If the backend supports CLI initialization, do it.
   108  	if cli, ok := b.(backend.CLI); ok {
   109  		if err := cli.CLIInit(cliOpts); err != nil {
   110  			return nil, fmt.Errorf(
   111  				"Error initializing backend %T: %s\n\n"+
   112  					"This is a bug, please report it to the backend developer",
   113  				b, err)
   114  		}
   115  	}
   116  
   117  	// If the result of loading the backend is an enhanced backend,
   118  	// then return that as-is. This works even if b == nil (it will be !ok).
   119  	if enhanced, ok := b.(backend.Enhanced); ok {
   120  		return enhanced, nil
   121  	}
   122  
   123  	// We either have a non-enhanced backend or no backend configured at
   124  	// all. In either case, we use local as our enhanced backend and the
   125  	// non-enhanced (if any) as the state backend.
   126  
   127  	if !opts.ForceLocal {
   128  		log.Printf("[INFO] command: backend %T is not enhanced, wrapping in local", b)
   129  	}
   130  
   131  	// Build the local backend
   132  	local := &backendlocal.Local{Backend: b}
   133  	if err := local.CLIInit(cliOpts); err != nil {
   134  		// Local backend isn't allowed to fail. It would be a bug.
   135  		panic(err)
   136  	}
   137  
   138  	return local, nil
   139  }
   140  
   141  // Operation initializes a new backend.Operation struct.
   142  //
   143  // This prepares the operation. After calling this, the caller is expected
   144  // to modify fields of the operation such as Sequence to specify what will
   145  // be called.
   146  func (m *Meta) Operation() *backend.Operation {
   147  	return &backend.Operation{
   148  		PlanOutBackend: m.backendState,
   149  		Targets:        m.targets,
   150  		UIIn:           m.UIInput(),
   151  		Environment:    m.Env(),
   152  	}
   153  }
   154  
   155  // backendConfig returns the local configuration for the backend
   156  func (m *Meta) backendConfig(opts *BackendOpts) (*config.Backend, error) {
   157  	// If no explicit path was given then it is okay for there to be
   158  	// no backend configuration found.
   159  	emptyOk := opts.ConfigPath == ""
   160  
   161  	// Determine the path to the configuration.
   162  	path := opts.ConfigPath
   163  
   164  	// If we had no path set, it is an error. We can't initialize unset
   165  	if path == "" {
   166  		path = "."
   167  	}
   168  
   169  	// Expand the path
   170  	if !filepath.IsAbs(path) {
   171  		var err error
   172  		path, err = filepath.Abs(path)
   173  		if err != nil {
   174  			return nil, fmt.Errorf(
   175  				"Error expanding path to backend config %q: %s", path, err)
   176  		}
   177  	}
   178  
   179  	log.Printf("[DEBUG] command: loading backend config file: %s", path)
   180  
   181  	// We first need to determine if we're loading a file or a directory.
   182  	fi, err := os.Stat(path)
   183  	if err != nil {
   184  		if os.IsNotExist(err) && emptyOk {
   185  			log.Printf(
   186  				"[INFO] command: backend config not found, returning nil: %s",
   187  				path)
   188  			return nil, nil
   189  		}
   190  
   191  		return nil, err
   192  	}
   193  
   194  	var f func(string) (*config.Config, error) = config.LoadFile
   195  	if fi.IsDir() {
   196  		f = config.LoadDir
   197  	}
   198  
   199  	// Load the configuration
   200  	c, err := f(path)
   201  	if err != nil {
   202  		// Check for the error where we have no config files and return nil
   203  		// as the configuration type.
   204  		if errwrap.ContainsType(err, new(config.ErrNoConfigsFound)) {
   205  			log.Printf(
   206  				"[INFO] command: backend config not found, returning nil: %s",
   207  				path)
   208  			return nil, nil
   209  		}
   210  
   211  		return nil, err
   212  	}
   213  
   214  	// If there is no Terraform configuration block, no backend config
   215  	if c.Terraform == nil {
   216  		return nil, nil
   217  	}
   218  
   219  	// Get the configuration for the backend itself.
   220  	backend := c.Terraform.Backend
   221  	if backend == nil {
   222  		return nil, nil
   223  	}
   224  
   225  	// If we have a config file set, load that and merge.
   226  	if opts.ConfigFile != "" {
   227  		log.Printf(
   228  			"[DEBUG] command: loading extra backend config from: %s",
   229  			opts.ConfigFile)
   230  		rc, err := m.backendConfigFile(opts.ConfigFile)
   231  		if err != nil {
   232  			return nil, fmt.Errorf(
   233  				"Error loading extra configuration file for backend: %s", err)
   234  		}
   235  
   236  		// Merge in the configuration
   237  		backend.RawConfig = backend.RawConfig.Merge(rc)
   238  	}
   239  
   240  	// Validate the backend early. We have to do this before the normal
   241  	// config validation pass since backend loading happens earlier.
   242  	if errs := backend.Validate(); len(errs) > 0 {
   243  		return nil, multierror.Append(nil, errs...)
   244  	}
   245  
   246  	// Return the configuration which may or may not be set
   247  	return backend, nil
   248  }
   249  
   250  // backendConfigFile loads the extra configuration to merge with the
   251  // backend configuration from an extra file if specified by
   252  // BackendOpts.ConfigFile.
   253  func (m *Meta) backendConfigFile(path string) (*config.RawConfig, error) {
   254  	// Read the file
   255  	d, err := ioutil.ReadFile(path)
   256  	if err != nil {
   257  		return nil, err
   258  	}
   259  
   260  	// Parse it
   261  	hclRoot, err := hcl.Parse(string(d))
   262  	if err != nil {
   263  		return nil, err
   264  	}
   265  
   266  	// Decode it
   267  	var c map[string]interface{}
   268  	if err := hcl.DecodeObject(&c, hclRoot); err != nil {
   269  		return nil, err
   270  	}
   271  
   272  	return config.NewRawConfig(c)
   273  }
   274  
   275  // backendFromConfig returns the initialized (not configured) backend
   276  // directly from the config/state..
   277  //
   278  // This function handles any edge cases around backend config loading. For
   279  // example: legacy remote state, new config changes, backend type changes,
   280  // etc.
   281  //
   282  // This function may query the user for input unless input is disabled, in
   283  // which case this function will error.
   284  func (m *Meta) backendFromConfig(opts *BackendOpts) (backend.Backend, error) {
   285  	// Get the local backend configuration.
   286  	c, err := m.backendConfig(opts)
   287  	if err != nil {
   288  		return nil, fmt.Errorf("Error loading backend config: %s", err)
   289  	}
   290  
   291  	// Get the path to where we store a local cache of backend configuration
   292  	// if we're using a remote backend. This may not yet exist which means
   293  	// we haven't used a non-local backend before. That is okay.
   294  	statePath := filepath.Join(m.DataDir(), DefaultStateFilename)
   295  	sMgr := &state.LocalState{Path: statePath}
   296  	if err := sMgr.RefreshState(); err != nil {
   297  		return nil, fmt.Errorf("Error loading state: %s", err)
   298  	}
   299  
   300  	// Load the state, it must be non-nil for the tests below but can be empty
   301  	s := sMgr.State()
   302  	if s == nil {
   303  		log.Printf("[DEBUG] command: no data state file found for backend config")
   304  		s = terraform.NewState()
   305  	}
   306  
   307  	// Upon return, we want to set the state we're using in-memory so that
   308  	// we can access it for commands.
   309  	m.backendState = nil
   310  	defer func() {
   311  		if s := sMgr.State(); s != nil && !s.Backend.Empty() {
   312  			m.backendState = s.Backend
   313  		}
   314  	}()
   315  
   316  	// This giant switch statement covers all eight possible combinations
   317  	// of state settings between: configuring new backends, saved (previously-
   318  	// configured) backends, and legacy remote state.
   319  	switch {
   320  	// No configuration set at all. Pure local state.
   321  	case c == nil && s.Remote.Empty() && s.Backend.Empty():
   322  		return nil, nil
   323  
   324  	// We're unsetting a backend (moving from backend => local)
   325  	case c == nil && s.Remote.Empty() && !s.Backend.Empty():
   326  		if !opts.Init {
   327  			initReason := fmt.Sprintf(
   328  				"Unsetting the previously set backend %q",
   329  				s.Backend.Type)
   330  			m.backendInitRequired(initReason)
   331  			return nil, errBackendInitRequired
   332  		}
   333  
   334  		return m.backend_c_r_S(c, sMgr, true)
   335  
   336  	// We have a legacy remote state configuration but no new backend config
   337  	case c == nil && !s.Remote.Empty() && s.Backend.Empty():
   338  		return m.backend_c_R_s(c, sMgr)
   339  
   340  	// We have a legacy remote state configuration simultaneously with a
   341  	// saved backend configuration while at the same time disabling backend
   342  	// configuration.
   343  	//
   344  	// This is a naturally impossible case: Terraform will never put you
   345  	// in this state, though it is theoretically possible through manual edits
   346  	case c == nil && !s.Remote.Empty() && !s.Backend.Empty():
   347  		if !opts.Init {
   348  			initReason := fmt.Sprintf(
   349  				"Unsetting the previously set backend %q",
   350  				s.Backend.Type)
   351  			m.backendInitRequired(initReason)
   352  			return nil, errBackendInitRequired
   353  		}
   354  
   355  		return m.backend_c_R_S(c, sMgr)
   356  
   357  	// Configuring a backend for the first time.
   358  	case c != nil && s.Remote.Empty() && s.Backend.Empty():
   359  		if !opts.Init {
   360  			initReason := fmt.Sprintf(
   361  				"Initial configuration of the requested backend %q",
   362  				c.Type)
   363  			m.backendInitRequired(initReason)
   364  			return nil, errBackendInitRequired
   365  		}
   366  
   367  		return m.backend_C_r_s(c, sMgr)
   368  
   369  	// Potentially changing a backend configuration
   370  	case c != nil && s.Remote.Empty() && !s.Backend.Empty():
   371  		// If our configuration is the same, then we're just initializing
   372  		// a previously configured remote backend.
   373  		if !s.Backend.Empty() && s.Backend.Hash == c.Hash {
   374  			return m.backend_C_r_S_unchanged(c, sMgr)
   375  		}
   376  
   377  		if !opts.Init {
   378  			initReason := fmt.Sprintf(
   379  				"Backend configuration changed for %q",
   380  				c.Type)
   381  			m.backendInitRequired(initReason)
   382  			return nil, errBackendInitRequired
   383  		}
   384  
   385  		log.Printf(
   386  			"[WARN] command: backend config change! saved: %d, new: %d",
   387  			s.Backend.Hash, c.Hash)
   388  		return m.backend_C_r_S_changed(c, sMgr, true)
   389  
   390  	// Configuring a backend for the first time while having legacy
   391  	// remote state. This is very possible if a Terraform user configures
   392  	// a backend prior to ever running Terraform on an old state.
   393  	case c != nil && !s.Remote.Empty() && s.Backend.Empty():
   394  		if !opts.Init {
   395  			initReason := fmt.Sprintf(
   396  				"Initial configuration for backend %q",
   397  				c.Type)
   398  			m.backendInitRequired(initReason)
   399  			return nil, errBackendInitRequired
   400  		}
   401  
   402  		return m.backend_C_R_s(c, sMgr)
   403  
   404  	// Configuring a backend with both a legacy remote state set
   405  	// and a pre-existing backend saved.
   406  	case c != nil && !s.Remote.Empty() && !s.Backend.Empty():
   407  		// If the hashes are the same, we have a legacy remote state with
   408  		// an unchanged stored backend state.
   409  		if s.Backend.Hash == c.Hash {
   410  			if !opts.Init {
   411  				initReason := fmt.Sprintf(
   412  					"Legacy remote state found with configured backend %q",
   413  					c.Type)
   414  				m.backendInitRequired(initReason)
   415  				return nil, errBackendInitRequired
   416  			}
   417  
   418  			return m.backend_C_R_S_unchanged(c, sMgr, true)
   419  		}
   420  
   421  		if !opts.Init {
   422  			initReason := fmt.Sprintf(
   423  				"Reconfiguring the backend %q",
   424  				c.Type)
   425  			m.backendInitRequired(initReason)
   426  			return nil, errBackendInitRequired
   427  		}
   428  
   429  		// We have change in all three
   430  		return m.backend_C_R_S_changed(c, sMgr)
   431  	default:
   432  		// This should be impossible since all state possibilties are
   433  		// tested above, but we need a default case anyways and we should
   434  		// protect against the scenario where a case is somehow removed.
   435  		return nil, fmt.Errorf(
   436  			"Unhandled backend configuration state. This is a bug. Please\n"+
   437  				"report this error with the following information.\n\n"+
   438  				"Config Nil: %v\n"+
   439  				"Saved Backend Empty: %v\n"+
   440  				"Legacy Remote Empty: %v\n",
   441  			c == nil, s.Backend.Empty(), s.Remote.Empty())
   442  	}
   443  }
   444  
   445  // backendFromPlan loads the backend from a given plan file.
   446  func (m *Meta) backendFromPlan(opts *BackendOpts) (backend.Backend, error) {
   447  	// Precondition check
   448  	if opts.Plan == nil {
   449  		panic("plan should not be nil")
   450  	}
   451  
   452  	// We currently don't allow "-state" to be specified.
   453  	if m.statePath != "" {
   454  		return nil, fmt.Errorf(
   455  			"State path cannot be specified with a plan file. The plan itself contains\n" +
   456  				"the state to use. If you wish to change that, please create a new plan\n" +
   457  				"and specify the state path when creating the plan.")
   458  	}
   459  
   460  	planState := opts.Plan.State
   461  	if planState == nil {
   462  		// The state can be nil, we just have to make it empty for the logic
   463  		// in this function.
   464  		planState = terraform.NewState()
   465  	}
   466  
   467  	// Validation only for non-local plans
   468  	local := planState.Remote.Empty() && planState.Backend.Empty()
   469  	if !local {
   470  		// We currently don't allow "-state-out" to be specified.
   471  		if m.stateOutPath != "" {
   472  			return nil, fmt.Errorf(strings.TrimSpace(errBackendPlanStateFlag))
   473  		}
   474  	}
   475  
   476  	/*
   477  		// Determine the path where we'd be writing state
   478  		path := DefaultStateFilename
   479  		if !planState.Remote.Empty() || !planState.Backend.Empty() {
   480  			path = filepath.Join(m.DataDir(), DefaultStateFilename)
   481  		}
   482  
   483  		// If the path exists, then we need to verify we're writing the same
   484  		// state lineage. If the path doesn't exist that's okay.
   485  		_, err := os.Stat(path)
   486  		if err != nil && !os.IsNotExist(err) {
   487  			return nil, fmt.Errorf("Error checking state destination: %s", err)
   488  		}
   489  		if err == nil {
   490  			// The file exists, we need to read it and compare
   491  			if err := m.backendFromPlan_compareStates(state, path); err != nil {
   492  				return nil, err
   493  			}
   494  		}
   495  	*/
   496  
   497  	// If we have a stateOutPath, we must also specify it as the
   498  	// input path so we can check it properly. We restore it after this
   499  	// function exits.
   500  	original := m.statePath
   501  	m.statePath = m.stateOutPath
   502  	defer func() { m.statePath = original }()
   503  
   504  	var b backend.Backend
   505  	var err error
   506  	switch {
   507  	// No remote state at all, all local
   508  	case planState.Remote.Empty() && planState.Backend.Empty():
   509  		// Get the local backend
   510  		b, err = m.Backend(&BackendOpts{ForceLocal: true})
   511  
   512  	// New backend configuration set
   513  	case planState.Remote.Empty() && !planState.Backend.Empty():
   514  		b, err = m.backendInitFromSaved(planState.Backend)
   515  
   516  	// Legacy remote state set
   517  	case !planState.Remote.Empty() && planState.Backend.Empty():
   518  		// Write our current state to an inmemory state just so that we
   519  		// have it in the format of state.State
   520  		inmem := &state.InmemState{}
   521  		inmem.WriteState(planState)
   522  
   523  		// Get the backend through the normal means of legacy state
   524  		b, err = m.backend_c_R_s(nil, inmem)
   525  
   526  	// Both set, this can't happen in a plan.
   527  	case !planState.Remote.Empty() && !planState.Backend.Empty():
   528  		return nil, fmt.Errorf(strings.TrimSpace(errBackendPlanBoth))
   529  	}
   530  
   531  	// If we had an error, return that
   532  	if err != nil {
   533  		return nil, err
   534  	}
   535  
   536  	env := m.Env()
   537  
   538  	// Get the state so we can determine the effect of using this plan
   539  	realMgr, err := b.State(env)
   540  	if err != nil {
   541  		return nil, fmt.Errorf("Error reading state: %s", err)
   542  	}
   543  
   544  	// Lock the state if we can
   545  	lockInfo := state.NewLockInfo()
   546  	lockInfo.Operation = "backend from plan"
   547  
   548  	lockID, err := clistate.Lock(realMgr, lockInfo, m.Ui, m.Colorize())
   549  	if err != nil {
   550  		return nil, fmt.Errorf("Error locking state: %s", err)
   551  	}
   552  	defer clistate.Unlock(realMgr, lockID, m.Ui, m.Colorize())
   553  
   554  	if err := realMgr.RefreshState(); err != nil {
   555  		return nil, fmt.Errorf("Error reading state: %s", err)
   556  	}
   557  	real := realMgr.State()
   558  	if real != nil {
   559  		// If they're not the same lineage, don't allow this
   560  		if !real.SameLineage(planState) {
   561  			return nil, fmt.Errorf(strings.TrimSpace(errBackendPlanLineageDiff))
   562  		}
   563  
   564  		// Compare ages
   565  		comp, err := real.CompareAges(planState)
   566  		if err != nil {
   567  			return nil, fmt.Errorf("Error comparing state ages for safety: %s", err)
   568  		}
   569  		switch comp {
   570  		case terraform.StateAgeEqual:
   571  			// State ages are equal, this is perfect
   572  
   573  		case terraform.StateAgeReceiverOlder:
   574  			// Real state is somehow older, this is okay.
   575  
   576  		case terraform.StateAgeReceiverNewer:
   577  			// If we have an older serial it is a problem but if we have a
   578  			// differing serial but are still identical, just let it through.
   579  			if real.Equal(planState) {
   580  				log.Printf(
   581  					"[WARN] command: state in plan has older serial, but Equal is true")
   582  				break
   583  			}
   584  
   585  			// The real state is newer, this is not allowed.
   586  			return nil, fmt.Errorf(
   587  				strings.TrimSpace(errBackendPlanOlder),
   588  				planState.Serial, real.Serial)
   589  		}
   590  	}
   591  
   592  	// Write the state
   593  	newState := opts.Plan.State.DeepCopy()
   594  	if newState != nil {
   595  		newState.Remote = nil
   596  		newState.Backend = nil
   597  	}
   598  
   599  	// realMgr locked above
   600  	if err := realMgr.WriteState(newState); err != nil {
   601  		return nil, fmt.Errorf("Error writing state: %s", err)
   602  	}
   603  	if err := realMgr.PersistState(); err != nil {
   604  		return nil, fmt.Errorf("Error writing state: %s", err)
   605  	}
   606  
   607  	return b, nil
   608  }
   609  
   610  //-------------------------------------------------------------------
   611  // Backend Config Scenarios
   612  //
   613  // The functions below cover handling all the various scenarios that
   614  // can exist when loading a backend. They are named in the format of
   615  // "backend_C_R_S" where C, R, S may be upper or lowercase. Lowercase
   616  // means it is false, uppercase means it is true. The full set of eight
   617  // possible cases is handled.
   618  //
   619  // The fields are:
   620  //
   621  //   * C - Backend configuration is set and changed in TF files
   622  //   * R - Legacy remote state is set
   623  //   * S - Backend configuration is set in the state
   624  //
   625  //-------------------------------------------------------------------
   626  
   627  // Unconfiguring a backend (moving from backend => local).
   628  func (m *Meta) backend_c_r_S(
   629  	c *config.Backend, sMgr state.State, output bool) (backend.Backend, error) {
   630  	s := sMgr.State()
   631  
   632  	// Get the backend type for output
   633  	backendType := s.Backend.Type
   634  
   635  	// Confirm with the user that the copy should occur
   636  	copy, err := m.confirm(&terraform.InputOpts{
   637  		Id:    "backend-migrate-to-local",
   638  		Query: fmt.Sprintf("Do you want to copy the state from %q?", s.Backend.Type),
   639  		Description: fmt.Sprintf(
   640  			strings.TrimSpace(inputBackendMigrateLocal), s.Backend.Type),
   641  	})
   642  	if err != nil {
   643  		return nil, fmt.Errorf(
   644  			"Error asking for state copy action: %s", err)
   645  	}
   646  
   647  	// If we're copying, perform the migration
   648  	if copy {
   649  		// Grab a purely local backend to get the local state if it exists
   650  		localB, err := m.Backend(&BackendOpts{ForceLocal: true})
   651  		if err != nil {
   652  			return nil, fmt.Errorf(strings.TrimSpace(errBackendLocalRead), err)
   653  		}
   654  
   655  		// Initialize the configured backend
   656  		b, err := m.backend_C_r_S_unchanged(c, sMgr)
   657  		if err != nil {
   658  			return nil, fmt.Errorf(
   659  				strings.TrimSpace(errBackendSavedUnsetConfig), s.Backend.Type, err)
   660  		}
   661  
   662  		// Perform the migration
   663  		err = m.backendMigrateState(&backendMigrateOpts{
   664  			OneType: s.Backend.Type,
   665  			TwoType: "local",
   666  			One:     b,
   667  			Two:     localB,
   668  		})
   669  		if err != nil {
   670  			return nil, err
   671  		}
   672  	}
   673  
   674  	// Remove the stored metadata
   675  	s.Backend = nil
   676  	if err := sMgr.WriteState(s); err != nil {
   677  		return nil, fmt.Errorf(strings.TrimSpace(errBackendClearSaved), err)
   678  	}
   679  	if err := sMgr.PersistState(); err != nil {
   680  		return nil, fmt.Errorf(strings.TrimSpace(errBackendClearSaved), err)
   681  	}
   682  
   683  	if output {
   684  		m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
   685  			"[reset][green]\n\n"+
   686  				strings.TrimSpace(successBackendUnset), backendType)))
   687  	}
   688  
   689  	// Return no backend
   690  	return nil, nil
   691  }
   692  
   693  // Legacy remote state
   694  func (m *Meta) backend_c_R_s(
   695  	c *config.Backend, sMgr state.State) (backend.Backend, error) {
   696  	s := sMgr.State()
   697  
   698  	// Warn the user
   699  	m.Ui.Warn(strings.TrimSpace(warnBackendLegacy) + "\n")
   700  
   701  	// We need to convert the config to map[string]interface{} since that
   702  	// is what the backends expect.
   703  	var configMap map[string]interface{}
   704  	if err := mapstructure.Decode(s.Remote.Config, &configMap); err != nil {
   705  		return nil, fmt.Errorf("Error configuring remote state: %s", err)
   706  	}
   707  
   708  	// Create the config
   709  	rawC, err := config.NewRawConfig(configMap)
   710  	if err != nil {
   711  		return nil, fmt.Errorf("Error configuring remote state: %s", err)
   712  	}
   713  	config := terraform.NewResourceConfig(rawC)
   714  
   715  	// Get the backend
   716  	f := backendinit.Backend(s.Remote.Type)
   717  	if f == nil {
   718  		return nil, fmt.Errorf(strings.TrimSpace(errBackendLegacyUnknown), s.Remote.Type)
   719  	}
   720  	b := f()
   721  
   722  	// Configure
   723  	if err := b.Configure(config); err != nil {
   724  		return nil, fmt.Errorf(errBackendLegacyConfig, err)
   725  	}
   726  
   727  	return b, nil
   728  }
   729  
   730  // Unsetting backend, saved backend, legacy remote state
   731  func (m *Meta) backend_c_R_S(
   732  	c *config.Backend, sMgr state.State) (backend.Backend, error) {
   733  	// Notify the user
   734  	m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
   735  		"[reset]%s\n\n",
   736  		strings.TrimSpace(outputBackendUnsetWithLegacy))))
   737  
   738  	// Get the backend type for later
   739  	backendType := sMgr.State().Backend.Type
   740  
   741  	// First, perform the configured => local tranasition
   742  	if _, err := m.backend_c_r_S(c, sMgr, false); err != nil {
   743  		return nil, err
   744  	}
   745  
   746  	// Grab a purely local backend
   747  	localB, err := m.Backend(&BackendOpts{ForceLocal: true})
   748  	if err != nil {
   749  		return nil, fmt.Errorf(errBackendLocalRead, err)
   750  	}
   751  
   752  	// Grab the state
   753  	s := sMgr.State()
   754  
   755  	// Ask the user if they want to migrate their existing remote state
   756  	copy, err := m.confirm(&terraform.InputOpts{
   757  		Id: "backend-migrate-to-new",
   758  		Query: fmt.Sprintf(
   759  			"Do you want to copy the legacy remote state from %q?",
   760  			s.Remote.Type),
   761  		Description: strings.TrimSpace(inputBackendMigrateLegacyLocal),
   762  	})
   763  	if err != nil {
   764  		return nil, fmt.Errorf(
   765  			"Error asking for state copy action: %s", err)
   766  	}
   767  
   768  	// If the user wants a copy, copy!
   769  	if copy {
   770  		// Initialize the legacy backend
   771  		oldB, err := m.backendInitFromLegacy(s.Remote)
   772  		if err != nil {
   773  			return nil, err
   774  		}
   775  
   776  		// Perform the migration
   777  		err = m.backendMigrateState(&backendMigrateOpts{
   778  			OneType: s.Remote.Type,
   779  			TwoType: "local",
   780  			One:     oldB,
   781  			Two:     localB,
   782  		})
   783  		if err != nil {
   784  			return nil, err
   785  		}
   786  	}
   787  
   788  	// Unset the remote state
   789  	s = sMgr.State()
   790  	if s == nil {
   791  		s = terraform.NewState()
   792  	}
   793  	s.Remote = nil
   794  	if err := sMgr.WriteState(s); err != nil {
   795  		return nil, fmt.Errorf(strings.TrimSpace(errBackendClearLegacy), err)
   796  	}
   797  	if err := sMgr.PersistState(); err != nil {
   798  		return nil, fmt.Errorf(strings.TrimSpace(errBackendClearLegacy), err)
   799  	}
   800  
   801  	m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
   802  		"[reset][green]\n\n"+
   803  			strings.TrimSpace(successBackendUnset), backendType)))
   804  
   805  	return nil, nil
   806  }
   807  
   808  // Configuring a backend for the first time with legacy remote state.
   809  func (m *Meta) backend_C_R_s(
   810  	c *config.Backend, sMgr state.State) (backend.Backend, error) {
   811  	// Notify the user
   812  	m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
   813  		"[reset]%s\n\n",
   814  		strings.TrimSpace(outputBackendConfigureWithLegacy))))
   815  
   816  	// First, configure the new backend
   817  	b, err := m.backendInitFromConfig(c)
   818  	if err != nil {
   819  		return nil, err
   820  	}
   821  
   822  	// Next, save the new configuration. This will not overwrite our
   823  	// legacy remote state. We'll handle that after.
   824  	s := sMgr.State()
   825  	if s == nil {
   826  		s = terraform.NewState()
   827  	}
   828  	s.Backend = &terraform.BackendState{
   829  		Type:   c.Type,
   830  		Config: c.RawConfig.Raw,
   831  		Hash:   c.Hash,
   832  	}
   833  	if err := sMgr.WriteState(s); err != nil {
   834  		return nil, fmt.Errorf(errBackendWriteSaved, err)
   835  	}
   836  	if err := sMgr.PersistState(); err != nil {
   837  		return nil, fmt.Errorf(errBackendWriteSaved, err)
   838  	}
   839  
   840  	// I don't know how this is possible but if we don't have remote
   841  	// state config anymore somehow, just return the backend. This
   842  	// shouldn't be possible, though.
   843  	if s.Remote.Empty() {
   844  		return b, nil
   845  	}
   846  
   847  	// Finally, ask the user if they want to copy the state from
   848  	// their old remote state location.
   849  	copy, err := m.confirm(&terraform.InputOpts{
   850  		Id: "backend-migrate-to-new",
   851  		Query: fmt.Sprintf(
   852  			"Do you want to copy the legacy remote state from %q?",
   853  			s.Remote.Type),
   854  		Description: strings.TrimSpace(inputBackendMigrateLegacy),
   855  	})
   856  	if err != nil {
   857  		return nil, fmt.Errorf(
   858  			"Error asking for state copy action: %s", err)
   859  	}
   860  
   861  	// If the user wants a copy, copy!
   862  	if copy {
   863  		// Initialize the legacy backend
   864  		oldB, err := m.backendInitFromLegacy(s.Remote)
   865  		if err != nil {
   866  			return nil, err
   867  		}
   868  
   869  		// Perform the migration
   870  		err = m.backendMigrateState(&backendMigrateOpts{
   871  			OneType: s.Remote.Type,
   872  			TwoType: c.Type,
   873  			One:     oldB,
   874  			Two:     b,
   875  		})
   876  		if err != nil {
   877  			return nil, err
   878  		}
   879  	}
   880  
   881  	// Unset the remote state
   882  	s = sMgr.State()
   883  	if s == nil {
   884  		s = terraform.NewState()
   885  	}
   886  	s.Remote = nil
   887  	if err := sMgr.WriteState(s); err != nil {
   888  		return nil, fmt.Errorf(strings.TrimSpace(errBackendClearLegacy), err)
   889  	}
   890  	if err := sMgr.PersistState(); err != nil {
   891  		return nil, fmt.Errorf(strings.TrimSpace(errBackendClearLegacy), err)
   892  	}
   893  
   894  	m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
   895  		"[reset][green]\n\n"+
   896  			strings.TrimSpace(successBackendSet), s.Backend.Type)))
   897  
   898  	return b, nil
   899  }
   900  
   901  // Configuring a backend for the first time.
   902  func (m *Meta) backend_C_r_s(
   903  	c *config.Backend, sMgr state.State) (backend.Backend, error) {
   904  	// Get the backend
   905  	b, err := m.backendInitFromConfig(c)
   906  	if err != nil {
   907  		return nil, err
   908  	}
   909  
   910  	// Grab a purely local backend to get the local state if it exists
   911  	localB, err := m.Backend(&BackendOpts{ForceLocal: true})
   912  	if err != nil {
   913  		return nil, fmt.Errorf(errBackendLocalRead, err)
   914  	}
   915  
   916  	env := m.Env()
   917  
   918  	localState, err := localB.State(env)
   919  	if err != nil {
   920  		return nil, fmt.Errorf(errBackendLocalRead, err)
   921  	}
   922  	if err := localState.RefreshState(); err != nil {
   923  		return nil, fmt.Errorf(errBackendLocalRead, err)
   924  	}
   925  
   926  	// If the local state is not empty, we need to potentially do a
   927  	// state migration to the new backend (with user permission).
   928  	if localS := localState.State(); !localS.Empty() {
   929  		// Perform the migration
   930  		err = m.backendMigrateState(&backendMigrateOpts{
   931  			OneType: "local",
   932  			TwoType: c.Type,
   933  			One:     localB,
   934  			Two:     b,
   935  		})
   936  		if err != nil {
   937  			return nil, err
   938  		}
   939  
   940  		// We always delete the local state
   941  		if err := localState.WriteState(nil); err != nil {
   942  			return nil, fmt.Errorf(errBackendMigrateLocalDelete, err)
   943  		}
   944  		if err := localState.PersistState(); err != nil {
   945  			return nil, fmt.Errorf(errBackendMigrateLocalDelete, err)
   946  		}
   947  	}
   948  
   949  	// Lock the state if we can
   950  	lockInfo := state.NewLockInfo()
   951  	lockInfo.Operation = "backend from config"
   952  
   953  	lockID, err := clistate.Lock(sMgr, lockInfo, m.Ui, m.Colorize())
   954  	if err != nil {
   955  		return nil, fmt.Errorf("Error locking state: %s", err)
   956  	}
   957  	defer clistate.Unlock(sMgr, lockID, m.Ui, m.Colorize())
   958  
   959  	// Store the metadata in our saved state location
   960  	s := sMgr.State()
   961  	if s == nil {
   962  		s = terraform.NewState()
   963  	}
   964  	s.Backend = &terraform.BackendState{
   965  		Type:   c.Type,
   966  		Config: c.RawConfig.Raw,
   967  		Hash:   c.Hash,
   968  	}
   969  
   970  	if err := sMgr.WriteState(s); err != nil {
   971  		return nil, fmt.Errorf(errBackendWriteSaved, err)
   972  	}
   973  	if err := sMgr.PersistState(); err != nil {
   974  		return nil, fmt.Errorf(errBackendWriteSaved, err)
   975  	}
   976  
   977  	m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
   978  		"[reset][green]\n\n"+
   979  			strings.TrimSpace(successBackendSet), s.Backend.Type)))
   980  
   981  	// Return the backend
   982  	return b, nil
   983  }
   984  
   985  // Changing a previously saved backend.
   986  func (m *Meta) backend_C_r_S_changed(
   987  	c *config.Backend, sMgr state.State, output bool) (backend.Backend, error) {
   988  	if output {
   989  		// Notify the user
   990  		m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
   991  			"[reset]%s\n\n",
   992  			strings.TrimSpace(outputBackendReconfigure))))
   993  	}
   994  
   995  	// Get the old state
   996  	s := sMgr.State()
   997  
   998  	// Get the backend
   999  	b, err := m.backendInitFromConfig(c)
  1000  	if err != nil {
  1001  		return nil, fmt.Errorf(
  1002  			"Error initializing new backend: %s", err)
  1003  	}
  1004  
  1005  	// Check with the user if we want to migrate state
  1006  	copy, err := m.confirm(&terraform.InputOpts{
  1007  		Id:          "backend-migrate-to-new",
  1008  		Query:       fmt.Sprintf("Do you want to copy the state from %q?", c.Type),
  1009  		Description: strings.TrimSpace(fmt.Sprintf(inputBackendMigrateChange, c.Type, s.Backend.Type)),
  1010  	})
  1011  	if err != nil {
  1012  		return nil, fmt.Errorf(
  1013  			"Error asking for state copy action: %s", err)
  1014  	}
  1015  
  1016  	// If we are, then we need to initialize the old backend and
  1017  	// perform the copy.
  1018  	if copy {
  1019  		// Grab the existing backend
  1020  		oldB, err := m.backend_C_r_S_unchanged(c, sMgr)
  1021  		if err != nil {
  1022  			return nil, fmt.Errorf(
  1023  				"Error loading previously configured backend: %s", err)
  1024  		}
  1025  
  1026  		// Perform the migration
  1027  		err = m.backendMigrateState(&backendMigrateOpts{
  1028  			OneType: s.Backend.Type,
  1029  			TwoType: c.Type,
  1030  			One:     oldB,
  1031  			Two:     b,
  1032  		})
  1033  		if err != nil {
  1034  			return nil, err
  1035  		}
  1036  	}
  1037  
  1038  	// Lock the state if we can
  1039  	lockInfo := state.NewLockInfo()
  1040  	lockInfo.Operation = "backend from config"
  1041  
  1042  	lockID, err := clistate.Lock(sMgr, lockInfo, m.Ui, m.Colorize())
  1043  	if err != nil {
  1044  		return nil, fmt.Errorf("Error locking state: %s", err)
  1045  	}
  1046  	defer clistate.Unlock(sMgr, lockID, m.Ui, m.Colorize())
  1047  
  1048  	// Update the backend state
  1049  	s = sMgr.State()
  1050  	if s == nil {
  1051  		s = terraform.NewState()
  1052  	}
  1053  	s.Backend = &terraform.BackendState{
  1054  		Type:   c.Type,
  1055  		Config: c.RawConfig.Raw,
  1056  		Hash:   c.Hash,
  1057  	}
  1058  
  1059  	if err := sMgr.WriteState(s); err != nil {
  1060  		return nil, fmt.Errorf(errBackendWriteSaved, err)
  1061  	}
  1062  	if err := sMgr.PersistState(); err != nil {
  1063  		return nil, fmt.Errorf(errBackendWriteSaved, err)
  1064  	}
  1065  
  1066  	if output {
  1067  		m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
  1068  			"[reset][green]\n\n"+
  1069  				strings.TrimSpace(successBackendSet), s.Backend.Type)))
  1070  	}
  1071  
  1072  	return b, nil
  1073  }
  1074  
  1075  // Initiailizing an unchanged saved backend
  1076  func (m *Meta) backend_C_r_S_unchanged(
  1077  	c *config.Backend, sMgr state.State) (backend.Backend, error) {
  1078  	s := sMgr.State()
  1079  
  1080  	// Create the config. We do this from the backend state since this
  1081  	// has the complete configuration data whereas the config itself
  1082  	// may require input.
  1083  	rawC, err := config.NewRawConfig(s.Backend.Config)
  1084  	if err != nil {
  1085  		return nil, fmt.Errorf("Error configuring backend: %s", err)
  1086  	}
  1087  	config := terraform.NewResourceConfig(rawC)
  1088  
  1089  	// Get the backend
  1090  	f := backendinit.Backend(s.Backend.Type)
  1091  	if f == nil {
  1092  		return nil, fmt.Errorf(strings.TrimSpace(errBackendSavedUnknown), s.Backend.Type)
  1093  	}
  1094  	b := f()
  1095  
  1096  	// Configure
  1097  	if err := b.Configure(config); err != nil {
  1098  		return nil, fmt.Errorf(errBackendSavedConfig, s.Backend.Type, err)
  1099  	}
  1100  
  1101  	return b, nil
  1102  }
  1103  
  1104  // Initiailizing a changed saved backend with legacy remote state.
  1105  func (m *Meta) backend_C_R_S_changed(
  1106  	c *config.Backend, sMgr state.State) (backend.Backend, error) {
  1107  	// Notify the user
  1108  	m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
  1109  		"[reset]%s\n\n",
  1110  		strings.TrimSpace(outputBackendSavedWithLegacyChanged))))
  1111  
  1112  	// Reconfigure the backend first
  1113  	if _, err := m.backend_C_r_S_changed(c, sMgr, false); err != nil {
  1114  		return nil, err
  1115  	}
  1116  
  1117  	// Handle the case where we have all set but unchanged
  1118  	b, err := m.backend_C_R_S_unchanged(c, sMgr, false)
  1119  	if err != nil {
  1120  		return nil, err
  1121  	}
  1122  
  1123  	// Output success message
  1124  	m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
  1125  		"[reset][green]\n\n"+
  1126  			strings.TrimSpace(successBackendReconfigureWithLegacy), c.Type)))
  1127  
  1128  	return b, nil
  1129  }
  1130  
  1131  // Initiailizing an unchanged saved backend with legacy remote state.
  1132  func (m *Meta) backend_C_R_S_unchanged(
  1133  	c *config.Backend, sMgr state.State, output bool) (backend.Backend, error) {
  1134  	if output {
  1135  		// Notify the user
  1136  		m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
  1137  			"[reset]%s\n\n",
  1138  			strings.TrimSpace(outputBackendSavedWithLegacy))))
  1139  	}
  1140  
  1141  	// Load the backend from the state
  1142  	s := sMgr.State()
  1143  	b, err := m.backendInitFromSaved(s.Backend)
  1144  	if err != nil {
  1145  		return nil, err
  1146  	}
  1147  
  1148  	// Ask if the user wants to move their legacy remote state
  1149  	copy, err := m.confirm(&terraform.InputOpts{
  1150  		Id: "backend-migrate-to-new",
  1151  		Query: fmt.Sprintf(
  1152  			"Do you want to copy the legacy remote state from %q?",
  1153  			s.Remote.Type),
  1154  		Description: strings.TrimSpace(inputBackendMigrateLegacy),
  1155  	})
  1156  	if err != nil {
  1157  		return nil, fmt.Errorf(
  1158  			"Error asking for state copy action: %s", err)
  1159  	}
  1160  
  1161  	// If the user wants a copy, copy!
  1162  	if copy {
  1163  		// Initialize the legacy backend
  1164  		oldB, err := m.backendInitFromLegacy(s.Remote)
  1165  		if err != nil {
  1166  			return nil, err
  1167  		}
  1168  
  1169  		// Perform the migration
  1170  		err = m.backendMigrateState(&backendMigrateOpts{
  1171  			OneType: s.Remote.Type,
  1172  			TwoType: s.Backend.Type,
  1173  			One:     oldB,
  1174  			Two:     b,
  1175  		})
  1176  		if err != nil {
  1177  			return nil, err
  1178  		}
  1179  	}
  1180  
  1181  	// Lock the state if we can
  1182  	lockInfo := state.NewLockInfo()
  1183  	lockInfo.Operation = "backend from config"
  1184  
  1185  	lockID, err := clistate.Lock(sMgr, lockInfo, m.Ui, m.Colorize())
  1186  	if err != nil {
  1187  		return nil, fmt.Errorf("Error locking state: %s", err)
  1188  	}
  1189  	defer clistate.Unlock(sMgr, lockID, m.Ui, m.Colorize())
  1190  
  1191  	// Unset the remote state
  1192  	s = sMgr.State()
  1193  	if s == nil {
  1194  		s = terraform.NewState()
  1195  	}
  1196  	s.Remote = nil
  1197  
  1198  	if err := sMgr.WriteState(s); err != nil {
  1199  		return nil, fmt.Errorf(strings.TrimSpace(errBackendClearLegacy), err)
  1200  	}
  1201  	if err := sMgr.PersistState(); err != nil {
  1202  		return nil, fmt.Errorf(strings.TrimSpace(errBackendClearLegacy), err)
  1203  	}
  1204  
  1205  	if output {
  1206  		m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
  1207  			"[reset][green]\n\n"+
  1208  				strings.TrimSpace(successBackendLegacyUnset), s.Backend.Type)))
  1209  	}
  1210  
  1211  	return b, nil
  1212  }
  1213  
  1214  //-------------------------------------------------------------------
  1215  // Reusable helper functions for backend management
  1216  //-------------------------------------------------------------------
  1217  
  1218  func (m *Meta) backendInitFromConfig(c *config.Backend) (backend.Backend, error) {
  1219  	// Create the config.
  1220  	config := terraform.NewResourceConfig(c.RawConfig)
  1221  
  1222  	// Get the backend
  1223  	f := backendinit.Backend(c.Type)
  1224  	if f == nil {
  1225  		return nil, fmt.Errorf(strings.TrimSpace(errBackendNewUnknown), c.Type)
  1226  	}
  1227  	b := f()
  1228  
  1229  	// TODO: test
  1230  	// Ask for input if we have input enabled
  1231  	if m.Input() {
  1232  		var err error
  1233  		config, err = b.Input(m.UIInput(), config)
  1234  		if err != nil {
  1235  			return nil, fmt.Errorf(
  1236  				"Error asking for input to configure the backend %q: %s",
  1237  				c.Type, err)
  1238  		}
  1239  	}
  1240  
  1241  	// Validate
  1242  	warns, errs := b.Validate(config)
  1243  	if len(errs) > 0 {
  1244  		return nil, fmt.Errorf(
  1245  			"Error configuring the backend %q: %s",
  1246  			c.Type, multierror.Append(nil, errs...))
  1247  	}
  1248  	if len(warns) > 0 {
  1249  		// TODO: warnings are currently ignored
  1250  	}
  1251  
  1252  	// Configure
  1253  	if err := b.Configure(config); err != nil {
  1254  		return nil, fmt.Errorf(errBackendNewConfig, c.Type, err)
  1255  	}
  1256  
  1257  	return b, nil
  1258  }
  1259  
  1260  func (m *Meta) backendInitFromLegacy(s *terraform.RemoteState) (backend.Backend, error) {
  1261  	// We need to convert the config to map[string]interface{} since that
  1262  	// is what the backends expect.
  1263  	var configMap map[string]interface{}
  1264  	if err := mapstructure.Decode(s.Config, &configMap); err != nil {
  1265  		return nil, fmt.Errorf("Error configuring remote state: %s", err)
  1266  	}
  1267  
  1268  	// Create the config
  1269  	rawC, err := config.NewRawConfig(configMap)
  1270  	if err != nil {
  1271  		return nil, fmt.Errorf("Error configuring remote state: %s", err)
  1272  	}
  1273  	config := terraform.NewResourceConfig(rawC)
  1274  
  1275  	// Initialize the legacy remote backend
  1276  	b := &backendlegacy.Backend{Type: s.Type}
  1277  
  1278  	// Configure
  1279  	if err := b.Configure(config); err != nil {
  1280  		return nil, fmt.Errorf(errBackendLegacyConfig, err)
  1281  	}
  1282  
  1283  	return b, nil
  1284  }
  1285  
  1286  func (m *Meta) backendInitFromSaved(s *terraform.BackendState) (backend.Backend, error) {
  1287  	// Create the config. We do this from the backend state since this
  1288  	// has the complete configuration data whereas the config itself
  1289  	// may require input.
  1290  	rawC, err := config.NewRawConfig(s.Config)
  1291  	if err != nil {
  1292  		return nil, fmt.Errorf("Error configuring backend: %s", err)
  1293  	}
  1294  	config := terraform.NewResourceConfig(rawC)
  1295  
  1296  	// Get the backend
  1297  	f := backendinit.Backend(s.Type)
  1298  	if f == nil {
  1299  		return nil, fmt.Errorf(strings.TrimSpace(errBackendSavedUnknown), s.Type)
  1300  	}
  1301  	b := f()
  1302  
  1303  	// Configure
  1304  	if err := b.Configure(config); err != nil {
  1305  		return nil, fmt.Errorf(errBackendSavedConfig, s.Type, err)
  1306  	}
  1307  
  1308  	return b, nil
  1309  }
  1310  
  1311  func (m *Meta) backendInitRequired(reason string) {
  1312  	m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
  1313  		"[reset]"+strings.TrimSpace(errBackendInit)+"\n", reason)))
  1314  }
  1315  
  1316  //-------------------------------------------------------------------
  1317  // Output constants and initialization code
  1318  //-------------------------------------------------------------------
  1319  
  1320  // errBackendInitRequired is the final error message shown when reinit
  1321  // is required for some reason. The error message includes the reason.
  1322  var errBackendInitRequired = errors.New(
  1323  	"Initialization required. Please see the error message above.")
  1324  
  1325  const errBackendLegacyConfig = `
  1326  One or more errors occurred while configuring the legacy remote state.
  1327  If fixing these errors requires changing your remote state configuration,
  1328  you must switch your configuration to the new remote backend configuration.
  1329  You can learn more about remote backends at the URL below:
  1330  
  1331  TODO: URL
  1332  
  1333  The error(s) configuring the legacy remote state:
  1334  
  1335  %s
  1336  `
  1337  
  1338  const errBackendLegacyUnknown = `
  1339  The legacy remote state type %q could not be found.
  1340  
  1341  Terraform 0.9.0 shipped with backwards compatible for all built-in
  1342  legacy remote state types. This error may mean that you were using a
  1343  custom Terraform build that perhaps supported a different type of
  1344  remote state.
  1345  
  1346  Please check with the creator of the remote state above and try again.
  1347  `
  1348  
  1349  const errBackendLocalRead = `
  1350  Error reading local state: %s
  1351  
  1352  Terraform is trying to read your local state to determine if there is
  1353  state to migrate to your newly configured backend. Terraform can't continue
  1354  without this check because that would risk losing state. Please resolve the
  1355  error above and try again.
  1356  `
  1357  
  1358  const errBackendMigrateLocalDelete = `
  1359  Error deleting local state after migration: %s
  1360  
  1361  Your local state is deleted after successfully migrating it to the newly
  1362  configured backend. As part of the deletion process, a backup is made at
  1363  the standard backup path unless explicitly asked not to. To cleanly operate
  1364  with a backend, we must delete the local state file. Please resolve the
  1365  issue above and retry the command.
  1366  `
  1367  
  1368  const errBackendMigrateNew = `
  1369  Error migrating local state to backend: %s
  1370  
  1371  Your local state remains intact and unmodified. Please resolve the error
  1372  above and try again.
  1373  `
  1374  
  1375  const errBackendNewConfig = `
  1376  Error configuring the backend %q: %s
  1377  
  1378  Please update the configuration in your Terraform files to fix this error
  1379  then run this command again.
  1380  `
  1381  
  1382  const errBackendNewRead = `
  1383  Error reading newly configured backend state: %s
  1384  
  1385  Terraform is trying to read the state from your newly configured backend
  1386  to determine the copy process for your existing state. Backends are expected
  1387  to not error even if there is no state yet written. Please resolve the
  1388  error above and try again.
  1389  `
  1390  
  1391  const errBackendNewUnknown = `
  1392  The backend %q could not be found.
  1393  
  1394  This is the backend specified in your Terraform configuration file.
  1395  This error could be a simple typo in your configuration, but it can also
  1396  be caused by using a Terraform version that doesn't support the specified
  1397  backend type. Please check your configuration and your Terraform version.
  1398  
  1399  If you'd like to run Terraform and store state locally, you can fix this
  1400  error by removing the backend configuration from your configuration.
  1401  `
  1402  
  1403  const errBackendRemoteRead = `
  1404  Error reading backend state: %s
  1405  
  1406  Terraform is trying to read the state from your configured backend to
  1407  determine if there is any migration steps necessary. Terraform can't continue
  1408  without this check because that would risk losing state. Please resolve the
  1409  error above and try again.
  1410  `
  1411  
  1412  const errBackendSavedConfig = `
  1413  Error configuring the backend %q: %s
  1414  
  1415  Please update the configuration in your Terraform files to fix this error.
  1416  If you'd like to update the configuration interactively without storing
  1417  the values in your configuration, run "terraform init".
  1418  `
  1419  
  1420  const errBackendSavedUnsetConfig = `
  1421  Error configuring the existing backend %q: %s
  1422  
  1423  Terraform must configure the existing backend in order to copy the state
  1424  from the existing backend, as requested. Please resolve the error and try
  1425  again. If you choose to not copy the existing state, Terraform will not
  1426  configure the backend. If the configuration is invalid, please update your
  1427  Terraform configuration with proper configuration for this backend first
  1428  before unsetting the backend.
  1429  `
  1430  
  1431  const errBackendSavedUnknown = `
  1432  The backend %q could not be found.
  1433  
  1434  This is the backend that this Terraform environment is configured to use
  1435  both in your configuration and saved locally as your last-used backend.
  1436  If it isn't found, it could mean an alternate version of Terraform was
  1437  used with this configuration. Please use the proper version of Terraform that
  1438  contains support for this backend.
  1439  
  1440  If you'd like to force remove this backend, you must update your configuration
  1441  to not use the backend and run "terraform init" (or any other command) again.
  1442  `
  1443  
  1444  const errBackendClearLegacy = `
  1445  Error clearing the legacy remote state configuration: %s
  1446  
  1447  Terraform completed configuring your backend. It is now safe to remove
  1448  the legacy remote state configuration, but an error occurred while trying
  1449  to do so. Please look at the error above, resolve it, and try again.
  1450  `
  1451  
  1452  const errBackendClearSaved = `
  1453  Error clearing the backend configuration: %s
  1454  
  1455  Terraform removes the saved backend configuration when you're removing a
  1456  configured backend. This must be done so future Terraform runs know to not
  1457  use the backend configuration. Please look at the error above, resolve it,
  1458  and try again.
  1459  `
  1460  
  1461  const errBackendInit = `
  1462  [reset][bold][yellow]Backend reinitialization required. Please run "terraform init".[reset]
  1463  [yellow]Reason: %s
  1464  
  1465  The "backend" is the interface that Terraform uses to store state,
  1466  perform operations, etc. If this message is showing up, it means that the
  1467  Terraform configuration you're using is using a custom configuration for
  1468  the Terraform backend.
  1469  
  1470  Changes to backend configurations require reinitialization. This allows
  1471  Terraform to setup the new configuration, copy existing state, etc. This is
  1472  only done during "terraform init". Please run that command now then try again.
  1473  
  1474  If the change reason above is incorrect, please verify your configuration
  1475  hasn't changed and try again. At this point, no changes to your existing
  1476  configuration or state have been made.
  1477  `
  1478  
  1479  const errBackendWriteSaved = `
  1480  Error saving the backend configuration: %s
  1481  
  1482  Terraform saves the complete backend configuration in a local file for
  1483  configuring the backend on future operations. This cannot be disabled. Errors
  1484  are usually due to simple file permission errors. Please look at the error
  1485  above, resolve it, and try again.
  1486  `
  1487  
  1488  const errBackendPlanBoth = `
  1489  The plan file contained both a legacy remote state and backend configuration.
  1490  This is not allowed. Please recreate the plan file with the latest version of
  1491  Terraform.
  1492  `
  1493  
  1494  const errBackendPlanLineageDiff = `
  1495  The plan file contains a state with a differing lineage than the current
  1496  state. By continuing, your current state would be overwritten by the state
  1497  in the plan. Please either update the plan with the latest state or delete
  1498  your current state and try again.
  1499  
  1500  "Lineage" is a unique identifier generated only once on the creation of
  1501  a new, empty state. If these values differ, it means they were created new
  1502  at different times. Therefore, Terraform must assume that they're completely
  1503  different states.
  1504  
  1505  The most common cause of seeing this error is using a plan that was
  1506  created against a different state. Perhaps the plan is very old and the
  1507  state has since been recreated, or perhaps the plan was against a competely
  1508  different infrastructure.
  1509  `
  1510  
  1511  const errBackendPlanStateFlag = `
  1512  The -state and -state-out flags cannot be set with a plan that has a remote
  1513  state. The plan itself contains the configuration for the remote backend to
  1514  store state. The state will be written there for consistency.
  1515  
  1516  If you wish to change this behavior, please create a plan from local state.
  1517  You may use the state flags with plans from local state to affect where
  1518  the final state is written.
  1519  `
  1520  
  1521  const errBackendPlanOlder = `
  1522  This plan was created against an older state than is current. Please create
  1523  a new plan file against the latest state and try again.
  1524  
  1525  Terraform doesn't allow you to run plans that were created from older
  1526  states since it doesn't properly represent the latest changes Terraform
  1527  may have made, and can result in unsafe behavior.
  1528  
  1529  Plan Serial:    %[1]d
  1530  Current Serial: %[2]d
  1531  `
  1532  
  1533  const inputBackendMigrateChange = `
  1534  Would you like to copy the state from your prior backend %q to the
  1535  newly configured %q backend? If you're reconfiguring the same backend,
  1536  answering "yes" or "no" shouldn't make a difference. Please answer exactly
  1537  "yes" or "no".
  1538  `
  1539  
  1540  const inputBackendMigrateLegacy = `
  1541  Terraform can copy the existing state in your legacy remote state
  1542  backend to your newly configured backend. Please answer "yes" or "no".
  1543  `
  1544  
  1545  const inputBackendMigrateLegacyLocal = `
  1546  Terraform can copy the existing state in your legacy remote state
  1547  backend to your local state. Please answer "yes" or "no".
  1548  `
  1549  
  1550  const inputBackendMigrateLocal = `
  1551  Terraform has detected you're unconfiguring your previously set backend.
  1552  Would you like to copy the state from %q to local state? Please answer
  1553  "yes" or "no". If you answer "no", you will start with a blank local state.
  1554  `
  1555  
  1556  const outputBackendConfigureWithLegacy = `
  1557  [reset][bold]New backend configuration detected with legacy remote state![reset]
  1558  
  1559  Terraform has detected that you're attempting to configure a new backend.
  1560  At the same time, legacy remote state configuration was found. Terraform will
  1561  first configure the new backend, and then ask if you'd like to migrate
  1562  your remote state to the new backend.
  1563  `
  1564  
  1565  const outputBackendReconfigure = `
  1566  [reset][bold]Backend configuration changed![reset]
  1567  
  1568  Terraform has detected that the configuration specified for the backend
  1569  has changed. Terraform will now reconfigure for this backend. If you didn't
  1570  intend to reconfigure your backend please undo any changes to the "backend"
  1571  section in your Terraform configuration.
  1572  `
  1573  
  1574  const outputBackendSavedWithLegacy = `
  1575  [reset][bold]Legacy remote state was detected![reset]
  1576  
  1577  Terraform has detected you still have legacy remote state enabled while
  1578  also having a backend configured. Terraform will now ask if you want to
  1579  migrate your legacy remote state data to the configured backend.
  1580  `
  1581  
  1582  const outputBackendSavedWithLegacyChanged = `
  1583  [reset][bold]Legacy remote state was detected while also changing your current backend!reset]
  1584  
  1585  Terraform has detected that you have legacy remote state, a configured
  1586  current backend, and you're attempting to reconfigure your backend. To handle
  1587  all of these changes, Terraform will first reconfigure your backend. After
  1588  this, Terraform will handle optionally copying your legacy remote state
  1589  into the newly configured backend.
  1590  `
  1591  
  1592  const outputBackendUnsetWithLegacy = `
  1593  [reset][bold]Detected a request to unset the backend with legacy remote state present![reset]
  1594  
  1595  Terraform has detected that you're attempting to unset a previously configured
  1596  backend (by not having the "backend" configuration set in your Terraform files).
  1597  At the same time, legacy remote state was detected. To handle this complex
  1598  scenario, Terraform will first unset your configured backend, and then
  1599  ask you how to handle the legacy remote state. This will be multi-step
  1600  process.
  1601  `
  1602  
  1603  const successBackendLegacyUnset = `
  1604  Terraform has successfully migrated from legacy remote state to your
  1605  configured remote state.
  1606  `
  1607  
  1608  const successBackendReconfigureWithLegacy = `
  1609  Terraform has successfully reconfigured your backend and migrate
  1610  from legacy remote state to the new backend.
  1611  `
  1612  
  1613  const successBackendUnset = `
  1614  Successfully unset the backend %q. Terraform will now operate locally.
  1615  `
  1616  
  1617  const successBackendSet = `
  1618  Successfully configured the backend %q! Terraform will automatically
  1619  use this backend unless the backend configuration changes.
  1620  `
  1621  
  1622  const warnBackendLegacy = `
  1623  Deprecation warning: This environment is configured to use legacy remote state.
  1624  Remote state changed significantly in Terraform 0.9. Please update your remote
  1625  state configuration to use the new 'backend' settings. For now, Terraform
  1626  will continue to use your existing settings. Legacy remote state support
  1627  will be removed in Terraform 0.11.
  1628  
  1629  You can find a guide for upgrading here:
  1630  
  1631  https://www.terraform.io/docs/backends/legacy-0-8.html
  1632  `