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  }