github.com/jzbruno/terraform@v0.10.3-0.20180104230435-18975d727047/backend/init/init.go (about) 1 // Package init contains the list of backends that can be initialized and 2 // basic helper functions for initializing those backends. 3 package init 4 5 import ( 6 "sync" 7 8 "github.com/hashicorp/terraform/backend" 9 "github.com/hashicorp/terraform/terraform" 10 11 backendatlas "github.com/hashicorp/terraform/backend/atlas" 12 backendlegacy "github.com/hashicorp/terraform/backend/legacy" 13 backendlocal "github.com/hashicorp/terraform/backend/local" 14 backendAzure "github.com/hashicorp/terraform/backend/remote-state/azure" 15 backendconsul "github.com/hashicorp/terraform/backend/remote-state/consul" 16 backendetcdv3 "github.com/hashicorp/terraform/backend/remote-state/etcdv3" 17 backendGCS "github.com/hashicorp/terraform/backend/remote-state/gcs" 18 backendinmem "github.com/hashicorp/terraform/backend/remote-state/inmem" 19 backendManta "github.com/hashicorp/terraform/backend/remote-state/manta" 20 backendS3 "github.com/hashicorp/terraform/backend/remote-state/s3" 21 backendSwift "github.com/hashicorp/terraform/backend/remote-state/swift" 22 ) 23 24 // backends is the list of available backends. This is a global variable 25 // because backends are currently hardcoded into Terraform and can't be 26 // modified without recompilation. 27 // 28 // To read an available backend, use the Backend function. This ensures 29 // safe concurrent read access to the list of built-in backends. 30 // 31 // Backends are hardcoded into Terraform because the API for backends uses 32 // complex structures and supporting that over the plugin system is currently 33 // prohibitively difficult. For those wanting to implement a custom backend, 34 // they can do so with recompilation. 35 var backends map[string]func() backend.Backend 36 var backendsLock sync.Mutex 37 38 func init() { 39 // Our hardcoded backends. We don't need to acquire a lock here 40 // since init() code is serial and can't spawn goroutines. 41 backends = map[string]func() backend.Backend{ 42 "atlas": func() backend.Backend { return &backendatlas.Backend{} }, 43 "local": func() backend.Backend { return &backendlocal.Local{} }, 44 "consul": func() backend.Backend { return backendconsul.New() }, 45 "inmem": func() backend.Backend { return backendinmem.New() }, 46 "swift": func() backend.Backend { return backendSwift.New() }, 47 "s3": func() backend.Backend { return backendS3.New() }, 48 "azure": deprecateBackend(backendAzure.New(), 49 `Warning: "azure" name is deprecated, please use "azurerm"`), 50 "azurerm": func() backend.Backend { return backendAzure.New() }, 51 "etcdv3": func() backend.Backend { return backendetcdv3.New() }, 52 "gcs": func() backend.Backend { return backendGCS.New() }, 53 "manta": func() backend.Backend { return backendManta.New() }, 54 } 55 56 // Add the legacy remote backends that haven't yet been convertd to 57 // the new backend API. 58 backendlegacy.Init(backends) 59 } 60 61 // Backend returns the initialization factory for the given backend, or 62 // nil if none exists. 63 func Backend(name string) func() backend.Backend { 64 backendsLock.Lock() 65 defer backendsLock.Unlock() 66 return backends[name] 67 } 68 69 // Set sets a new backend in the list of backends. If f is nil then the 70 // backend will be removed from the map. If this backend already exists 71 // then it will be overwritten. 72 // 73 // This method sets this backend globally and care should be taken to do 74 // this only before Terraform is executing to prevent odd behavior of backends 75 // changing mid-execution. 76 func Set(name string, f func() backend.Backend) { 77 backendsLock.Lock() 78 defer backendsLock.Unlock() 79 80 if f == nil { 81 delete(backends, name) 82 return 83 } 84 85 backends[name] = f 86 } 87 88 // deprecatedBackendShim is used to wrap a backend and inject a deprecation 89 // warning into the Validate method. 90 type deprecatedBackendShim struct { 91 backend.Backend 92 Message string 93 } 94 95 // Validate the Backend then add the deprecation warning. 96 func (b deprecatedBackendShim) Validate(c *terraform.ResourceConfig) ([]string, []error) { 97 warns, errs := b.Backend.Validate(c) 98 warns = append(warns, b.Message) 99 return warns, errs 100 } 101 102 // DeprecateBackend can be used to wrap a backend to retrun a deprecation 103 // warning during validation. 104 func deprecateBackend(b backend.Backend, message string) func() backend.Backend { 105 // Since a Backend wrapped by deprecatedBackendShim can no longer be 106 // asserted as an Enhanced or Local backend, disallow those types here 107 // entirely. If something other than a basic backend.Backend needs to be 108 // deprecated, we can add that functionality to schema.Backend or the 109 // backend itself. 110 if _, ok := b.(backend.Enhanced); ok { 111 panic("cannot use DeprecateBackend on an Enhanced Backend") 112 } 113 114 if _, ok := b.(backend.Local); ok { 115 panic("cannot use DeprecateBackend on a Local Backend") 116 } 117 118 return func() backend.Backend { 119 return deprecatedBackendShim{ 120 Backend: b, 121 Message: message, 122 } 123 } 124 }