gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/config/source/etcd/etcd.go (about)

     1  package etcd
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"time"
     8  
     9  	cetcd "github.com/coreos/etcd/clientv3"
    10  	"github.com/coreos/etcd/mvcc/mvccpb"
    11  	"gitee.com/liuxuezhan/go-micro-v1.18.0/config/source"
    12  )
    13  
    14  // Currently a single etcd reader
    15  type etcd struct {
    16  	prefix      string
    17  	stripPrefix string
    18  	opts        source.Options
    19  	client      *cetcd.Client
    20  	cerr        error
    21  }
    22  
    23  var (
    24  	DefaultPrefix = "/micro/config/"
    25  )
    26  
    27  func (c *etcd) Read() (*source.ChangeSet, error) {
    28  	if c.cerr != nil {
    29  		return nil, c.cerr
    30  	}
    31  
    32  	rsp, err := c.client.Get(context.Background(), c.prefix, cetcd.WithPrefix())
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  
    37  	if rsp == nil || len(rsp.Kvs) == 0 {
    38  		return nil, fmt.Errorf("source not found: %s", c.prefix)
    39  	}
    40  
    41  	kvs := make([]*mvccpb.KeyValue, 0, len(rsp.Kvs))
    42  	for _, v := range rsp.Kvs {
    43  		kvs = append(kvs, (*mvccpb.KeyValue)(v))
    44  	}
    45  
    46  	data := makeMap(c.opts.Encoder, kvs, c.stripPrefix)
    47  
    48  	b, err := c.opts.Encoder.Encode(data)
    49  	if err != nil {
    50  		return nil, fmt.Errorf("error reading source: %v", err)
    51  	}
    52  
    53  	cs := &source.ChangeSet{
    54  		Timestamp: time.Now(),
    55  		Source:    c.String(),
    56  		Data:      b,
    57  		Format:    c.opts.Encoder.String(),
    58  	}
    59  	cs.Checksum = cs.Sum()
    60  
    61  	return cs, nil
    62  }
    63  
    64  func (c *etcd) String() string {
    65  	return "etcd"
    66  }
    67  
    68  func (c *etcd) Watch() (source.Watcher, error) {
    69  	if c.cerr != nil {
    70  		return nil, c.cerr
    71  	}
    72  	cs, err := c.Read()
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	return newWatcher(c.prefix, c.stripPrefix, c.client.Watcher, cs, c.opts)
    77  }
    78  
    79  func NewSource(opts ...source.Option) source.Source {
    80  	options := source.NewOptions(opts...)
    81  
    82  	var endpoints []string
    83  
    84  	// check if there are any addrs
    85  	addrs, ok := options.Context.Value(addressKey{}).([]string)
    86  	if ok {
    87  		for _, a := range addrs {
    88  			addr, port, err := net.SplitHostPort(a)
    89  			if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" {
    90  				port = "2379"
    91  				addr = a
    92  				endpoints = append(endpoints, fmt.Sprintf("%s:%s", addr, port))
    93  			} else if err == nil {
    94  				endpoints = append(endpoints, fmt.Sprintf("%s:%s", addr, port))
    95  			}
    96  		}
    97  	}
    98  
    99  	if len(endpoints) == 0 {
   100  		endpoints = []string{"localhost:2379"}
   101  	}
   102  
   103  	// check dial timeout option
   104  	dialTimeout, ok := options.Context.Value(dialTimeoutKey{}).(time.Duration)
   105  	if !ok {
   106  		dialTimeout = 3 * time.Second // default dial timeout
   107  	}
   108  
   109  	config := cetcd.Config{
   110  		Endpoints:   endpoints,
   111  		DialTimeout: dialTimeout,
   112  	}
   113  
   114  	u, ok := options.Context.Value(authKey{}).(*authCreds)
   115  	if ok {
   116  		config.Username = u.Username
   117  		config.Password = u.Password
   118  	}
   119  
   120  	// use default config
   121  	client, err := cetcd.New(config)
   122  
   123  	prefix := DefaultPrefix
   124  	sp := ""
   125  	f, ok := options.Context.Value(prefixKey{}).(string)
   126  	if ok {
   127  		prefix = f
   128  	}
   129  
   130  	if b, ok := options.Context.Value(stripPrefixKey{}).(bool); ok && b {
   131  		sp = prefix
   132  	}
   133  
   134  	return &etcd{
   135  		prefix:      prefix,
   136  		stripPrefix: sp,
   137  		opts:        options,
   138  		client:      client,
   139  		cerr:        err,
   140  	}
   141  }