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