github.com/whiteboxio/flow@v0.0.3-0.20190918184116-508d75d68a2c/pkg/cast/types.go (about) 1 package cast 2 3 import ( 4 "fmt" 5 "sort" 6 "strings" 7 8 "github.com/awesome-flow/flow/pkg/types" 9 ) 10 11 // CfgMapper is the root-level system config encorporating the primary config 12 // blocks, as: system, components and pipeline. 13 type CfgMapper struct{} 14 15 var _ Mapper = (*CfgMapper)(nil) 16 17 func errUnknownValType(castType string, kv *types.KeyValue) error { 18 return fmt.Errorf("%s cast failed for key: %q, val: %#v: unknown value type", castType, kv.Key, kv.Value) 19 } 20 21 func errUnknownKeys(castType string, kv *types.KeyValue, unknown map[string]struct{}) error { 22 unknownArr := make([]string, 0, len(unknown)) 23 for k := range unknown { 24 unknownArr = append(unknownArr, k) 25 } 26 sort.Strings(unknownArr) 27 return fmt.Errorf("%s cast failed for key: %q: unknown attributes: [%s]", castType, kv.Key, strings.Join(unknownArr, ", ")) 28 } 29 30 // Map converts map[string]Value to types.Cfg{} structure. 31 // Lookup keys are: 32 // * components 33 // * pipeline 34 // * system 35 // No extra keys are allowed under this section. 36 func (*CfgMapper) Map(kv *types.KeyValue) (*types.KeyValue, error) { 37 var resKV *types.KeyValue 38 var err error 39 if vmap, ok := kv.Value.(map[string]types.Value); ok { 40 res := types.Cfg{} 41 keys := make(map[string]struct{}) 42 for k := range vmap { 43 keys[k] = struct{}{} 44 } 45 if components, ok := vmap["actors"]; ok { 46 delete(keys, "actors") 47 res.Actors = components.(map[string]types.CfgBlockActor) 48 } 49 if pipeline, ok := vmap["pipeline"]; ok { 50 delete(keys, "pipeline") 51 res.Pipeline = pipeline.(map[string]types.CfgBlockPipeline) 52 } 53 if system, ok := vmap["system"]; ok { 54 delete(keys, "system") 55 res.System = system.(types.CfgBlockSystem) 56 } 57 if len(keys) > 0 { 58 err = errUnknownKeys("Cfg", kv, keys) 59 } else { 60 resKV = &types.KeyValue{Key: kv.Key, Value: res} 61 } 62 } else { 63 err = errUnknownValType("Cfg", kv) 64 } 65 if err != nil { 66 return nil, err 67 } 68 return resKV, nil 69 } 70 71 //============================================================================// 72 73 // CfgBlockSystemMapper represents the system config section. 74 type CfgBlockSystemMapper struct{} 75 76 var _ Mapper = (*CfgBlockSystemMapper)(nil) 77 78 // Map converts map[string]Value to types.CfgBlockSystem{} structure. 79 // Lookup keys are: 80 // * maxprocs 81 // * admin 82 // * metrics 83 // No extra keys are allowed under this section. 84 func (*CfgBlockSystemMapper) Map(kv *types.KeyValue) (*types.KeyValue, error) { 85 var resKV *types.KeyValue 86 var err error 87 if vmap, ok := kv.Value.(map[string]types.Value); ok { 88 res := types.CfgBlockSystem{} 89 keys := make(map[string]struct{}) 90 for k := range vmap { 91 keys[k] = struct{}{} 92 } 93 if maxprocs, ok := vmap["maxprocs"]; ok { 94 delete(keys, "maxprocs") 95 res.Maxprocs = maxprocs.(int) 96 } 97 if admin, ok := vmap["admin"]; ok { 98 delete(keys, "admin") 99 res.Admin = admin.(types.CfgBlockSystemAdmin) 100 } 101 if metrics, ok := vmap["metrics"]; ok { 102 delete(keys, "metrics") 103 res.Metrics = metrics.(types.CfgBlockSystemMetrics) 104 } 105 if len(keys) > 0 { 106 err = errUnknownKeys("CfgBlockSystem", kv, keys) 107 } else { 108 resKV = &types.KeyValue{Key: kv.Key, Value: res} 109 } 110 } else { 111 err = errUnknownValType("CfgBlockSystem", kv) 112 } 113 if err != nil { 114 return nil, err 115 } 116 return resKV, nil 117 } 118 119 //============================================================================// 120 121 // CfgBlockSystemAdminMapper represents a mapper for system.admin config section. 122 type CfgBlockSystemAdminMapper struct{} 123 124 var _ Mapper = (*CfgBlockSystemAdminMapper)(nil) 125 126 // Map converts map[string]Value to types.CfgBlockSystemAdmin{} structure. 127 // Lookup keys are: 128 // * enabled 129 // * bind_addr 130 // No extra keys are allowed under this section. 131 func (*CfgBlockSystemAdminMapper) Map(kv *types.KeyValue) (*types.KeyValue, error) { 132 var resKV *types.KeyValue 133 var err error 134 if vmap, ok := kv.Value.(map[string]types.Value); ok { 135 res := types.CfgBlockSystemAdmin{} 136 keys := make(map[string]struct{}) 137 for k := range vmap { 138 keys[k] = struct{}{} 139 } 140 if enabled, ok := vmap["enabled"]; ok { 141 delete(keys, "enabled") 142 res.Enabled = enabled.(bool) 143 } 144 if bind, ok := vmap["bind"]; ok { 145 delete(keys, "bind") 146 res.Bind = bind.(string) 147 } 148 if len(keys) > 0 { 149 err = errUnknownKeys("CfgBlockSystemAdmin", kv, keys) 150 } else { 151 resKV = &types.KeyValue{Key: kv.Key, Value: res} 152 } 153 } else { 154 err = errUnknownValType("CfgBlockSystemAdmin", kv) 155 } 156 if err != nil { 157 return nil, err 158 } 159 return resKV, nil 160 } 161 162 //============================================================================// 163 164 // CfgBlockSystemMetricsMapper represents a mapper for system.metrics section. 165 type CfgBlockSystemMetricsMapper struct{} 166 167 var _ Mapper = (*CfgBlockSystemMetricsMapper)(nil) 168 169 // Map converts map[string]Value to types.CfgBlockSystemMetrics{} structure. 170 // Lookup keys are: 171 // * enabled 172 // * interval 173 // * receiver 174 // No extra keys are allowed in this section. 175 func (*CfgBlockSystemMetricsMapper) Map(kv *types.KeyValue) (*types.KeyValue, error) { 176 var resKV *types.KeyValue 177 var err error 178 if vmap, ok := kv.Value.(map[string]types.Value); ok { 179 res := types.CfgBlockSystemMetrics{} 180 keys := make(map[string]struct{}) 181 for k := range vmap { 182 keys[k] = struct{}{} 183 } 184 if enabled, ok := vmap["enabled"]; ok { 185 delete(keys, "enabled") 186 res.Enabled = enabled.(bool) 187 } 188 if interval, ok := vmap["interval"]; ok { 189 delete(keys, "interval") 190 res.Interval = interval.(int) 191 } 192 if receiver, ok := vmap["receiver"]; ok { 193 delete(keys, "receiver") 194 res.Receiver = receiver.(types.CfgBlockSystemMetricsReceiver) 195 } 196 if len(keys) > 0 { 197 err = errUnknownKeys("CfgBlockSystemMetrics", kv, keys) 198 } else { 199 resKV = &types.KeyValue{Key: kv.Key, Value: res} 200 } 201 } else { 202 err = errUnknownValType("CfgBlockSystemMetrics", kv) 203 } 204 if err != nil { 205 return nil, err 206 } 207 return resKV, nil 208 } 209 210 //============================================================================// 211 212 // CfgBlockSystemMetricsReceiverMapper represents a mapper for 213 // system.metrics.receiver section. 214 type CfgBlockSystemMetricsReceiverMapper struct{} 215 216 var _ Mapper = (*CfgBlockSystemMetricsReceiverMapper)(nil) 217 218 // Map convers map[string]Value to types.CfgBlockSystemMetricsReceiver{} structure. 219 // Lookup keys are: 220 // * type 221 // * params 222 // No extra keys are allowed in this section. 223 func (*CfgBlockSystemMetricsReceiverMapper) Map(kv *types.KeyValue) (*types.KeyValue, error) { 224 var resKV *types.KeyValue 225 var err error 226 if vmap, ok := kv.Value.(map[string]types.Value); ok { 227 res := types.CfgBlockSystemMetricsReceiver{} 228 keys := make(map[string]struct{}) 229 for k := range vmap { 230 keys[k] = struct{}{} 231 } 232 if tp, ok := vmap["type"]; ok { 233 delete(keys, "type") 234 res.Type = tp.(string) 235 } 236 if params, ok := vmap["params"]; ok { 237 delete(keys, "params") 238 res.Params = params.(map[string]types.Value) 239 } 240 if len(keys) > 0 { 241 err = errUnknownKeys("CfgBlockSystemMetricsReceiver", kv, keys) 242 } else { 243 resKV = &types.KeyValue{Key: kv.Key, Value: res} 244 } 245 } else { 246 err = errUnknownValType("CfgBlockSystemMetricsReceiver", kv) 247 } 248 if err != nil { 249 return nil, err 250 } 251 return resKV, nil 252 } 253 254 //============================================================================// 255 256 // MapCfgBlockActorMapper represents a mapper for components config section. 257 type MapCfgBlockActorMapper struct{} 258 259 var _ Mapper = (*MapCfgBlockActorMapper)(nil) 260 261 // Map converts map[string]Value to map[string]types.CfgBlockActor. 262 // All keys from the original map will be kept in the resulting structure. 263 func (*MapCfgBlockActorMapper) Map(kv *types.KeyValue) (*types.KeyValue, error) { 264 if vmap, ok := kv.Value.(map[string]types.Value); ok { 265 res := make(map[string]types.CfgBlockActor) 266 for k, v := range vmap { 267 res[k] = v.(types.CfgBlockActor) 268 } 269 return &types.KeyValue{Key: kv.Key, Value: res}, nil 270 } 271 return nil, errUnknownValType("map[string]CfgBlockActor", kv) 272 } 273 274 //============================================================================// 275 276 // CfgBlockActorMapper represents a mapper for components.* config section. 277 type CfgBlockActorMapper struct{} 278 279 var _ Mapper = (*CfgBlockActorMapper)(nil) 280 281 // Map converts map[string]Value to types.CfgBlockActor{}. 282 // Lookup keys are: 283 // * constructor 284 // * module 285 // * params 286 // No extra keys are allowed in this section. 287 func (*CfgBlockActorMapper) Map(kv *types.KeyValue) (*types.KeyValue, error) { 288 var resKV *types.KeyValue 289 var err error 290 if vmap, ok := kv.Value.(map[string]types.Value); ok { 291 res := types.CfgBlockActor{} 292 keys := make(map[string]struct{}) 293 for k := range vmap { 294 keys[k] = struct{}{} 295 } 296 if builder, ok := vmap["builder"]; ok { 297 delete(keys, "builder") 298 res.Builder = builder.(string) 299 } 300 if module, ok := vmap["module"]; ok { 301 delete(keys, "module") 302 res.Module = module.(string) 303 } 304 if params, ok := vmap["params"]; ok { 305 delete(keys, "params") 306 res.Params = params.(map[string]types.Value) 307 } 308 if len(keys) > 0 { 309 err = errUnknownKeys("CfgBlockActor", kv, keys) 310 } else { 311 resKV = &types.KeyValue{Key: kv.Key, Value: res} 312 } 313 } else { 314 err = errUnknownValType("CfgBlockActor", kv) 315 } 316 if err != nil { 317 return nil, err 318 } 319 return resKV, nil 320 } 321 322 //============================================================================// 323 324 // MapCfgBlockPipelineMapper represents a mapper for pipeline config section. 325 type MapCfgBlockPipelineMapper struct{} 326 327 var _ Mapper = (*MapCfgBlockActorMapper)(nil) 328 329 // Map converts map[string]Value to map[string]types.CfgBlockPipeline. 330 // All keys from the original map will be kept in the resulting map. 331 func (*MapCfgBlockPipelineMapper) Map(kv *types.KeyValue) (*types.KeyValue, error) { 332 if vmap, ok := kv.Value.(map[string]types.Value); ok { 333 res := make(map[string]types.CfgBlockPipeline) 334 for k, v := range vmap { 335 res[k] = v.(types.CfgBlockPipeline) 336 } 337 return &types.KeyValue{Key: kv.Key, Value: res}, nil 338 } 339 return nil, errUnknownValType("map[string]CfgBlockPipeline", kv) 340 } 341 342 //============================================================================// 343 344 // CfgBlockPipelineMapper represents a mapper for pipeline.* config section. 345 type CfgBlockPipelineMapper struct{} 346 347 var _ Mapper = (*CfgBlockPipelineMapper)(nil) 348 349 // Map converts map[string]Value to types.CfgBlockPipeline structure. 350 // Lookup keys are: 351 // * connect 352 // * links 353 // * routes 354 // No extra keys are allowed in this section. 355 func (*CfgBlockPipelineMapper) Map(kv *types.KeyValue) (*types.KeyValue, error) { 356 var resKV *types.KeyValue 357 var err error 358 if vmap, ok := kv.Value.(map[string]types.Value); ok { 359 res := types.CfgBlockPipeline{} 360 keys := make(map[string]struct{}) 361 for k := range vmap { 362 keys[k] = struct{}{} 363 } 364 if connect, ok := vmap["connect"]; ok { 365 delete(keys, "connect") 366 res.Connect = connect.([]string) 367 } 368 if len(keys) > 0 { 369 err = errUnknownKeys("CfgBlockPipeline", kv, keys) 370 } else { 371 resKV = &types.KeyValue{Key: kv.Key, Value: res} 372 } 373 } else { 374 err = errUnknownValType("CfgBlockPipeline", kv) 375 } 376 if err != nil { 377 return nil, err 378 } 379 return resKV, nil 380 } 381 382 //============================================================================// 383 384 // ArrStrMapper represents a mapper for string arrays. 385 type ArrStrMapper struct{} 386 387 var _ Mapper = (*ArrStrMapper)(nil) 388 389 // Map converts string or []interface{} to []string. 390 func (*ArrStrMapper) Map(kv *types.KeyValue) (*types.KeyValue, error) { 391 // []interface{}, not []Value because factual arguments are not being 392 // type casted 393 if sv, ok := kv.Value.(string); ok { 394 return &types.KeyValue{Key: kv.Key, Value: []string{sv}}, nil 395 } 396 if arr, ok := kv.Value.([]interface{}); ok { 397 res := make([]string, 0, len(arr)) 398 for _, v := range arr { 399 res = append(res, v.(string)) 400 } 401 return &types.KeyValue{Key: kv.Key, Value: res}, nil 402 } 403 return nil, errUnknownValType("[]string", kv) 404 } 405 406 //============================================================================// 407 408 // MapStrToStrMapper represents a mapper for map[string]string maps. 409 type MapStrToStrMapper struct{} 410 411 var _ Mapper = (*MapStrToStrMapper)(nil) 412 413 // Map converts from map[string]types.Value to map[string]string. 414 func (*MapStrToStrMapper) Map(kv *types.KeyValue) (*types.KeyValue, error) { 415 if mp, ok := kv.Value.(map[string]types.Value); ok { 416 res := make(map[string]string) 417 for k, v := range mp { 418 res[k] = v.(string) 419 } 420 return &types.KeyValue{Key: kv.Key, Value: res}, nil 421 } 422 return nil, errUnknownValType("map[string]string", kv) 423 }