mirror of
https://github.com/k3s-io/k3s.git
synced 2024-06-07 19:41:36 +00:00
201 lines
4.1 KiB
Go
201 lines
4.1 KiB
Go
package schemas
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/rancher/wrangler/pkg/data/convert"
|
|
"github.com/rancher/wrangler/pkg/merr"
|
|
"github.com/rancher/wrangler/pkg/name"
|
|
)
|
|
|
|
type SchemasInitFunc func(*Schemas) *Schemas
|
|
|
|
type MapperFactory func() Mapper
|
|
|
|
type FieldMapperFactory func(fieldName string, args ...string) Mapper
|
|
|
|
type Schemas struct {
|
|
sync.Mutex
|
|
processingTypes map[reflect.Type]*Schema
|
|
typeNames map[reflect.Type]string
|
|
schemasByID map[string]*Schema
|
|
mappers map[string][]Mapper
|
|
embedded map[string]*Schema
|
|
fieldMappers map[string]FieldMapperFactory
|
|
DefaultMapper MapperFactory
|
|
DefaultPostMapper MapperFactory
|
|
schemas []*Schema
|
|
}
|
|
|
|
func EmptySchemas() *Schemas {
|
|
s, _ := NewSchemas()
|
|
return s
|
|
}
|
|
|
|
func NewSchemas(schemas ...*Schemas) (*Schemas, error) {
|
|
var (
|
|
errs []error
|
|
)
|
|
|
|
s := &Schemas{
|
|
processingTypes: map[reflect.Type]*Schema{},
|
|
typeNames: map[reflect.Type]string{},
|
|
schemasByID: map[string]*Schema{},
|
|
mappers: map[string][]Mapper{},
|
|
embedded: map[string]*Schema{},
|
|
}
|
|
|
|
for _, schemas := range schemas {
|
|
if _, err := s.AddSchemas(schemas); err != nil {
|
|
errs = append(errs, err)
|
|
}
|
|
}
|
|
|
|
return s, merr.NewErrors(errs...)
|
|
}
|
|
|
|
func (s *Schemas) Init(initFunc SchemasInitFunc) *Schemas {
|
|
return initFunc(s)
|
|
}
|
|
|
|
func (s *Schemas) MustAddSchemas(schema *Schemas) *Schemas {
|
|
s, err := s.AddSchemas(schema)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (s *Schemas) AddSchemas(schema *Schemas) (*Schemas, error) {
|
|
var errs []error
|
|
for _, schema := range schema.Schemas() {
|
|
if err := s.AddSchema(*schema); err != nil {
|
|
errs = append(errs, err)
|
|
}
|
|
}
|
|
return s, merr.NewErrors(errs...)
|
|
}
|
|
|
|
func (s *Schemas) RemoveSchema(schema Schema) *Schemas {
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
return s.doRemoveSchema(schema)
|
|
}
|
|
|
|
func (s *Schemas) doRemoveSchema(schema Schema) *Schemas {
|
|
delete(s.schemasByID, schema.ID)
|
|
return s
|
|
}
|
|
|
|
func (s *Schemas) MustAddSchema(schema Schema) *Schemas {
|
|
err := s.AddSchema(schema)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (s *Schemas) AddSchema(schema Schema) error {
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
return s.doAddSchema(schema)
|
|
}
|
|
|
|
func (s *Schemas) doAddSchema(schema Schema) error {
|
|
if err := s.setupDefaults(&schema); err != nil {
|
|
return err
|
|
}
|
|
|
|
existing, ok := s.schemasByID[schema.ID]
|
|
if ok {
|
|
*existing = schema
|
|
} else {
|
|
s.schemasByID[schema.ID] = &schema
|
|
s.schemas = append(s.schemas, &schema)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *Schemas) setupDefaults(schema *Schema) (err error) {
|
|
if schema.ID == "" {
|
|
return fmt.Errorf("ID is not set on schema: %v", schema)
|
|
}
|
|
if schema.PluralName == "" {
|
|
schema.PluralName = name.GuessPluralName(schema.ID)
|
|
}
|
|
if schema.CodeName == "" {
|
|
schema.CodeName = convert.Capitalize(schema.ID)
|
|
}
|
|
if schema.CodeNamePlural == "" {
|
|
schema.CodeNamePlural = name.GuessPluralName(schema.CodeName)
|
|
}
|
|
if err := s.assignMappers(schema); err != nil {
|
|
return err
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Schemas) AddFieldMapper(name string, factory FieldMapperFactory) *Schemas {
|
|
if s.fieldMappers == nil {
|
|
s.fieldMappers = map[string]FieldMapperFactory{}
|
|
}
|
|
s.fieldMappers[name] = factory
|
|
return s
|
|
}
|
|
|
|
func (s *Schemas) AddMapper(schemaID string, mapper Mapper) *Schemas {
|
|
s.mappers[schemaID] = append(s.mappers[schemaID], mapper)
|
|
return s
|
|
}
|
|
|
|
func (s *Schemas) Schemas() []*Schema {
|
|
return s.schemas
|
|
}
|
|
|
|
func (s *Schemas) SchemasByID() map[string]*Schema {
|
|
return s.schemasByID
|
|
}
|
|
|
|
func (s *Schemas) mapper(schemaID string) []Mapper {
|
|
return s.mappers[schemaID]
|
|
}
|
|
|
|
func (s *Schemas) Schema(name string) *Schema {
|
|
return s.doSchema(name, true)
|
|
}
|
|
|
|
func (s *Schemas) doSchema(name string, lock bool) *Schema {
|
|
if lock {
|
|
s.Lock()
|
|
}
|
|
schema, ok := s.schemasByID[name]
|
|
if lock {
|
|
s.Unlock()
|
|
}
|
|
if ok {
|
|
return schema
|
|
}
|
|
|
|
for _, check := range s.schemas {
|
|
if strings.EqualFold(check.ID, name) || strings.EqualFold(check.PluralName, name) {
|
|
return check
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
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
|
|
}
|