// Backend initializes and returns the backend for this CLI session.
//
// The backend is used to perform the actual Terraform operations. This
// abstraction enables easily sliding in new Terraform behavior such as
// remote state storage, remote operations, etc. while allowing the CLI
// to remain mostly identical.
//
// This will initialize a new backend for each call, which can carry some
// overhead with it. Please reuse the returned value for optimal behavior.
//
// Only one backend should be used per Meta. This function is stateful
// and is unsafe to create multiple backends used at once. This function
// can be called multiple times with each backend being "live" (usable)
// one at a time.
//
// A side-effect of this method is the population of m.backendState, recording
// the final resolved backend configuration after dealing with overrides from
// the "terraform init" command line, etc.
Backend initializes and returns the backend for this CLI session.

The backend is used to perform the actual Terraform operations. This
abstraction enables easily sliding in new Terraform behavior such as
remote state storage, remote operations, etc. while allowing the CLI
to remain mostly identical.

This will initialize a new backend for each call, which can carry some
overhead with it. Please reuse the returned value for optimal behavior.

Only one backend should be used per Meta. This function is stateful
and is unsafe to create multiple backends used at once. This function
can be called multiple times with each backend being "live" (usable)
one at a time.

A side-effect of this method is the population of m.backendState, recording
the final resolved backend configuration after dealing with overrides from
the "terraform init" command line, etc.
// Backend initializes and returns the backend for this CLI session . // // The backend is used to perform the actual Terraform operations . This // abstraction enables easily sliding in new Terraform behavior such as // remote state storage remote operations etc . while allowing the CLI // to remain mostly identical . // // This will initialize a new backend for each call which can carry some // overhead with it . Please reuse the returned value for optimal behavior . // // Only one backend should be used per Meta . This function is stateful // and is unsafe to create multiple backends used at once . This function // can be called multiple times with each backend being " live " ( usable ) // one at a time . // // A side - effect of this method is the population of m . backendState recording // the final resolved backend configuration after dealing with overrides from // the " terraform init " command line etc .
func (m *Meta) Backend(opts *BackendOpts) (backend.Enhanced, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics
	if opts == nil {
		opts = &BackendOpts{}
	}
	var b backend.Backend
	if !opts.ForceLocal {
		var backendDiags tfdiags.Diagnostics
		b, backendDiags = m.backendFromConfig(opts)
		diags = diags.Append(backendDiags)
		if opts.Init && b != nil && !diags.HasErrors() {
			if err := m.selectWorkspace(b); err != nil {
				diags = diags.Append(err)
			}
		}
		if diags.HasErrors() {
			return nil, diags
		}
		log.Printf("[TRACE] Meta.Backend: instantiated backend of type %T", b)
	}
	cliOpts, err := m.backendCLIOpts()
	if err != nil {
		diags = diags.Append(err)
		return nil, diags
	}
	cliOpts.Validation = true
	if cli, ok := b.(backend.CLI); ok {
		if err := cli.CLIInit(cliOpts); err != nil {
			diags = diags.Append(fmt.Errorf(
				"Error initializing backend %T: %s\n\n"+
					"This is a bug; please report it to the backend developer",
				b, err,
			))
			return nil, diags
		}
	}
	if enhanced, ok := b.(backend.Enhanced); ok {
		log.Printf("[TRACE] Meta.Backend: backend %T supports operations", b)
		return enhanced, nil
	}
	if !opts.ForceLocal {
		log.Printf("[TRACE] Meta.Backend: backend %T does not support operations, so wrapping it in a local backend", b)
	}
	local := backendLocal.NewWithBackend(b)
	if err := local.CLIInit(cliOpts); err != nil {
		panic(err)
	}
	 FIXME: We should refactor this so that we more directly and explicitly
	 treat the local backend as the default, including in the UI shown to
	 the user, since the local backend should only be used when learning or
	 in exceptional cases and so it's better to help the user learn that
	 by introducing it as a concept.
	if m.backendState == nil {
		 NOTE: This synthetic object is intentionally _not_ retained in the
		 on-disk record of the backend configuration, which was already dealt
		 with inside backendFromConfig, because we still need that codepath
		 to be able to recognize the lack of a config as distinct from
		 explicitly setting local until we do some more refactoring here.
		m.backendState = &terraform.BackendState{
			Type:      "local",
			ConfigRaw: json.RawMessage("{}"),
		}
	}
	return local, nil
}
func ( m * Meta ) Backend ( opts * BackendOpts ) ( backend . Enhanced , tfdiags . Diagnostics ) { var diags tfdiags . Diagnostics if opts == nil { opts = & BackendOpts { } } var b backend . Backend if ! opts . ForceLocal { var backendDiags tfdiags . Diagnostics b , backendDiags = m . backendFromConfig ( opts ) diags = diags . Append ( backendDiags ) if opts . Init && b != nil && ! diags . HasErrors ( ) { if err := m . selectWorkspace ( b ) ; err != nil { diags = diags . Append ( err ) } } if diags . HasErrors ( ) { return nil , diags } log . Printf ( " " , b ) } cliOpts , err := m . backendCLIOpts ( ) if err != nil { diags = diags . Append ( err ) return nil , diags } cliOpts . Validation = true if cli , ok := b . ( backend . CLI ) ; ok { if err := cli . CLIInit ( cliOpts ) ; err != nil { diags = diags . Append ( fmt . Errorf ( " \n \n " + " " , b , err , ) ) return nil , diags } } if enhanced , ok := b . ( backend . Enhanced ) ; ok { log . Printf ( " " , b ) return enhanced , nil } if ! opts . ForceLocal { log . Printf ( " " , b ) } local := backendLocal . NewWithBackend ( b ) if err := local . CLIInit ( cliOpts ) ; err != nil { panic ( err ) } if m . backendState == nil { m . backendState = & terraform . BackendState { Type : " " , ConfigRaw : json . RawMessage ( " " ) , } } return local , nil }
Backend initializes and returns the backend for this CLI session.
Backend initializes and returns the backend for this CLI session .
// If no opts are set, then initialize // Initialize a backend from the config unless we're forcing a purely // local operation. // Its possible that the currently selected workspace doesn't exist, so // we call selectWorkspace to ensure an existing workspace is selected. // Setup the CLI opts we pass into backends that support it. // If the backend supports CLI initialization, do it. // If the result of loading the backend is an enhanced backend, // then return that as-is. This works even if b == nil (it will be !ok). // We either have a non-enhanced backend or no backend configured at // all. In either case, we use local as our enhanced backend and the // non-enhanced (if any) as the state backend. // Build the local backend // Local backend isn't allowed to fail. It would be a bug. // If we got here from backendFromConfig returning nil then m.backendState // won't be set, since that codepath considers that to be no backend at all, // but our caller considers that to be the local backend with no config // and so we'll synthesize a backend state so other code doesn't need to // care about this special case. // // FIXME: We should refactor this so that we more directly and explicitly // treat the local backend as the default, including in the UI shown to // the user, since the local backend should only be used when learning or // in exceptional cases and so it's better to help the user learn that // by introducing it as a concept. // NOTE: This synthetic object is intentionally _not_ retained in the // on-disk record of the backend configuration, which was already dealt // with inside backendFromConfig, because we still need that codepath // to be able to recognize the lack of a config as distinct from // explicitly setting local until we do some more refactoring here.