Files
2017-02-14 13:59:07 -08:00

136 lines
2.8 KiB
Go

package api
import (
"encoding/json"
"errors"
"reflect"
"github.com/rancher/go-rancher/client"
)
func toMap(obj interface{}) (map[string]interface{}, error) {
result := map[string]interface{}{}
bytes, err := json.Marshal(obj)
if err != nil {
return result, err
}
err = json.Unmarshal(bytes, &result)
return result, err
}
func getEmbedded(obj interface{}, checkType reflect.Type) interface{} {
val := reflect.ValueOf(obj)
for val.Kind() == reflect.Ptr || val.Kind() == reflect.Interface {
val = val.Elem()
}
if val.Kind() != reflect.Struct {
panic("Passed type is not a struct got: " + val.Kind().String())
}
t := val.Type()
for i := 0; i < val.NumField(); i++ {
if t.Field(i).Anonymous && t.Field(i).Type == checkType {
if !val.Field(i).CanAddr() {
panic("Field " + t.Field(i).Name + " is not addressable, pass pointer")
}
return val.Field(i).Addr().Interface()
}
}
return nil
}
func getCollection(obj interface{}) *client.Collection {
val := getEmbedded(obj, reflect.TypeOf(client.Collection{}))
if val == nil {
return nil
}
return val.(*client.Collection)
}
func getResource(obj interface{}) *client.Resource {
r, ok := obj.(*client.Resource)
if ok {
return r
}
rObj, ok := obj.(client.Resource)
if ok {
return &rObj
}
val := getEmbedded(obj, reflect.TypeOf(client.Resource{}))
if val == nil {
return nil
}
return val.(*client.Resource)
}
func CollectionToMap(obj interface{}, schemas *client.Schemas) (map[string]interface{}, []map[string]interface{}, error) {
result := map[string]interface{}{}
data := []map[string]interface{}{}
if obj == nil {
return result, data, nil
}
c := getCollection(obj)
if c == nil {
return result, data, errors.New("value is not a Collection")
}
val := reflect.ValueOf(obj)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
val = val.FieldByName("Data")
for i := 0; i < val.Len(); i++ {
obj := val.Index(i)
if obj.Kind() != reflect.Ptr && obj.Kind() != reflect.Interface {
obj = obj.Addr()
}
dataObj, err := ResourceToMap(obj.Interface(), schemas)
if err != nil {
return result, data, err
}
data = append(data, dataObj)
}
collectionMap, err := toMap(obj)
if err != nil {
return result, data, err
}
collectionMap["data"] = data
return collectionMap, data, nil
}
func ResourceToMap(obj interface{}, schemas *client.Schemas) (map[string]interface{}, error) {
result := map[string]interface{}{}
if obj == nil {
return result, nil
}
resource := getResource(obj)
if resource == nil {
return result, errors.New("value is not a Resource")
}
objMap, err := toMap(obj)
if err != nil {
return result, err
}
schema := schemas.Schema(resource.Type)
for k, v := range objMap {
_, ok := schema.CheckField(k)
if !ok {
continue
}
result[k] = v
}
return result, nil
}