@@ -12,6 +12,7 @@ import (
12
12
"os/user"
13
13
"path/filepath"
14
14
"testing"
15
+ "time"
15
16
16
17
. "github.com/onsi/ginkgo/v2"
17
18
. "github.com/onsi/gomega"
45
46
gvrEvent schema.GroupVersionResource
46
47
gvrConfigurationPolicy schema.GroupVersionResource
47
48
gvrConstraintTemplate schema.GroupVersionResource
49
+ gvrCRD schema.GroupVersionResource
48
50
kubeconfigHub string
49
51
kubeconfigManaged string
50
52
defaultTimeoutSeconds int
@@ -106,6 +108,12 @@ var _ = BeforeSuite(func() {
106
108
Version : "v1" ,
107
109
Resource : "constrainttemplates" ,
108
110
}
111
+ gvrCRD = schema.GroupVersionResource {
112
+ Group : "apiextensions.k8s.io" ,
113
+ Version : "v1" ,
114
+ Resource : "customresourcedefinitions" ,
115
+ }
116
+
109
117
clientHub = NewKubeClient ("" , kubeconfigHub , "" )
110
118
clientHubDynamic = NewKubeClientDynamic ("" , kubeconfigHub , "" )
111
119
clientManaged = NewKubeClient ("" , kubeconfigManaged , "" )
@@ -174,6 +182,50 @@ var _ = BeforeSuite(func() {
174
182
ClientSet : kubernetes .NewForConfigOrDie (managedConfig ),
175
183
ControllerName : "status-sync-controller-test" ,
176
184
}
185
+
186
+ if ! gkSyncDisabled {
187
+ // This section deletes and then re-creates the Gatekeeper ConstraintTemplate CRD, which
188
+ // should cause the gatekeeper-sync controller to stop and then restart. Tests then verify
189
+ // that gatekeeper-sync is running correctly, ensuring that there is not a bug in the
190
+ // restart procedure.
191
+
192
+ // AI-ASSISTED: The code in this block was based on output from Cursor using claude-4-sonnet.
193
+
194
+ gkCRDName := "constrainttemplates.templates.gatekeeper.sh"
195
+
196
+ By ("Deleting the constrainttemplate CRD to simulate uninstalling Gatekeeper" )
197
+
198
+ originalCRD , err := clientManagedDynamic .Resource (gvrCRD ).Get (context .TODO (), gkCRDName , metav1.GetOptions {})
199
+ Expect (err ).ToNot (HaveOccurred ())
200
+
201
+ err = clientManagedDynamic .Resource (gvrCRD ).Delete (context .TODO (), gkCRDName , metav1.DeleteOptions {})
202
+ Expect (err ).ToNot (HaveOccurred ())
203
+
204
+ Eventually (func () bool {
205
+ _ , err := clientManagedDynamic .Resource (gvrCRD ).Get (
206
+ context .TODO (), gkCRDName , metav1.GetOptions {},
207
+ )
208
+
209
+ return k8serrors .IsNotFound (err )
210
+ }, defaultTimeoutSeconds , 1 ).Should (BeTrue ())
211
+
212
+ By ("Waiting 10 seconds for the manager to detect missing CRD" )
213
+ time .Sleep (10 * time .Second )
214
+
215
+ // Cleanup fields that would cause the Create to fail
216
+ unstructured .RemoveNestedField (originalCRD .Object , "metadata" , "resourceVersion" )
217
+ unstructured .RemoveNestedField (originalCRD .Object , "metadata" , "uid" )
218
+ unstructured .RemoveNestedField (originalCRD .Object , "metadata" , "generation" )
219
+ unstructured .RemoveNestedField (originalCRD .Object , "metadata" , "creationTimestamp" )
220
+ unstructured .RemoveNestedField (originalCRD .Object , "status" )
221
+
222
+ By ("Re-creating the constrainttemplate CRD to simulate re-installing Gatekeeper" )
223
+ _ , err = clientManagedDynamic .Resource (gvrCRD ).Create (context .TODO (), originalCRD , metav1.CreateOptions {})
224
+ Expect (err ).ToNot (HaveOccurred ())
225
+
226
+ By ("Waiting 10 seconds for the manager to detect the fresh CRD" )
227
+ time .Sleep (10 * time .Second )
228
+ }
177
229
})
178
230
179
231
func NewKubeClient (url , kubeconfig , context string ) kubernetes.Interface {
0 commit comments