schema.go raw
1 package schema
2
3 import (
4 "encoding/json"
5 "fmt"
6 "reflect"
7
8 "github.com/mimuret/golang-iij-dpf/pkg/api"
9 "github.com/mimuret/golang-iij-dpf/pkg/apis"
10 "github.com/mimuret/golang-iij-dpf/pkg/meta"
11 )
12
13 var SchemaSet = NewSchemaSet()
14
15 type Register struct {
16 Group string
17 }
18
19 func NewRegister(groupName string) *Register {
20 return &Register{Group: groupName}
21 }
22
23 func (r *Register) Add(items ...apis.Spec) {
24 SchemaSet.Add(r.Group, items)
25 }
26
27 func NewSchemaSet() *schemaSet {
28 return &schemaSet{}
29 }
30
31 type schemaSet map[string]*schema
32
33 func (s schemaSet) Add(groupName string, items []apis.Spec) {
34 if _, ok := s[groupName]; !ok {
35 s[groupName] = &schema{group: groupName, objectMap: make(map[string]apis.Spec)}
36 }
37 s[groupName].Add(items)
38 }
39
40 type schema struct {
41 group string
42 objectMap map[string]apis.Spec
43 }
44
45 func (s *schema) Add(items []apis.Spec) {
46 for _, item := range items {
47 st := reflect.TypeOf(item)
48 if st.Kind() != reflect.Ptr {
49 name := st.Elem().Name()
50 panic(fmt.Sprintf("schema.Add name: `%s` is not ptr %v", name, item))
51 }
52 name := st.Elem().Name()
53 if v, ok := s.objectMap[name]; ok {
54 panic(fmt.Sprintf("schema.Add name: `%s` is duplicated, old: %v, new: %v", name, v, item))
55 }
56 s.objectMap[name] = item
57 }
58 }
59
60 func (s schemaSet) Parse(bs []byte) (apis.Spec, error) {
61 kv := &meta.KindVersion{}
62 if err := json.Unmarshal(bs, kv); err != nil {
63 return nil, fmt.Errorf("failed to parse json: %w", err)
64 }
65 if kv.Kind == "" {
66 return nil, fmt.Errorf("kind value is not exist")
67 }
68 if kv.APIVersion == "" {
69 return nil, fmt.Errorf("apiVersion value is not exist")
70 }
71 gs, ok := s[kv.APIVersion]
72 if !ok {
73 return nil, fmt.Errorf("apiVersion `%s` is not support", kv.APIVersion)
74 }
75
76 spec, ok := gs.objectMap[kv.Kind]
77 if !ok {
78 return nil, fmt.Errorf("kind value `%s` is not supported", kv.Kind)
79 }
80 obj, ok := spec.DeepCopyObject().(apis.Spec)
81 if !ok {
82 return nil, fmt.Errorf("kind value `%s` DeepCopyObject is invalid", kv.Kind)
83 }
84 if err := api.UnMarshalInput(bs, obj); err != nil {
85 return nil, fmt.Errorf("failed to parse resource: %w", err)
86 }
87 return obj, nil
88 }
89