From c1906d594f3ae7bb7c1479b5dfbae281b7c8d9bd Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Tue, 21 Nov 2017 16:23:45 -0700 Subject: [PATCH] Update norman --- vendor.conf | 2 +- .../rancher/norman/clientbase/common.go | 14 +- .../rancher/norman/clientbase/ops.go | 46 +++--- .../norman/controller/generic_controller.go | 8 +- .../norman/generator/controller_template.go | 2 +- .../rancher/norman/generator/funcs.go | 9 +- .../rancher/norman/generator/generator.go | 20 ++- .../rancher/norman/generator/type_template.go | 4 +- .../rancher/norman/types/condition.go | 142 +++++++++--------- .../rancher/norman/types/convert/convert.go | 4 +- .../rancher/norman/types/convert/ref.go | 11 ++ .../norman/types/convert/value_set_string.go | 3 +- .../rancher/norman/types/factory/schemas.go | 19 +++ .../github.com/rancher/norman/types/mapper.go | 64 +++++--- .../rancher/norman/types/mapper/access.go | 33 ++++ .../rancher/norman/types/mapper/check.go | 15 ++ .../norman/types/mapper/display_name.go | 28 ++++ .../norman/types/{mapping => }/mapper/drop.go | 5 - .../types/{mapping => }/mapper/embed.go | 15 +- .../norman/types/{mapping => }/mapper/enum.go | 3 +- .../norman/types/mapper/label_field.go | 25 +++ .../rancher/norman/types/mapper/metadata.go | 30 ++++ .../norman/types/{mapping => }/mapper/move.go | 32 ++-- .../rancher/norman/types/mapper/object.go | 25 +++ .../rancher/norman/types/mapper/read_only.go | 41 +++++ .../norman/types/mapper/rename_reference.go | 53 +++++++ .../rancher/norman/types/mapper/scope.go | 37 +++++ .../rancher/norman/types/mapper/set_value.go | 49 ++++++ .../{mapping => }/mapper/slice_to_map.go | 8 +- .../types/{mapping => }/mapper/union_embed.go | 0 .../types/{mapping => }/mapper/values.go | 6 +- .../norman/types/mapping/mapper/check.go | 28 ---- .../norman/types/mapping/mapper/copy.go | 25 --- .../types/mapping/mapper/label_field.go | 25 --- .../norman/types/mapping/mapper/object.go | 19 --- .../norman/types/mapping/mapper/read_only.go | 30 ---- .../norman/types/mapping/mapper/swap.go | 20 --- .../norman/types/mapping/mapper/type.go | 1 - .../rancher/norman/types/reflection.go | 93 +++++++++++- .../rancher/norman/types/schema_funcs.go | 26 ++++ .../rancher/norman/types/schemas.go | 52 ++++--- .../rancher/norman/types/server_types.go | 82 +++++++--- .../rancher/norman/types/slice/contains.go | 10 ++ .../github.com/rancher/norman/types/types.go | 29 +++- 44 files changed, 814 insertions(+), 379 deletions(-) create mode 100644 vendor/github.com/rancher/norman/types/convert/ref.go create mode 100644 vendor/github.com/rancher/norman/types/factory/schemas.go create mode 100644 vendor/github.com/rancher/norman/types/mapper/access.go create mode 100644 vendor/github.com/rancher/norman/types/mapper/check.go create mode 100644 vendor/github.com/rancher/norman/types/mapper/display_name.go rename vendor/github.com/rancher/norman/types/{mapping => }/mapper/drop.go (88%) rename vendor/github.com/rancher/norman/types/{mapping => }/mapper/embed.go (85%) rename vendor/github.com/rancher/norman/types/{mapping => }/mapper/enum.go (92%) create mode 100644 vendor/github.com/rancher/norman/types/mapper/label_field.go create mode 100644 vendor/github.com/rancher/norman/types/mapper/metadata.go rename vendor/github.com/rancher/norman/types/{mapping => }/mapper/move.go (69%) create mode 100644 vendor/github.com/rancher/norman/types/mapper/object.go create mode 100644 vendor/github.com/rancher/norman/types/mapper/read_only.go create mode 100644 vendor/github.com/rancher/norman/types/mapper/rename_reference.go create mode 100644 vendor/github.com/rancher/norman/types/mapper/scope.go create mode 100644 vendor/github.com/rancher/norman/types/mapper/set_value.go rename vendor/github.com/rancher/norman/types/{mapping => }/mapper/slice_to_map.go (83%) rename vendor/github.com/rancher/norman/types/{mapping => }/mapper/union_embed.go (100%) rename vendor/github.com/rancher/norman/types/{mapping => }/mapper/values.go (92%) delete mode 100644 vendor/github.com/rancher/norman/types/mapping/mapper/check.go delete mode 100644 vendor/github.com/rancher/norman/types/mapping/mapper/copy.go delete mode 100644 vendor/github.com/rancher/norman/types/mapping/mapper/label_field.go delete mode 100644 vendor/github.com/rancher/norman/types/mapping/mapper/object.go delete mode 100644 vendor/github.com/rancher/norman/types/mapping/mapper/read_only.go delete mode 100644 vendor/github.com/rancher/norman/types/mapping/mapper/swap.go delete mode 100644 vendor/github.com/rancher/norman/types/mapping/mapper/type.go create mode 100644 vendor/github.com/rancher/norman/types/schema_funcs.go create mode 100644 vendor/github.com/rancher/norman/types/slice/contains.go diff --git a/vendor.conf b/vendor.conf index 15ea699f..e59a4b2e 100644 --- a/vendor.conf +++ b/vendor.conf @@ -3,4 +3,4 @@ github.com/rancher/types k8s.io/kubernetes v1.8.3 transitive=true,staging=true bitbucket.org/ww/goautoneg a547fc61f48d567d5b4ec6f8aee5573d8efce11d https://github.com/rancher/goautoneg.git -github.com/rancher/norman 80024df69414f7cce0847ea72b0557f14edbc852 +github.com/rancher/norman faa1fb2148211044253fc2f6403008958c72b1f0 diff --git a/vendor/github.com/rancher/norman/clientbase/common.go b/vendor/github.com/rancher/norman/clientbase/common.go index 16fa88d3..11cd3de9 100644 --- a/vendor/github.com/rancher/norman/clientbase/common.go +++ b/vendor/github.com/rancher/norman/clientbase/common.go @@ -55,7 +55,7 @@ func IsNotFound(err error) bool { return apiError.StatusCode == http.StatusNotFound } -func newApiError(resp *http.Response, url string) *APIError { +func newAPIError(resp *http.Response, url string) *APIError { contents, err := ioutil.ReadAll(resp.Body) var body string if err != nil { @@ -161,7 +161,7 @@ func NewAPIClient(opts *ClientOpts) (APIBaseClient, error) { defer resp.Body.Close() if resp.StatusCode != 200 { - return result, newApiError(resp, opts.URL) + return result, newAPIError(resp, opts.URL) } schemasURLs := resp.Header.Get("X-API-Schemas") @@ -184,7 +184,7 @@ func NewAPIClient(opts *ClientOpts) (APIBaseClient, error) { defer resp.Body.Close() if resp.StatusCode != 200 { - return result, newApiError(resp, opts.URL) + return result, newAPIError(resp, opts.URL) } } @@ -244,7 +244,7 @@ func (a *APIBaseClient) Post(url string, createObj interface{}, respObject inter func (a *APIBaseClient) GetLink(resource types.Resource, link string, respObject interface{}) error { url := resource.Links[link] if url == "" { - return fmt.Errorf("Failed to find link: %s", link) + return fmt.Errorf("failed to find link: %s", link) } return a.Ops.DoGet(url, &types.ListOpts{}, respObject) @@ -270,12 +270,12 @@ func (a *APIBaseClient) Delete(existing *types.Resource) error { } func (a *APIBaseClient) Reload(existing *types.Resource, output interface{}) error { - selfUrl, ok := existing.Links[SELF] + selfURL, ok := existing.Links[SELF] if !ok { - return errors.New(fmt.Sprintf("Failed to find self URL of [%v]", existing)) + return fmt.Errorf("failed to find self URL of [%v]", existing) } - return a.Ops.DoGet(selfUrl, NewListOpts(), output) + return a.Ops.DoGet(selfURL, NewListOpts(), output) } func (a *APIBaseClient) Action(schemaType string, action string, diff --git a/vendor/github.com/rancher/norman/clientbase/ops.go b/vendor/github.com/rancher/norman/clientbase/ops.go index 0a9fd93e..d60e6c15 100644 --- a/vendor/github.com/rancher/norman/clientbase/ops.go +++ b/vendor/github.com/rancher/norman/clientbase/ops.go @@ -34,7 +34,7 @@ func (a *APIOperations) DoDelete(url string) error { io.Copy(ioutil.Discard, resp.Body) if resp.StatusCode >= 300 { - return newApiError(resp, url) + return newAPIError(resp, url) } return nil @@ -68,7 +68,7 @@ func (a *APIOperations) DoGet(url string, opts *types.ListOpts, respObject inter defer resp.Body.Close() if resp.StatusCode != 200 { - return newApiError(resp, url) + return newAPIError(resp, url) } byteContent, err := ioutil.ReadAll(resp.Body) @@ -97,16 +97,16 @@ func (a *APIOperations) DoList(schemaType string, opts *types.ListOpts, respObje return errors.New("Resource type [" + schemaType + "] is not listable") } - collectionUrl, ok := schema.Links[COLLECTION] + collectionURL, ok := schema.Links[COLLECTION] if !ok { return errors.New("Failed to find collection URL for [" + schemaType + "]") } - return a.DoGet(collectionUrl, opts, respObject) + return a.DoGet(collectionURL, opts, respObject) } -func (a *APIOperations) DoNext(nextUrl string, respObject interface{}) error { - return a.DoGet(nextUrl, nil, respObject) +func (a *APIOperations) DoNext(nextURL string, respObject interface{}) error { + return a.DoGet(nextURL, nil, respObject) } func (a *APIOperations) DoModify(method string, url string, createObj interface{}, respObject interface{}) error { @@ -136,7 +136,7 @@ func (a *APIOperations) DoModify(method string, url string, createObj interface{ defer resp.Body.Close() if resp.StatusCode >= 300 { - return newApiError(resp, url) + return newAPIError(resp, url) } byteContent, err := ioutil.ReadAll(resp.Body) @@ -170,16 +170,16 @@ func (a *APIOperations) DoCreate(schemaType string, createObj interface{}, respO return errors.New("Resource type [" + schemaType + "] is not creatable") } - var collectionUrl string - collectionUrl, ok = schema.Links[COLLECTION] + var collectionURL string + collectionURL, ok = schema.Links[COLLECTION] if !ok { // return errors.New("Failed to find collection URL for [" + schemaType + "]") // This is a hack to address https://github.com/rancher/cattle/issues/254 re := regexp.MustCompile("schemas.*") - collectionUrl = re.ReplaceAllString(schema.Links[SELF], schema.PluralName) + collectionURL = re.ReplaceAllString(schema.Links[SELF], schema.PluralName) } - return a.DoModify("POST", collectionUrl, createObj, respObject) + return a.DoModify("POST", collectionURL, createObj, respObject) } func (a *APIOperations) DoUpdate(schemaType string, existing *types.Resource, updates interface{}, respObject interface{}) error { @@ -187,9 +187,9 @@ func (a *APIOperations) DoUpdate(schemaType string, existing *types.Resource, up return errors.New("Existing object is nil") } - selfUrl, ok := existing.Links[SELF] + selfURL, ok := existing.Links[SELF] if !ok { - return errors.New(fmt.Sprintf("Failed to find self URL of [%v]", existing)) + return fmt.Errorf("failed to find self URL of [%v]", existing) } if updates == nil { @@ -209,7 +209,7 @@ func (a *APIOperations) DoUpdate(schemaType string, existing *types.Resource, up return errors.New("Resource type [" + schemaType + "] is not updatable") } - return a.DoModify("PUT", selfUrl, updates, respObject) + return a.DoModify("PUT", selfURL, updates, respObject) } func (a *APIOperations) DoByID(schemaType string, id string, respObject interface{}) error { @@ -222,12 +222,12 @@ func (a *APIOperations) DoByID(schemaType string, id string, respObject interfac return errors.New("Resource type [" + schemaType + "] can not be looked up by ID") } - collectionUrl, ok := schema.Links[COLLECTION] + collectionURL, ok := schema.Links[COLLECTION] if !ok { return errors.New("Failed to find collection URL for [" + schemaType + "]") } - return a.DoGet(collectionUrl+"/"+id, nil, respObject) + return a.DoGet(collectionURL+"/"+id, nil, respObject) } func (a *APIOperations) DoResourceDelete(schemaType string, existing *types.Resource) error { @@ -240,12 +240,12 @@ func (a *APIOperations) DoResourceDelete(schemaType string, existing *types.Reso return errors.New("Resource type [" + schemaType + "] can not be deleted") } - selfUrl, ok := existing.Links[SELF] + selfURL, ok := existing.Links[SELF] if !ok { - return errors.New(fmt.Sprintf("Failed to find self URL of [%v]", existing)) + return fmt.Errorf("failed to find self URL of [%v]", existing) } - return a.DoDelete(selfUrl) + return a.DoDelete(selfURL) } func (a *APIOperations) DoAction(schemaType string, action string, @@ -255,9 +255,9 @@ func (a *APIOperations) DoAction(schemaType string, action string, return errors.New("Existing object is nil") } - actionUrl, ok := existing.Actions[action] + actionURL, ok := existing.Actions[action] if !ok { - return errors.New(fmt.Sprintf("Action [%v] not available on [%v]", action, existing)) + return fmt.Errorf("action [%v] not available on [%v]", action, existing) } _, ok = a.Types[schemaType] @@ -278,7 +278,7 @@ func (a *APIOperations) DoAction(schemaType string, action string, input = bytes.NewBuffer(bodyContent) } - req, err := http.NewRequest("POST", actionUrl, input) + req, err := http.NewRequest("POST", actionURL, input) if err != nil { return err } @@ -295,7 +295,7 @@ func (a *APIOperations) DoAction(schemaType string, action string, defer resp.Body.Close() if resp.StatusCode >= 300 { - return newApiError(resp, actionUrl) + return newAPIError(resp, actionURL) } byteContent, err := ioutil.ReadAll(resp.Body) diff --git a/vendor/github.com/rancher/norman/controller/generic_controller.go b/vendor/github.com/rancher/norman/controller/generic_controller.go index 9d41235e..6129f445 100644 --- a/vendor/github.com/rancher/norman/controller/generic_controller.go +++ b/vendor/github.com/rancher/norman/controller/generic_controller.go @@ -25,7 +25,7 @@ type GenericController interface { Informer() cache.SharedIndexInformer AddHandler(handler HandlerFunc) Enqueue(namespace, name string) - Start(threadiness int, ctx context.Context) error + Start(ctx context.Context, threadiness int) error } type genericController struct { @@ -69,12 +69,12 @@ func (g *genericController) AddHandler(handler HandlerFunc) { g.handlers = append(g.handlers, handler) } -func (g *genericController) Start(threadiness int, ctx context.Context) error { +func (g *genericController) Start(ctx context.Context, threadiness int) error { g.Lock() defer g.Unlock() if !g.running { - go g.run(threadiness, ctx) + go g.run(ctx, threadiness) } g.running = true @@ -88,7 +88,7 @@ func (g *genericController) queueObject(obj interface{}) { } } -func (g *genericController) run(threadiness int, ctx context.Context) { +func (g *genericController) run(ctx context.Context, threadiness int) { defer utilruntime.HandleCrash() defer g.queue.ShutDown() diff --git a/vendor/github.com/rancher/norman/generator/controller_template.go b/vendor/github.com/rancher/norman/generator/controller_template.go index d61ecdb5..d370235f 100644 --- a/vendor/github.com/rancher/norman/generator/controller_template.go +++ b/vendor/github.com/rancher/norman/generator/controller_template.go @@ -43,7 +43,7 @@ type {{.schema.CodeName}}Controller interface { Informer() cache.SharedIndexInformer AddHandler(handler {{.schema.CodeName}}HandlerFunc) Enqueue(namespace, name string) - Start(threadiness int, ctx context.Context) error + Start(ctx context.Context, threadiness int) error } type {{.schema.CodeName}}Interface interface { diff --git a/vendor/github.com/rancher/norman/generator/funcs.go b/vendor/github.com/rancher/norman/generator/funcs.go index c744b373..6af1d3e7 100644 --- a/vendor/github.com/rancher/norman/generator/funcs.go +++ b/vendor/github.com/rancher/norman/generator/funcs.go @@ -11,11 +11,10 @@ import ( func funcs() template.FuncMap { return template.FuncMap{ - "toLowerCamelCase": convert.LowerTitle, - "capitalize": convert.Capitalize, - "upper": strings.ToUpper, - "toLower": strings.ToLower, - "hasGet": hasGet, + "capitalize": convert.Capitalize, + "upper": strings.ToUpper, + "toLower": strings.ToLower, + "hasGet": hasGet, } } diff --git a/vendor/github.com/rancher/norman/generator/generator.go b/vendor/github.com/rancher/norman/generator/generator.go index 0f599f7d..69675425 100644 --- a/vendor/github.com/rancher/norman/generator/generator.go +++ b/vendor/github.com/rancher/norman/generator/generator.go @@ -30,6 +30,11 @@ var ( underscoreRegexp = regexp.MustCompile(`([a-z])([A-Z])`) ) +type fieldInfo struct { + Name string + Type string +} + func getGoType(field types.Field, schema *types.Schema, schemas *types.Schemas) string { return getTypeString(field.Nullable, field.Type, schema, schemas) } @@ -87,10 +92,13 @@ func getTypeString(nullable bool, typeName string, schema *types.Schema, schemas return name } -func getTypeMap(schema *types.Schema, schemas *types.Schemas) map[string]string { - result := map[string]string{} - for _, field := range schema.ResourceFields { - result[field.CodeName] = getGoType(field, schema, schemas) +func getTypeMap(schema *types.Schema, schemas *types.Schemas) map[string]fieldInfo { + result := map[string]fieldInfo{} + for name, field := range schema.ResourceFields { + result[field.CodeName] = fieldInfo{ + Name: name, + Type: getGoType(field, schema, schemas), + } } return result } @@ -143,9 +151,7 @@ func generateController(outputDir string, schema *types.Schema, schemas *types.S } return typeTemplate.Execute(output, map[string]interface{}{ - "schema": schema, - "structFields": getTypeMap(schema, schemas), - "resourceActions": getResourceActions(schema, schemas), + "schema": schema, }) } diff --git a/vendor/github.com/rancher/norman/generator/type_template.go b/vendor/github.com/rancher/norman/generator/type_template.go index 7f05c567..e790936a 100644 --- a/vendor/github.com/rancher/norman/generator/type_template.go +++ b/vendor/github.com/rancher/norman/generator/type_template.go @@ -11,7 +11,7 @@ import ( const ( {{.schema.CodeName}}Type = "{{.schema.ID}}" {{- range $key, $value := .structFields}} - {{$.schema.CodeName}}Field{{$key}} = "{{$key | toLowerCamelCase }}" + {{$.schema.CodeName}}Field{{$key}} = "{{$value.Name}}" {{- end}} ) @@ -20,7 +20,7 @@ type {{.schema.CodeName}} struct { types.Resource {{- end}} {{- range $key, $value := .structFields}} - {{$key}} {{$value}} %BACK%json:"{{$key | toLowerCamelCase }},omitempty"%BACK% + {{$key}} {{$value.Type}} %BACK%json:"{{$value.Name}},omitempty"%BACK% {{- end}} } diff --git a/vendor/github.com/rancher/norman/types/condition.go b/vendor/github.com/rancher/norman/types/condition.go index 0d5bdd07..aebe36e4 100644 --- a/vendor/github.com/rancher/norman/types/condition.go +++ b/vendor/github.com/rancher/norman/types/condition.go @@ -1,108 +1,108 @@ package types -var ( - COND_EQ = QueryConditionType{"eq", 1} - COND_NE = QueryConditionType{"ne", 1} - COND_NULL = QueryConditionType{"null", 0} - COND_NOTNULL = QueryConditionType{"notnull", 0} - COND_IN = QueryConditionType{"in", -1} - COND_NOTIN = QueryConditionType{"notin", -1} - COND_OR = QueryConditionType{"or", 1} - COND_AND = QueryConditionType{"and", 1} +import ( + "github.com/rancher/norman/types/convert" +) - mods = map[string]QueryConditionType{ - COND_EQ.Name: COND_EQ, - COND_NE.Name: COND_NE, - COND_NULL.Name: COND_NULL, - COND_NOTNULL.Name: COND_NOTNULL, - COND_IN.Name: COND_IN, - COND_NOTIN.Name: COND_NOTIN, - COND_OR.Name: COND_OR, - COND_AND.Name: COND_AND, +var ( + CondEQ = QueryConditionType{ModifierEQ, 1} + CondNE = QueryConditionType{ModifierNE, 1} + CondNull = QueryConditionType{ModifierNull, 0} + CondNotNull = QueryConditionType{ModifierNotNull, 0} + CondIn = QueryConditionType{ModifierIn, -1} + CondNotIn = QueryConditionType{ModifierNotIn, -1} + CondOr = QueryConditionType{ModifierType("or"), 1} + CondAnd = QueryConditionType{ModifierType("and"), 1} + + mods = map[ModifierType]QueryConditionType{ + CondEQ.Name: CondEQ, + CondNE.Name: CondNE, + CondNull.Name: CondNull, + CondNotNull.Name: CondNotNull, + CondIn.Name: CondIn, + CondNotIn.Name: CondNotIn, + CondOr.Name: CondOr, + CondAnd.Name: CondAnd, } ) type QueryConditionType struct { - Name string + Name ModifierType Args int } type QueryCondition struct { Field string - Values []interface{} + Value string + Values map[string]bool conditionType QueryConditionType left, right *QueryCondition } +func (q *QueryCondition) Valid(data map[string]interface{}) bool { + switch q.conditionType { + case CondAnd: + if q.left == nil || q.right == nil { + return false + } + return q.left.Valid(data) && q.right.Valid(data) + case CondOr: + if q.left == nil || q.right == nil { + return false + } + return q.left.Valid(data) || q.right.Valid(data) + case CondEQ: + return q.Value == convert.ToString(data[q.Field]) + case CondNE: + return q.Value != convert.ToString(data[q.Field]) + case CondIn: + return q.Values[convert.ToString(data[q.Field])] + case CondNotIn: + return !q.Values[convert.ToString(data[q.Field])] + case CondNotNull: + return convert.ToString(data[q.Field]) != "" + case CondNull: + return convert.ToString(data[q.Field]) == "" + } + + return false +} + func (q *QueryCondition) ToCondition() Condition { cond := Condition{ Modifier: q.conditionType.Name, } - if q.conditionType.Args == 1 && len(q.Values) > 0 { - cond.Value = q.Values[0] + if q.conditionType.Args == 1 { + cond.Value = q.Value } else if q.conditionType.Args == -1 { - cond.Value = q.Values + stringValues := []string{} + for val := range q.Values { + stringValues = append(stringValues, val) + } + cond.Value = stringValues } return cond } -func ValidMod(mod string) bool { +func ValidMod(mod ModifierType) bool { _, ok := mods[mod] return ok } -func NewConditionFromString(field, mod string, values ...interface{}) *QueryCondition { - return &QueryCondition{ +func NewConditionFromString(field string, mod ModifierType, values ...string) *QueryCondition { + q := &QueryCondition{ Field: field, - Values: values, conditionType: mods[mod], + Values: map[string]bool{}, } -} -func NewCondition(mod QueryConditionType, values ...interface{}) *QueryCondition { - return &QueryCondition{ - Values: values, - conditionType: mod, + for i, value := range values { + if i == 0 { + q.Value = value + } + q.Values[value] = true } -} -func NE(value interface{}) *QueryCondition { - return NewCondition(COND_NE, value) -} - -func EQ(value interface{}) *QueryCondition { - return NewCondition(COND_EQ, value) -} - -func NULL(value interface{}) *QueryCondition { - return NewCondition(COND_NULL) -} - -func NOTNULL(value interface{}) *QueryCondition { - return NewCondition(COND_NOTNULL) -} - -func IN(values ...interface{}) *QueryCondition { - return NewCondition(COND_IN, values...) -} - -func NOTIN(values ...interface{}) *QueryCondition { - return NewCondition(COND_NOTIN, values...) -} - -func (c *QueryCondition) AND(right *QueryCondition) *QueryCondition { - return &QueryCondition{ - conditionType: COND_AND, - left: c, - right: right, - } -} - -func (c *QueryCondition) OR(right *QueryCondition) *QueryCondition { - return &QueryCondition{ - conditionType: COND_OR, - left: c, - right: right, - } + return q } diff --git a/vendor/github.com/rancher/norman/types/convert/convert.go b/vendor/github.com/rancher/norman/types/convert/convert.go index 1e585bc5..421d7aed 100644 --- a/vendor/github.com/rancher/norman/types/convert/convert.go +++ b/vendor/github.com/rancher/norman/types/convert/convert.go @@ -132,12 +132,12 @@ func ToStringSlice(data interface{}) []string { return nil } -func ToObj(data interface{}, obj interface{}) error { +func ToObj(data interface{}, into interface{}) error { bytes, err := json.Marshal(data) if err != nil { return err } - return json.Unmarshal(bytes, obj) + return json.Unmarshal(bytes, into) } func EncodeToMap(obj interface{}) (map[string]interface{}, error) { diff --git a/vendor/github.com/rancher/norman/types/convert/ref.go b/vendor/github.com/rancher/norman/types/convert/ref.go new file mode 100644 index 00000000..b269a76c --- /dev/null +++ b/vendor/github.com/rancher/norman/types/convert/ref.go @@ -0,0 +1,11 @@ +package convert + +import "fmt" + +func ToReference(typeName string) string { + return fmt.Sprintf("reference[%s]", typeName) +} + +func ToFullReference(path, typeName string) string { + return fmt.Sprintf("reference[%s/schemas/%s]", path, typeName) +} diff --git a/vendor/github.com/rancher/norman/types/convert/value_set_string.go b/vendor/github.com/rancher/norman/types/convert/value_set_string.go index 88f981d3..d9b329fa 100644 --- a/vendor/github.com/rancher/norman/types/convert/value_set_string.go +++ b/vendor/github.com/rancher/norman/types/convert/value_set_string.go @@ -13,7 +13,6 @@ func ToValuesSlice(value string) []string { value = strings.TrimSpace(value) if strings.HasPrefix(value, "(") && strings.HasSuffix(value, ")") { return splitRegexp.Split(value[1:len(value)-1], -1) - } else { - return []string{value} } + return []string{value} } diff --git a/vendor/github.com/rancher/norman/types/factory/schemas.go b/vendor/github.com/rancher/norman/types/factory/schemas.go new file mode 100644 index 00000000..055daee0 --- /dev/null +++ b/vendor/github.com/rancher/norman/types/factory/schemas.go @@ -0,0 +1,19 @@ +package factory + +import ( + "github.com/rancher/norman/types" + "github.com/rancher/norman/types/mapper" + "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func Schemas(version *types.APIVersion) *types.Schemas { + s := types.NewSchemas() + s.DefaultMappers = []types.Mapper{ + mapper.NewObject(), + } + s.DefaultPostMappers = []types.Mapper{ + &mapper.RenameReference{}, + } + s.AddMapperForType(version, v1.ObjectMeta{}, mapper.NewMetadataMapper()) + return s +} diff --git a/vendor/github.com/rancher/norman/types/mapper.go b/vendor/github.com/rancher/norman/types/mapper.go index 0b43e6c0..3bd85878 100644 --- a/vendor/github.com/rancher/norman/types/mapper.go +++ b/vendor/github.com/rancher/norman/types/mapper.go @@ -1,7 +1,6 @@ package types import ( - "github.com/pkg/errors" "github.com/rancher/norman/types/definition" ) @@ -11,14 +10,37 @@ type Mapper interface { ModifySchema(schema *Schema, schemas *Schemas) error } -type TypeMapper struct { +type Mappers []Mapper + +func (m Mappers) FromInternal(data map[string]interface{}) { + for _, mapper := range m { + mapper.FromInternal(data) + } +} + +func (m Mappers) ToInternal(data map[string]interface{}) { + for i := len(m) - 1; i >= 0; i-- { + m[i].ToInternal(data) + } +} + +func (m Mappers) ModifySchema(schema *Schema, schemas *Schemas) error { + for _, mapper := range m { + if err := mapper.ModifySchema(schema, schemas); err != nil { + return err + } + } + return nil +} + +type typeMapper struct { Mappers []Mapper typeName string subSchemas map[string]*Schema subArraySchemas map[string]*Schema } -func (t *TypeMapper) FromInternal(data map[string]interface{}) { +func (t *typeMapper) FromInternal(data map[string]interface{}) { for fieldName, schema := range t.subSchemas { if schema.Mapper == nil { continue @@ -38,19 +60,29 @@ func (t *TypeMapper) FromInternal(data map[string]interface{}) { } } - for _, mapper := range t.Mappers { - mapper.FromInternal(data) - } + Mappers(t.Mappers).FromInternal(data) if data != nil { - data["type"] = t.typeName + if _, ok := data["type"]; !ok { + data["type"] = t.typeName + } + name, _ := data["name"].(string) + namespace, _ := data["namespace"].(string) + + if _, ok := data["id"]; !ok { + if name != "" { + if namespace == "" { + data["id"] = name + } else { + data["id"] = namespace + ":" + name + } + } + } } } -func (t *TypeMapper) ToInternal(data map[string]interface{}) { - for i := len(t.Mappers) - 1; i >= 0; i-- { - t.Mappers[i].ToInternal(data) - } +func (t *typeMapper) ToInternal(data map[string]interface{}) { + Mappers(t.Mappers).ToInternal(data) for fieldName, schema := range t.subArraySchemas { if schema.Mapper == nil { @@ -71,7 +103,7 @@ func (t *TypeMapper) ToInternal(data map[string]interface{}) { } } -func (t *TypeMapper) ModifySchema(schema *Schema, schemas *Schemas) error { +func (t *typeMapper) ModifySchema(schema *Schema, schemas *Schemas) error { t.subSchemas = map[string]*Schema{} t.subArraySchemas = map[string]*Schema{} t.typeName = schema.ID @@ -94,11 +126,5 @@ func (t *TypeMapper) ModifySchema(schema *Schema, schemas *Schemas) error { } } - for _, mapper := range t.Mappers { - if err := mapper.ModifySchema(schema, schemas); err != nil { - return errors.Wrapf(err, "mapping type %s", schema.ID) - } - } - - return nil + return Mappers(t.Mappers).ModifySchema(schema, schemas) } diff --git a/vendor/github.com/rancher/norman/types/mapper/access.go b/vendor/github.com/rancher/norman/types/mapper/access.go new file mode 100644 index 00000000..14043c58 --- /dev/null +++ b/vendor/github.com/rancher/norman/types/mapper/access.go @@ -0,0 +1,33 @@ +package mapper + +import ( + "strings" + + "github.com/rancher/norman/types" +) + +type Access struct { + Fields map[string]string +} + +func (e Access) FromInternal(data map[string]interface{}) { +} + +func (e Access) ToInternal(data map[string]interface{}) { +} + +func (e Access) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { + for name, access := range e.Fields { + if err := validateField(name, schema); err != nil { + return err + } + + field := schema.ResourceFields[name] + field.Create = strings.Contains(access, "c") + field.Update = strings.Contains(access, "u") + field.WriteOnly = strings.Contains(access, "o") + + schema.ResourceFields[name] = field + } + return nil +} diff --git a/vendor/github.com/rancher/norman/types/mapper/check.go b/vendor/github.com/rancher/norman/types/mapper/check.go new file mode 100644 index 00000000..30e7cefa --- /dev/null +++ b/vendor/github.com/rancher/norman/types/mapper/check.go @@ -0,0 +1,15 @@ +package mapper + +import ( + "fmt" + + "github.com/rancher/norman/types" +) + +func validateField(field string, schema *types.Schema) error { + if _, ok := schema.ResourceFields[field]; !ok { + return fmt.Errorf("field %s missing on schema %s", field, schema.ID) + } + + return nil +} diff --git a/vendor/github.com/rancher/norman/types/mapper/display_name.go b/vendor/github.com/rancher/norman/types/mapper/display_name.go new file mode 100644 index 00000000..506aff16 --- /dev/null +++ b/vendor/github.com/rancher/norman/types/mapper/display_name.go @@ -0,0 +1,28 @@ +package mapper + +import ( + "github.com/rancher/norman/types" +) + +var displayNameMappers = types.Mappers{ + &Move{From: "name", To: "id"}, + &Move{From: "displayName", To: "name"}, + Access{Fields: map[string]string{ + "id": "", + }}, +} + +type DisplayName struct { +} + +func (d DisplayName) FromInternal(data map[string]interface{}) { + displayNameMappers.FromInternal(data) +} + +func (d DisplayName) ToInternal(data map[string]interface{}) { + displayNameMappers.ToInternal(data) +} + +func (d DisplayName) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { + return displayNameMappers.ModifySchema(schema, schemas) +} diff --git a/vendor/github.com/rancher/norman/types/mapping/mapper/drop.go b/vendor/github.com/rancher/norman/types/mapper/drop.go similarity index 88% rename from vendor/github.com/rancher/norman/types/mapping/mapper/drop.go rename to vendor/github.com/rancher/norman/types/mapper/drop.go index a76d9ac5..64032d8f 100644 --- a/vendor/github.com/rancher/norman/types/mapping/mapper/drop.go +++ b/vendor/github.com/rancher/norman/types/mapper/drop.go @@ -18,11 +18,6 @@ func (d Drop) ToInternal(data map[string]interface{}) { } func (d Drop) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - _, err := getInternal(schema) - if err != nil { - return err - } - if _, ok := schema.ResourceFields[d.Field]; !ok { return fmt.Errorf("can not drop missing field %s on %s", d.Field, schema.ID) } diff --git a/vendor/github.com/rancher/norman/types/mapping/mapper/embed.go b/vendor/github.com/rancher/norman/types/mapper/embed.go similarity index 85% rename from vendor/github.com/rancher/norman/types/mapping/mapper/embed.go rename to vendor/github.com/rancher/norman/types/mapper/embed.go index ea5c3e80..2c48945b 100644 --- a/vendor/github.com/rancher/norman/types/mapping/mapper/embed.go +++ b/vendor/github.com/rancher/norman/types/mapper/embed.go @@ -8,7 +8,9 @@ import ( type Embed struct { Field string + Optional bool ReadOnly bool + Ignore []string ignoreOverride bool embeddedFields []string } @@ -37,20 +39,29 @@ func (e *Embed) ToInternal(data map[string]interface{}) { } func (e *Embed) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - internalSchema, err := validateInternalField(e.Field, schema) + err := validateField(e.Field, schema) if err != nil { + if e.Optional { + return nil + } return err } e.embeddedFields = []string{} - embeddedSchemaID := internalSchema.ResourceFields[e.Field].Type + embeddedSchemaID := schema.ResourceFields[e.Field].Type embeddedSchema := schemas.Schema(&schema.Version, embeddedSchemaID) if embeddedSchema == nil { return fmt.Errorf("failed to find schema %s for embedding", embeddedSchemaID) } for name, field := range embeddedSchema.ResourceFields { + for _, ignore := range e.Ignore { + if ignore == name { + continue + } + } + if !e.ignoreOverride { if _, ok := schema.ResourceFields[name]; ok { return fmt.Errorf("embedding field %s on %s will overwrite the field %s", diff --git a/vendor/github.com/rancher/norman/types/mapping/mapper/enum.go b/vendor/github.com/rancher/norman/types/mapper/enum.go similarity index 92% rename from vendor/github.com/rancher/norman/types/mapping/mapper/enum.go rename to vendor/github.com/rancher/norman/types/mapper/enum.go index e2c276e3..96d2e69f 100644 --- a/vendor/github.com/rancher/norman/types/mapping/mapper/enum.go +++ b/vendor/github.com/rancher/norman/types/mapper/enum.go @@ -44,6 +44,5 @@ func (e Enum) ToInternal(data map[string]interface{}) { } func (e Enum) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - _, err := validateInternalField(e.Field, schema) - return err + return validateField(e.Field, schema) } diff --git a/vendor/github.com/rancher/norman/types/mapper/label_field.go b/vendor/github.com/rancher/norman/types/mapper/label_field.go new file mode 100644 index 00000000..6a05d57a --- /dev/null +++ b/vendor/github.com/rancher/norman/types/mapper/label_field.go @@ -0,0 +1,25 @@ +package mapper + +import "github.com/rancher/norman/types" + +type LabelField struct { + Field string +} + +func (e LabelField) FromInternal(data map[string]interface{}) { + v, ok := RemoveValue(data, "labels", "io.cattle.field."+e.Field) + if ok { + data[e.Field] = v + } +} + +func (e LabelField) ToInternal(data map[string]interface{}) { + v, ok := data[e.Field] + if ok { + PutValue(data, v, "labels", "io.cattle.field."+e.Field) + } +} + +func (e LabelField) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { + return validateField(e.Field, schema) +} diff --git a/vendor/github.com/rancher/norman/types/mapper/metadata.go b/vendor/github.com/rancher/norman/types/mapper/metadata.go new file mode 100644 index 00000000..ddbfa5f8 --- /dev/null +++ b/vendor/github.com/rancher/norman/types/mapper/metadata.go @@ -0,0 +1,30 @@ +package mapper + +import ( + "github.com/rancher/norman/types" +) + +func NewMetadataMapper() types.Mapper { + return types.Mappers{ + Drop{"generateName"}, + Move{From: "selfLink", To: "resourcePath"}, + Move{From: "uid", To: "uuid"}, + Drop{"resourceVersion"}, + Drop{"generation"}, + Move{From: "creationTimestamp", To: "created"}, + Move{From: "deletionTimestamp", To: "removed"}, + Drop{"deletionGracePeriodSeconds"}, + Drop{"initializers"}, + Drop{"finalizers"}, + Drop{"clusterName"}, + ReadOnly{Field: "*"}, + Access{ + Fields: map[string]string{ + "name": "c", + "namespace": "cu", + "labels": "cu", + "annotations": "cu", + }, + }, + } +} diff --git a/vendor/github.com/rancher/norman/types/mapping/mapper/move.go b/vendor/github.com/rancher/norman/types/mapper/move.go similarity index 69% rename from vendor/github.com/rancher/norman/types/mapping/mapper/move.go rename to vendor/github.com/rancher/norman/types/mapper/move.go index 2016b82e..e39d361d 100644 --- a/vendor/github.com/rancher/norman/types/mapping/mapper/move.go +++ b/vendor/github.com/rancher/norman/types/mapper/move.go @@ -10,7 +10,9 @@ import ( ) type Move struct { - From, To string + From, To string + DestDefined bool + NoDeleteFromField bool } func (m Move) FromInternal(data map[string]interface{}) { @@ -26,37 +28,31 @@ func (m Move) ToInternal(data map[string]interface{}) { } func (m Move) ModifySchema(s *types.Schema, schemas *types.Schemas) error { - internalSchema, err := getInternal(s) - if err != nil { - return err - } - - _, _, fromInternalField, ok, err := getField(internalSchema, schemas, m.From) + fromSchema, _, fromField, ok, err := getField(s, schemas, m.From) if err != nil { return err } if !ok { - return fmt.Errorf("missing field %s on internal schema %s", m.From, internalSchema.ID) + return fmt.Errorf("failed to find field %s on schema %s", m.From, s.ID) } - fromSchema, _, _, _, err := getField(s, schemas, m.From) - if err != nil { - return err - } - - toSchema, toFieldName, toField, ok, err := getField(s, schemas, m.To) + toSchema, toFieldName, _, ok, err := getField(s, schemas, m.To) if err != nil { return err } _, ok = toSchema.ResourceFields[toFieldName] - if ok && !strings.Contains(m.To, "/") { + if ok && !strings.Contains(m.To, "/") && !m.DestDefined { return fmt.Errorf("field %s already exists on schema %s", m.To, s.ID) } - delete(fromSchema.ResourceFields, m.From) + if !m.NoDeleteFromField { + delete(fromSchema.ResourceFields, m.From) + } - toField.CodeName = convert.Capitalize(toFieldName) - toSchema.ResourceFields[toFieldName] = fromInternalField + if !m.DestDefined { + fromField.CodeName = convert.Capitalize(toFieldName) + toSchema.ResourceFields[toFieldName] = fromField + } return nil } diff --git a/vendor/github.com/rancher/norman/types/mapper/object.go b/vendor/github.com/rancher/norman/types/mapper/object.go new file mode 100644 index 00000000..21329574 --- /dev/null +++ b/vendor/github.com/rancher/norman/types/mapper/object.go @@ -0,0 +1,25 @@ +package mapper + +import "github.com/rancher/norman/types" + +type Object struct { + types.Mappers +} + +func NewObject(mappers ...types.Mapper) Object { + return Object{ + Mappers: append([]types.Mapper{ + &Embed{Field: "metadata"}, + &Embed{Field: "spec", Optional: true}, + &ReadOnly{Field: "status", Optional: true}, + &Drop{"kind"}, + &Drop{"apiVersion"}, + &Scope{ + IfNot: types.NamespaceScope, + Mappers: []types.Mapper{ + &Drop{"namespace"}, + }, + }, + }, mappers...), + } +} diff --git a/vendor/github.com/rancher/norman/types/mapper/read_only.go b/vendor/github.com/rancher/norman/types/mapper/read_only.go new file mode 100644 index 00000000..71054496 --- /dev/null +++ b/vendor/github.com/rancher/norman/types/mapper/read_only.go @@ -0,0 +1,41 @@ +package mapper + +import ( + "github.com/rancher/norman/types" +) + +type ReadOnly struct { + Field string + Optional bool +} + +func (r ReadOnly) FromInternal(data map[string]interface{}) { +} + +func (r ReadOnly) ToInternal(data map[string]interface{}) { +} + +func (r ReadOnly) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { + if r.Field == "*" { + for name, field := range schema.ResourceFields { + field.Create = false + field.Update = false + schema.ResourceFields[name] = field + } + return nil + } + + if err := validateField(r.Field, schema); err != nil { + if r.Optional { + return nil + } + return err + } + + field := schema.ResourceFields[r.Field] + field.Create = false + field.Update = false + schema.ResourceFields[r.Field] = field + + return nil +} diff --git a/vendor/github.com/rancher/norman/types/mapper/rename_reference.go b/vendor/github.com/rancher/norman/types/mapper/rename_reference.go new file mode 100644 index 00000000..2dc4deb8 --- /dev/null +++ b/vendor/github.com/rancher/norman/types/mapper/rename_reference.go @@ -0,0 +1,53 @@ +package mapper + +import ( + "strings" + + "github.com/rancher/norman/types" + "github.com/rancher/norman/types/definition" +) + +type RenameReference struct { + mapper types.Mapper +} + +func (r *RenameReference) FromInternal(data map[string]interface{}) { + if r.mapper != nil { + r.mapper.FromInternal(data) + } +} + +func (r *RenameReference) ToInternal(data map[string]interface{}) { + if r.mapper != nil { + r.mapper.ToInternal(data) + } +} + +func (r *RenameReference) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { + var mappers []types.Mapper + for name, field := range schema.ResourceFields { + if definition.IsReferenceType(field.Type) && strings.HasSuffix(name, "Name") { + newName := strings.TrimSuffix(name, "Name") + "Id" + move := Move{From: name, To: newName} + if err := move.ModifySchema(schema, schemas); err != nil { + return err + } + + mappers = append(mappers, move) + } else if definition.IsArrayType(field.Type) && definition.IsReferenceType(definition.SubType(field.Type)) && strings.HasSuffix(name, "Names") { + newName := strings.TrimSuffix(name, "Names") + "Ids" + move := Move{From: name, To: newName} + if err := move.ModifySchema(schema, schemas); err != nil { + return err + } + + mappers = append(mappers, move) + } + } + + if len(mappers) > 0 { + r.mapper = types.Mappers(mappers) + } + + return nil +} diff --git a/vendor/github.com/rancher/norman/types/mapper/scope.go b/vendor/github.com/rancher/norman/types/mapper/scope.go new file mode 100644 index 00000000..fcb59694 --- /dev/null +++ b/vendor/github.com/rancher/norman/types/mapper/scope.go @@ -0,0 +1,37 @@ +package mapper + +import ( + "github.com/rancher/norman/types" +) + +type Scope struct { + If types.TypeScope + IfNot types.TypeScope + Mappers []types.Mapper + run bool +} + +func (s *Scope) FromInternal(data map[string]interface{}) { + if s.run { + types.Mappers(s.Mappers).FromInternal(data) + } +} + +func (s *Scope) ToInternal(data map[string]interface{}) { + if s.run { + types.Mappers(s.Mappers).ToInternal(data) + } +} + +func (s *Scope) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { + if s.If != "" { + s.run = schema.Scope == s.If + } + if s.IfNot != "" { + s.run = schema.Scope != s.IfNot + } + if s.run { + return types.Mappers(s.Mappers).ModifySchema(schema, schemas) + } + return nil +} diff --git a/vendor/github.com/rancher/norman/types/mapper/set_value.go b/vendor/github.com/rancher/norman/types/mapper/set_value.go new file mode 100644 index 00000000..4f9b553b --- /dev/null +++ b/vendor/github.com/rancher/norman/types/mapper/set_value.go @@ -0,0 +1,49 @@ +package mapper + +import ( + "fmt" + + "strings" + + "github.com/rancher/norman/types" +) + +type SetValue struct { + From, To string + Value interface{} + IfEq interface{} +} + +func (s SetValue) FromInternal(data map[string]interface{}) { + v, ok := GetValue(data, strings.Split(s.From, "/")...) + if !ok { + return + } + + if v == s.IfEq { + PutValue(data, s.Value, strings.Split(s.To, "/")...) + } +} + +func (s SetValue) ToInternal(data map[string]interface{}) { + v, ok := GetValue(data, strings.Split(s.To, "/")...) + if !ok { + return + } + + if v == s.Value { + PutValue(data, s.IfEq, strings.Split(s.From, "/")...) + } +} + +func (s SetValue) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { + _, _, _, ok, err := getField(schema, schemas, s.To) + if err != nil { + return err + } + if !ok { + return fmt.Errorf("failed to find defined field for %s on schemas %s", s.To, schema.ID) + } + + return nil +} diff --git a/vendor/github.com/rancher/norman/types/mapping/mapper/slice_to_map.go b/vendor/github.com/rancher/norman/types/mapper/slice_to_map.go similarity index 83% rename from vendor/github.com/rancher/norman/types/mapping/mapper/slice_to_map.go rename to vendor/github.com/rancher/norman/types/mapper/slice_to_map.go index 1b94449c..b42d1e5c 100644 --- a/vendor/github.com/rancher/norman/types/mapping/mapper/slice_to_map.go +++ b/vendor/github.com/rancher/norman/types/mapper/slice_to_map.go @@ -31,7 +31,7 @@ func (s SliceToMap) FromInternal(data map[string]interface{}) { func (s SliceToMap) ToInternal(data map[string]interface{}) { datas, _ := data[s.Field].(map[string]interface{}) - result := []map[string]interface{}{} + var result []map[string]interface{} for name, item := range datas { mapItem, _ := item.(map[string]interface{}) @@ -47,14 +47,14 @@ func (s SliceToMap) ToInternal(data map[string]interface{}) { } func (s SliceToMap) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - internalSchema, err := validateInternalField(s.Field, schema) + err := validateField(s.Field, schema) if err != nil { return err } - field := internalSchema.ResourceFields[s.Field] + field := schema.ResourceFields[s.Field] if !definition.IsArrayType(field.Type) { - return fmt.Errorf("field %s on %s is not an array", s.Field, internalSchema.ID) + return fmt.Errorf("field %s on %s is not an array", s.Field, schema.ID) } field.Type = "map[" + definition.SubType(field.Type) + "]" diff --git a/vendor/github.com/rancher/norman/types/mapping/mapper/union_embed.go b/vendor/github.com/rancher/norman/types/mapper/union_embed.go similarity index 100% rename from vendor/github.com/rancher/norman/types/mapping/mapper/union_embed.go rename to vendor/github.com/rancher/norman/types/mapper/union_embed.go diff --git a/vendor/github.com/rancher/norman/types/mapping/mapper/values.go b/vendor/github.com/rancher/norman/types/mapper/values.go similarity index 92% rename from vendor/github.com/rancher/norman/types/mapping/mapper/values.go rename to vendor/github.com/rancher/norman/types/mapper/values.go index f19b002d..41cdaba5 100644 --- a/vendor/github.com/rancher/norman/types/mapping/mapper/values.go +++ b/vendor/github.com/rancher/norman/types/mapper/values.go @@ -6,9 +6,8 @@ func RemoveValue(data map[string]interface{}, keys ...string) (interface{}, bool val, ok := data[key] delete(data, key) return val, ok - } else { - data, _ = data[key].(map[string]interface{}) } + data, _ = data[key].(map[string]interface{}) } return nil, false @@ -51,9 +50,8 @@ func GetValue(data map[string]interface{}, keys ...string) (interface{}, bool) { if i == len(keys)-1 { val, ok := data[key] return val, ok - } else { - data, _ = data[key].(map[string]interface{}) } + data, _ = data[key].(map[string]interface{}) } return nil, false diff --git a/vendor/github.com/rancher/norman/types/mapping/mapper/check.go b/vendor/github.com/rancher/norman/types/mapping/mapper/check.go deleted file mode 100644 index 58993615..00000000 --- a/vendor/github.com/rancher/norman/types/mapping/mapper/check.go +++ /dev/null @@ -1,28 +0,0 @@ -package mapper - -import ( - "fmt" - - "github.com/rancher/norman/types" -) - -func getInternal(schema *types.Schema) (*types.Schema, error) { - if schema.InternalSchema == nil { - return nil, fmt.Errorf("no internal schema found for schema %s", schema.ID) - } - - return schema.InternalSchema, nil -} - -func validateInternalField(field string, schema *types.Schema) (*types.Schema, error) { - internalSchema, err := getInternal(schema) - if err != nil { - return nil, err - } - - if _, ok := internalSchema.ResourceFields[field]; !ok { - return nil, fmt.Errorf("field %s missing on internal schema %s", field, schema.ID) - } - - return internalSchema, nil -} diff --git a/vendor/github.com/rancher/norman/types/mapping/mapper/copy.go b/vendor/github.com/rancher/norman/types/mapping/mapper/copy.go deleted file mode 100644 index 45baab24..00000000 --- a/vendor/github.com/rancher/norman/types/mapping/mapper/copy.go +++ /dev/null @@ -1,25 +0,0 @@ -package mapper - -import "strings" - -type Copy struct { - From, To string -} - -func (c Copy) Forward(data map[string]interface{}) { - val, ok := GetValue(data, strings.Split(c.From, "/")...) - if !ok { - return - } - - PutValue(data, val, strings.Split(c.To, "/")...) -} - -func (c Copy) Back(data map[string]interface{}) { - val, ok := GetValue(data, strings.Split(c.To, "/")...) - if !ok { - return - } - - PutValue(data, val, strings.Split(c.From, "/")...) -} diff --git a/vendor/github.com/rancher/norman/types/mapping/mapper/label_field.go b/vendor/github.com/rancher/norman/types/mapping/mapper/label_field.go deleted file mode 100644 index 5a0babf9..00000000 --- a/vendor/github.com/rancher/norman/types/mapping/mapper/label_field.go +++ /dev/null @@ -1,25 +0,0 @@ -package mapper - -//type LabelField struct { -// Fields []string -//} -// -//func (l LabelField) Forward(data map[string]interface{}) { -// for _, field := range l.Fields { -// moveForLabel(field).Forward(data) -// } -// -//} -// -//func (l LabelField) Back(data map[string]interface{}) { -// for _, field := range l.Fields { -// moveForLabel(field).Back(data) -// } -//} -// -//func moveForLabel(field string) *Enum { -// return &Enum{ -// From: field, -// To: "metadata/labels/io.cattle.field." + strings.ToLower(field), -// } -//} diff --git a/vendor/github.com/rancher/norman/types/mapping/mapper/object.go b/vendor/github.com/rancher/norman/types/mapping/mapper/object.go deleted file mode 100644 index afb0a366..00000000 --- a/vendor/github.com/rancher/norman/types/mapping/mapper/object.go +++ /dev/null @@ -1,19 +0,0 @@ -package mapper - -import "github.com/rancher/norman/types" - -type Object struct { - types.TypeMapper -} - -func NewObject(mappers ...types.Mapper) *Object { - return &Object{ - TypeMapper: types.TypeMapper{ - Mappers: append([]types.Mapper{ - &Embed{Field: "metadata"}, - &Embed{Field: "spec"}, - &ReadOnly{"status"}, - }, mappers...), - }, - } -} diff --git a/vendor/github.com/rancher/norman/types/mapping/mapper/read_only.go b/vendor/github.com/rancher/norman/types/mapping/mapper/read_only.go deleted file mode 100644 index 8e5056e6..00000000 --- a/vendor/github.com/rancher/norman/types/mapping/mapper/read_only.go +++ /dev/null @@ -1,30 +0,0 @@ -package mapper - -import ( - "fmt" - - "github.com/rancher/norman/types" -) - -type ReadOnly struct { - Field string -} - -func (r *ReadOnly) FromInternal(data map[string]interface{}) { -} - -func (r *ReadOnly) ToInternal(data map[string]interface{}) { -} - -func (r *ReadOnly) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - field, ok := schema.ResourceFields[r.Field] - if !ok { - return fmt.Errorf("failed to find field %s on schema %s", r.Field, schema.ID) - } - - field.Create = false - field.Update = false - schema.ResourceFields[r.Field] = field - - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapping/mapper/swap.go b/vendor/github.com/rancher/norman/types/mapping/mapper/swap.go deleted file mode 100644 index f135ac4c..00000000 --- a/vendor/github.com/rancher/norman/types/mapping/mapper/swap.go +++ /dev/null @@ -1,20 +0,0 @@ -package mapper - -type Swap struct { - Left, Right string -} - -func (s Swap) Forward(data map[string]interface{}) { - rightValue, rightOk := data[s.Right] - leftValue, leftOk := data[s.Left] - if rightOk { - data[s.Left] = rightValue - } - if leftOk { - data[s.Right] = leftValue - } -} - -func (s Swap) Back(data map[string]interface{}) { - s.Forward(data) -} diff --git a/vendor/github.com/rancher/norman/types/mapping/mapper/type.go b/vendor/github.com/rancher/norman/types/mapping/mapper/type.go deleted file mode 100644 index ad5eac35..00000000 --- a/vendor/github.com/rancher/norman/types/mapping/mapper/type.go +++ /dev/null @@ -1 +0,0 @@ -package mapper diff --git a/vendor/github.com/rancher/norman/types/reflection.go b/vendor/github.com/rancher/norman/types/reflection.go index e0e5e968..2c7bd6ee 100644 --- a/vendor/github.com/rancher/norman/types/reflection.go +++ b/vendor/github.com/rancher/norman/types/reflection.go @@ -6,12 +6,17 @@ import ( "strconv" "strings" + "net/http" + "github.com/rancher/norman/types/convert" + "github.com/rancher/norman/types/definition" + "github.com/rancher/norman/types/slice" "github.com/sirupsen/logrus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) var ( + namespacedType = reflect.TypeOf(Namespaced{}) resourceType = reflect.TypeOf(Resource{}) typeType = reflect.TypeOf(metav1.TypeMeta{}) metaType = reflect.TypeOf(metav1.ObjectMeta{}) @@ -21,10 +26,17 @@ var ( } ) -func (s *Schemas) AddMapperForType(version *APIVersion, obj interface{}, mapper Mapper) *Schemas { +func (s *Schemas) AddMapperForType(version *APIVersion, obj interface{}, mapper ...Mapper) *Schemas { + if len(mapper) == 0 { + return s + } + t := reflect.TypeOf(obj) typeName := convert.LowerTitle(t.Name()) - return s.AddMapper(version, typeName, mapper) + if len(mapper) == 1 { + return s.AddMapper(version, typeName, mapper[0]) + } + return s.AddMapper(version, typeName, Mappers(mapper)) } func (s *Schemas) MustImport(version *APIVersion, obj interface{}, externalOverrides ...interface{}) *Schemas { @@ -36,8 +48,13 @@ func (s *Schemas) MustImport(version *APIVersion, obj interface{}, externalOverr return s } +func (s *Schemas) MustImportAndCustomize(version *APIVersion, obj interface{}, f func(*Schema), externalOverrides ...interface{}) *Schemas { + return s.MustImport(version, obj, externalOverrides...). + MustCustomizeType(version, obj, f) +} + func (s *Schemas) Import(version *APIVersion, obj interface{}, externalOverrides ...interface{}) (*Schema, error) { - types := []reflect.Type{} + var types []reflect.Type for _, override := range externalOverrides { types = append(types, reflect.TypeOf(override)) } @@ -61,6 +78,54 @@ func (s *Schemas) newSchemaFromType(version *APIVersion, t reflect.Type, typeNam return schema, nil } +func (s *Schemas) setupFilters(schema *Schema) { + if !slice.ContainsString(schema.CollectionMethods, http.MethodGet) { + return + } + for fieldName, field := range schema.ResourceFields { + var mods []ModifierType + switch field.Type { + case "enum": + mods = []ModifierType{ModifierEQ, ModifierNE, ModifierIn, ModifierNotIn} + case "string": + mods = []ModifierType{ModifierEQ, ModifierNE, ModifierIn, ModifierNotIn} + case "int": + mods = []ModifierType{ModifierEQ, ModifierNE, ModifierIn, ModifierNotIn} + case "boolean": + mods = []ModifierType{ModifierEQ, ModifierNE} + default: + if definition.IsReferenceType(field.Type) { + mods = []ModifierType{ModifierEQ, ModifierNE, ModifierIn, ModifierNotIn} + } + } + + if len(mods) > 0 { + if schema.CollectionFilters == nil { + schema.CollectionFilters = map[string]Filter{} + } + schema.CollectionFilters[fieldName] = Filter{ + Modifiers: mods, + } + } + } +} + +func (s *Schemas) MustCustomizeType(version *APIVersion, obj interface{}, f func(*Schema)) *Schemas { + name := convert.LowerTitle(reflect.TypeOf(obj).Name()) + schema := s.Schema(version, name) + if schema == nil { + panic("Failed to find schema " + name) + } + + f(schema) + + if schema.SubContext != "" { + s.schemasBySubContext[schema.SubContext] = schema + } + + return s +} + func (s *Schemas) importType(version *APIVersion, t reflect.Type, overrides ...reflect.Type) (*Schema, error) { typeName := convert.LowerTitle(t.Name()) @@ -76,8 +141,13 @@ func (s *Schemas) importType(version *APIVersion, t reflect.Type, overrides ...r return nil, err } - mapper := s.mapper(&schema.Version, schema.ID) - if mapper != nil { + mappers := s.mapper(&schema.Version, schema.ID) + if schema.CanList() { + mappers = append(s.DefaultMappers, mappers...) + } + mappers = append(mappers, s.DefaultPostMappers...) + + if len(mappers) > 0 { copy, err := s.newSchemaFromType(version, t, typeName) if err != nil { return nil, err @@ -91,14 +161,16 @@ func (s *Schemas) importType(version *APIVersion, t reflect.Type, overrides ...r } } - if mapper == nil { - mapper = &TypeMapper{} + mapper := &typeMapper{ + Mappers: mappers, } if err := mapper.ModifySchema(schema, s); err != nil { return nil, err } + s.setupFilters(schema) + schema.Mapper = mapper s.AddSchema(schema) @@ -146,6 +218,9 @@ func (s *Schemas) readFields(schema *Schema, t reflect.Type) error { t = t.Elem() } if t.Kind() == reflect.Struct { + if t == namespacedType { + schema.Scope = NamespaceScope + } if err := s.readFields(schema, t); err != nil { return err } @@ -156,6 +231,9 @@ func (s *Schemas) readFields(schema *Schema, t reflect.Type) error { fieldName := jsonName if fieldName == "" { fieldName = convert.LowerTitle(field.Name) + if strings.HasSuffix(fieldName, "ID") { + fieldName = strings.TrimSuffix(fieldName, "ID") + "Id" + } } if blacklistNames[fieldName] { @@ -168,6 +246,7 @@ func (s *Schemas) readFields(schema *Schema, t reflect.Type) error { schemaField := Field{ Create: true, Update: true, + Nullable: true, CodeName: field.Name, } diff --git a/vendor/github.com/rancher/norman/types/schema_funcs.go b/vendor/github.com/rancher/norman/types/schema_funcs.go new file mode 100644 index 00000000..df6f6ff6 --- /dev/null +++ b/vendor/github.com/rancher/norman/types/schema_funcs.go @@ -0,0 +1,26 @@ +package types + +import ( + "net/http" + + "github.com/rancher/norman/types/slice" +) + +func (s *Schema) MustCustomizeField(name string, f func(f Field) Field) *Schema { + field, ok := s.ResourceFields[name] + if !ok { + panic("Failed to find field " + name + " on schema " + s.ID) + } + s.ResourceFields[name] = f(field) + return s +} + +func (v *APIVersion) Equals(other *APIVersion) bool { + return v.Version == other.Version && + v.Group == other.Group && + v.Path == other.Path +} + +func (s *Schema) CanList() bool { + return slice.ContainsString(s.CollectionMethods, http.MethodGet) +} diff --git a/vendor/github.com/rancher/norman/types/schemas.go b/vendor/github.com/rancher/norman/types/schemas.go index bbdf4256..047021ee 100644 --- a/vendor/github.com/rancher/norman/types/schemas.go +++ b/vendor/github.com/rancher/norman/types/schemas.go @@ -16,17 +16,21 @@ type SchemaCollection struct { type SchemaInitFunc func(*Schemas) *Schemas type Schemas struct { - schemasByPath map[string]map[string]*Schema - mappers map[string]map[string]Mapper - versions []APIVersion - schemas []*Schema - errors []error + schemasByPath map[string]map[string]*Schema + schemasBySubContext map[string]*Schema + mappers map[string]map[string][]Mapper + DefaultMappers []Mapper + DefaultPostMappers []Mapper + versions []APIVersion + schemas []*Schema + errors []error } func NewSchemas() *Schemas { return &Schemas{ - schemasByPath: map[string]map[string]*Schema{}, - mappers: map[string]map[string]Mapper{}, + schemasByPath: map[string]map[string]*Schema{}, + schemasBySubContext: map[string]*Schema{}, + mappers: map[string]map[string][]Mapper{}, } } @@ -38,6 +42,14 @@ func (s *Schemas) Err() error { return NewErrors(s.errors) } +func (s *Schemas) SubContext(subContext string) *Schema { + return s.schemasBySubContext[subContext] +} + +func (s *Schemas) SubContextSchemas() map[string]*Schema { + return s.schemasBySubContext +} + func (s *Schemas) AddSchemas(schema *Schemas) *Schemas { for _, schema := range schema.Schemas() { s.AddSchema(schema) @@ -46,7 +58,7 @@ func (s *Schemas) AddSchemas(schema *Schemas) *Schemas { } func (s *Schemas) AddSchema(schema *Schema) *Schemas { - schema.Type = "schema" + schema.Type = "/v1-meta/schemas/schema" if schema.ID == "" { s.errors = append(s.errors, fmt.Errorf("ID is not set on schema: %v", schema)) return s @@ -64,6 +76,9 @@ func (s *Schemas) AddSchema(schema *Schema) *Schemas { if schema.CodeNamePlural == "" { schema.CodeNamePlural = name.GuessPluralName(schema.CodeName) } + if schema.BaseType == "" { + schema.BaseType = schema.ID + } schemas, ok := s.schemasByPath[schema.Version.Path] if !ok { @@ -77,20 +92,21 @@ func (s *Schemas) AddSchema(schema *Schema) *Schemas { s.schemas = append(s.schemas, schema) } + if schema.SubContext != "" { + s.schemasBySubContext[schema.SubContext] = schema + } + return s } func (s *Schemas) AddMapper(version *APIVersion, schemaID string, mapper Mapper) *Schemas { mappers, ok := s.mappers[version.Path] if !ok { - mappers = map[string]Mapper{} + mappers = map[string][]Mapper{} s.mappers[version.Path] = mappers } - if _, ok := mappers[schemaID]; !ok { - mappers[schemaID] = mapper - } - + mappers[schemaID] = append(mappers[schemaID], mapper) return s } @@ -106,7 +122,7 @@ func (s *Schemas) Schemas() []*Schema { return s.schemas } -func (s *Schemas) mapper(version *APIVersion, name string) Mapper { +func (s *Schemas) mapper(version *APIVersion, name string) []Mapper { var ( path string ) @@ -139,10 +155,10 @@ func (s *Schemas) Schema(version *APIVersion, name string) *Schema { path string ) - if strings.Contains(name, "/") { - idx := strings.LastIndex(name, "/") - path = name[0:idx] - name = name[idx+1:] + if strings.Contains(name, "/schemas/") { + parts := strings.SplitN(name, "/schemas/", 2) + path = parts[0] + name = parts[1] } else if version != nil { path = version.Path } else { diff --git a/vendor/github.com/rancher/norman/types/server_types.go b/vendor/github.com/rancher/norman/types/server_types.go index c719d965..fd452f82 100644 --- a/vendor/github.com/rancher/norman/types/server_types.go +++ b/vendor/github.com/rancher/norman/types/server_types.go @@ -27,12 +27,14 @@ func (r *RawResource) MarshalJSON() ([]byte, error) { if r.ID != "" { data["id"] = r.ID } + data["type"] = r.Type + data["baseType"] = r.Schema.BaseType data["links"] = r.Links if r.ActionLinks { data["actionLinks"] = r.Actions } else { - data["action"] = r.Actions + data["actions"] = r.Actions } return json.Marshal(data) } @@ -41,12 +43,19 @@ type ActionHandler func(actionName string, action *Action, request *APIContext) type RequestHandler func(request *APIContext) error +type QueryFilter func(opts QueryOptions, data []map[string]interface{}) []map[string]interface{} + type Validator func(request *APIContext, data map[string]interface{}) error type Formatter func(request *APIContext, resource *RawResource) type ErrorHandler func(request *APIContext, err error) +type SubContextAttributeProvider interface { + Query(apiContext *APIContext, schema *Schema) []*QueryCondition + Create(apiContext *APIContext, schema *Schema) map[string]interface{} +} + type ResponseWriter interface { Write(apiContext *APIContext, code int, obj interface{}) } @@ -57,22 +66,24 @@ type AccessControl interface { } type APIContext struct { - Action string - ID string - Type string - Link string - Method string - Schema *Schema - Schemas *Schemas - Version *APIVersion - ResponseFormat string - ReferenceValidator ReferenceValidator - ResponseWriter ResponseWriter - QueryOptions *QueryOptions - Body map[string]interface{} - URLBuilder URLBuilder - AccessControl AccessControl - SubContext map[string]interface{} + Action string + ID string + Type string + Link string + Method string + Schema *Schema + Schemas *Schemas + Version *APIVersion + ResponseFormat string + ReferenceValidator ReferenceValidator + ResponseWriter ResponseWriter + QueryFilter QueryFilter + SubContextAttributeProvider SubContextAttributeProvider + //QueryOptions *QueryOptions + URLBuilder URLBuilder + AccessControl AccessControl + SubContext map[string]string + Attributes map[string]interface{} Request *http.Request Response http.ResponseWriter @@ -82,6 +93,30 @@ func (r *APIContext) WriteResponse(code int, obj interface{}) { r.ResponseWriter.Write(r, code, obj) } +func (r *APIContext) FilterList(opts QueryOptions, obj []map[string]interface{}) []map[string]interface{} { + return r.QueryFilter(opts, obj) +} + +func (r *APIContext) FilterObject(opts QueryOptions, obj map[string]interface{}) map[string]interface{} { + opts.Pagination = nil + result := r.QueryFilter(opts, []map[string]interface{}{obj}) + if len(result) == 0 { + return nil + } + return result[0] +} + +func (r *APIContext) Filter(opts QueryOptions, obj interface{}) interface{} { + switch v := obj.(type) { + case []map[string]interface{}: + return r.FilterList(opts, v) + case map[string]interface{}: + return r.FilterObject(opts, v) + } + + return nil +} + var ( ASC = SortOrder("asc") DESC = SortOrder("desc") @@ -100,20 +135,21 @@ type ReferenceValidator interface { type URLBuilder interface { Current() string - Collection(schema *Schema) string + Collection(schema *Schema, versionOverride *APIVersion) string + SubContextCollection(subContext *Schema, contextName string, schema *Schema) string + SchemaLink(schema *Schema) string ResourceLink(resource *RawResource) string RelativeToRoot(path string) string - //Link(resource Resource, name string) string - //ReferenceLink(resource Resource) string - //ReferenceByIdLink(resourceType string, id string) string - Version(version string) string + Version(version APIVersion) string + Marker(marker string) string ReverseSort(order SortOrder) string + Sort(field string) string SetSubContext(subContext string) } type Store interface { ByID(apiContext *APIContext, schema *Schema, id string) (map[string]interface{}, error) - List(apiContext *APIContext, schema *Schema, opt *QueryOptions) ([]map[string]interface{}, error) + List(apiContext *APIContext, schema *Schema, opt QueryOptions) ([]map[string]interface{}, error) Create(apiContext *APIContext, schema *Schema, data map[string]interface{}) (map[string]interface{}, error) Update(apiContext *APIContext, schema *Schema, data map[string]interface{}, id string) (map[string]interface{}, error) Delete(apiContext *APIContext, schema *Schema, id string) error diff --git a/vendor/github.com/rancher/norman/types/slice/contains.go b/vendor/github.com/rancher/norman/types/slice/contains.go new file mode 100644 index 00000000..170f11d1 --- /dev/null +++ b/vendor/github.com/rancher/norman/types/slice/contains.go @@ -0,0 +1,10 @@ +package slice + +func ContainsString(slice []string, item string) bool { + for _, j := range slice { + if j == item { + return true + } + } + return false +} diff --git a/vendor/github.com/rancher/norman/types/types.go b/vendor/github.com/rancher/norman/types/types.go index 36eddca1..b465f86a 100644 --- a/vendor/github.com/rancher/norman/types/types.go +++ b/vendor/github.com/rancher/norman/types/types.go @@ -27,12 +27,23 @@ type Sort struct { Name string `json:"name,omitempty"` Order SortOrder `json:"order,omitempty"` Reverse string `json:"reverse,omitempty"` - Links map[string]string `json:"sortLinks,omitempty"` + Links map[string]string `json:"links,omitempty"` } +var ( + ModifierEQ ModifierType = "eq" + ModifierNE ModifierType = "ne" + ModifierNull ModifierType = "null" + ModifierNotNull ModifierType = "notnull" + ModifierIn ModifierType = "in" + ModifierNotIn ModifierType = "notin" +) + +type ModifierType string + type Condition struct { - Modifier string `json:"modifier,omitempty"` - Value interface{} `json:"value,omitempty"` + Modifier ModifierType `json:"modifier,omitempty"` + Value interface{} `json:"value,omitempty"` } type Pagination struct { @@ -40,6 +51,7 @@ type Pagination struct { First string `json:"first,omitempty"` Previous string `json:"previous,omitempty"` Next string `json:"next,omitempty"` + Last string `json:"last,omitempty"` Limit *int64 `json:"limit,omitempty"` Total *int64 `json:"total,omitempty"` Partial bool `json:"partial,omitempty"` @@ -59,12 +71,20 @@ type APIVersion struct { SubContexts map[string]bool `json:"subContext,omitempty"` } +type Namespaced struct{} + +var NamespaceScope TypeScope = "namespace" + +type TypeScope string + type Schema struct { ID string `json:"id,omitempty"` CodeName string `json:"-"` CodeNamePlural string `json:"-"` PkgName string `json:"-"` Type string `json:"type,omitempty"` + BaseType string `json:"baseType,omitempty"` + SubContext string `json:"-,omitempty"` Links map[string]string `json:"links"` Version APIVersion `json:"version"` PluralName string `json:"pluralName,omitempty"` @@ -75,6 +95,7 @@ type Schema struct { CollectionFields map[string]Field `json:"collectionFields,omitempty"` CollectionActions map[string]Action `json:"collectionActions,omitempty"` CollectionFilters map[string]Filter `json:"collectionFilters,omitempty"` + Scope TypeScope `json:"-"` InternalSchema *Schema `json:"-"` Mapper Mapper `json:"-"` @@ -115,7 +136,7 @@ type Action struct { } type Filter struct { - Modifiers []string `json:"modifiers,omitempty"` + Modifiers []ModifierType `json:"modifiers,omitempty"` } type ListOpts struct {