github.com/hugorut/terraform@v1.1.3/src/backend/remote-state/etcdv3/backend.go (about) 1 package etcd 2 3 import ( 4 "context" 5 6 "github.com/hugorut/terraform/src/backend" 7 "github.com/hugorut/terraform/src/legacy/helper/schema" 8 etcdv3 "go.etcd.io/etcd/clientv3" 9 "go.etcd.io/etcd/pkg/transport" 10 ) 11 12 const ( 13 endpointsKey = "endpoints" 14 usernameKey = "username" 15 usernameEnvVarName = "ETCDV3_USERNAME" 16 passwordKey = "password" 17 passwordEnvVarName = "ETCDV3_PASSWORD" 18 maxRequestBytesKey = "max_request_bytes" 19 prefixKey = "prefix" 20 lockKey = "lock" 21 cacertPathKey = "cacert_path" 22 certPathKey = "cert_path" 23 keyPathKey = "key_path" 24 ) 25 26 func New() backend.Backend { 27 s := &schema.Backend{ 28 Schema: map[string]*schema.Schema{ 29 endpointsKey: &schema.Schema{ 30 Type: schema.TypeList, 31 Elem: &schema.Schema{ 32 Type: schema.TypeString, 33 }, 34 MinItems: 1, 35 Required: true, 36 Description: "Endpoints for the etcd cluster.", 37 }, 38 39 usernameKey: &schema.Schema{ 40 Type: schema.TypeString, 41 Optional: true, 42 Description: "Username used to connect to the etcd cluster.", 43 DefaultFunc: schema.EnvDefaultFunc(usernameEnvVarName, ""), 44 }, 45 46 passwordKey: &schema.Schema{ 47 Type: schema.TypeString, 48 Optional: true, 49 Description: "Password used to connect to the etcd cluster.", 50 DefaultFunc: schema.EnvDefaultFunc(passwordEnvVarName, ""), 51 }, 52 53 maxRequestBytesKey: &schema.Schema{ 54 Type: schema.TypeInt, 55 Optional: true, 56 Description: "The max request size to send to etcd.", 57 Default: 0, 58 }, 59 60 prefixKey: &schema.Schema{ 61 Type: schema.TypeString, 62 Optional: true, 63 Description: "An optional prefix to be added to keys when to storing state in etcd.", 64 Default: "", 65 }, 66 67 lockKey: &schema.Schema{ 68 Type: schema.TypeBool, 69 Optional: true, 70 Description: "Whether to lock state access.", 71 Default: true, 72 }, 73 74 cacertPathKey: &schema.Schema{ 75 Type: schema.TypeString, 76 Optional: true, 77 Description: "The path to a PEM-encoded CA bundle with which to verify certificates of TLS-enabled etcd servers.", 78 Default: "", 79 }, 80 81 certPathKey: &schema.Schema{ 82 Type: schema.TypeString, 83 Optional: true, 84 Description: "The path to a PEM-encoded certificate to provide to etcd for secure client identification.", 85 Default: "", 86 }, 87 88 keyPathKey: &schema.Schema{ 89 Type: schema.TypeString, 90 Optional: true, 91 Description: "The path to a PEM-encoded key to provide to etcd for secure client identification.", 92 Default: "", 93 }, 94 }, 95 } 96 97 result := &Backend{Backend: s} 98 result.Backend.ConfigureFunc = result.configure 99 return result 100 } 101 102 type Backend struct { 103 *schema.Backend 104 105 // The fields below are set from configure. 106 client *etcdv3.Client 107 data *schema.ResourceData 108 lock bool 109 prefix string 110 } 111 112 func (b *Backend) configure(ctx context.Context) error { 113 var err error 114 // Grab the resource data. 115 b.data = schema.FromContextBackendConfig(ctx) 116 // Store the lock information. 117 b.lock = b.data.Get(lockKey).(bool) 118 // Store the prefix information. 119 b.prefix = b.data.Get(prefixKey).(string) 120 // Initialize a client to test config. 121 b.client, err = b.rawClient() 122 // Return err, if any. 123 return err 124 } 125 126 func (b *Backend) rawClient() (*etcdv3.Client, error) { 127 config := etcdv3.Config{} 128 tlsInfo := transport.TLSInfo{} 129 130 if v, ok := b.data.GetOk(endpointsKey); ok { 131 config.Endpoints = retrieveEndpoints(v) 132 } 133 if v, ok := b.data.GetOk(usernameKey); ok && v.(string) != "" { 134 config.Username = v.(string) 135 } 136 if v, ok := b.data.GetOk(passwordKey); ok && v.(string) != "" { 137 config.Password = v.(string) 138 } 139 if v, ok := b.data.GetOk(maxRequestBytesKey); ok && v.(int) != 0 { 140 config.MaxCallSendMsgSize = v.(int) 141 } 142 if v, ok := b.data.GetOk(cacertPathKey); ok && v.(string) != "" { 143 tlsInfo.TrustedCAFile = v.(string) 144 } 145 if v, ok := b.data.GetOk(certPathKey); ok && v.(string) != "" { 146 tlsInfo.CertFile = v.(string) 147 } 148 if v, ok := b.data.GetOk(keyPathKey); ok && v.(string) != "" { 149 tlsInfo.KeyFile = v.(string) 150 } 151 152 if tlsCfg, err := tlsInfo.ClientConfig(); err != nil { 153 return nil, err 154 } else if !tlsInfo.Empty() { 155 config.TLS = tlsCfg // Assign TLS configuration only if it valid and non-empty. 156 } 157 158 return etcdv3.New(config) 159 } 160 161 func retrieveEndpoints(v interface{}) []string { 162 var endpoints []string 163 list := v.([]interface{}) 164 for _, ep := range list { 165 endpoints = append(endpoints, ep.(string)) 166 } 167 return endpoints 168 }