diff --git a/vendor.conf b/vendor.conf index 4366f6fc..267b407b 100644 --- a/vendor.conf +++ b/vendor.conf @@ -5,4 +5,4 @@ k8s.io/kubernetes v1.8.3 bitbucket.org/ww/goautoneg a547fc61f48d567d5b4ec6f8aee5573d8efce11d https://github.com/rancher/goautoneg.git golang.org/x/sync fd80eb99c8f653c847d294a001bdf2a3a6f768f5 -github.com/rancher/norman 41c044bb256b54652f7fae51fde7c45cb6c4ccb9 +github.com/rancher/norman d20a37adbef4e306cb354ad643b2c2d9b1d8a403 diff --git a/vendor/github.com/rancher/norman/generator/generator.go b/vendor/github.com/rancher/norman/generator/generator.go index 41222513..6de26646 100644 --- a/vendor/github.com/rancher/norman/generator/generator.go +++ b/vendor/github.com/rancher/norman/generator/generator.go @@ -122,6 +122,21 @@ func getResourceActions(schema *types.Schema, schemas *types.Schemas) map[string return result } +func getCollectionActions(schema *types.Schema, schemas *types.Schemas) map[string]types.Action { + result := map[string]types.Action{} + for name, action := range schema.CollectionActions { + if action.Output != "" { + output := strings.TrimSuffix(action.Output, "Collection") + if schemas.Schema(&schema.Version, output) != nil { + result[name] = action + } + } else { + result[name] = action + } + } + return result +} + func generateType(outputDir string, schema *types.Schema, schemas *types.Schemas) error { filePath := strings.ToLower("zz_generated_" + addUnderscore(schema.ID) + ".go") output, err := os.Create(path.Join(outputDir, filePath)) @@ -138,9 +153,10 @@ func generateType(outputDir string, schema *types.Schema, schemas *types.Schemas } return typeTemplate.Execute(output, map[string]interface{}{ - "schema": schema, - "structFields": getTypeMap(schema, schemas), - "resourceActions": getResourceActions(schema, schemas), + "schema": schema, + "structFields": getTypeMap(schema, schemas), + "resourceActions": getResourceActions(schema, schemas), + "collectionActions": getCollectionActions(schema, schemas), }) } @@ -224,7 +240,7 @@ func generateScheme(external bool, outputDir string, version *types.APIVersion, if !external { names = append(names, schema.CodeName) } - if schema.CanList(nil) { + if schema.CanList(nil) == nil { names = append(names, schema.CodeName+"List") } } diff --git a/vendor/github.com/rancher/norman/generator/type_template.go b/vendor/github.com/rancher/norman/generator/type_template.go index 7b28fadf..b5a887df 100644 --- a/vendor/github.com/rancher/norman/generator/type_template.go +++ b/vendor/github.com/rancher/norman/generator/type_template.go @@ -41,12 +41,25 @@ type {{.schema.CodeName}}Operations interface { Create(opts *{{.schema.CodeName}}) (*{{.schema.CodeName}}, error) Update(existing *{{.schema.CodeName}}, updates interface{}) (*{{.schema.CodeName}}, error) ByID(id string) (*{{.schema.CodeName}}, error) - Delete(container *{{.schema.CodeName}}) error{{range $key, $value := .resourceActions}} - {{if eq $value.Input "" }} - Action{{$key | capitalize}} (*{{$.schema.CodeName}}) (*{{.Output | capitalize}}, error) - {{else}} - Action{{$key | capitalize}} (*{{$.schema.CodeName}}, *{{$value.Input | capitalize}}) (*{{.Output | capitalize}}, error) - {{end}}{{end}} + Delete(container *{{.schema.CodeName}}) error + {{range $key, $value := .resourceActions}} + {{if eq $value.Input "" }} + Action{{$key | capitalize}} (*{{$.schema.CodeName}}) (*{{.Output | capitalize}}, error) + {{else}} + Action{{$key | capitalize}} (*{{$.schema.CodeName}}, *{{$value.Input | capitalize}}) (*{{.Output | capitalize}}, error) + {{end}} + {{end}} + {{range $key, $value := .collectionActions}} + {{if (and (eq $value.Input "") (eq $value.Output ""))}} + Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}) (error) + {{else if (and (eq $value.Input "") (ne $value.Output ""))}} + Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}) (*{{.Output | capitalize}}, error) + {{else if (and (ne $value.Input "") (eq $value.Output ""))}} + Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}, input *{{$value.Input | capitalize}}) (error) + {{else}} + Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}, input *{{$value.Input | capitalize}}) (*{{.Output | capitalize}}, error) + {{end}} + {{end}} } func new{{.schema.CodeName}}Client(apiClient *Client) *{{.schema.CodeName}}Client { @@ -109,4 +122,27 @@ func (c *{{.schema.CodeName}}Client) Delete(container *{{.schema.CodeName}}) err return resp, err } {{end}} + +{{range $key, $value := .collectionActions}} + {{if (and (eq $value.Input "") (eq $value.Output ""))}} + func (c *{{$.schema.CodeName}}Client) Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}) (error) { + err := c.apiClient.Ops.DoAction({{$.schema.CodeName}}Type, "{{$key}}", &resource.Resource, nil, nil) + return err + {{else if (and (eq $value.Input "") (ne $value.Output ""))}} + func (c *{{$.schema.CodeName}}Client) Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}) (*{{.Output | capitalize}}, error) { + resp := &{{.Output | capitalize}}{} + err := c.apiClient.Ops.DoAction({{$.schema.CodeName}}Type, "{{$key}}", &resource.Resource, nil, resp) + return resp, err + {{else if (and (ne $value.Input "") (eq $value.Output ""))}} + func (c *{{$.schema.CodeName}}Client) Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}, input *{{$value.Input | capitalize}}) (error) { + err := c.apiClient.Ops.DoAction({{$.schema.CodeName}}Type, "{{$key}}", &resource.Resource, input, nil) + return err + {{else}} + func (c *{{$.schema.CodeName}}Client) Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}, input *{{$value.Input | capitalize}}) (*{{.Output | capitalize}}, error) { + resp := &{{.Output | capitalize}}{} + err := c.apiClient.Ops.DoAction({{$.schema.CodeName}}Type, "{{$key}}", &resource.Resource, input, resp) + return resp, err + {{end}} + } +{{end}} {{end}}` diff --git a/vendor/github.com/rancher/norman/httperror/error.go b/vendor/github.com/rancher/norman/httperror/error.go index c721dfd9..090724cb 100644 --- a/vendor/github.com/rancher/norman/httperror/error.go +++ b/vendor/github.com/rancher/norman/httperror/error.go @@ -34,40 +34,40 @@ var ( ) type ErrorCode struct { - code string + Code string Status int } func (e ErrorCode) String() string { - return fmt.Sprintf("%s %d", e.code, e.Status) + return fmt.Sprintf("%s %d", e.Code, e.Status) } type APIError struct { - code ErrorCode - message string + Code ErrorCode + Message string Cause error - fieldName string + FieldName string } func NewAPIErrorLong(status int, code, message string) error { return NewAPIError(ErrorCode{ - code: code, + Code: code, Status: status, }, message) } func NewAPIError(code ErrorCode, message string) error { return &APIError{ - code: code, - message: message, + Code: code, + Message: message, } } func NewFieldAPIError(code ErrorCode, fieldName, message string) error { return &APIError{ - code: code, - message: message, - fieldName: fieldName, + Code: code, + Message: message, + FieldName: fieldName, } } @@ -76,9 +76,9 @@ func NewFieldAPIError(code ErrorCode, fieldName, message string) error { func WrapFieldAPIError(err error, code ErrorCode, fieldName, message string) error { return &APIError{ Cause: err, - code: code, - message: message, - fieldName: fieldName, + Code: code, + Message: message, + FieldName: fieldName, } } @@ -86,17 +86,17 @@ func WrapFieldAPIError(err error, code ErrorCode, fieldName, message string) err // err WILL NOT be in the API response func WrapAPIError(err error, code ErrorCode, message string) error { return &APIError{ - code: code, - message: message, + Code: code, + Message: message, Cause: err, } } func (a *APIError) Error() string { - if a.fieldName != "" { - return fmt.Sprintf("%s=%s: %s", a.fieldName, a.code, a.message) + if a.FieldName != "" { + return fmt.Sprintf("%s=%s: %s", a.FieldName, a.Code, a.Message) } - return fmt.Sprintf("%s: %s", a.code, a.message) + return fmt.Sprintf("%s: %s", a.Code, a.Message) } func IsAPIError(err error) bool { @@ -106,7 +106,7 @@ func IsAPIError(err error) bool { func IsConflict(err error) bool { if apiError, ok := err.(*APIError); ok { - return apiError.code.Status == 409 + return apiError.Code.Status == 409 } return false diff --git a/vendor/github.com/rancher/norman/httperror/handler.go b/vendor/github.com/rancher/norman/httperror/handler.go deleted file mode 100644 index 3db377dc..00000000 --- a/vendor/github.com/rancher/norman/httperror/handler.go +++ /dev/null @@ -1,40 +0,0 @@ -package httperror - -import ( - "github.com/rancher/norman/types" - "github.com/sirupsen/logrus" -) - -func ErrorHandler(request *types.APIContext, err error) { - var error *APIError - if apiError, ok := err.(*APIError); ok { - if apiError.Cause != nil { - logrus.Errorf("API error response %v for %v %v. Cause: %v", apiError.code.Status, request.Request.Method, - request.Request.RequestURI, apiError.Cause) - } - error = apiError - } else { - logrus.Errorf("Unknown error: %v", err) - error = &APIError{ - code: ServerError, - message: err.Error(), - } - } - - data := toError(error) - request.WriteResponse(error.code.Status, data) -} - -func toError(apiError *APIError) map[string]interface{} { - e := map[string]interface{}{ - "type": "/meta/schemas/error", - "status": apiError.code.Status, - "code": apiError.code.code, - "message": apiError.message, - } - if apiError.fieldName != "" { - e["fieldName"] = apiError.fieldName - } - - return e -} diff --git a/vendor/github.com/rancher/norman/types/mapper/metadata.go b/vendor/github.com/rancher/norman/types/mapper/metadata.go index e2f8b76d..130786c5 100644 --- a/vendor/github.com/rancher/norman/types/mapper/metadata.go +++ b/vendor/github.com/rancher/norman/types/mapper/metadata.go @@ -8,7 +8,6 @@ func NewMetadataMapper() types.Mapper { return types.Mappers{ ChangeType{Field: "name", Type: "dnsLabel"}, Drop{Field: "generateName"}, - Drop{Field: "selfLink"}, Move{From: "uid", To: "uuid"}, Drop{Field: "resourceVersion"}, Drop{Field: "generation"}, diff --git a/vendor/github.com/rancher/norman/types/mapper/object.go b/vendor/github.com/rancher/norman/types/mapper/object.go index 3d752e66..750f8f85 100644 --- a/vendor/github.com/rancher/norman/types/mapper/object.go +++ b/vendor/github.com/rancher/norman/types/mapper/object.go @@ -16,6 +16,7 @@ func NewObject(mappers ...types.Mapper) Object { &ReadOnly{Field: "status", Optional: true, SubFields: true}, Drop{Field: "kind"}, Drop{Field: "apiVersion"}, + Move{From: "selfLink", To: ".selfLink", DestDefined: true}, &Scope{ IfNot: types.NamespaceScope, Mappers: []types.Mapper{ diff --git a/vendor/github.com/rancher/norman/types/reflection.go b/vendor/github.com/rancher/norman/types/reflection.go index 1935ab7a..263566b0 100644 --- a/vendor/github.com/rancher/norman/types/reflection.go +++ b/vendor/github.com/rancher/norman/types/reflection.go @@ -151,7 +151,7 @@ func (s *Schemas) importType(version *APIVersion, t reflect.Type, overrides ...r mappers := s.mapper(&schema.Version, schema.ID) if s.DefaultMappers != nil { - if schema.CanList(nil) { + if schema.CanList(nil) == nil { mappers = append(s.DefaultMappers(), mappers...) } } @@ -175,7 +175,7 @@ func (s *Schemas) importType(version *APIVersion, t reflect.Type, overrides ...r mapper := &typeMapper{ Mappers: mappers, - root: schema.CanList(nil), + root: schema.CanList(nil) == nil, } if err := mapper.ModifySchema(schema, s); err != nil { diff --git a/vendor/github.com/rancher/norman/types/schema_funcs.go b/vendor/github.com/rancher/norman/types/schema_funcs.go index a6f26b9d..f104728a 100644 --- a/vendor/github.com/rancher/norman/types/schema_funcs.go +++ b/vendor/github.com/rancher/norman/types/schema_funcs.go @@ -3,6 +3,7 @@ package types import ( "net/http" + "github.com/rancher/norman/httperror" "github.com/rancher/norman/types/slice" ) @@ -21,37 +22,52 @@ func (v *APIVersion) Equals(other *APIVersion) bool { v.Path == other.Path } -func (s *Schema) CanList(context *APIContext) bool { +func (s *Schema) CanList(context *APIContext) error { if context == nil { - return slice.ContainsString(s.CollectionMethods, http.MethodGet) + if slice.ContainsString(s.CollectionMethods, http.MethodGet) { + return nil + } + return httperror.NewAPIError(httperror.PermissionDenied, "can not list "+s.ID) } return context.AccessControl.CanList(context, s) } -func (s *Schema) CanGet(context *APIContext) bool { +func (s *Schema) CanGet(context *APIContext) error { if context == nil { - return slice.ContainsString(s.ResourceMethods, http.MethodGet) + if slice.ContainsString(s.ResourceMethods, http.MethodGet) { + return nil + } + return httperror.NewAPIError(httperror.PermissionDenied, "can not get "+s.ID) } return context.AccessControl.CanGet(context, s) } -func (s *Schema) CanCreate(context *APIContext) bool { +func (s *Schema) CanCreate(context *APIContext) error { if context == nil { - return slice.ContainsString(s.CollectionMethods, http.MethodPost) + if slice.ContainsString(s.CollectionMethods, http.MethodPost) { + return nil + } + return httperror.NewAPIError(httperror.PermissionDenied, "can not create "+s.ID) } return context.AccessControl.CanCreate(context, s) } -func (s *Schema) CanUpdate(context *APIContext) bool { +func (s *Schema) CanUpdate(context *APIContext) error { if context == nil { - return slice.ContainsString(s.ResourceMethods, http.MethodPut) + if slice.ContainsString(s.ResourceMethods, http.MethodPut) { + return nil + } + return httperror.NewAPIError(httperror.PermissionDenied, "can not update "+s.ID) } return context.AccessControl.CanUpdate(context, nil, s) } -func (s *Schema) CanDelete(context *APIContext) bool { +func (s *Schema) CanDelete(context *APIContext) error { if context == nil { - return slice.ContainsString(s.ResourceMethods, http.MethodDelete) + if slice.ContainsString(s.ResourceMethods, http.MethodDelete) { + return nil + } + return httperror.NewAPIError(httperror.PermissionDenied, "can not delete "+s.ID) } return context.AccessControl.CanDelete(context, nil, s) } diff --git a/vendor/github.com/rancher/norman/types/server_types.go b/vendor/github.com/rancher/norman/types/server_types.go index 74c6c89a..f58c9915 100644 --- a/vendor/github.com/rancher/norman/types/server_types.go +++ b/vendor/github.com/rancher/norman/types/server_types.go @@ -69,11 +69,11 @@ type ResponseWriter interface { } type AccessControl interface { - CanCreate(apiContext *APIContext, schema *Schema) bool - CanList(apiContext *APIContext, schema *Schema) bool - CanGet(apiContext *APIContext, schema *Schema) bool - CanUpdate(apiContext *APIContext, obj map[string]interface{}, schema *Schema) bool - CanDelete(apiContext *APIContext, obj map[string]interface{}, schema *Schema) bool + CanCreate(apiContext *APIContext, schema *Schema) error + CanList(apiContext *APIContext, schema *Schema) error + CanGet(apiContext *APIContext, schema *Schema) error + CanUpdate(apiContext *APIContext, obj map[string]interface{}, schema *Schema) error + CanDelete(apiContext *APIContext, obj map[string]interface{}, schema *Schema) error Filter(apiContext *APIContext, schema *Schema, obj map[string]interface{}, context map[string]string) map[string]interface{} FilterList(apiContext *APIContext, schema *Schema, obj []map[string]interface{}, context map[string]string) []map[string]interface{} @@ -184,6 +184,7 @@ type URLBuilder interface { FilterLink(schema *Schema, fieldName string, value string) string Action(action string, resource *RawResource) string ResourceLinkByID(schema *Schema, id string) string + ActionLinkByID(schema *Schema, id string, action string) string } type StorageContext string