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