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 }