github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/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-svchost/disco" 9 "github.com/muratcelep/terraform/not-internal/backend" 10 "github.com/muratcelep/terraform/not-internal/tfdiags" 11 "github.com/zclconf/go-cty/cty" 12 13 backendLocal "github.com/muratcelep/terraform/not-internal/backend/local" 14 backendRemote "github.com/muratcelep/terraform/not-internal/backend/remote" 15 backendArtifactory "github.com/muratcelep/terraform/not-internal/backend/remote-state/artifactory" 16 backendAzure "github.com/muratcelep/terraform/not-internal/backend/remote-state/azure" 17 backendConsul "github.com/muratcelep/terraform/not-internal/backend/remote-state/consul" 18 backendCos "github.com/muratcelep/terraform/not-internal/backend/remote-state/cos" 19 backendEtcdv2 "github.com/muratcelep/terraform/not-internal/backend/remote-state/etcdv2" 20 backendEtcdv3 "github.com/muratcelep/terraform/not-internal/backend/remote-state/etcdv3" 21 backendGCS "github.com/muratcelep/terraform/not-internal/backend/remote-state/gcs" 22 backendHTTP "github.com/muratcelep/terraform/not-internal/backend/remote-state/http" 23 backendInmem "github.com/muratcelep/terraform/not-internal/backend/remote-state/inmem" 24 backendKubernetes "github.com/muratcelep/terraform/not-internal/backend/remote-state/kubernetes" 25 backendManta "github.com/muratcelep/terraform/not-internal/backend/remote-state/manta" 26 backendOSS "github.com/muratcelep/terraform/not-internal/backend/remote-state/oss" 27 backendPg "github.com/muratcelep/terraform/not-internal/backend/remote-state/pg" 28 backendS3 "github.com/muratcelep/terraform/not-internal/backend/remote-state/s3" 29 backendSwift "github.com/muratcelep/terraform/not-internal/backend/remote-state/swift" 30 backendCloud "github.com/muratcelep/terraform/not-internal/cloud" 31 ) 32 33 // backends is the list of available backends. This is a global variable 34 // because backends are currently hardcoded into Terraform and can't be 35 // modified without recompilation. 36 // 37 // To read an available backend, use the Backend function. This ensures 38 // safe concurrent read access to the list of built-in backends. 39 // 40 // Backends are hardcoded into Terraform because the API for backends uses 41 // complex structures and supporting that over the plugin system is currently 42 // prohibitively difficult. For those wanting to implement a custom backend, 43 // they can do so with recompilation. 44 var backends map[string]backend.InitFn 45 var backendsLock sync.Mutex 46 47 // Init initializes the backends map with all our hardcoded backends. 48 func Init(services *disco.Disco) { 49 backendsLock.Lock() 50 defer backendsLock.Unlock() 51 52 backends = map[string]backend.InitFn{ 53 "local": func() backend.Backend { return backendLocal.New() }, 54 "remote": func() backend.Backend { return backendRemote.New(services) }, 55 56 // Remote State backends. 57 "artifactory": func() backend.Backend { return backendArtifactory.New() }, 58 "azurerm": func() backend.Backend { return backendAzure.New() }, 59 "consul": func() backend.Backend { return backendConsul.New() }, 60 "cos": func() backend.Backend { return backendCos.New() }, 61 "etcd": func() backend.Backend { return backendEtcdv2.New() }, 62 "etcdv3": func() backend.Backend { return backendEtcdv3.New() }, 63 "gcs": func() backend.Backend { return backendGCS.New() }, 64 "http": func() backend.Backend { return backendHTTP.New() }, 65 "inmem": func() backend.Backend { return backendInmem.New() }, 66 "kubernetes": func() backend.Backend { return backendKubernetes.New() }, 67 "manta": func() backend.Backend { return backendManta.New() }, 68 "oss": func() backend.Backend { return backendOSS.New() }, 69 "pg": func() backend.Backend { return backendPg.New() }, 70 "s3": func() backend.Backend { return backendS3.New() }, 71 "swift": func() backend.Backend { return backendSwift.New() }, 72 73 // Terraform Cloud 'backend' 74 // This is an implementation detail only, used for the cloud package 75 "cloud": func() backend.Backend { return backendCloud.New(services) }, 76 77 // Deprecated backends. 78 "azure": func() backend.Backend { 79 return deprecateBackend( 80 backendAzure.New(), 81 `Warning: "azure" name is deprecated, please use "azurerm"`, 82 ) 83 }, 84 } 85 } 86 87 // Backend returns the initialization factory for the given backend, or 88 // nil if none exists. 89 func Backend(name string) backend.InitFn { 90 backendsLock.Lock() 91 defer backendsLock.Unlock() 92 return backends[name] 93 } 94 95 // Set sets a new backend in the list of backends. If f is nil then the 96 // backend will be removed from the map. If this backend already exists 97 // then it will be overwritten. 98 // 99 // This method sets this backend globally and care should be taken to do 100 // this only before Terraform is executing to prevent odd behavior of backends 101 // changing mid-execution. 102 func Set(name string, f backend.InitFn) { 103 backendsLock.Lock() 104 defer backendsLock.Unlock() 105 106 if f == nil { 107 delete(backends, name) 108 return 109 } 110 111 backends[name] = f 112 } 113 114 // deprecatedBackendShim is used to wrap a backend and inject a deprecation 115 // warning into the Validate method. 116 type deprecatedBackendShim struct { 117 backend.Backend 118 Message string 119 } 120 121 // PrepareConfig delegates to the wrapped backend to validate its config 122 // and then appends shim's deprecation warning. 123 func (b deprecatedBackendShim) PrepareConfig(obj cty.Value) (cty.Value, tfdiags.Diagnostics) { 124 newObj, diags := b.Backend.PrepareConfig(obj) 125 return newObj, diags.Append(tfdiags.SimpleWarning(b.Message)) 126 } 127 128 // DeprecateBackend can be used to wrap a backend to retrun a deprecation 129 // warning during validation. 130 func deprecateBackend(b backend.Backend, message string) backend.Backend { 131 // Since a Backend wrapped by deprecatedBackendShim can no longer be 132 // asserted as an Enhanced or Local backend, disallow those types here 133 // entirely. If something other than a basic backend.Backend needs to be 134 // deprecated, we can add that functionality to schema.Backend or the 135 // backend itself. 136 if _, ok := b.(backend.Enhanced); ok { 137 panic("cannot use DeprecateBackend on an Enhanced Backend") 138 } 139 140 if _, ok := b.(backend.Local); ok { 141 panic("cannot use DeprecateBackend on a Local Backend") 142 } 143 144 return deprecatedBackendShim{ 145 Backend: b, 146 Message: message, 147 } 148 }