mirror of
https://github.com/rancher/norman.git
synced 2025-08-16 22:37:07 +00:00
Added enable function to schemas. This allows filtering of schemas which is a required part of feature flagging in rancher. Added addFeature functions to controller template for adding handlers that can be disabled if their associated feature is disabled.
153 lines
4.5 KiB
Go
153 lines
4.5 KiB
Go
package schema
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/rancher/norman/httperror"
|
|
"github.com/rancher/norman/store/empty"
|
|
"github.com/rancher/norman/types"
|
|
"github.com/rancher/norman/types/definition"
|
|
"github.com/rancher/norman/types/slice"
|
|
)
|
|
|
|
type Store struct {
|
|
empty.Store
|
|
}
|
|
|
|
func NewSchemaStore() types.Store {
|
|
return &Store{}
|
|
}
|
|
|
|
func (s *Store) ByID(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) {
|
|
for _, schema := range apiContext.Schemas.SchemasForVersion(*apiContext.Version) {
|
|
if strings.EqualFold(schema.ID, id) {
|
|
if schema.Enabled != nil {
|
|
if !schema.Enabled() {
|
|
return nil, httperror.NewAPIError(httperror.NotFound, "schema disabled")
|
|
}
|
|
}
|
|
|
|
schemaData := map[string]interface{}{}
|
|
|
|
data, err := json.Marshal(s.modifyForAccessControl(apiContext, *schema))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return schemaData, json.Unmarshal(data, &schemaData)
|
|
}
|
|
}
|
|
return nil, httperror.NewAPIError(httperror.NotFound, "no such schema")
|
|
}
|
|
|
|
func (s *Store) modifyForAccessControl(context *types.APIContext, schema types.Schema) *types.Schema {
|
|
var resourceMethods []string
|
|
if slice.ContainsString(schema.ResourceMethods, http.MethodPut) && schema.CanUpdate(context) == nil {
|
|
resourceMethods = append(resourceMethods, http.MethodPut)
|
|
}
|
|
if slice.ContainsString(schema.ResourceMethods, http.MethodDelete) && schema.CanDelete(context) == nil {
|
|
resourceMethods = append(resourceMethods, http.MethodDelete)
|
|
}
|
|
if slice.ContainsString(schema.ResourceMethods, http.MethodGet) && schema.CanGet(context) == nil {
|
|
resourceMethods = append(resourceMethods, http.MethodGet)
|
|
}
|
|
|
|
var collectionMethods []string
|
|
if slice.ContainsString(schema.CollectionMethods, http.MethodPost) && schema.CanCreate(context) == nil {
|
|
collectionMethods = append(collectionMethods, http.MethodPost)
|
|
}
|
|
if slice.ContainsString(schema.CollectionMethods, http.MethodGet) && schema.CanList(context) == nil {
|
|
collectionMethods = append(collectionMethods, http.MethodGet)
|
|
}
|
|
|
|
schema.ResourceMethods = resourceMethods
|
|
schema.CollectionMethods = collectionMethods
|
|
|
|
return &schema
|
|
}
|
|
|
|
func (s *Store) Watch(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) (chan map[string]interface{}, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (s *Store) List(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) ([]map[string]interface{}, error) {
|
|
schemaMap := apiContext.Schemas.SchemasForVersion(*apiContext.Version)
|
|
schemas := make([]*types.Schema, 0, len(schemaMap))
|
|
schemaData := make([]map[string]interface{}, 0, len(schemaMap))
|
|
|
|
included := map[string]bool{}
|
|
|
|
for _, schema := range schemaMap {
|
|
if included[schema.ID] {
|
|
continue
|
|
}
|
|
|
|
if schema.Enabled != nil {
|
|
if !schema.Enabled() {
|
|
continue
|
|
}
|
|
}
|
|
|
|
if schema.CanList(apiContext) == nil || schema.CanGet(apiContext) == nil {
|
|
schemas = s.addSchema(apiContext, schema, schemaMap, schemas, included)
|
|
}
|
|
}
|
|
|
|
data, err := json.Marshal(schemas)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return schemaData, json.Unmarshal(data, &schemaData)
|
|
}
|
|
|
|
func (s *Store) addSchema(apiContext *types.APIContext, schema *types.Schema, schemaMap map[string]*types.Schema, schemas []*types.Schema, included map[string]bool) []*types.Schema {
|
|
included[schema.ID] = true
|
|
schemas = s.traverseAndAdd(apiContext, schema, schemaMap, schemas, included)
|
|
schemas = append(schemas, s.modifyForAccessControl(apiContext, *schema))
|
|
return schemas
|
|
}
|
|
|
|
func (s *Store) traverseAndAdd(apiContext *types.APIContext, schema *types.Schema, schemaMap map[string]*types.Schema, schemas []*types.Schema, included map[string]bool) []*types.Schema {
|
|
for _, field := range schema.ResourceFields {
|
|
t := ""
|
|
subType := field.Type
|
|
for subType != t {
|
|
t = subType
|
|
subType = definition.SubType(t)
|
|
}
|
|
|
|
if refSchema, ok := schemaMap[t]; ok && !included[t] {
|
|
schemas = s.addSchema(apiContext, refSchema, schemaMap, schemas, included)
|
|
}
|
|
}
|
|
|
|
for _, action := range schema.ResourceActions {
|
|
for _, t := range []string{action.Output, action.Input} {
|
|
if t == "" {
|
|
continue
|
|
}
|
|
|
|
if refSchema, ok := schemaMap[t]; ok && !included[t] {
|
|
schemas = s.addSchema(apiContext, refSchema, schemaMap, schemas, included)
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, action := range schema.CollectionActions {
|
|
for _, t := range []string{action.Output, action.Input} {
|
|
if t == "" {
|
|
continue
|
|
}
|
|
|
|
if refSchema, ok := schemaMap[t]; ok && !included[t] {
|
|
schemas = s.addSchema(apiContext, refSchema, schemaMap, schemas, included)
|
|
}
|
|
}
|
|
}
|
|
|
|
return schemas
|
|
}
|