11package tests
22
33import (
4+ "bytes"
45 "fmt"
56 "os"
67 "path/filepath"
78 "strings"
89
910 . "github.com/onsi/ginkgo/v2"
1011 . "github.com/onsi/gomega"
12+ yamlpatch "github.com/vmware-archive/yaml-patch"
1113
1214 "github.com/ghodss/yaml"
1315
@@ -139,7 +141,7 @@ func GenerateTestSuite(suiteSpec SuiteSpec) {
139141 })
140142
141143 generateOnCreateTable (suiteSpec .Tests .OnCreate )
142- generateOnUpdateTable (suiteSpec .Tests .OnUpdate )
144+ generateOnUpdateTable (suiteSpec .Tests .OnUpdate , crdFilename )
143145 })
144146 }
145147}
@@ -200,9 +202,10 @@ func generateOnCreateTable(onCreateTests []OnCreateTestSpec) {
200202
201203// generateOnUpdateTable generates a table of tests from the defined OnUpdate tests
202204// within the test suite test spec.
203- func generateOnUpdateTable (onUpdateTests []OnUpdateTestSpec ) {
205+ func generateOnUpdateTable (onUpdateTests []OnUpdateTestSpec , crdFileName string ) {
204206 type onUpdateTableInput struct {
205207 featureGate string
208+ crdPatches []Patch
206209 initial []byte
207210 updated []byte
208211 expected []byte
@@ -211,6 +214,24 @@ func generateOnUpdateTable(onUpdateTests []OnUpdateTestSpec) {
211214 }
212215
213216 var assertOnUpdate interface {} = func (in onUpdateTableInput ) {
217+ var originalCRDObjectKey client.ObjectKey
218+ var originalCRDSpec apiextensionsv1.CustomResourceDefinitionSpec
219+
220+ if len (in .crdPatches ) > 0 {
221+ patchedCRD , err := getPatchedCRD (crdFileName , in .crdPatches )
222+ Expect (err ).ToNot (HaveOccurred (), "could not load patched crd" )
223+
224+ originalCRDObjectKey = objectKey (patchedCRD )
225+
226+ originalCRD := & apiextensionsv1.CustomResourceDefinition {}
227+ Expect (k8sClient .Get (ctx , originalCRDObjectKey , originalCRD ))
228+
229+ originalCRDSpec = * originalCRD .Spec .DeepCopy ()
230+ originalCRD .Spec = patchedCRD .Spec
231+
232+ Expect (k8sClient .Update (ctx , originalCRD )).To (Succeed (), "failed updating patched CRD schema" )
233+ }
234+
214235 initialObj , err := newUnstructuredFrom (in .initial )
215236 Expect (err ).ToNot (HaveOccurred (), "initial data should be a valid Kubernetes YAML resource" )
216237
@@ -227,6 +248,15 @@ func generateOnUpdateTable(onUpdateTests []OnUpdateTestSpec) {
227248 Expect (k8sClient .Status ().Update (ctx , initialObj )).ToNot (HaveOccurred (), "initial object status should update successfully" )
228249 }
229250
251+ if len (in .crdPatches ) > 0 {
252+ originalCRD := & apiextensionsv1.CustomResourceDefinition {}
253+ Expect (k8sClient .Get (ctx , originalCRDObjectKey , originalCRD ))
254+
255+ originalCRD .Spec = originalCRDSpec
256+
257+ Expect (k8sClient .Update (ctx , originalCRD )).To (Succeed ())
258+ }
259+
230260 // Fetch the object we just created from the API.
231261 gotObj := newEmptyUnstructuredFrom (initialObj )
232262 Expect (k8sClient .Get (ctx , objectKey (initialObj ), gotObj ))
@@ -250,7 +280,7 @@ func generateOnUpdateTable(onUpdateTests []OnUpdateTestSpec) {
250280 Expect (err ).To (MatchError (ContainSubstring (in .expectedError )))
251281 return
252282 }
253- Expect (err ).ToNot (HaveOccurred ())
283+ Expect (err ).ToNot (HaveOccurred (), "unexpected error updating spec" )
254284
255285 if updatedObjStatus != nil {
256286 Expect (unstructured .SetNestedField (updatedObj .Object , updatedObjStatus , "status" )).To (Succeed (), "should be able to restore updated status" )
@@ -260,7 +290,7 @@ func generateOnUpdateTable(onUpdateTests []OnUpdateTestSpec) {
260290 Expect (err ).To (MatchError (ContainSubstring (in .expectedStatusError )))
261291 return
262292 }
263- Expect (err ).ToNot (HaveOccurred ())
293+ Expect (err ).ToNot (HaveOccurred (), "unexpected error updating status" )
264294 }
265295
266296 Expect (k8sClient .Get (ctx , objectKey (initialObj ), gotObj ))
@@ -282,6 +312,7 @@ func generateOnUpdateTable(onUpdateTests []OnUpdateTestSpec) {
282312 // Convert the test specs into table entries
283313 for _ , testEntry := range onUpdateTests {
284314 tableEntries = append (tableEntries , Entry (testEntry .Name , onUpdateTableInput {
315+ crdPatches : testEntry .InitialCRDPatches ,
285316 initial : []byte (testEntry .Initial ),
286317 updated : []byte (testEntry .Updated ),
287318 expected : []byte (testEntry .Expected ),
@@ -453,3 +484,35 @@ func getSuiteSpecTestVersion(suiteSpec SuiteSpec) (string, error) {
453484
454485 return version , nil
455486}
487+
488+ func getPatchedCRD (crdFileName string , patches []Patch ) (* apiextensionsv1.CustomResourceDefinition , error ) {
489+ patch := yamlpatch.Patch {}
490+
491+ for _ , p := range patches {
492+ patch = append (patch , yamlpatch.Operation {
493+ Op : yamlpatch .Op (p .Op ),
494+ Path : yamlpatch .OpPath (p .Path ),
495+ Value : yamlpatch .NewNode (p .Value ),
496+ })
497+ }
498+
499+ baseDoc , err := os .ReadFile (crdFileName )
500+ if err != nil {
501+ return nil , fmt .Errorf ("could not read file %q: %w" , crdFileName , err )
502+ }
503+
504+ patchedDoc , err := patch .Apply (baseDoc )
505+ if err != nil {
506+ return nil , fmt .Errorf ("could not apply patch: %w" , err )
507+ }
508+
509+ placeholderWrapper := yamlpatch .NewPlaceholderWrapper ("{{" , "}}" )
510+ patchedData := bytes .NewBuffer (placeholderWrapper .Unwrap (patchedDoc ))
511+
512+ crd := & apiextensionsv1.CustomResourceDefinition {}
513+ if err := yaml .Unmarshal (patchedData .Bytes (), crd ); err != nil {
514+ return nil , fmt .Errorf ("could not unmarshal CRD: %w" , err )
515+ }
516+
517+ return crd , nil
518+ }
0 commit comments