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