mirror of
https://github.com/rancher/norman.git
synced 2025-09-03 08:14:40 +00:00
Refactor types
This commit is contained in:
@@ -12,8 +12,8 @@ var (
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<!-- If you are reading this, there is a good chance you would prefer sending an
|
<!-- If you are reading this, there is a good chance you would prefer sending an
|
||||||
"Accept: application/json" header and receiving actual JSON responses. -->
|
"Accept: application/json" header and receiving actual JSON responses. -->
|
||||||
<link rel="stylesheet" type="text/css" href="https://releases.rancher.com/api-ui/1.1.1/ui.min.css" />
|
<link rel="stylesheet" type="text/css" href="https://releases.rancher.com/api-ui/1.1.2/ui.min.css" />
|
||||||
<script src="https://releases.rancher.com/api-ui/1.1.1/ui.min.js"></script>
|
<script src="https://releases.rancher.com/api-ui/1.1.2/ui.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
var user = "admin";
|
var user = "admin";
|
||||||
var curlUser='${CATTLE_ACCESS_KEY}:${CATTLE_SECRET_KEY}';
|
var curlUser='${CATTLE_ACCESS_KEY}:${CATTLE_SECRET_KEY}';
|
||||||
|
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/rancher/norman/parse"
|
"github.com/rancher/norman/parse"
|
||||||
"github.com/rancher/norman/parse/builder"
|
"github.com/rancher/norman/parse/builder"
|
||||||
"github.com/rancher/norman/types"
|
"github.com/rancher/norman/types"
|
||||||
|
"github.com/rancher/norman/types/definition"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -90,7 +91,7 @@ func toString(val interface{}) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (j *JSONResponseWriter) convert(b *builder.Builder, context *types.APIContext, input map[string]interface{}) *types.RawResource {
|
func (j *JSONResponseWriter) convert(b *builder.Builder, context *types.APIContext, input map[string]interface{}) *types.RawResource {
|
||||||
schema := context.Schemas.Schema(context.Version, fmt.Sprint(input["type"]))
|
schema := context.Schemas.Schema(context.Version, definition.GetFullType(input))
|
||||||
if schema == nil {
|
if schema == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/rancher/norman/api"
|
"github.com/rancher/norman/api"
|
||||||
"github.com/rancher/norman/store/crd"
|
"github.com/rancher/norman/store/crd"
|
||||||
"github.com/rancher/norman/types"
|
"github.com/rancher/norman/types"
|
||||||
|
"github.com/rancher/norman/types/factory"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ var (
|
|||||||
Path: "/example/v1",
|
Path: "/example/v1",
|
||||||
}
|
}
|
||||||
|
|
||||||
Schemas = types.NewSchemas()
|
Schemas = factory.Schemas(&version)
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -63,7 +63,7 @@ type {{.schema.CodeName}}Interface interface {
|
|||||||
Get(name string, opts metav1.GetOptions) (*{{.prefix}}{{.schema.CodeName}}, error)
|
Get(name string, opts metav1.GetOptions) (*{{.prefix}}{{.schema.CodeName}}, error)
|
||||||
Update(*{{.prefix}}{{.schema.CodeName}}) (*{{.prefix}}{{.schema.CodeName}}, error)
|
Update(*{{.prefix}}{{.schema.CodeName}}) (*{{.prefix}}{{.schema.CodeName}}, error)
|
||||||
Delete(name string, options *metav1.DeleteOptions) error
|
Delete(name string, options *metav1.DeleteOptions) error
|
||||||
List(opts metav1.ListOptions) (*{{.prefix}}{{.schema.CodeName}}List, error)
|
List(opts metav1.ListOptions) (*{{.schema.CodeName}}List, error)
|
||||||
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||||
DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error
|
DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error
|
||||||
Controller() {{.schema.CodeName}}Controller
|
Controller() {{.schema.CodeName}}Controller
|
||||||
@@ -181,9 +181,9 @@ func (s *{{.schema.ID}}Client) Delete(name string, options *metav1.DeleteOptions
|
|||||||
return s.objectClient.Delete(name, options)
|
return s.objectClient.Delete(name, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *{{.schema.ID}}Client) List(opts metav1.ListOptions) (*{{.prefix}}{{.schema.CodeName}}List, error) {
|
func (s *{{.schema.ID}}Client) List(opts metav1.ListOptions) (*{{.schema.CodeName}}List, error) {
|
||||||
obj, err := s.objectClient.List(opts)
|
obj, err := s.objectClient.List(opts)
|
||||||
return obj.(*{{.prefix}}{{.schema.CodeName}}List), err
|
return obj.(*{{.schema.CodeName}}List), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *{{.schema.ID}}Client) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
func (s *{{.schema.ID}}Client) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||||
|
@@ -113,6 +113,10 @@ func (b *Builder) checkDefaultAndRequired(schema *types.Schema, input map[string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if op == List && fieldMatchesOp(field, List) && definition.IsReferenceType(field.Type) && !hasKey {
|
||||||
|
result[fieldName] = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -264,7 +268,7 @@ func (b *Builder) convertReferenceType(fieldType string, value interface{}) (str
|
|||||||
func (b *Builder) convertArray(fieldType string, value interface{}, op Operation) ([]interface{}, error) {
|
func (b *Builder) convertArray(fieldType string, value interface{}, op Operation) ([]interface{}, error) {
|
||||||
if strSliceValue, ok := value.([]string); ok {
|
if strSliceValue, ok := value.([]string); ok {
|
||||||
// Form data will be []string
|
// Form data will be []string
|
||||||
result := []interface{}{}
|
var result []interface{}
|
||||||
for _, value := range strSliceValue {
|
for _, value := range strSliceValue {
|
||||||
result = append(result, value)
|
result = append(result, value)
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/rancher/norman/types"
|
"github.com/rancher/norman/types"
|
||||||
"github.com/rancher/norman/types/convert"
|
"github.com/rancher/norman/types/convert"
|
||||||
"github.com/rancher/norman/types/mapper"
|
"github.com/rancher/norman/types/values"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@@ -41,6 +41,11 @@ func NewProxyStore(k8sClient rest.Interface,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Store) ByID(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) {
|
func (p *Store) ByID(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) {
|
||||||
|
_, result, err := p.byID(apiContext, schema, id)
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Store) byID(apiContext *types.APIContext, schema *types.Schema, id string) (string, map[string]interface{}, error) {
|
||||||
namespace, id := splitID(id)
|
namespace, id := splitID(id)
|
||||||
|
|
||||||
req := p.common(namespace, p.k8sClient.Get()).
|
req := p.common(namespace, p.k8sClient.Get()).
|
||||||
@@ -132,11 +137,11 @@ func (p *Store) Create(apiContext *types.APIContext, schema *types.Schema, data
|
|||||||
namespace, _ := data["namespaceId"].(string)
|
namespace, _ := data["namespaceId"].(string)
|
||||||
p.toInternal(schema.Mapper, data)
|
p.toInternal(schema.Mapper, data)
|
||||||
|
|
||||||
name, _ := mapper.GetValueN(data, "metadata", "name").(string)
|
name, _ := values.GetValueN(data, "metadata", "name").(string)
|
||||||
if name == "" {
|
if name == "" {
|
||||||
generated, _ := mapper.GetValueN(data, "metadata", "generateName").(string)
|
generated, _ := values.GetValueN(data, "metadata", "generateName").(string)
|
||||||
if generated == "" {
|
if generated == "" {
|
||||||
mapper.PutValue(data, strings.ToLower(schema.ID+"-"), "metadata", "generateName")
|
values.PutValue(data, strings.ToLower(schema.ID+"-"), "metadata", "generateName")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +150,8 @@ func (p *Store) Create(apiContext *types.APIContext, schema *types.Schema, data
|
|||||||
Object: data,
|
Object: data,
|
||||||
})
|
})
|
||||||
|
|
||||||
return p.singleResult(schema, req)
|
_, result, err := p.singleResult(schema, req)
|
||||||
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Store) toInternal(mapper types.Mapper, data map[string]interface{}) {
|
func (p *Store) toInternal(mapper types.Mapper, data map[string]interface{}) {
|
||||||
@@ -162,7 +168,7 @@ func (p *Store) toInternal(mapper types.Mapper, data map[string]interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Store) Update(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}, id string) (map[string]interface{}, error) {
|
func (p *Store) Update(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}, id string) (map[string]interface{}, error) {
|
||||||
existing, err := p.ByID(apiContext, schema, id)
|
resourceVersion, existing, err := p.byID(apiContext, schema, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
@@ -174,13 +180,16 @@ func (p *Store) Update(apiContext *types.APIContext, schema *types.Schema, data
|
|||||||
p.toInternal(schema.Mapper, existing)
|
p.toInternal(schema.Mapper, existing)
|
||||||
namespace, id := splitID(id)
|
namespace, id := splitID(id)
|
||||||
|
|
||||||
|
values.PutValue(existing, resourceVersion, "metadata", "resourceVersion")
|
||||||
|
|
||||||
req := p.common(namespace, p.k8sClient.Put()).
|
req := p.common(namespace, p.k8sClient.Put()).
|
||||||
Body(&unstructured.Unstructured{
|
Body(&unstructured.Unstructured{
|
||||||
Object: existing,
|
Object: existing,
|
||||||
}).
|
}).
|
||||||
Name(id)
|
Name(id)
|
||||||
|
|
||||||
return p.singleResult(schema, req)
|
_, result, err := p.singleResult(schema, req)
|
||||||
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Store) Delete(apiContext *types.APIContext, schema *types.Schema, id string) error {
|
func (p *Store) Delete(apiContext *types.APIContext, schema *types.Schema, id string) error {
|
||||||
@@ -196,15 +205,16 @@ func (p *Store) Delete(apiContext *types.APIContext, schema *types.Schema, id st
|
|||||||
return req.Do().Error()
|
return req.Do().Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Store) singleResult(schema *types.Schema, req *rest.Request) (map[string]interface{}, error) {
|
func (p *Store) singleResult(schema *types.Schema, req *rest.Request) (string, map[string]interface{}, error) {
|
||||||
result := &unstructured.Unstructured{}
|
result := &unstructured.Unstructured{}
|
||||||
err := req.Do().Into(result)
|
err := req.Do().Into(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version := result.GetResourceVersion()
|
||||||
p.fromInternal(schema, result.Object)
|
p.fromInternal(schema, result.Object)
|
||||||
return result.Object, nil
|
return version, result.Object, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func splitID(id string) (string, string) {
|
func splitID(id string) (string, string) {
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
package definition
|
package definition
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/rancher/norman/types/convert"
|
||||||
|
)
|
||||||
|
|
||||||
func IsMapType(fieldType string) bool {
|
func IsMapType(fieldType string) bool {
|
||||||
return strings.HasPrefix(fieldType, "map[") && strings.HasSuffix(fieldType, "]")
|
return strings.HasPrefix(fieldType, "map[") && strings.HasSuffix(fieldType, "]")
|
||||||
@@ -26,3 +30,12 @@ func SubType(fieldType string) string {
|
|||||||
|
|
||||||
return fieldType[i+1 : len(fieldType)-1]
|
return fieldType[i+1 : len(fieldType)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetType(data map[string]interface{}) string {
|
||||||
|
parts := strings.Split(GetFullType(data), "/")
|
||||||
|
return parts[len(parts)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFullType(data map[string]interface{}) string {
|
||||||
|
return convert.ToString(data["type"])
|
||||||
|
}
|
||||||
|
@@ -8,11 +8,15 @@ import (
|
|||||||
|
|
||||||
func Schemas(version *types.APIVersion) *types.Schemas {
|
func Schemas(version *types.APIVersion) *types.Schemas {
|
||||||
s := types.NewSchemas()
|
s := types.NewSchemas()
|
||||||
s.DefaultMappers = []types.Mapper{
|
s.DefaultMappers = func() []types.Mapper {
|
||||||
mapper.NewObject(),
|
return []types.Mapper{
|
||||||
|
mapper.NewObject(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
s.DefaultPostMappers = []types.Mapper{
|
s.DefaultPostMappers = func() []types.Mapper {
|
||||||
&mapper.RenameReference{},
|
return []types.Mapper{
|
||||||
|
&mapper.RenameReference{},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
s.AddMapperForType(version, v1.ObjectMeta{}, mapper.NewMetadataMapper())
|
s.AddMapperForType(version, v1.ObjectMeta{}, mapper.NewMetadataMapper())
|
||||||
return s
|
return s
|
||||||
|
@@ -1,13 +1,16 @@
|
|||||||
package mapper
|
package mapper
|
||||||
|
|
||||||
import "github.com/rancher/norman/types"
|
import (
|
||||||
|
"github.com/rancher/norman/types"
|
||||||
|
"github.com/rancher/norman/types/values"
|
||||||
|
)
|
||||||
|
|
||||||
type LabelField struct {
|
type LabelField struct {
|
||||||
Field string
|
Field string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e LabelField) FromInternal(data map[string]interface{}) {
|
func (e LabelField) FromInternal(data map[string]interface{}) {
|
||||||
v, ok := RemoveValue(data, "labels", "io.cattle.field."+e.Field)
|
v, ok := values.RemoveValue(data, "labels", "io.cattle.field."+e.Field)
|
||||||
if ok {
|
if ok {
|
||||||
data[e.Field] = v
|
data[e.Field] = v
|
||||||
}
|
}
|
||||||
@@ -16,7 +19,7 @@ func (e LabelField) FromInternal(data map[string]interface{}) {
|
|||||||
func (e LabelField) ToInternal(data map[string]interface{}) {
|
func (e LabelField) ToInternal(data map[string]interface{}) {
|
||||||
v, ok := data[e.Field]
|
v, ok := data[e.Field]
|
||||||
if ok {
|
if ok {
|
||||||
PutValue(data, v, "labels", "io.cattle.field."+e.Field)
|
values.PutValue(data, v, "labels", "io.cattle.field."+e.Field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/rancher/norman/types"
|
"github.com/rancher/norman/types"
|
||||||
"github.com/rancher/norman/types/convert"
|
"github.com/rancher/norman/types/convert"
|
||||||
"github.com/rancher/norman/types/definition"
|
"github.com/rancher/norman/types/definition"
|
||||||
|
"github.com/rancher/norman/types/values"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Move struct {
|
type Move struct {
|
||||||
@@ -17,14 +18,14 @@ type Move struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m Move) FromInternal(data map[string]interface{}) {
|
func (m Move) FromInternal(data map[string]interface{}) {
|
||||||
if v, ok := RemoveValue(data, strings.Split(m.From, "/")...); ok {
|
if v, ok := values.RemoveValue(data, strings.Split(m.From, "/")...); ok {
|
||||||
PutValue(data, v, strings.Split(m.To, "/")...)
|
values.PutValue(data, v, strings.Split(m.To, "/")...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Move) ToInternal(data map[string]interface{}) {
|
func (m Move) ToInternal(data map[string]interface{}) {
|
||||||
if v, ok := RemoveValue(data, strings.Split(m.To, "/")...); ok {
|
if v, ok := values.RemoveValue(data, strings.Split(m.To, "/")...); ok {
|
||||||
PutValue(data, v, strings.Split(m.From, "/")...)
|
values.PutValue(data, v, strings.Split(m.From, "/")...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
package mapper
|
package mapper
|
||||||
|
|
||||||
import "github.com/rancher/norman/types"
|
import (
|
||||||
|
"github.com/rancher/norman/types"
|
||||||
|
)
|
||||||
|
|
||||||
type Object struct {
|
type Object struct {
|
||||||
types.Mappers
|
types.Mappers
|
||||||
@@ -12,8 +14,8 @@ func NewObject(mappers ...types.Mapper) Object {
|
|||||||
&Embed{Field: "metadata"},
|
&Embed{Field: "metadata"},
|
||||||
&Embed{Field: "spec", Optional: true},
|
&Embed{Field: "spec", Optional: true},
|
||||||
&ReadOnly{Field: "status", Optional: true},
|
&ReadOnly{Field: "status", Optional: true},
|
||||||
&Drop{"kind"},
|
Drop{"kind"},
|
||||||
&Drop{"apiVersion"},
|
Drop{"apiVersion"},
|
||||||
&Scope{
|
&Scope{
|
||||||
IfNot: types.NamespaceScope,
|
IfNot: types.NamespaceScope,
|
||||||
Mappers: []types.Mapper{
|
Mappers: []types.Mapper{
|
||||||
|
@@ -6,6 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/rancher/norman/types"
|
"github.com/rancher/norman/types"
|
||||||
|
"github.com/rancher/norman/types/values"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SetValue struct {
|
type SetValue struct {
|
||||||
@@ -15,24 +16,24 @@ type SetValue struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s SetValue) FromInternal(data map[string]interface{}) {
|
func (s SetValue) FromInternal(data map[string]interface{}) {
|
||||||
v, ok := GetValue(data, strings.Split(s.From, "/")...)
|
v, ok := values.GetValue(data, strings.Split(s.From, "/")...)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if v == s.IfEq {
|
if v == s.IfEq {
|
||||||
PutValue(data, s.Value, strings.Split(s.To, "/")...)
|
values.PutValue(data, s.Value, strings.Split(s.To, "/")...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s SetValue) ToInternal(data map[string]interface{}) {
|
func (s SetValue) ToInternal(data map[string]interface{}) {
|
||||||
v, ok := GetValue(data, strings.Split(s.To, "/")...)
|
v, ok := values.GetValue(data, strings.Split(s.To, "/")...)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if v == s.Value {
|
if v == s.Value {
|
||||||
PutValue(data, s.IfEq, strings.Split(s.From, "/")...)
|
values.PutValue(data, s.IfEq, strings.Split(s.From, "/")...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -142,10 +142,14 @@ func (s *Schemas) importType(version *APIVersion, t reflect.Type, overrides ...r
|
|||||||
}
|
}
|
||||||
|
|
||||||
mappers := s.mapper(&schema.Version, schema.ID)
|
mappers := s.mapper(&schema.Version, schema.ID)
|
||||||
if schema.CanList() {
|
if s.DefaultMappers != nil {
|
||||||
mappers = append(s.DefaultMappers, mappers...)
|
if schema.CanList() {
|
||||||
|
mappers = append(s.DefaultMappers(), mappers...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if s.DefaultPostMappers != nil {
|
||||||
|
mappers = append(mappers, s.DefaultPostMappers()...)
|
||||||
}
|
}
|
||||||
mappers = append(mappers, s.DefaultPostMappers...)
|
|
||||||
|
|
||||||
if len(mappers) > 0 {
|
if len(mappers) > 0 {
|
||||||
copy, err := s.newSchemaFromType(version, t, typeName)
|
copy, err := s.newSchemaFromType(version, t, typeName)
|
||||||
|
@@ -15,12 +15,14 @@ type SchemaCollection struct {
|
|||||||
|
|
||||||
type SchemaInitFunc func(*Schemas) *Schemas
|
type SchemaInitFunc func(*Schemas) *Schemas
|
||||||
|
|
||||||
|
type MappersFactory func() []Mapper
|
||||||
|
|
||||||
type Schemas struct {
|
type Schemas struct {
|
||||||
schemasByPath map[string]map[string]*Schema
|
schemasByPath map[string]map[string]*Schema
|
||||||
schemasBySubContext map[string]*Schema
|
schemasBySubContext map[string]*Schema
|
||||||
mappers map[string]map[string][]Mapper
|
mappers map[string]map[string][]Mapper
|
||||||
DefaultMappers []Mapper
|
DefaultMappers MappersFactory
|
||||||
DefaultPostMappers []Mapper
|
DefaultPostMappers MappersFactory
|
||||||
versions []APIVersion
|
versions []APIVersion
|
||||||
schemas []*Schema
|
schemas []*Schema
|
||||||
errors []error
|
errors []error
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package mapper
|
package values
|
||||||
|
|
||||||
func RemoveValue(data map[string]interface{}, keys ...string) (interface{}, bool) {
|
func RemoveValue(data map[string]interface{}, keys ...string) (interface{}, bool) {
|
||||||
for i, key := range keys {
|
for i, key := range keys {
|
Reference in New Issue
Block a user