-
Notifications
You must be signed in to change notification settings - Fork 771
/
config.go
474 lines (431 loc) · 19.4 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package config
import (
"encoding/json"
"time"
"github.com/uber-go/tally/m3"
"github.com/uber-go/tally/prometheus"
"github.com/uber/ringpop-go/discovery"
"github.com/uber/cadence/common"
"github.com/uber/cadence/common/auth"
"github.com/uber/cadence/common/service/dynamicconfig"
)
type (
// Config contains the configuration for a set of cadence services
Config struct {
// Ringpop is the ringpop related configuration
Ringpop Ringpop `yaml:"ringpop"`
// Persistence contains the configuration for cadence datastores
Persistence Persistence `yaml:"persistence"`
// Log is the logging config
Log Logger `yaml:"log"`
// ClusterMetadata is the config containing all valid clusters and active cluster
ClusterMetadata *ClusterMetadata `yaml:"clusterMetadata"`
// DCRedirectionPolicy contains the frontend datacenter redirection policy
DCRedirectionPolicy DCRedirectionPolicy `yaml:"dcRedirectionPolicy"`
// Services is a map of service name to service config items
Services map[string]Service `yaml:"services"`
// Kafka is the config for connecting to kafka
Kafka KafkaConfig `yaml:"kafka"`
// Archival is the config for archival
Archival Archival `yaml:"archival"`
// PublicClient is config for connecting to cadence frontend
PublicClient PublicClient `yaml:"publicClient"`
// DynamicConfigClient is the config for setting up the file based dynamic config client
// Filepath should be relative to the root directory
DynamicConfigClient dynamicconfig.FileBasedClientConfig `yaml:"dynamicConfigClient"`
// DomainDefaults is the default config for every domain
DomainDefaults DomainDefaults `yaml:"domainDefaults"`
// Blobstore is the config for setting up blobstore
Blobstore Blobstore `yaml:"blobstore"`
}
// Service contains the service specific config items
Service struct {
// TChannel is the tchannel configuration
RPC RPC `yaml:"rpc"`
// Metrics is the metrics subsystem configuration
Metrics Metrics `yaml:"metrics"`
// PProf is the PProf configuration
PProf PProf `yaml:"pprof"`
}
// PProf contains the rpc config items
PProf struct {
// Port is the port on which the PProf will bind to
Port int `yaml:"port"`
}
// RPC contains the rpc config items
RPC struct {
// Port is the port on which the channel will bind to
Port int `yaml:"port"`
// BindOnLocalHost is true if localhost is the bind address
BindOnLocalHost bool `yaml:"bindOnLocalHost"`
// BindOnIP can be used to bind service on specific ip (eg. `0.0.0.0`) -
// check net.ParseIP for supported syntax, only IPv4 is supported,
// mutually exclusive with `BindOnLocalHost` option
BindOnIP string `yaml:"bindOnIP"`
// DisableLogging disables all logging for rpc
DisableLogging bool `yaml:"disableLogging"`
// LogLevel is the desired log level
LogLevel string `yaml:"logLevel"`
}
// Blobstore contains the config for blobstore
Blobstore struct {
Filestore *FileBlobstore `yaml:"filestore"`
}
// FileBlobstore contains the config for a file backed blobstore
FileBlobstore struct {
OutputDirectory string `yaml:"outputDirectory"`
}
// Ringpop contains the ringpop config items
Ringpop struct {
// Name to be used in ringpop advertisement
Name string `yaml:"name" validate:"nonzero"`
// BootstrapMode is a enum that defines the ringpop bootstrap method
BootstrapMode BootstrapMode `yaml:"bootstrapMode"`
// BootstrapHosts is a list of seed hosts to be used for ringpop bootstrap
BootstrapHosts []string `yaml:"bootstrapHosts"`
// BootstrapFile is the file path to be used for ringpop bootstrap
BootstrapFile string `yaml:"bootstrapFile"`
// MaxJoinDuration is the max wait time to join the ring
MaxJoinDuration time.Duration `yaml:"maxJoinDuration"`
// Custom discovery provider, cannot be specified through yaml
DiscoveryProvider discovery.DiscoverProvider `yaml:"-"`
}
// Persistence contains the configuration for data store / persistence layer
Persistence struct {
// DefaultStore is the name of the default data store to use
DefaultStore string `yaml:"defaultStore" validate:"nonzero"`
// VisibilityStore is the name of the datastore to be used for visibility records
VisibilityStore string `yaml:"visibilityStore" validate:"nonzero"`
// AdvancedVisibilityStore is the name of the datastore to be used for visibility records
AdvancedVisibilityStore string `yaml:"advancedVisibilityStore"`
// HistoryMaxConns is the desired number of conns to history store. Value specified
// here overrides the MaxConns config specified as part of datastore
HistoryMaxConns int `yaml:"historyMaxConns"`
// NumHistoryShards is the desired number of history shards. This config doesn't
// belong here, needs refactoring
NumHistoryShards int `yaml:"numHistoryShards" validate:"nonzero"`
// DataStores contains the configuration for all datastores
DataStores map[string]DataStore `yaml:"datastores"`
// VisibilityConfig is config for visibility sampling
VisibilityConfig *VisibilityConfig `yaml:"-" json:"-"`
// TransactionSizeLimit is the largest allowed transaction size
TransactionSizeLimit dynamicconfig.IntPropertyFn `yaml:"-" json:"-"`
// ErrorInjectionRate is the the rate for injecting random error
ErrorInjectionRate dynamicconfig.FloatPropertyFn `yaml:"-" json:"-"`
}
// DataStore is the configuration for a single datastore
DataStore struct {
// Cassandra contains the config for a cassandra datastore
Cassandra *Cassandra `yaml:"cassandra"`
// SQL contains the config for a SQL based datastore
SQL *SQL `yaml:"sql"`
// ElasticSearch contains the config for a ElasticSearch datastore
ElasticSearch *ElasticSearchConfig `yaml:"elasticsearch"`
}
// VisibilityConfig is config for visibility
VisibilityConfig struct {
// EnableSampling for visibility
EnableSampling dynamicconfig.BoolPropertyFn `yaml:"-" json:"-"`
// EnableReadFromClosedExecutionV2 read closed from v2 table
EnableReadFromClosedExecutionV2 dynamicconfig.BoolPropertyFn `yaml:"-" json:"-"`
// VisibilityOpenMaxQPS max QPS for record open workflows
VisibilityOpenMaxQPS dynamicconfig.IntPropertyFnWithDomainFilter `yaml:"-" json:"-"`
// VisibilityClosedMaxQPS max QPS for record closed workflows
VisibilityClosedMaxQPS dynamicconfig.IntPropertyFnWithDomainFilter `yaml:"-" json:"-"`
// VisibilityListMaxQPS max QPS for list workflow
VisibilityListMaxQPS dynamicconfig.IntPropertyFnWithDomainFilter `yaml:"-" json:"-"`
// ESIndexMaxResultWindow ElasticSearch index setting max_result_window
ESIndexMaxResultWindow dynamicconfig.IntPropertyFn `yaml:"-" json:"-"`
// MaxQPS is overall max QPS
MaxQPS dynamicconfig.IntPropertyFn `yaml:"-" json:"-"`
// ValidSearchAttributes is legal indexed keys that can be used in list APIs
ValidSearchAttributes dynamicconfig.MapPropertyFn `yaml:"-" json:"-"`
}
// Cassandra contains configuration to connect to Cassandra cluster
Cassandra struct {
// Hosts is a csv of cassandra endpoints
Hosts string `yaml:"hosts" validate:"nonzero"`
// Port is the cassandra port used for connection by gocql client
Port int `yaml:"port"`
// User is the cassandra user used for authentication by gocql client
User string `yaml:"user"`
// Password is the cassandra password used for authentication by gocql client
Password string `yaml:"password"`
// keyspace is the cassandra keyspace
Keyspace string `yaml:"keyspace" validate:"nonzero"`
// Region is the region filter arg for cassandra
Region string `yaml:"region"`
// Datacenter is the data center filter arg for cassandra
Datacenter string `yaml:"datacenter"`
// MaxConns is the max number of connections to this datastore for a single keyspace
MaxConns int `yaml:"maxConns"`
// TLS configuration
TLS *auth.TLS `yaml:"tls"`
// TODO: add a field for custom gocql client
}
// SQL is the configuration for connecting to a SQL backed datastore
SQL struct {
// User is the username to be used for the conn
User string `yaml:"user"`
// Password is the password corresponding to the user name
Password string `yaml:"password"`
// PluginName is the name of SQL plugin
PluginName string `yaml:"pluginName" validate:"nonzero"`
// DatabaseName is the name of SQL database to connect to
DatabaseName string `yaml:"databaseName" validate:"nonzero"`
// ConnectAddr is the remote addr of the database
ConnectAddr string `yaml:"connectAddr" validate:"nonzero"`
// ConnectProtocol is the protocol that goes with the ConnectAddr ex - tcp, unix
ConnectProtocol string `yaml:"connectProtocol" validate:"nonzero"`
// ConnectAttributes is a set of key-value attributes to be sent as part of connect data_source_name url
ConnectAttributes map[string]string `yaml:"connectAttributes"`
// MaxConns the max number of connections to this datastore
MaxConns int `yaml:"maxConns"`
// MaxIdleConns is the max number of idle connections to this datastore
MaxIdleConns int `yaml:"maxIdleConns"`
// MaxConnLifetime is the maximum time a connection can be alive
MaxConnLifetime time.Duration `yaml:"maxConnLifetime"`
// NumShards is the number of storage shards to use for tables
// in a sharded sql database. The default value for this param is 1
NumShards int `yaml:"nShards"`
// TLS is the configuration for TLS connections
TLS *auth.TLS `yaml:"tls"`
// EncodingType is the configuration for the type of encoding used for sql blobs
EncodingType string `yaml:"encodingType"`
// DecodingTypes is the configuration for all the sql blob decoding types which need to be supported
// DecodingTypes should not be removed unless there are no blobs in database with the encoding type
DecodingTypes []string `yaml:"decodingTypes"`
}
// CustomDatastoreConfig is the configuration for connecting to a custom datastore that is not supported by cadence core
CustomDatastoreConfig struct {
// Name of the custom datastore
Name string `yaml:"name"`
// Options is a set of key-value attributes that can be used by AbstractDatastoreFactory implementation
Options map[string]string `yaml:"options"`
}
// Replicator describes the configuration of replicator
Replicator struct{}
// Logger contains the config items for logger
Logger struct {
// Stdout is true if the output needs to goto standard out
Stdout bool `yaml:"stdout"`
// Level is the desired log level
Level string `yaml:"level"`
// OutputFile is the path to the log output file
OutputFile string `yaml:"outputFile"`
}
// ClusterMetadata contains the all cluster which participated in cross DC
ClusterMetadata struct {
EnableGlobalDomain bool `yaml:"enableGlobalDomain"`
// FailoverVersionIncrement is the increment of each cluster version when failover happens
FailoverVersionIncrement int64 `yaml:"failoverVersionIncrement"`
// MasterClusterName is the master cluster name, only the master cluster can register / update domain
// all clusters can do domain failover
MasterClusterName string `yaml:"masterClusterName"`
// CurrentClusterName is the name of the current cluster
CurrentClusterName string `yaml:"currentClusterName"`
// ClusterInformation contains all cluster names to corresponding information about that cluster
ClusterInformation map[string]ClusterInformation `yaml:"clusterInformation"`
}
// ClusterInformation contains the information about each cluster which participated in cross DC
ClusterInformation struct {
Enabled bool `yaml:"enabled"`
InitialFailoverVersion int64 `yaml:"initialFailoverVersion"`
// RPCName indicate the remote service name
RPCName string `yaml:"rpcName"`
// Address indicate the remote service address(Host:Port). Host can be DNS name.
RPCAddress string `yaml:"rpcAddress"`
}
// ReplicationTaskProcessorConfig is the config for replication task processor.
ReplicationTaskProcessorConfig struct {
NoTaskInitialWaitIntervalSecs int `yaml:"noTaskInitialWaitIntervalSecs"`
NoTaskWaitBackoffCoefficient float64 `yaml:"noTaskWaitBackoffCoefficient"`
NoTaskMaxWaitIntervalSecs int `yaml:"noTaskMaxWaitIntervalSecs"`
}
// DCRedirectionPolicy contains the frontend datacenter redirection policy
DCRedirectionPolicy struct {
Policy string `yaml:"policy"`
ToDC string `yaml:"toDC"`
}
// Metrics contains the config items for metrics subsystem
Metrics struct {
// M3 is the configuration for m3 metrics reporter
M3 *m3.Configuration `yaml:"m3"`
// Statsd is the configuration for statsd reporter
Statsd *Statsd `yaml:"statsd"`
// Prometheus is the configuration for prometheus reporter
Prometheus *prometheus.Configuration `yaml:"prometheus"`
// Tags is the set of key-value pairs to be reported
// as part of every metric
Tags map[string]string `yaml:"tags"`
// Prefix sets the prefix to all outgoing metrics
Prefix string `yaml:"prefix"`
}
// Statsd contains the config items for statsd metrics reporter
Statsd struct {
// The host and port of the statsd server
HostPort string `yaml:"hostPort" validate:"nonzero"`
// The prefix to use in reporting to statsd
Prefix string `yaml:"prefix" validate:"nonzero"`
// FlushInterval is the maximum interval for sending packets.
// If it is not specified, it defaults to 1 second.
FlushInterval time.Duration `yaml:"flushInterval"`
// FlushBytes specifies the maximum udp packet size you wish to send.
// If FlushBytes is unspecified, it defaults to 1432 bytes, which is
// considered safe for local traffic.
FlushBytes int `yaml:"flushBytes"`
}
// Archival contains the config for archival
Archival struct {
// History is the config for the history archival
History HistoryArchival `yaml:"history"`
// Visibility is the config for visibility archival
Visibility VisibilityArchival `yaml:"visibility"`
}
// HistoryArchival contains the config for history archival
HistoryArchival struct {
// Status is the status of history archival either: enabled, disabled, or paused
Status string `yaml:"status"`
// EnableRead whether history can be read from archival
EnableRead bool `yaml:"enableRead"`
// Provider contains the config for all history archivers
Provider *HistoryArchiverProvider `yaml:"provider"`
}
// HistoryArchiverProvider contains the config for all history archivers
HistoryArchiverProvider struct {
Filestore *FilestoreArchiver `yaml:"filestore"`
Gstorage *GstorageArchiver `yaml:"gstorage"`
S3store *S3Archiver `yaml:"s3store"`
}
// VisibilityArchival contains the config for visibility archival
VisibilityArchival struct {
// Status is the status of visibility archival either: enabled, disabled, or paused
Status string `yaml:"status"`
// EnableRead whether visibility can be read from archival
EnableRead bool `yaml:"enableRead"`
// Provider contains the config for all visibility archivers
Provider *VisibilityArchiverProvider `yaml:"provider"`
}
// VisibilityArchiverProvider contains the config for all visibility archivers
VisibilityArchiverProvider struct {
Filestore *FilestoreArchiver `yaml:"filestore"`
S3store *S3Archiver `yaml:"s3store"`
Gstorage *GstorageArchiver `yaml:"gstorage"`
}
// FilestoreArchiver contain the config for filestore archiver
FilestoreArchiver struct {
FileMode string `yaml:"fileMode"`
DirMode string `yaml:"dirMode"`
}
// GstorageArchiver contain the config for google storage archiver
GstorageArchiver struct {
CredentialsPath string `yaml:"credentialsPath"`
}
// S3Archiver contains the config for S3 archiver
S3Archiver struct {
Region string `yaml:"region"`
Endpoint *string `yaml:"endpoint"`
S3ForcePathStyle bool `yaml:"s3ForcePathStyle"`
}
// PublicClient is config for connecting to cadence frontend
PublicClient struct {
// HostPort is the host port to connect on. Host can be DNS name
HostPort string `yaml:"hostPort" validate:"nonzero"`
// interval to refresh DNS. Default to 10s
RefreshInterval time.Duration `yaml:"RefreshInterval"`
}
// DomainDefaults is the default config for each domain
DomainDefaults struct {
// Archival is the default archival config for each domain
Archival ArchivalDomainDefaults `yaml:"archival"`
}
// ArchivalDomainDefaults is the default archival config for each domain
ArchivalDomainDefaults struct {
// History is the domain default history archival config for each domain
History HistoryArchivalDomainDefaults `yaml:"history"`
// Visibility is the domain default visibility archival config for each domain
Visibility VisibilityArchivalDomainDefaults `yaml:"visibility"`
}
// HistoryArchivalDomainDefaults is the default history archival config for each domain
HistoryArchivalDomainDefaults struct {
// Status is the domain default status of history archival: enabled or disabled
Status string `yaml:"status"`
// URI is the domain default URI for history archiver
URI string `yaml:"URI"`
}
// VisibilityArchivalDomainDefaults is the default visibility archival config for each domain
VisibilityArchivalDomainDefaults struct {
// Status is the domain default status of visibility archival: enabled or disabled
Status string `yaml:"status"`
// URI is the domain default URI for visibility archiver
URI string `yaml:"URI"`
}
// BootstrapMode is an enum type for ringpop bootstrap mode
BootstrapMode int
)
// ValidateAndFillDefaults validates this config and fills default values if needed
func (c *Config) ValidateAndFillDefaults() error {
if err := c.validate(); err != nil {
return err
}
if err := c.fillDefaults(); err != nil {
return err
}
return nil
}
func (c *Config) validate() error {
if err := c.Persistence.Validate(); err != nil {
return err
}
return c.Archival.Validate(&c.DomainDefaults.Archival)
}
func (c *Config) fillDefaults() error {
// filling default encodingType/decodingTypes for SQL persistence
for k, store := range c.Persistence.DataStores {
if store.SQL != nil {
if store.SQL.EncodingType == "" {
store.SQL.EncodingType = string(common.EncodingTypeThriftRW)
}
if len(store.SQL.DecodingTypes) == 0 {
store.SQL.DecodingTypes = []string{
string(common.EncodingTypeThriftRW),
}
}
c.Persistence.DataStores[k] = store
}
}
// filling RPCName with a default value if empty
if c.ClusterMetadata != nil {
for k, cluster := range c.ClusterMetadata.ClusterInformation {
if cluster.RPCName == "" {
cluster.RPCName = "cadence-frontend"
c.ClusterMetadata.ClusterInformation[k] = cluster
}
}
}
return nil
}
// String converts the config object into a string
func (c *Config) String() string {
out, _ := json.MarshalIndent(c, "", " ")
return string(out)
}