github.com/m3db/m3@v1.5.0/src/cluster/client/etcd/config.go (about)

     1  // Copyright (c) 2017 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package etcd
    22  
    23  import (
    24  	"os"
    25  	"time"
    26  
    27  	"github.com/uber-go/tally"
    28  	"google.golang.org/grpc"
    29  
    30  	"github.com/m3db/m3/src/cluster/client"
    31  	"github.com/m3db/m3/src/cluster/services"
    32  	"github.com/m3db/m3/src/x/instrument"
    33  	"github.com/m3db/m3/src/x/retry"
    34  )
    35  
    36  // ClusterConfig is the config for a zoned etcd cluster.
    37  type ClusterConfig struct {
    38  	Zone             string           `yaml:"zone"`
    39  	Endpoints        []string         `yaml:"endpoints"`
    40  	KeepAlive        *KeepAliveConfig `yaml:"keepAlive"`
    41  	TLS              *TLSConfig       `yaml:"tls"`
    42  	AutoSyncInterval time.Duration    `yaml:"autoSyncInterval"`
    43  
    44  	DialOptions []grpc.DialOption `yaml:"-"` // nonserializable
    45  }
    46  
    47  // NewCluster creates a new Cluster.
    48  func (c ClusterConfig) NewCluster() Cluster {
    49  	keepAliveOpts := NewKeepAliveOptions()
    50  	if c.KeepAlive != nil {
    51  		keepAliveOpts = c.KeepAlive.NewOptions()
    52  	}
    53  	return NewCluster().
    54  		SetZone(c.Zone).
    55  		SetEndpoints(c.Endpoints).
    56  		SetDialOptions(c.DialOptions).
    57  		SetKeepAliveOptions(keepAliveOpts).
    58  		SetTLSOptions(c.TLS.newOptions()).
    59  		SetAutoSyncInterval(c.AutoSyncInterval)
    60  }
    61  
    62  // TLSConfig is the config for TLS.
    63  type TLSConfig struct {
    64  	CrtPath   string `yaml:"crtPath"`
    65  	CACrtPath string `yaml:"caCrtPath"`
    66  	KeyPath   string `yaml:"keyPath"`
    67  }
    68  
    69  func (c *TLSConfig) newOptions() TLSOptions {
    70  	opts := NewTLSOptions()
    71  	if c == nil {
    72  		return opts
    73  	}
    74  
    75  	return opts.
    76  		SetCrtPath(c.CrtPath).
    77  		SetKeyPath(c.KeyPath).
    78  		SetCACrtPath(c.CACrtPath)
    79  }
    80  
    81  // KeepAliveConfig configures keepAlive behavior.
    82  type KeepAliveConfig struct {
    83  	Enabled bool          `yaml:"enabled"`
    84  	Period  time.Duration `yaml:"period"`
    85  	Jitter  time.Duration `yaml:"jitter"`
    86  	Timeout time.Duration `yaml:"timeout"`
    87  }
    88  
    89  // NewOptions constructs options based on the config.
    90  func (c *KeepAliveConfig) NewOptions() KeepAliveOptions {
    91  	return NewKeepAliveOptions().
    92  		SetKeepAliveEnabled(c.Enabled).
    93  		SetKeepAlivePeriod(c.Period).
    94  		SetKeepAlivePeriodMaxJitter(c.Jitter).
    95  		SetKeepAliveTimeout(c.Timeout)
    96  }
    97  
    98  // Configuration is for config service client.
    99  type Configuration struct {
   100  	Zone              string                 `yaml:"zone"`
   101  	Env               string                 `yaml:"env"`
   102  	Service           string                 `yaml:"service" validate:"nonzero"`
   103  	CacheDir          string                 `yaml:"cacheDir"`
   104  	ETCDClusters      []ClusterConfig        `yaml:"etcdClusters"`
   105  	SDConfig          services.Configuration `yaml:"m3sd"`
   106  	WatchWithRevision int64                  `yaml:"watchWithRevision"`
   107  	NewDirectoryMode  *os.FileMode           `yaml:"newDirectoryMode"`
   108  
   109  	Retry                  retry.Configuration `yaml:"retry"`
   110  	RequestTimeout         time.Duration       `yaml:"requestTimeout"`
   111  	WatchChanInitTimeout   time.Duration       `yaml:"watchChanInitTimeout"`
   112  	WatchChanCheckInterval time.Duration       `yaml:"watchChanCheckInterval"`
   113  	WatchChanResetInterval time.Duration       `yaml:"watchChanResetInterval"`
   114  	// EnableFastGets trades consistency for latency and throughput using clientv3.WithSerializable()
   115  	// on etcd ops.
   116  	EnableFastGets bool `yaml:"enableFastGets"`
   117  }
   118  
   119  // NewClient creates a new config service client.
   120  func (cfg Configuration) NewClient(iopts instrument.Options) (client.Client, error) {
   121  	return NewConfigServiceClient(cfg.NewOptions().SetInstrumentOptions(iopts))
   122  }
   123  
   124  // NewOptions returns a new Options.
   125  func (cfg Configuration) NewOptions() Options {
   126  	opts := NewOptions().
   127  		SetZone(cfg.Zone).
   128  		SetEnv(cfg.Env).
   129  		SetService(cfg.Service).
   130  		SetCacheDir(cfg.CacheDir).
   131  		SetClusters(cfg.etcdClusters()).
   132  		SetServicesOptions(cfg.SDConfig.NewOptions()).
   133  		SetWatchWithRevision(cfg.WatchWithRevision).
   134  		SetEnableFastGets(cfg.EnableFastGets).
   135  		SetRetryOptions(cfg.Retry.NewOptions(tally.NoopScope))
   136  
   137  	if cfg.RequestTimeout > 0 {
   138  		opts = opts.SetRequestTimeout(cfg.RequestTimeout)
   139  	}
   140  
   141  	if cfg.WatchChanInitTimeout > 0 {
   142  		opts = opts.SetWatchChanInitTimeout(cfg.WatchChanInitTimeout)
   143  	}
   144  
   145  	if cfg.WatchChanCheckInterval > 0 {
   146  		opts = opts.SetWatchChanCheckInterval(cfg.WatchChanCheckInterval)
   147  	}
   148  
   149  	if cfg.WatchChanResetInterval > 0 {
   150  		opts = opts.SetWatchChanResetInterval(cfg.WatchChanResetInterval)
   151  	}
   152  
   153  	if v := cfg.NewDirectoryMode; v != nil {
   154  		opts = opts.SetNewDirectoryMode(*v)
   155  	} else {
   156  		opts = opts.SetNewDirectoryMode(defaultDirectoryMode)
   157  	}
   158  
   159  	return opts
   160  }
   161  
   162  func (cfg Configuration) etcdClusters() []Cluster {
   163  	res := make([]Cluster, len(cfg.ETCDClusters))
   164  	for i, c := range cfg.ETCDClusters {
   165  		res[i] = c.NewCluster()
   166  	}
   167  
   168  	return res
   169  }