github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/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 configures the etcd client's AutoSyncInterval
    43  	// (go.etcd.io/etcd/client/v3@v3.6.0-alpha.0/config.go:32).
    44  	// By default, it is 1m.
    45  	//
    46  	// Advanced:
    47  	//
    48  	// One important difference from the etcd config: we have autosync *on* by default (unlike etcd), meaning that
    49  	// the zero value here doesn't indicate autosync off.
    50  	// Instead, users should pass in a negative value to indicate "disable autosync"
    51  	// Only do this if you truly have a good reason for it! Most production use cases want autosync on.
    52  	AutoSyncInterval time.Duration `yaml:"autoSyncInterval"`
    53  	DialTimeout      time.Duration `yaml:"dialTimeout"`
    54  
    55  	DialOptions []grpc.DialOption `yaml:"-"` // nonserializable
    56  }
    57  
    58  // NewCluster creates a new Cluster.
    59  func (c ClusterConfig) NewCluster() Cluster {
    60  	keepAliveOpts := NewKeepAliveOptions()
    61  	if c.KeepAlive != nil {
    62  		keepAliveOpts = c.KeepAlive.NewOptions()
    63  	}
    64  
    65  	cluster := NewCluster().
    66  		SetZone(c.Zone).
    67  		SetEndpoints(c.Endpoints).
    68  		SetDialOptions(c.DialOptions).
    69  		SetKeepAliveOptions(keepAliveOpts).
    70  		SetTLSOptions(c.TLS.newOptions())
    71  
    72  	// Autosync should *always* be on, unless the user very explicitly requests it to be off. They can do this via a
    73  	// negative value (in which case we can assume they know what they're doing).
    74  	// Therefore, only update if it's nonzero, on the assumption that zero is just the empty value.
    75  	if c.AutoSyncInterval != 0 {
    76  		cluster = cluster.SetAutoSyncInterval(c.AutoSyncInterval)
    77  	}
    78  
    79  	if c.DialTimeout > 0 {
    80  		cluster = cluster.SetDialTimeout(c.DialTimeout)
    81  	}
    82  
    83  	return cluster
    84  }
    85  
    86  // TLSConfig is the config for TLS.
    87  type TLSConfig struct {
    88  	CrtPath   string `yaml:"crtPath"`
    89  	CACrtPath string `yaml:"caCrtPath"`
    90  	KeyPath   string `yaml:"keyPath"`
    91  }
    92  
    93  func (c *TLSConfig) newOptions() TLSOptions {
    94  	opts := NewTLSOptions()
    95  	if c == nil {
    96  		return opts
    97  	}
    98  
    99  	return opts.
   100  		SetCrtPath(c.CrtPath).
   101  		SetKeyPath(c.KeyPath).
   102  		SetCACrtPath(c.CACrtPath)
   103  }
   104  
   105  // KeepAliveConfig configures keepAlive behavior.
   106  type KeepAliveConfig struct {
   107  	Enabled bool          `yaml:"enabled"`
   108  	Period  time.Duration `yaml:"period"`
   109  	Jitter  time.Duration `yaml:"jitter"`
   110  	Timeout time.Duration `yaml:"timeout"`
   111  }
   112  
   113  // NewOptions constructs options based on the config.
   114  func (c *KeepAliveConfig) NewOptions() KeepAliveOptions {
   115  	return NewKeepAliveOptions().
   116  		SetKeepAliveEnabled(c.Enabled).
   117  		SetKeepAlivePeriod(c.Period).
   118  		SetKeepAlivePeriodMaxJitter(c.Jitter).
   119  		SetKeepAliveTimeout(c.Timeout)
   120  }
   121  
   122  // Configuration is for config service client.
   123  type Configuration struct {
   124  	Zone              string                 `yaml:"zone"`
   125  	Env               string                 `yaml:"env"`
   126  	Service           string                 `yaml:"service" validate:"nonzero"`
   127  	CacheDir          string                 `yaml:"cacheDir"`
   128  	ETCDClusters      []ClusterConfig        `yaml:"etcdClusters"`
   129  	SDConfig          services.Configuration `yaml:"m3sd"`
   130  	WatchWithRevision int64                  `yaml:"watchWithRevision"`
   131  	NewDirectoryMode  *os.FileMode           `yaml:"newDirectoryMode"`
   132  
   133  	Retry                  retry.Configuration `yaml:"retry"`
   134  	RequestTimeout         time.Duration       `yaml:"requestTimeout"`
   135  	WatchChanInitTimeout   time.Duration       `yaml:"watchChanInitTimeout"`
   136  	WatchChanCheckInterval time.Duration       `yaml:"watchChanCheckInterval"`
   137  	WatchChanResetInterval time.Duration       `yaml:"watchChanResetInterval"`
   138  	// EnableFastGets trades consistency for latency and throughput using clientv3.WithSerializable()
   139  	// on etcd ops.
   140  	EnableFastGets bool `yaml:"enableFastGets"`
   141  }
   142  
   143  // NewClient creates a new config service client.
   144  func (cfg Configuration) NewClient(iopts instrument.Options) (client.Client, error) {
   145  	return NewConfigServiceClient(cfg.NewOptions().SetInstrumentOptions(iopts))
   146  }
   147  
   148  // NewOptions returns a new Options.
   149  func (cfg Configuration) NewOptions() Options {
   150  	opts := NewOptions().
   151  		SetZone(cfg.Zone).
   152  		SetEnv(cfg.Env).
   153  		SetService(cfg.Service).
   154  		SetCacheDir(cfg.CacheDir).
   155  		SetClusters(cfg.etcdClusters()).
   156  		SetServicesOptions(cfg.SDConfig.NewOptions()).
   157  		SetWatchWithRevision(cfg.WatchWithRevision).
   158  		SetEnableFastGets(cfg.EnableFastGets).
   159  		SetRetryOptions(cfg.Retry.NewOptions(tally.NoopScope))
   160  
   161  	if cfg.RequestTimeout > 0 {
   162  		opts = opts.SetRequestTimeout(cfg.RequestTimeout)
   163  	}
   164  
   165  	if cfg.WatchChanInitTimeout > 0 {
   166  		opts = opts.SetWatchChanInitTimeout(cfg.WatchChanInitTimeout)
   167  	}
   168  
   169  	if cfg.WatchChanCheckInterval > 0 {
   170  		opts = opts.SetWatchChanCheckInterval(cfg.WatchChanCheckInterval)
   171  	}
   172  
   173  	if cfg.WatchChanResetInterval > 0 {
   174  		opts = opts.SetWatchChanResetInterval(cfg.WatchChanResetInterval)
   175  	}
   176  
   177  	if v := cfg.NewDirectoryMode; v != nil {
   178  		opts = opts.SetNewDirectoryMode(*v)
   179  	} else {
   180  		opts = opts.SetNewDirectoryMode(defaultDirectoryMode)
   181  	}
   182  
   183  	return opts
   184  }
   185  
   186  func (cfg Configuration) etcdClusters() []Cluster {
   187  	res := make([]Cluster, len(cfg.ETCDClusters))
   188  	for i, c := range cfg.ETCDClusters {
   189  		res[i] = c.NewCluster()
   190  	}
   191  
   192  	return res
   193  }