github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/discovery/config.go (about) 1 // Copyright (c) 2020 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 discovery provides discovery configuration. 22 package discovery 23 24 import ( 25 "fmt" 26 27 etcdclient "github.com/m3db/m3/src/cluster/client/etcd" 28 "github.com/m3db/m3/src/dbnode/environment" 29 ) 30 31 const ( 32 defaultEnvironment = "default_env" 33 defaultZone = "embedded" 34 defaultM3DBService = "m3db" 35 defaultM3AggregatorService = "m3aggregator" 36 defaultCacheDirectory = "/var/lib/m3kv" 37 defaultSingleNodeClusterEndpoint = "127.0.0.1:2379" 38 defaultSingleNodeClusterSeedEndpoint = "http://127.0.0.1:2380" 39 ) 40 41 var validDiscoveryConfigTypes = []ConfigurationType{ 42 ConfigType, 43 M3DBSingleNodeType, 44 M3DBClusterType, 45 M3AggregatorClusterType, 46 } 47 48 // ConfigurationType defines the type of discovery configuration. 49 type ConfigurationType uint 50 51 const ( 52 // ConfigType defines a generic definition for service discovery via etcd. 53 ConfigType ConfigurationType = iota 54 // M3DBSingleNodeType defines configuration for a single M3DB node via etcd. 55 M3DBSingleNodeType 56 // M3DBClusterType defines M3DB discovery via etcd. 57 M3DBClusterType 58 // M3AggregatorClusterType defines M3DB discovery via etcd. 59 M3AggregatorClusterType 60 ) 61 62 // MarshalYAML marshals a ConfigurationType. 63 func (t *ConfigurationType) MarshalYAML() (interface{}, error) { 64 return t.String(), nil 65 } 66 67 // UnmarshalYAML unmarshals an ConfigurationType into a valid type from string. 68 func (t *ConfigurationType) UnmarshalYAML(unmarshal func(interface{}) error) error { 69 var str string 70 if err := unmarshal(&str); err != nil { 71 return err 72 } 73 74 // If unspecified, use default mode. 75 if str == "" { 76 *t = ConfigType 77 78 return nil 79 } 80 81 for _, valid := range validDiscoveryConfigTypes { 82 if str == valid.String() { 83 *t = valid 84 85 return nil 86 } 87 } 88 89 return fmt.Errorf("invalid ConfigurationType '%s' valid types are: %s", 90 str, validDiscoveryConfigTypes) 91 } 92 93 // String returns the discovery configuration type as a string. 94 func (t ConfigurationType) String() string { 95 switch t { 96 case ConfigType: 97 return "config" 98 case M3DBSingleNodeType: 99 return "m3db_single_node" 100 case M3DBClusterType: 101 return "m3db_cluster" 102 case M3AggregatorClusterType: 103 return "m3aggregator_cluster" 104 } 105 return "unknown" 106 } 107 108 // Configuration defines how services are to be discovered. 109 type Configuration struct { 110 // Type defines the type of discovery configuration being used. 111 Type *ConfigurationType `yaml:"type"` 112 113 // M3DBCluster defines M3DB discovery via etcd. 114 M3DBCluster *M3DBClusterDiscoveryConfiguration `yaml:"m3dbCluster"` 115 116 // M3AggregatorCluster defines M3Aggregator discovery via etcd. 117 M3AggregatorCluster *M3AggregatorClusterDiscoveryConfiguration `yaml:"m3AggregatorCluster"` 118 119 // Config defines a generic definition for service discovery via etcd. 120 Config *environment.Configuration `yaml:"config"` 121 } 122 123 // M3DBClusterDiscoveryConfiguration defines discovery configuration for M3DB. 124 type M3DBClusterDiscoveryConfiguration struct { 125 Env string `yaml:"env" validate:"nonzero"` 126 Zone *string `yaml:"zone"` 127 Endpoints []string `yaml:"endpoints"` 128 } 129 130 // M3AggregatorClusterDiscoveryConfiguration defines discovery configuration for M3Aggregator. 131 type M3AggregatorClusterDiscoveryConfiguration struct { 132 Env string `yaml:"env"` 133 Zone *string `yaml:"zone"` 134 Endpoints []string `yaml:"endpoints"` 135 } 136 137 // EnvironmentConfig provides the environment configuration 138 // based on the type of discovery configuration set. 139 func (c *Configuration) EnvironmentConfig( 140 hostID string, 141 ) (environment.Configuration, error) { 142 discoveryConfigType := ConfigType 143 if c.Type != nil { 144 discoveryConfigType = *c.Type 145 } 146 147 switch discoveryConfigType { 148 case ConfigType: 149 return *c.Config, nil 150 case M3DBSingleNodeType: 151 return c.m3dbSingleNodeEnvConfig(hostID), nil 152 case M3DBClusterType: 153 return c.envConfig( 154 discoveryConfigType, 155 defaultM3DBService, 156 c.M3DBCluster.Zone, 157 c.M3DBCluster.Env, 158 c.M3DBCluster.Endpoints, 159 ) 160 case M3AggregatorClusterType: 161 return c.envConfig( 162 discoveryConfigType, 163 defaultM3AggregatorService, 164 c.M3AggregatorCluster.Zone, 165 c.M3AggregatorCluster.Env, 166 c.M3AggregatorCluster.Endpoints, 167 ) 168 } 169 170 return environment.Configuration{}, fmt.Errorf("unrecognized discovery type: %d", c.Type) 171 } 172 173 func (c *Configuration) m3dbSingleNodeEnvConfig( 174 hostID string, 175 ) environment.Configuration { 176 return environment.Configuration{ 177 Services: []*environment.DynamicCluster{ 178 { 179 Service: &etcdclient.Configuration{ 180 Service: defaultM3DBService, 181 CacheDir: defaultCacheDirectory, 182 Zone: defaultZone, 183 Env: defaultEnvironment, 184 ETCDClusters: []etcdclient.ClusterConfig{ 185 { 186 Zone: defaultZone, 187 Endpoints: []string{defaultSingleNodeClusterEndpoint}, 188 }, 189 }, 190 }, 191 }, 192 }, 193 SeedNodes: &environment.SeedNodesConfig{ 194 InitialCluster: []environment.SeedNode{ 195 { 196 HostID: hostID, 197 Endpoint: defaultSingleNodeClusterSeedEndpoint, 198 }, 199 }, 200 }, 201 } 202 } 203 204 func (c *Configuration) envConfig( 205 configType ConfigurationType, 206 service string, 207 zone *string, 208 env string, 209 endpoints []string, 210 ) (environment.Configuration, error) { 211 if c == nil { 212 err := fmt.Errorf("discovery configuration required for type: %s", 213 configType.String()) 214 return environment.Configuration{}, err 215 } 216 217 validZone := defaultZone 218 if zone != nil { 219 validZone = *zone 220 } 221 222 return environment.Configuration{ 223 Services: []*environment.DynamicCluster{ 224 { 225 Service: &etcdclient.Configuration{ 226 Service: service, 227 CacheDir: defaultCacheDirectory, 228 Zone: validZone, 229 Env: env, 230 ETCDClusters: []etcdclient.ClusterConfig{ 231 { 232 Zone: validZone, 233 Endpoints: endpoints, 234 }, 235 }, 236 }, 237 }, 238 }, 239 }, nil 240 }