in cluster-autoscaler/cloudprovider/exoscale/internal/github.com/exoscale/egoscale/serialization.go [75:176]
func prepareValues(prefix string, command interface{}) (url.Values, error) {
params := url.Values{}
value := reflect.ValueOf(command)
typeof := reflect.TypeOf(command)
// Going up the pointer chain to find the underlying struct
for typeof.Kind() == reflect.Ptr {
typeof = typeof.Elem()
value = value.Elem()
}
// Checking for nil commands
if !value.IsValid() {
return nil, fmt.Errorf("cannot serialize the invalid value %#v", command)
}
for i := 0; i < typeof.NumField(); i++ {
field := typeof.Field(i)
if field.Name == "_" {
continue
}
val := value.Field(i)
tag := field.Tag
var err error
var name string
var value interface{}
if json, ok := tag.Lookup("json"); ok {
n, required := ExtractJSONTag(field.Name, json)
name = prefix + n
switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
value, err = prepareInt(val.Int(), required)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
value, err = prepareUint(val.Uint(), required)
case reflect.Float32, reflect.Float64:
value, err = prepareFloat(val.Float(), required)
case reflect.String:
value, err = prepareString(val.String(), required)
case reflect.Bool:
value, err = prepareBool(val.Bool(), required)
case reflect.Map:
if val.Len() == 0 {
if required {
err = fmt.Errorf("field is required, got empty map")
}
} else {
value, err = prepareMap(name, val.Interface())
}
case reflect.Ptr:
value, err = preparePtr(field.Type.Elem().Kind(), val, required)
case reflect.Slice:
value, err = prepareSlice(name, field.Type, val, required)
case reflect.Struct:
value, err = prepareStruct(val.Interface(), required)
default:
if required {
err = fmt.Errorf("unsupported type")
}
}
} else {
switch val.Kind() {
case reflect.Struct:
value, err = prepareEmbedStruct(val.Interface())
default:
log.Printf("[SKIP] %s.%s no json label found", typeof.Name(), field.Name)
}
}
if err != nil {
return nil, fmt.Errorf("%s.%s (%v) %s", typeof.Name(), field.Name, val.Kind(), err)
}
switch v := value.(type) {
case *string:
if name != "" && v != nil {
params.Set(name, *v)
}
case url.Values:
for k, xs := range v {
for _, x := range xs {
params.Add(k, x)
}
}
}
}
return params, nil
}