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 }