github.com/aristanetworks/goarista@v0.0.0-20240514173732-cca2755bbd44/elasticsearch/mappings.go (about) 1 // Copyright (c) 2016 Arista Networks, Inc. 2 // Use of this source code is governed by the Apache License 2.0 3 // that can be found in the COPYING file. 4 5 package elasticsearch 6 7 import ( 8 "encoding/json" 9 "fmt" 10 "math" 11 "strings" 12 13 "github.com/openconfig/gnmi/proto/gnmi" 14 ) 15 16 // EscapeFieldName escapes field names for Elasticsearch 17 func EscapeFieldName(name string) string { 18 return strings.Replace(name, ".", "_", -1) 19 } 20 21 // SetKey fills a Data map's relevant key if the key is a simple type. 22 func SetKey(m map[string]interface{}, key interface{}) error { 23 // In the case of gnmi, these will always be strings 24 if str, ok := key.(string); ok { 25 m["KeyString"] = &str 26 return nil 27 } 28 return fmt.Errorf("unknown type %v", key) 29 } 30 31 // SetValue fills a Data map's relevant Value fields 32 func SetValue(m map[string]interface{}, val interface{}) error { 33 if val == nil { 34 return nil 35 } 36 if str := toStringPtr(val); str != nil { 37 m["ValueString"] = str 38 } else if long := toLongPtr(val); long != nil { 39 m["ValueLong"] = long 40 } else if bl := toBoolPtr(val); bl != nil { 41 m["ValueBool"] = bl 42 } else if dub := toDoublePtr(val); dub != nil { 43 m["ValueDouble"] = dub 44 } else if arr := toValueArray(val); arr != nil { 45 m["Value"] = arr 46 } else if json, err := toJSONValue(val); err == nil { 47 switch tv := json.(type) { 48 case string: 49 m["ValueString"] = &tv 50 case int, uint: 51 m["ValueLong"] = &tv 52 case bool: 53 m["ValueBool"] = &tv 54 case float32: 55 m["ValueDouble"] = &tv 56 case float64: 57 m["ValueDouble"] = &tv 58 } 59 } else if bytesVal, ok := val.(*gnmi.TypedValue_BytesVal); ok { 60 // TODO: handle byte arrays properly (BUG589248) 61 fmt.Printf("ignoring byte array with string value %s\n", bytesVal.BytesVal) 62 } else { 63 // this type may not be supported yet, or could not convert 64 return fmt.Errorf("unknown type %T for value %v", val, val) 65 } 66 return nil 67 } 68 69 // *TypedValue_StringVal 70 func toStringPtr(val interface{}) *string { 71 if tv, ok := val.(*gnmi.TypedValue_StringVal); ok { 72 return &tv.StringVal 73 } 74 return nil 75 } 76 77 // *TypedValue_IntVal, *TypedValue_UintVal 78 func toLongPtr(val interface{}) *int64 { 79 switch tv := val.(type) { 80 case *gnmi.TypedValue_IntVal: 81 val := int64(tv.IntVal) 82 return &val 83 case *gnmi.TypedValue_UintVal: 84 val := int64(tv.UintVal) 85 return &val 86 } 87 return nil 88 } 89 90 // *TypedValue_BoolVal 91 func toBoolPtr(val interface{}) *bool { 92 if tv, ok := val.(*gnmi.TypedValue_BoolVal); ok { 93 return &tv.BoolVal 94 } 95 return nil 96 } 97 98 // *TypedValue_FloatVal, *TypedValue_DecimalVal 99 func toDoublePtr(val interface{}) *float64 { 100 switch tv := val.(type) { 101 case *gnmi.TypedValue_FloatVal: 102 val := float64(tv.FloatVal) 103 if !math.IsInf(val, 0) && !math.IsNaN(val) { 104 return &val 105 } 106 case *gnmi.TypedValue_DoubleVal: 107 val := float64(tv.DoubleVal) 108 if !math.IsInf(val, 0) && !math.IsNaN(val) { 109 return &val 110 } 111 case *gnmi.TypedValue_DecimalVal: 112 // convert to float64 for now 113 val := float64(tv.DecimalVal.Digits) 114 for i := 0; i < int(tv.DecimalVal.Precision); i++ { 115 val /= 10 116 } 117 if !math.IsInf(val, 0) && !math.IsNaN(val) { 118 return &val 119 } 120 } 121 return nil 122 } 123 124 // Flatten a non-simple type into a []*field 125 func toValueArray(val interface{}) []*map[string]interface{} { 126 if tv, ok := val.(*gnmi.TypedValue_LeaflistVal); ok { 127 elements := tv.LeaflistVal.Element 128 fields := make([]*map[string]interface{}, len(elements)) 129 // LeaflistVal should only have simple types 130 for i, el := range elements { 131 m := make(map[string]interface{}) 132 if str := toStringPtr(el.Value); str != nil { 133 m["String"] = str 134 } else if long := toLongPtr(el.Value); long != nil { 135 m["Long"] = long 136 } else if bl := toBoolPtr(el.Value); bl != nil { 137 m["Bool"] = bl 138 } else if dub := toDoublePtr(el.Value); dub != nil { 139 m["Double"] = dub 140 } else { 141 // this type is not supported yet 142 return nil 143 } 144 fields[i] = &m 145 } 146 return fields 147 } 148 return nil 149 } 150 151 // *TypedValue_JsonVal, *TypedValue_JsonIetfVal 152 func toJSONValue(val interface{}) (interface{}, error) { 153 var out interface{} 154 if tv, ok := val.(*gnmi.TypedValue_JsonVal); ok { 155 err := json.Unmarshal(tv.JsonVal, &out) 156 return out, err 157 } 158 if tv, ok := val.(*gnmi.TypedValue_JsonIetfVal); ok { 159 err := json.Unmarshal(tv.JsonIetfVal, &out) 160 return out, err 161 } 162 return nil, nil 163 }