github.com/hooklift/terraform@v0.11.0-beta1.0.20171117000744-6786c1361ffe/backend/backend.go (about)

     1  // Package backend provides interfaces that the CLI uses to interact with
     2  // Terraform. A backend provides the abstraction that allows the same CLI
     3  // to simultaneously support both local and remote operations for seamlessly
     4  // using Terraform in a team environment.
     5  package backend
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  	"time"
    11  
    12  	"github.com/hashicorp/terraform/config/module"
    13  	"github.com/hashicorp/terraform/state"
    14  	"github.com/hashicorp/terraform/terraform"
    15  )
    16  
    17  // This is the name of the default, initial state that every backend
    18  // must have. This state cannot be deleted.
    19  const DefaultStateName = "default"
    20  
    21  // Error value to return when a named state operation isn't supported.
    22  // This must be returned rather than a custom error so that the Terraform
    23  // CLI can detect it and handle it appropriately.
    24  var ErrNamedStatesNotSupported = errors.New("named states not supported")
    25  
    26  // Backend is the minimal interface that must be implemented to enable Terraform.
    27  type Backend interface {
    28  	// Ask for input and configure the backend. Similar to
    29  	// terraform.ResourceProvider.
    30  	Input(terraform.UIInput, *terraform.ResourceConfig) (*terraform.ResourceConfig, error)
    31  	Validate(*terraform.ResourceConfig) ([]string, []error)
    32  	Configure(*terraform.ResourceConfig) error
    33  
    34  	// State returns the current state for this environment. This state may
    35  	// not be loaded locally: the proper APIs should be called on state.State
    36  	// to load the state. If the state.State is a state.Locker, it's up to the
    37  	// caller to call Lock and Unlock as needed.
    38  	//
    39  	// If the named state doesn't exist it will be created. The "default" state
    40  	// is always assumed to exist.
    41  	State(name string) (state.State, error)
    42  
    43  	// DeleteState removes the named state if it exists. It is an error
    44  	// to delete the default state.
    45  	//
    46  	// DeleteState does not prevent deleting a state that is in use. It is the
    47  	// responsibility of the caller to hold a Lock on the state when calling
    48  	// this method.
    49  	DeleteState(name string) error
    50  
    51  	// States returns a list of configured named states.
    52  	States() ([]string, error)
    53  }
    54  
    55  // Enhanced implements additional behavior on top of a normal backend.
    56  //
    57  // Enhanced backends allow customizing the behavior of Terraform operations.
    58  // This allows Terraform to potentially run operations remotely, load
    59  // configurations from external sources, etc.
    60  type Enhanced interface {
    61  	Backend
    62  
    63  	// Operation performs a Terraform operation such as refresh, plan, apply.
    64  	// It is up to the implementation to determine what "performing" means.
    65  	// This DOES NOT BLOCK. The context returned as part of RunningOperation
    66  	// should be used to block for completion.
    67  	// If the state used in the operation can be locked, it is the
    68  	// responsibility of the Backend to lock the state for the duration of the
    69  	// running operation.
    70  	Operation(context.Context, *Operation) (*RunningOperation, error)
    71  }
    72  
    73  // Local implements additional behavior on a Backend that allows local
    74  // operations in addition to remote operations.
    75  //
    76  // This enables more behaviors of Terraform that require more data such
    77  // as `console`, `import`, `graph`. These require direct access to
    78  // configurations, variables, and more. Not all backends may support this
    79  // so we separate it out into its own optional interface.
    80  type Local interface {
    81  	// Context returns a runnable terraform Context. The operation parameter
    82  	// doesn't need a Type set but it needs other options set such as Module.
    83  	Context(*Operation) (*terraform.Context, state.State, error)
    84  }
    85  
    86  // An operation represents an operation for Terraform to execute.
    87  //
    88  // Note that not all fields are supported by all backends and can result
    89  // in an error if set. All backend implementations should show user-friendly
    90  // errors explaining any incorrectly set values. For example, the local
    91  // backend doesn't support a PlanId being set.
    92  //
    93  // The operation options are purposely designed to have maximal compatibility
    94  // between Terraform and Terraform Servers (a commercial product offered by
    95  // HashiCorp). Therefore, it isn't expected that other implementation support
    96  // every possible option. The struct here is generalized in order to allow
    97  // even partial implementations to exist in the open, without walling off
    98  // remote functionality 100% behind a commercial wall. Anyone can implement
    99  // against this interface and have Terraform interact with it just as it
   100  // would with HashiCorp-provided Terraform Servers.
   101  type Operation struct {
   102  	// Type is the operation to perform.
   103  	Type OperationType
   104  
   105  	// PlanId is an opaque value that backends can use to execute a specific
   106  	// plan for an apply operation.
   107  	//
   108  	// PlanOutBackend is the backend to store with the plan. This is the
   109  	// backend that will be used when applying the plan.
   110  	PlanId         string
   111  	PlanRefresh    bool   // PlanRefresh will do a refresh before a plan
   112  	PlanOutPath    string // PlanOutPath is the path to save the plan
   113  	PlanOutBackend *terraform.BackendState
   114  
   115  	// Module settings specify the root module to use for operations.
   116  	Module *module.Tree
   117  
   118  	// Plan is a plan that was passed as an argument. This is valid for
   119  	// plan and apply arguments but may not work for all backends.
   120  	Plan *terraform.Plan
   121  
   122  	// The options below are more self-explanatory and affect the runtime
   123  	// behavior of the operation.
   124  	Destroy      bool
   125  	Targets      []string
   126  	Variables    map[string]interface{}
   127  	AutoApprove  bool
   128  	DestroyForce bool
   129  
   130  	// Input/output/control options.
   131  	UIIn  terraform.UIInput
   132  	UIOut terraform.UIOutput
   133  
   134  	// If LockState is true, the Operation must Lock any
   135  	// state.Lockers for its duration, and Unlock when complete.
   136  	LockState bool
   137  
   138  	// The duration to retry obtaining a State lock.
   139  	StateLockTimeout time.Duration
   140  
   141  	// Workspace is the name of the workspace that this operation should run
   142  	// in, which controls which named state is used.
   143  	Workspace string
   144  }
   145  
   146  // RunningOperation is the result of starting an operation.
   147  type RunningOperation struct {
   148  	// Context should be used to track Done and Err for errors.
   149  	//
   150  	// For implementers of a backend, this context should not wrap the
   151  	// passed in context. Otherwise, canceling the parent context will
   152  	// immediately mark this context as "done" but those aren't the semantics
   153  	// we want: we want this context to be done only when the operation itself
   154  	// is fully done.
   155  	context.Context
   156  
   157  	// Err is the error of the operation. This is populated after
   158  	// the operation has completed.
   159  	Err error
   160  
   161  	// PlanEmpty is populated after a Plan operation completes without error
   162  	// to note whether a plan is empty or has changes.
   163  	PlanEmpty bool
   164  
   165  	// State is the final state after the operation completed. Persisting
   166  	// this state is managed by the backend. This should only be read
   167  	// after the operation completes to avoid read/write races.
   168  	State *terraform.State
   169  }