func prepareValues()

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
}