2017-02-22 20:17:06 +01:00
|
|
|
// Package init contains the list of backends that can be initialized and
|
|
|
|
// basic helper functions for initializing those backends.
|
|
|
|
package init
|
|
|
|
|
|
|
|
import (
|
2018-07-04 17:24:49 +02:00
|
|
|
"os"
|
2017-02-22 20:17:06 +01:00
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/hashicorp/terraform/backend"
|
2018-07-04 17:24:49 +02:00
|
|
|
"github.com/hashicorp/terraform/svchost/disco"
|
2017-08-17 17:39:33 +02:00
|
|
|
"github.com/hashicorp/terraform/terraform"
|
2017-02-22 20:17:06 +01:00
|
|
|
|
2018-07-04 12:07:44 +02:00
|
|
|
backendAtlas "github.com/hashicorp/terraform/backend/atlas"
|
|
|
|
backendLegacy "github.com/hashicorp/terraform/backend/legacy"
|
|
|
|
backendLocal "github.com/hashicorp/terraform/backend/local"
|
2018-07-04 17:24:49 +02:00
|
|
|
backendRemote "github.com/hashicorp/terraform/backend/remote"
|
2017-03-30 16:33:54 +02:00
|
|
|
backendAzure "github.com/hashicorp/terraform/backend/remote-state/azure"
|
2018-07-04 12:07:44 +02:00
|
|
|
backendConsul "github.com/hashicorp/terraform/backend/remote-state/consul"
|
|
|
|
backendEtcdv3 "github.com/hashicorp/terraform/backend/remote-state/etcdv3"
|
2017-09-08 16:11:41 +02:00
|
|
|
backendGCS "github.com/hashicorp/terraform/backend/remote-state/gcs"
|
2018-07-04 12:07:44 +02:00
|
|
|
backendInmem "github.com/hashicorp/terraform/backend/remote-state/inmem"
|
2017-10-09 13:46:54 +02:00
|
|
|
backendManta "github.com/hashicorp/terraform/backend/remote-state/manta"
|
2017-03-21 18:43:31 +01:00
|
|
|
backendS3 "github.com/hashicorp/terraform/backend/remote-state/s3"
|
2017-04-22 22:42:37 +02:00
|
|
|
backendSwift "github.com/hashicorp/terraform/backend/remote-state/swift"
|
2017-02-22 20:17:06 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// backends is the list of available backends. This is a global variable
|
|
|
|
// because backends are currently hardcoded into Terraform and can't be
|
|
|
|
// modified without recompilation.
|
|
|
|
//
|
|
|
|
// To read an available backend, use the Backend function. This ensures
|
|
|
|
// safe concurrent read access to the list of built-in backends.
|
|
|
|
//
|
|
|
|
// Backends are hardcoded into Terraform because the API for backends uses
|
|
|
|
// complex structures and supporting that over the plugin system is currently
|
|
|
|
// prohibitively difficult. For those wanting to implement a custom backend,
|
|
|
|
// they can do so with recompilation.
|
2018-07-04 17:24:49 +02:00
|
|
|
var backends map[string]backend.InitFn
|
2017-02-22 20:17:06 +01:00
|
|
|
var backendsLock sync.Mutex
|
|
|
|
|
2018-07-04 17:24:49 +02:00
|
|
|
// Init initializes the backends map with all our hardcoded backends.
|
|
|
|
func Init(services *disco.Disco) {
|
|
|
|
backendsLock.Lock()
|
|
|
|
defer backendsLock.Unlock()
|
|
|
|
|
|
|
|
backends = map[string]backend.InitFn{
|
|
|
|
// Enhanced backends.
|
2018-07-04 12:11:35 +02:00
|
|
|
"local": func() backend.Backend { return backendLocal.New() },
|
2018-07-04 17:24:49 +02:00
|
|
|
"remote": func() backend.Backend {
|
|
|
|
b := backendRemote.New(services)
|
|
|
|
if os.Getenv("TF_FORCE_LOCAL_BACKEND") != "" {
|
|
|
|
return backendLocal.NewWithBackend(b)
|
|
|
|
}
|
|
|
|
return b
|
|
|
|
},
|
|
|
|
|
|
|
|
// Remote State backends.
|
|
|
|
"atlas": func() backend.Backend { return backendAtlas.New() },
|
2017-08-17 17:37:51 +02:00
|
|
|
"azurerm": func() backend.Backend { return backendAzure.New() },
|
2018-07-04 12:07:44 +02:00
|
|
|
"consul": func() backend.Backend { return backendConsul.New() },
|
|
|
|
"etcdv3": func() backend.Backend { return backendEtcdv3.New() },
|
2017-09-08 16:11:41 +02:00
|
|
|
"gcs": func() backend.Backend { return backendGCS.New() },
|
2018-07-04 12:07:44 +02:00
|
|
|
"inmem": func() backend.Backend { return backendInmem.New() },
|
2017-10-09 13:46:54 +02:00
|
|
|
"manta": func() backend.Backend { return backendManta.New() },
|
2018-07-04 12:07:44 +02:00
|
|
|
"s3": func() backend.Backend { return backendS3.New() },
|
|
|
|
"swift": func() backend.Backend { return backendSwift.New() },
|
2018-07-04 17:24:49 +02:00
|
|
|
|
|
|
|
// Deprecated backends.
|
|
|
|
"azure": deprecateBackend(backendAzure.New(),
|
|
|
|
`Warning: "azure" name is deprecated, please use "azurerm"`),
|
2017-02-22 20:17:06 +01:00
|
|
|
}
|
|
|
|
|
2018-07-04 12:07:44 +02:00
|
|
|
// Add the legacy remote backends that haven't yet been converted to
|
2017-02-22 20:17:06 +01:00
|
|
|
// the new backend API.
|
2018-07-04 12:07:44 +02:00
|
|
|
backendLegacy.Init(backends)
|
2017-02-22 20:17:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Backend returns the initialization factory for the given backend, or
|
|
|
|
// nil if none exists.
|
2018-07-04 17:24:49 +02:00
|
|
|
func Backend(name string) backend.InitFn {
|
2017-02-22 20:17:06 +01:00
|
|
|
backendsLock.Lock()
|
|
|
|
defer backendsLock.Unlock()
|
|
|
|
return backends[name]
|
|
|
|
}
|
|
|
|
|
2017-02-22 20:37:56 +01:00
|
|
|
// Set sets a new backend in the list of backends. If f is nil then the
|
|
|
|
// backend will be removed from the map. If this backend already exists
|
|
|
|
// then it will be overwritten.
|
|
|
|
//
|
|
|
|
// This method sets this backend globally and care should be taken to do
|
|
|
|
// this only before Terraform is executing to prevent odd behavior of backends
|
|
|
|
// changing mid-execution.
|
2018-07-04 17:24:49 +02:00
|
|
|
func Set(name string, f backend.InitFn) {
|
2017-02-22 20:37:56 +01:00
|
|
|
backendsLock.Lock()
|
|
|
|
defer backendsLock.Unlock()
|
|
|
|
|
|
|
|
if f == nil {
|
|
|
|
delete(backends, name)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
backends[name] = f
|
|
|
|
}
|
2017-08-17 17:39:33 +02:00
|
|
|
|
|
|
|
// deprecatedBackendShim is used to wrap a backend and inject a deprecation
|
|
|
|
// warning into the Validate method.
|
|
|
|
type deprecatedBackendShim struct {
|
|
|
|
backend.Backend
|
|
|
|
Message string
|
|
|
|
}
|
|
|
|
|
|
|
|
// Validate the Backend then add the deprecation warning.
|
|
|
|
func (b deprecatedBackendShim) Validate(c *terraform.ResourceConfig) ([]string, []error) {
|
|
|
|
warns, errs := b.Backend.Validate(c)
|
|
|
|
warns = append(warns, b.Message)
|
|
|
|
return warns, errs
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeprecateBackend can be used to wrap a backend to retrun a deprecation
|
|
|
|
// warning during validation.
|
2018-07-04 17:24:49 +02:00
|
|
|
func deprecateBackend(b backend.Backend, message string) backend.InitFn {
|
2017-08-17 17:39:33 +02:00
|
|
|
// Since a Backend wrapped by deprecatedBackendShim can no longer be
|
|
|
|
// asserted as an Enhanced or Local backend, disallow those types here
|
|
|
|
// entirely. If something other than a basic backend.Backend needs to be
|
|
|
|
// deprecated, we can add that functionality to schema.Backend or the
|
|
|
|
// backend itself.
|
|
|
|
if _, ok := b.(backend.Enhanced); ok {
|
|
|
|
panic("cannot use DeprecateBackend on an Enhanced Backend")
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := b.(backend.Local); ok {
|
|
|
|
panic("cannot use DeprecateBackend on a Local Backend")
|
|
|
|
}
|
|
|
|
|
|
|
|
return func() backend.Backend {
|
|
|
|
return deprecatedBackendShim{
|
|
|
|
Backend: b,
|
|
|
|
Message: message,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|