@@ -18,6 +18,7 @@ package v4
1818
1919import (
2020 "fmt"
21+ "os"
2122 "path/filepath"
2223 "strings"
2324
@@ -55,6 +56,8 @@ func GenerateV4(kbc *utils.TestContext) {
5556 err = utils .ImplementWebhooks (webhookFilePath , strings .ToLower (kbc .Kind ))
5657 ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
5758
59+ scaffoldConversionWebhook (kbc )
60+
5861 ExpectWithOffset (1 , pluginutil .UncommentCode (
5962 filepath .Join (kbc .Dir , "config" , "default" , "kustomization.yaml" ),
6063 "#- ../certmanager" , "#" )).To (Succeed ())
@@ -92,6 +95,8 @@ func GenerateV4WithoutMetrics(kbc *utils.TestContext) {
9295 err = utils .ImplementWebhooks (webhookFilePath , strings .ToLower (kbc .Kind ))
9396 ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
9497
98+ scaffoldConversionWebhook (kbc )
99+
95100 ExpectWithOffset (1 , pluginutil .UncommentCode (
96101 filepath .Join (kbc .Dir , "config" , "default" , "kustomization.yaml" ),
97102 "#- ../certmanager" , "#" )).To (Succeed ())
@@ -153,6 +158,8 @@ func GenerateV4WithNetworkPolicies(kbc *utils.TestContext) {
153158 err = utils .ImplementWebhooks (webhookFilePath , strings .ToLower (kbc .Kind ))
154159 ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
155160
161+ scaffoldConversionWebhook (kbc )
162+
156163 ExpectWithOffset (1 , pluginutil .UncommentCode (
157164 filepath .Join (kbc .Dir , "config" , "default" , "kustomization.yaml" ),
158165 "#- ../certmanager" , "#" )).To (Succeed ())
@@ -368,3 +375,114 @@ func uncommentPodStandards(kbc *utils.TestContext) {
368375 ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
369376 }
370377}
378+
379+ // scaffoldConversionWebhook sets up conversion webhooks for testing the ConversionTest API
380+ func scaffoldConversionWebhook (kbc * utils.TestContext ) {
381+ By ("scaffolding conversion webhooks for testing ConversionTest v1 to v2 conversion" )
382+
383+ // Create API for v1 (hub) with conversion enabled
384+ err := kbc .CreateAPI (
385+ "--group" , kbc .Group ,
386+ "--version" , "v1" ,
387+ "--kind" , "ConversionTest" ,
388+ "--controller=true" ,
389+ "--resource=true" ,
390+ "--make=false" ,
391+ )
392+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred (), "failed to create v1 API for conversion testing" )
393+
394+ // Create API for v2 (spoke) without a controller
395+ err = kbc .CreateAPI (
396+ "--group" , kbc .Group ,
397+ "--version" , "v2" ,
398+ "--kind" , "ConversionTest" ,
399+ "--controller=false" ,
400+ "--resource=true" ,
401+ "--make=false" ,
402+ )
403+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred (), "failed to create v2 API for conversion testing" )
404+
405+ // Create the conversion webhook for v1
406+ By ("setting up the conversion webhook for v1" )
407+ err = kbc .CreateWebhook (
408+ "--group" , kbc .Group ,
409+ "--version" , "v1" ,
410+ "--kind" , "ConversionTest" ,
411+ "--conversion" ,
412+ "--make=false" ,
413+ )
414+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred (), "failed to create conversion webhook for v1" )
415+
416+ // Insert Size field in v1
417+ By ("implementing the size spec in v1" )
418+ ExpectWithOffset (1 , pluginutil .InsertCode (
419+ filepath .Join (kbc .Dir , "api" , "v1" , "conversiontest_types.go" ),
420+ "Foo string `json:\" foo,omitempty\" `" ,
421+ "\n \t Size int `json:\" size,omitempty\" ` // Number of desired instances" ,
422+ )).NotTo (HaveOccurred (), "failed to add size spec to conversiontest_types v1" )
423+
424+ // Insert Replicas field in v2
425+ By ("implementing the replicas spec in v2" )
426+ ExpectWithOffset (1 , pluginutil .InsertCode (
427+ filepath .Join (kbc .Dir , "api" , "v2" , "conversiontest_types.go" ),
428+ "Foo string `json:\" foo,omitempty\" `" ,
429+ "\n \t Replicas int `json:\" replicas,omitempty\" ` // Number of replicas" ,
430+ )).NotTo (HaveOccurred (), "failed to add replicas spec to conversiontest_types v2" )
431+
432+ // TODO: Remove the code bellow when we have hub and spoke scaffolded by
433+ // Kubebuilder. Intead of create the file we will replace the TODO(user)
434+ // with the code implementation.
435+ By ("implementing markers" )
436+ ExpectWithOffset (1 , pluginutil .InsertCode (
437+ filepath .Join (kbc .Dir , "api" , "v1" , "conversiontest_types.go" ),
438+ "// +kubebuilder:object:root=true\n // +kubebuilder:subresource:status" ,
439+ "\n // +kubebuilder:storageversion\n // +kubebuilder:conversion:hub\n " ,
440+ )).NotTo (HaveOccurred (), "failed to add markers to conversiontest_types v1" )
441+
442+ // Create the hub conversion file in v1
443+ By ("creating the conversion implementation in v1 as hub" )
444+ err = os .WriteFile (filepath .Join (kbc .Dir , "api" , "v1" , "conversiontest_conversion.go" ), []byte (`
445+ package v1
446+
447+ // ConversionTest defines the hub conversion logic.
448+ // Implement the Hub interface to signal that v1 is the hub version.
449+ func (*ConversionTest) Hub() {}
450+ ` ), 0644 )
451+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred (), "failed to create hub conversion file in v1" )
452+
453+ // Create the conversion file in v2
454+ By ("creating the conversion implementation in v2" )
455+ err = os .WriteFile (filepath .Join (kbc .Dir , "api" , "v2" , "conversiontest_conversion.go" ), []byte (`
456+ package v2
457+
458+ import (
459+ "log"
460+
461+ "sigs.k8s.io/controller-runtime/pkg/conversion"
462+ v1 "sigs.k8s.io/kubebuilder/v4/api/v1"
463+ )
464+
465+ // ConvertTo converts this ConversionTest to the Hub version (v1).
466+ func (src *ConversionTest) ConvertTo(dstRaw conversion.Hub) error {
467+ dst := dstRaw.(*v1.ConversionTest)
468+ log.Printf("Converting from %T to %T", src.APIVersion, dst.APIVersion)
469+
470+ // Implement conversion logic from v2 to v1
471+ dst.Spec.Size = src.Spec.Replicas // Convert replicas in v2 to size in v1
472+
473+ return nil
474+ }
475+
476+ // ConvertFrom converts the Hub version (v1) to this ConversionTest (v2).
477+ func (dst *ConversionTest) ConvertFrom(srcRaw conversion.Hub) error {
478+ src := srcRaw.(*v1.ConversionTest)
479+ log.Printf("Converting from %T to %T", src.APIVersion, dst.APIVersion)
480+
481+ // Implement conversion logic from v1 to v2
482+ dst.Spec.Replicas = src.Spec.Size // Convert size in v1 to replicas in v2
483+
484+ return nil
485+ }
486+ ` ), 0644 )
487+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred (), "failed to create conversion file in v2" )
488+ }
0 commit comments