mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Forward-port the plan state check from the 0.9 series. 0.10 has improved the serial handling for the state, so this adds relevant comments and some more test coverage for the case of an incrementing serial during apply.
129 lines
3.4 KiB
Go
129 lines
3.4 KiB
Go
package local
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"strings"
|
|
|
|
"github.com/hashicorp/errwrap"
|
|
"github.com/hashicorp/go-multierror"
|
|
"github.com/hashicorp/terraform/backend"
|
|
"github.com/hashicorp/terraform/state"
|
|
"github.com/hashicorp/terraform/terraform"
|
|
)
|
|
|
|
// backend.Local implementation.
|
|
func (b *Local) Context(op *backend.Operation) (*terraform.Context, state.State, error) {
|
|
// Make sure the type is invalid. We use this as a way to know not
|
|
// to ask for input/validate.
|
|
op.Type = backend.OperationTypeInvalid
|
|
|
|
return b.context(op)
|
|
}
|
|
|
|
func (b *Local) context(op *backend.Operation) (*terraform.Context, state.State, error) {
|
|
// Get the state.
|
|
s, err := b.State(op.Workspace)
|
|
if err != nil {
|
|
return nil, nil, errwrap.Wrapf("Error loading state: {{err}}", err)
|
|
}
|
|
|
|
if err := s.RefreshState(); err != nil {
|
|
return nil, nil, errwrap.Wrapf("Error loading state: {{err}}", err)
|
|
}
|
|
|
|
// Initialize our context options
|
|
var opts terraform.ContextOpts
|
|
if v := b.ContextOpts; v != nil {
|
|
opts = *v
|
|
}
|
|
|
|
// Copy set options from the operation
|
|
opts.Destroy = op.Destroy
|
|
opts.Module = op.Module
|
|
opts.Targets = op.Targets
|
|
opts.UIInput = op.UIIn
|
|
if op.Variables != nil {
|
|
opts.Variables = op.Variables
|
|
}
|
|
|
|
// Load our state
|
|
// By the time we get here, the backend creation code in "command" took
|
|
// care of making s.State() return a state compatible with our plan,
|
|
// if any, so we can safely pass this value in both the plan context
|
|
// and new context cases below.
|
|
opts.State = s.State()
|
|
|
|
// Build the context
|
|
var tfCtx *terraform.Context
|
|
if op.Plan != nil {
|
|
tfCtx, err = op.Plan.Context(&opts)
|
|
} else {
|
|
tfCtx, err = terraform.NewContext(&opts)
|
|
}
|
|
|
|
// any errors resolving plugins returns this
|
|
if rpe, ok := err.(*terraform.ResourceProviderError); ok {
|
|
b.pluginInitRequired(rpe)
|
|
// we wrote the full UI error here, so return a generic error for flow
|
|
// control in the command.
|
|
return nil, nil, errors.New("error satisfying plugin requirements")
|
|
}
|
|
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
// If we have an operation, then we automatically do the input/validate
|
|
// here since every option requires this.
|
|
if op.Type != backend.OperationTypeInvalid {
|
|
// If input asking is enabled, then do that
|
|
if op.Plan == nil && b.OpInput {
|
|
mode := terraform.InputModeProvider
|
|
mode |= terraform.InputModeVar
|
|
mode |= terraform.InputModeVarUnset
|
|
|
|
if err := tfCtx.Input(mode); err != nil {
|
|
return nil, nil, errwrap.Wrapf("Error asking for user input: {{err}}", err)
|
|
}
|
|
}
|
|
|
|
// If validation is enabled, validate
|
|
if b.OpValidation {
|
|
// We ignore warnings here on purpose. We expect users to be listening
|
|
// to the terraform.Hook called after a validation.
|
|
ws, es := tfCtx.Validate()
|
|
if len(ws) > 0 {
|
|
// Log just in case the CLI isn't enabled
|
|
log.Printf("[WARN] backend/local: %d warnings: %v", len(ws), ws)
|
|
|
|
// If we have a CLI, output the warnings
|
|
if b.CLI != nil {
|
|
b.CLI.Warn(strings.TrimSpace(validateWarnHeader) + "\n")
|
|
for _, w := range ws {
|
|
b.CLI.Warn(fmt.Sprintf(" * %s", w))
|
|
}
|
|
|
|
// Make a newline before continuing
|
|
b.CLI.Output("")
|
|
}
|
|
}
|
|
|
|
if len(es) > 0 {
|
|
return nil, nil, multierror.Append(nil, es...)
|
|
}
|
|
}
|
|
}
|
|
|
|
return tfCtx, s, nil
|
|
}
|
|
|
|
const validateWarnHeader = `
|
|
There are warnings related to your configuration. If no errors occurred,
|
|
Terraform will continue despite these warnings. It is a good idea to resolve
|
|
these warnings in the near future.
|
|
|
|
Warnings:
|
|
`
|