1
0
mirror of https://github.com/rancher/norman.git synced 2025-09-03 00:06:24 +00:00

Refactor types

This commit is contained in:
Darren Shepherd
2017-11-29 14:27:02 -07:00
parent ee148b4d18
commit 15e105a0ab
15 changed files with 89 additions and 43 deletions

View File

@@ -12,8 +12,8 @@ var (
<!DOCTYPE html>
<!-- If you are reading this, there is a good chance you would prefer sending an
"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" />
<script src="https://releases.rancher.com/api-ui/1.1.1/ui.min.js"></script>
<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.2/ui.min.js"></script>
<script>
var user = "admin";
var curlUser='${CATTLE_ACCESS_KEY}:${CATTLE_SECRET_KEY}';

View File

@@ -10,6 +10,7 @@ import (
"github.com/rancher/norman/parse"
"github.com/rancher/norman/parse/builder"
"github.com/rancher/norman/types"
"github.com/rancher/norman/types/definition"
"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 {
schema := context.Schemas.Schema(context.Version, fmt.Sprint(input["type"]))
schema := context.Schemas.Schema(context.Version, definition.GetFullType(input))
if schema == nil {
return nil
}

View File

@@ -8,6 +8,7 @@ import (
"github.com/rancher/norman/api"
"github.com/rancher/norman/store/crd"
"github.com/rancher/norman/types"
"github.com/rancher/norman/types/factory"
"k8s.io/client-go/tools/clientcmd"
)
@@ -29,7 +30,7 @@ var (
Path: "/example/v1",
}
Schemas = types.NewSchemas()
Schemas = factory.Schemas(&version)
)
func main() {

View File

@@ -63,7 +63,7 @@ type {{.schema.CodeName}}Interface interface {
Get(name string, opts metav1.GetOptions) (*{{.prefix}}{{.schema.CodeName}}, error)
Update(*{{.prefix}}{{.schema.CodeName}}) (*{{.prefix}}{{.schema.CodeName}}, 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)
DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error
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)
}
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)
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) {

View File

@@ -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
@@ -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) {
if strSliceValue, ok := value.([]string); ok {
// Form data will be []string
result := []interface{}{}
var result []interface{}
for _, value := range strSliceValue {
result = append(result, value)
}

View File

@@ -6,7 +6,7 @@ import (
"github.com/rancher/norman/types"
"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"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"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) {
_, 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)
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)
p.toInternal(schema.Mapper, data)
name, _ := mapper.GetValueN(data, "metadata", "name").(string)
name, _ := values.GetValueN(data, "metadata", "name").(string)
if name == "" {
generated, _ := mapper.GetValueN(data, "metadata", "generateName").(string)
generated, _ := values.GetValueN(data, "metadata", "generateName").(string)
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,
})
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{}) {
@@ -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) {
existing, err := p.ByID(apiContext, schema, id)
resourceVersion, existing, err := p.byID(apiContext, schema, id)
if err != nil {
return data, nil
}
@@ -174,13 +180,16 @@ func (p *Store) Update(apiContext *types.APIContext, schema *types.Schema, data
p.toInternal(schema.Mapper, existing)
namespace, id := splitID(id)
values.PutValue(existing, resourceVersion, "metadata", "resourceVersion")
req := p.common(namespace, p.k8sClient.Put()).
Body(&unstructured.Unstructured{
Object: existing,
}).
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 {
@@ -196,15 +205,16 @@ func (p *Store) Delete(apiContext *types.APIContext, schema *types.Schema, id st
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{}
err := req.Do().Into(result)
if err != nil {
return nil, err
return "", nil, err
}
version := result.GetResourceVersion()
p.fromInternal(schema, result.Object)
return result.Object, nil
return version, result.Object, nil
}
func splitID(id string) (string, string) {

View File

@@ -1,6 +1,10 @@
package definition
import "strings"
import (
"strings"
"github.com/rancher/norman/types/convert"
)
func IsMapType(fieldType string) bool {
return strings.HasPrefix(fieldType, "map[") && strings.HasSuffix(fieldType, "]")
@@ -26,3 +30,12 @@ func SubType(fieldType string) string {
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"])
}

View File

@@ -8,11 +8,15 @@ import (
func Schemas(version *types.APIVersion) *types.Schemas {
s := types.NewSchemas()
s.DefaultMappers = []types.Mapper{
mapper.NewObject(),
s.DefaultMappers = func() []types.Mapper {
return []types.Mapper{
mapper.NewObject(),
}
}
s.DefaultPostMappers = []types.Mapper{
&mapper.RenameReference{},
s.DefaultPostMappers = func() []types.Mapper {
return []types.Mapper{
&mapper.RenameReference{},
}
}
s.AddMapperForType(version, v1.ObjectMeta{}, mapper.NewMetadataMapper())
return s

View File

@@ -1,13 +1,16 @@
package mapper
import "github.com/rancher/norman/types"
import (
"github.com/rancher/norman/types"
"github.com/rancher/norman/types/values"
)
type LabelField struct {
Field string
}
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 {
data[e.Field] = v
}
@@ -16,7 +19,7 @@ func (e LabelField) FromInternal(data map[string]interface{}) {
func (e LabelField) ToInternal(data map[string]interface{}) {
v, ok := data[e.Field]
if ok {
PutValue(data, v, "labels", "io.cattle.field."+e.Field)
values.PutValue(data, v, "labels", "io.cattle.field."+e.Field)
}
}

View File

@@ -8,6 +8,7 @@ import (
"github.com/rancher/norman/types"
"github.com/rancher/norman/types/convert"
"github.com/rancher/norman/types/definition"
"github.com/rancher/norman/types/values"
)
type Move struct {
@@ -17,14 +18,14 @@ type Move struct {
}
func (m Move) FromInternal(data map[string]interface{}) {
if v, ok := RemoveValue(data, strings.Split(m.From, "/")...); ok {
PutValue(data, v, strings.Split(m.To, "/")...)
if v, ok := values.RemoveValue(data, strings.Split(m.From, "/")...); ok {
values.PutValue(data, v, strings.Split(m.To, "/")...)
}
}
func (m Move) ToInternal(data map[string]interface{}) {
if v, ok := RemoveValue(data, strings.Split(m.To, "/")...); ok {
PutValue(data, v, strings.Split(m.From, "/")...)
if v, ok := values.RemoveValue(data, strings.Split(m.To, "/")...); ok {
values.PutValue(data, v, strings.Split(m.From, "/")...)
}
}

View File

@@ -1,6 +1,8 @@
package mapper
import "github.com/rancher/norman/types"
import (
"github.com/rancher/norman/types"
)
type Object struct {
types.Mappers
@@ -12,8 +14,8 @@ func NewObject(mappers ...types.Mapper) Object {
&Embed{Field: "metadata"},
&Embed{Field: "spec", Optional: true},
&ReadOnly{Field: "status", Optional: true},
&Drop{"kind"},
&Drop{"apiVersion"},
Drop{"kind"},
Drop{"apiVersion"},
&Scope{
IfNot: types.NamespaceScope,
Mappers: []types.Mapper{

View File

@@ -6,6 +6,7 @@ import (
"strings"
"github.com/rancher/norman/types"
"github.com/rancher/norman/types/values"
)
type SetValue struct {
@@ -15,24 +16,24 @@ type SetValue struct {
}
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 {
return
}
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{}) {
v, ok := GetValue(data, strings.Split(s.To, "/")...)
v, ok := values.GetValue(data, strings.Split(s.To, "/")...)
if !ok {
return
}
if v == s.Value {
PutValue(data, s.IfEq, strings.Split(s.From, "/")...)
values.PutValue(data, s.IfEq, strings.Split(s.From, "/")...)
}
}

View File

@@ -142,10 +142,14 @@ func (s *Schemas) importType(version *APIVersion, t reflect.Type, overrides ...r
}
mappers := s.mapper(&schema.Version, schema.ID)
if schema.CanList() {
mappers = append(s.DefaultMappers, mappers...)
if s.DefaultMappers != nil {
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 {
copy, err := s.newSchemaFromType(version, t, typeName)

View File

@@ -15,12 +15,14 @@ type SchemaCollection struct {
type SchemaInitFunc func(*Schemas) *Schemas
type MappersFactory func() []Mapper
type Schemas struct {
schemasByPath map[string]map[string]*Schema
schemasBySubContext map[string]*Schema
mappers map[string]map[string][]Mapper
DefaultMappers []Mapper
DefaultPostMappers []Mapper
DefaultMappers MappersFactory
DefaultPostMappers MappersFactory
versions []APIVersion
schemas []*Schema
errors []error

View File

@@ -1,4 +1,4 @@
package mapper
package values
func RemoveValue(data map[string]interface{}, keys ...string) (interface{}, bool) {
for i, key := range keys {