@@ -17,8 +17,13 @@ limitations under the License.
17
17
package mockkubeapiserver
18
18
19
19
import (
20
+ "fmt"
21
+
22
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
20
23
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
21
24
"k8s.io/apimachinery/pkg/runtime/schema"
25
+ "k8s.io/apimachinery/pkg/types"
26
+ "k8s.io/klog/v2"
22
27
)
23
28
24
29
func (s * MemoryStorage ) objectChanged (u * unstructured.Unstructured ) {
@@ -27,6 +32,10 @@ func (s *MemoryStorage) objectChanged(u *unstructured.Unstructured) {
27
32
switch gvk .GroupKind () {
28
33
case schema.GroupKind {Kind : "Namespace" }:
29
34
s .namespaceChanged (u )
35
+ case schema.GroupKind {Group : "apiextensions.k8s.io" , Kind : "CustomResourceDefinition" }:
36
+ if err := s .crdChanged (u ); err != nil {
37
+ klog .Warningf ("crd change was invalid: %v" , err )
38
+ }
30
39
}
31
40
}
32
41
@@ -57,3 +66,87 @@ func (s *MemoryStorage) namespaceChanged(u *unstructured.Unstructured) {
57
66
unstructured .SetNestedSlice (u .Object , finalizers , "spec" , "finalizers" )
58
67
}
59
68
}
69
+
70
+ func (s * MemoryStorage ) crdChanged (u * unstructured.Unstructured ) error {
71
+ // TODO: Deleted / changed CRDs
72
+
73
+ group , _ , _ := unstructured .NestedString (u .Object , "spec" , "group" )
74
+ if group == "" {
75
+ return fmt .Errorf ("spec.group not set" )
76
+ }
77
+
78
+ kind , _ , _ := unstructured .NestedString (u .Object , "spec" , "names" , "kind" )
79
+ if kind == "" {
80
+ return fmt .Errorf ("spec.names.kind not set" )
81
+ }
82
+
83
+ resource , _ , _ := unstructured .NestedString (u .Object , "spec" , "names" , "plural" )
84
+ if resource == "" {
85
+ return fmt .Errorf ("spec.names.plural not set" )
86
+ }
87
+
88
+ scope , _ , _ := unstructured .NestedString (u .Object , "spec" , "scope" )
89
+ if scope == "" {
90
+ return fmt .Errorf ("spec.scope not set" )
91
+ }
92
+
93
+ versionsObj , found , _ := unstructured .NestedFieldNoCopy (u .Object , "spec" , "versions" )
94
+ if ! found {
95
+ return fmt .Errorf ("spec.versions not set" )
96
+ }
97
+
98
+ versions , ok := versionsObj .([]interface {})
99
+ if ! ok {
100
+ return fmt .Errorf ("spec.versions not a slice" )
101
+ }
102
+
103
+ for _ , versionObj := range versions {
104
+ version , ok := versionObj .(map [string ]interface {})
105
+ if ! ok {
106
+ return fmt .Errorf ("spec.versions element not an object" )
107
+ }
108
+
109
+ versionName , _ , _ := unstructured .NestedString (version , "name" )
110
+ if versionName == "" {
111
+ return fmt .Errorf ("version name not set" )
112
+ }
113
+ gvk := schema.GroupVersionKind {Group : group , Version : versionName , Kind : kind }
114
+ gvr := gvk .GroupVersion ().WithResource (resource )
115
+ gr := gvr .GroupResource ()
116
+
117
+ storage := & resourceStorage {
118
+ GroupResource : gr ,
119
+ objects : make (map [types.NamespacedName ]* unstructured.Unstructured ),
120
+ }
121
+
122
+ // TODO: share storage across different versions
123
+ s .resourceStorages [gr ] = storage
124
+
125
+ r := & ResourceInfo {
126
+ API : metav1.APIResource {
127
+ Name : resource ,
128
+ Group : gvk .Group ,
129
+ Version : gvk .Version ,
130
+ Kind : gvk .Kind ,
131
+ },
132
+ GVK : gvk ,
133
+ GVR : gvr ,
134
+ storage : storage ,
135
+ }
136
+ r .ListGVK = gvk .GroupVersion ().WithKind (gvk .Kind + "List" )
137
+
138
+ // TODO: Set r.TypeInfo from schema
139
+
140
+ switch scope {
141
+ case "Namespaced" :
142
+ r .API .Namespaced = true
143
+ case "Cluster" :
144
+ r .API .Namespaced = false
145
+ default :
146
+ return fmt .Errorf ("scope %q is not recognized" , scope )
147
+ }
148
+
149
+ s .schema .resources = append (s .schema .resources , r )
150
+ }
151
+ return nil
152
+ }
0 commit comments