Skip to content

Commit f6a5c89

Browse files
authored
Merge pull request #359 from justinsb/crd_ready
mockkubeapiserver: ensure CRDs become ready
2 parents bdee2d1 + b027d66 commit f6a5c89

File tree

3 files changed

+77
-6
lines changed

3 files changed

+77
-6
lines changed

mockkubeapiserver/apiserver.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func NewMockKubeAPIServer(addr string, options ...Option) (*MockKubeAPIServer, e
5151
}
5252

5353
// These hooks mock behaviour that would otherwise require full controllers
54-
s.storage.AddStorageHook(&hooks.CRDHook{})
54+
s.storage.AddStorageHook(&hooks.CRDHook{Storage: s.storage})
5555
s.storage.AddStorageHook(&hooks.NamespaceHook{})
5656
s.storage.AddStorageHook(&hooks.DeploymentHook{})
5757

mockkubeapiserver/hooks/crd.go

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,92 @@ limitations under the License.
1717
package hooks
1818

1919
import (
20+
"fmt"
21+
2022
"k8s.io/apimachinery/pkg/runtime/schema"
2123
"k8s.io/klog/v2"
2224
"sigs.k8s.io/kubebuilder-declarative-pattern/mockkubeapiserver/storage"
2325
)
2426

2527
// CRDHook implements functionality for CRD objects (the definitions themselves, not instances of CRDs)
2628
type CRDHook struct {
27-
storage storage.Storage
29+
Storage storage.Storage
2830
}
2931

3032
func (s *CRDHook) OnWatchEvent(ev *storage.WatchEvent) {
3133
switch ev.GroupKind() {
3234
case schema.GroupKind{Group: "apiextensions.k8s.io", Kind: "CustomResourceDefinition"}:
3335
// When a CRD is created, we notify the storage layer so it can store instances of the CRD
34-
if err := s.storage.UpdateCRD(ev); err != nil {
36+
if err := s.Storage.UpdateCRD(ev); err != nil {
3537
klog.Warningf("crd change was invalid: %v", err)
3638
}
39+
40+
if err := s.updateCRDConditions(ev); err != nil {
41+
klog.Fatalf("could not update crd status: %v", err)
42+
}
43+
}
44+
}
45+
func (s *CRDHook) updateCRDConditions(ev *storage.WatchEvent) error {
46+
u := ev.Unstructured()
47+
48+
// So that CRDs become ready, we immediately update the status.
49+
// We could do something better here, like e.g. a 1 second pause before changing the status
50+
statusObj := u.Object["status"]
51+
if statusObj == nil {
52+
statusObj = make(map[string]interface{})
53+
u.Object["status"] = statusObj
3754
}
55+
status, ok := statusObj.(map[string]interface{})
56+
if !ok {
57+
return fmt.Errorf("status was of unexpected type %T", statusObj)
58+
}
59+
60+
generation := u.GetGeneration()
61+
if generation == 0 {
62+
generation = 1
63+
u.SetGeneration(generation)
64+
}
65+
66+
var conditions []interface{}
67+
conditions = append(conditions, map[string]interface{}{
68+
"type": "NamesAccepted",
69+
"status": "True",
70+
"reason": "NoConflicts",
71+
"message": "no conflicts found",
72+
})
73+
conditions = append(conditions, map[string]interface{}{
74+
"type": "Established",
75+
"status": "True",
76+
"reason": "InitialNamesAccepted",
77+
"message": "the initial names have been accepted",
78+
})
79+
status["conditions"] = conditions
80+
81+
// TODO: More of status? Here is an example of the full status
82+
// status:
83+
// acceptedNames:
84+
// kind: VolumeSnapshot
85+
// listKind: VolumeSnapshotList
86+
// plural: volumesnapshots
87+
// singular: volumesnapshot
88+
// conditions:
89+
// - lastTransitionTime: "2023-09-21T01:04:36Z"
90+
// message: no conflicts found
91+
// reason: NoConflicts
92+
// status: "True"
93+
// type: NamesAccepted
94+
// - lastTransitionTime: "2023-09-21T01:04:36Z"
95+
// message: the initial names have been accepted
96+
// reason: InitialNamesAccepted
97+
// status: "True"
98+
// type: Established
99+
// - lastTransitionTime: "2023-09-21T01:04:36Z"
100+
// message: approved in https://github.com/kubernetes-csi/external-snapshotter/pull/419
101+
// reason: ApprovedAnnotation
102+
// status: "True"
103+
// type: KubernetesAPIApprovalPolicyConformant
104+
// storedVersions:
105+
// - v1
106+
107+
return nil
38108
}

mockkubeapiserver/storage/memorystorage/crd.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ func (s *MemoryStorage) UpdateCRD(ev *storage.WatchEvent) error {
6262
gr := gvr.GroupResource()
6363

6464
storage := &resourceStorage{
65-
GroupResource: gr,
66-
objects: make(map[types.NamespacedName]*unstructured.Unstructured),
67-
parent: s,
65+
GroupResource: gr,
66+
objects: make(map[types.NamespacedName]*unstructured.Unstructured),
67+
parent: s,
68+
resourceVersionClock: &s.resourceVersionClock,
6869
}
6970

7071
// TODO: share storage across different versions

0 commit comments

Comments
 (0)