github.com/zntrio/harp/v2@v2.0.9/pkg/sdk/value/flatmap/flatmap.go (about) 1 // Licensed to Elasticsearch B.V. under one or more contributor 2 // license agreements. See the NOTICE file distributed with 3 // this work for additional information regarding copyright 4 // ownership. Elasticsearch B.V. licenses this file to you under 5 // the Apache License, Version 2.0 (the "License"); you may 6 // not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, 12 // software distributed under the License is distributed on an 13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 // KIND, either express or implied. See the License for the 15 // specific language governing permissions and limitations 16 // under the License. 17 18 package flatmap 19 20 import ( 21 "fmt" 22 "path" 23 "reflect" 24 25 "github.com/zntrio/harp/v2/pkg/bundle" 26 ) 27 28 // ----------------------------------------------------------------------------- 29 30 // Flatten takes a structure and turns into a flat map[string]string. 31 func Flatten(thing map[string]interface{}) map[string]bundle.KV { 32 result := make(map[string]string) 33 34 // Flatten recursively the map 35 for k, raw := range thing { 36 flatten(result, k, reflect.ValueOf(raw)) 37 } 38 39 // Unpack leaf as secrets 40 jsonMap := map[string]bundle.KV{} 41 for k, v := range result { 42 // Get last element as secret name 43 packageName, secretName := path.Split(k) 44 45 // Remove trailing path separator 46 packageName = path.Clean(packageName) 47 48 // Check if package already is registered 49 p, ok := jsonMap[packageName] 50 if !ok { 51 p = bundle.KV{} 52 } 53 54 // Assign secret 55 p[secretName] = v 56 57 // Re-assign to map 58 jsonMap[packageName] = p 59 } 60 61 // Return json map 62 return jsonMap 63 } 64 65 func flatten(result map[string]string, prefix string, v reflect.Value) { 66 if v.Kind() == reflect.Interface { 67 v = v.Elem() 68 } 69 70 switch v.Kind() { 71 case reflect.Bool: 72 if v.Bool() { 73 result[prefix] = "true" 74 } else { 75 result[prefix] = "false" 76 } 77 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 78 result[prefix] = fmt.Sprintf("%d", v.Int()) 79 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 80 result[prefix] = fmt.Sprintf("%d", v.Uint()) 81 case reflect.Float32, reflect.Float64: 82 result[prefix] = fmt.Sprintf("%f", v.Float()) 83 case reflect.Map: 84 flattenMap(result, prefix, v) 85 case reflect.Slice, reflect.Array: 86 flattenSlice(result, prefix, v) 87 case reflect.String: 88 result[prefix] = v.String() 89 case reflect.Chan, reflect.Complex128, reflect.Complex64, reflect.Func, reflect.Interface: 90 // ignore 91 case reflect.Invalid, reflect.Ptr, reflect.Struct, reflect.Uintptr, reflect.UnsafePointer: 92 // ignore 93 default: 94 panic(fmt.Sprintf("Unknown: %s", v)) 95 } 96 } 97 98 func flattenMap(result map[string]string, prefix string, v reflect.Value) { 99 for _, k := range v.MapKeys() { 100 if k.Kind() == reflect.Interface { 101 k = k.Elem() 102 } 103 104 if k.Kind() != reflect.String { 105 panic(fmt.Sprintf("%s: map key is not string: %s", prefix, k)) 106 } 107 108 flatten(result, fmt.Sprintf("%s/%s", prefix, k.String()), v.MapIndex(k)) 109 } 110 } 111 112 func flattenSlice(result map[string]string, prefix string, v reflect.Value) { 113 prefix += "/" 114 115 result[prefix+"#"] = fmt.Sprintf("%d", v.Len()) 116 for i := 0; i < v.Len(); i++ { 117 flatten(result, fmt.Sprintf("%s%d", prefix, i), v.Index(i)) 118 } 119 }