Skip to content

Commit edd1837

Browse files
committed
mockkubeapiserver: Add basic CRD handling
When a user creates a CRD, register it as a recognized type.
1 parent a32093e commit edd1837

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

mockkubeapiserver/apiserver.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func (s *MockKubeAPIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
8989
}
9090
}
9191

92-
klog.Infof("kubeapiserver request: %s %s", r.Method, r.URL)
92+
klog.V(4).Infof("kubeapiserver request: %s %s", r.Method, r.URL)
9393

9494
path := r.URL.Path
9595
tokens := strings.Split(strings.Trim(path, "/"), "/")

mockkubeapiserver/controllers.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@ limitations under the License.
1717
package mockkubeapiserver
1818

1919
import (
20+
"fmt"
21+
22+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2023
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2124
"k8s.io/apimachinery/pkg/runtime/schema"
25+
"k8s.io/apimachinery/pkg/types"
26+
"k8s.io/klog/v2"
2227
)
2328

2429
func (s *MemoryStorage) objectChanged(u *unstructured.Unstructured) {
@@ -27,6 +32,10 @@ func (s *MemoryStorage) objectChanged(u *unstructured.Unstructured) {
2732
switch gvk.GroupKind() {
2833
case schema.GroupKind{Kind: "Namespace"}:
2934
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+
}
3039
}
3140
}
3241

@@ -57,3 +66,87 @@ func (s *MemoryStorage) namespaceChanged(u *unstructured.Unstructured) {
5766
unstructured.SetNestedSlice(u.Object, finalizers, "spec", "finalizers")
5867
}
5968
}
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

Comments
 (0)