github.com/nais/knorten@v0.0.0-20240104110906-55926958e361/pkg/reflect/reflect.go (about)

     1  package reflect
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"reflect"
     8  	"strings"
     9  )
    10  
    11  func reflectValueToString(value reflect.Value) (string, error) {
    12  	switch value.Type().Kind() {
    13  	case reflect.String:
    14  		return value.String(), nil
    15  	case reflect.Slice:
    16  		parts, ok := value.Interface().([]string)
    17  		if !ok {
    18  			return "", errors.New("unable to parse reflect slice")
    19  		}
    20  
    21  		quotified := make([]string, len(parts))
    22  		for i, v := range parts {
    23  			quotified[i] = fmt.Sprintf("%q", v)
    24  		}
    25  		return fmt.Sprintf("[%v]", strings.Join(quotified, ", ")), nil
    26  	default:
    27  		return "", errors.New("helm value must be string or slice of strings, unable to parse helm value")
    28  
    29  	}
    30  }
    31  
    32  func CreateChartValues(form any) (map[string]string, error) {
    33  	values := reflect.ValueOf(form)
    34  	fields := reflect.VisibleFields(reflect.TypeOf(form))
    35  
    36  	chartValues := map[string]string{}
    37  
    38  	for _, field := range fields {
    39  		tag := field.Tag.Get("helm")
    40  		if tag == "" {
    41  			continue
    42  		}
    43  		value := values.FieldByName(field.Name)
    44  		valueAsString, err := reflectValueToString(value)
    45  		if err != nil {
    46  			return map[string]string{}, fmt.Errorf("key %v: %v", tag, err)
    47  		}
    48  
    49  		if valueAsString != "" {
    50  			chartValues[tag] = valueAsString
    51  		}
    52  	}
    53  
    54  	return chartValues, nil
    55  }
    56  
    57  func InterfaceToStruct(obj any, values map[string]string) error {
    58  	structValue := reflect.ValueOf(obj).Elem()
    59  	fields := reflect.VisibleFields(structValue.Type())
    60  	for _, field := range fields {
    61  		fieldTag := field.Tag.Get("helm")
    62  		if fieldTag == "" {
    63  			continue
    64  		}
    65  
    66  		value := values[fieldTag]
    67  
    68  		structValue := reflect.ValueOf(obj).Elem()
    69  		structFieldValue := structValue.FieldByName(field.Name)
    70  
    71  		if !structFieldValue.IsValid() {
    72  			return fmt.Errorf("no such field: %s in obj", field.Name)
    73  		}
    74  
    75  		if !structFieldValue.CanSet() {
    76  			return fmt.Errorf("cannot set %s field value", field.Name)
    77  		}
    78  
    79  		kind := structFieldValue.Kind()
    80  		switch kind {
    81  		case reflect.String:
    82  			structFieldValue.Set(reflect.ValueOf(value))
    83  		case reflect.Slice:
    84  			var slice []string
    85  			err := json.Unmarshal([]byte(value), &slice)
    86  			if err != nil {
    87  				return err
    88  			}
    89  			structFieldValue.Set(reflect.ValueOf(slice))
    90  		default:
    91  			return fmt.Errorf("unknown kind('%v')", kind)
    92  		}
    93  	}
    94  
    95  	return nil
    96  }