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