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  }