From 8c681722cbffdb8289d41c0e65faf8f79e389113 Mon Sep 17 00:00:00 2001 From: Hans Rakers Date: Mon, 15 Dec 2025 16:12:51 +0100 Subject: [PATCH 1/5] feat: Implement CRD migration --- config/rbac/role.yaml | 24 ++++++++++++++++++++ go.mod | 2 +- main.go | 53 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 55e39c0e..73a61a22 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -24,6 +24,17 @@ rules: - patch - update - watch +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + - customresourcedefinitions/status + verbs: + - get + - list + - patch + - update + - watch - apiGroups: - authentication.k8s.io resources: @@ -78,8 +89,10 @@ rules: - infrastructure.cluster.x-k8s.io resources: - cloudstackaffinitygroups/status + - cloudstackclustertemplates/status - cloudstackisolatednetworks/status - cloudstackmachines/status + - cloudstackmachinestatecheckers/status - cloudstackmachinetemplates/status verbs: - get @@ -95,6 +108,17 @@ rules: - get - patch - update +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - cloudstackclustertemplates + - cloudstackmachinestatecheckers + verbs: + - get + - list + - patch + - update + - watch - apiGroups: - infrastructure.cluster.x-k8s.io resources: diff --git a/go.mod b/go.mod index f781ae64..8452abdb 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( golang.org/x/text v0.28.0 gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.33.3 + k8s.io/apiextensions-apiserver v0.33.3 k8s.io/apimachinery v0.33.3 k8s.io/client-go v0.33.3 k8s.io/component-base v0.33.3 @@ -95,7 +96,6 @@ require ( google.golang.org/protobuf v1.36.6 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - k8s.io/apiextensions-apiserver v0.33.3 // indirect k8s.io/apiserver v0.33.3 // indirect k8s.io/cluster-bootstrap v0.33.3 // indirect k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect diff --git a/main.go b/main.go index 1266befd..686d12e4 100644 --- a/main.go +++ b/main.go @@ -27,6 +27,7 @@ import ( "github.com/spf13/pflag" corev1 "k8s.io/api/core/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" @@ -37,6 +38,7 @@ import ( logsv1 "k8s.io/component-base/logs/api/v1" "k8s.io/klog/v2" clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2" + "sigs.k8s.io/cluster-api/controllers/crdmigrator" "sigs.k8s.io/cluster-api/controllers/remote" "sigs.k8s.io/cluster-api/feature" "sigs.k8s.io/cluster-api/util/flags" @@ -61,6 +63,7 @@ var ( ) func init() { + utilruntime.Must(apiextensionsv1.AddToScheme(scheme)) utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(clusterv1.AddToScheme(scheme)) utilruntime.Must(infrav1beta1.AddToScheme(scheme)) @@ -90,6 +93,7 @@ var ( managerOptions = flags.ManagerOptions{} logOptions = logs.NewOptions() showVersion bool + skipCRDMigrationPhases []string cloudStackClusterConcurrency int cloudStackMachineConcurrency int @@ -180,6 +184,9 @@ func initFlags(fs *pflag.FlagSet) { fs.StringVar(&healthAddr, "health-addr", ":9440", "The address the health endpoint binds to.") + fs.StringArrayVar(&skipCRDMigrationPhases, "skip-crd-migration-phases", []string{}, + "List of CRD migration phases to skip. Valid values are: StorageVersionMigration, CleanupManagedFields.") + fs.BoolVar(&showVersion, "version", false, "Show current version and exit.") flags.AddManagerOptions(fs, &managerOptions) @@ -190,6 +197,11 @@ func initFlags(fs *pflag.FlagSet) { // Add RBAC for the authorized diagnostics endpoint. // +kubebuilder:rbac:groups=authentication.k8s.io,resources=tokenreviews,verbs=create // +kubebuilder:rbac:groups=authorization.k8s.io,resources=subjectaccessreviews,verbs=create +// Setup CRD migrator +// +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch;update;patch +// +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions/status,verbs=get;list;watch;update;patch +// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=cloudstackclusters;cloudstackmachines;cloudstackmachinetemplates;cloudstackclustertemplates;cloudstackfailuredomains;cloudstackisolatednetworks;cloudstackaffinitygroups;cloudstackmachinestatecheckers,verbs=get;list;watch;patch;update +// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=cloudstackclusters/status;cloudstackmachines/status;cloudstackmachinetemplates/status;cloudstackclustertemplates/status;cloudstackfailuredomains/status;cloudstackisolatednetworks/status;cloudstackaffinitygroups/status;cloudstackmachinestatecheckers/status,verbs=get;patch;update func main() { initFlags(pflag.CommandLine) @@ -308,6 +320,47 @@ func setupChecks(mgr ctrl.Manager) { func setupReconcilers(ctx context.Context, mgr manager.Manager) { scopeFactory := scope.NewClientScopeFactory(10) + + crdMigratorConfig := map[client.Object]crdmigrator.ByObjectConfig{ + &infrav1.CloudStackCluster{}: { + UseCache: true, + }, + &infrav1.CloudStackMachine{}: { + UseCache: true, + }, + &infrav1.CloudStackMachineTemplate{}: { + UseCache: true, + }, + &infrav1.CloudStackClusterTemplate{}: { + UseCache: true, + }, + &infrav1.CloudStackFailureDomain{}: { + UseCache: true, + }, + &infrav1.CloudStackIsolatedNetwork{}: { + UseCache: true, + }, + &infrav1.CloudStackAffinityGroup{}: { + UseCache: true, + }, + &infrav1.CloudStackMachineStateChecker{}: { + UseCache: true, + }, + } + crdMigratorSkipPhases := []crdmigrator.Phase{} + for _, p := range skipCRDMigrationPhases { + crdMigratorSkipPhases = append(crdMigratorSkipPhases, crdmigrator.Phase(p)) + } + if err := (&crdmigrator.CRDMigrator{ + Client: mgr.GetClient(), + APIReader: mgr.GetAPIReader(), + SkipCRDMigrationPhases: crdMigratorSkipPhases, + Config: crdMigratorConfig, + }).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil { + setupLog.Error(err, "unable to setup CRD migrator") + os.Exit(1) + } + if err := (&controllers.CloudStackClusterReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), From da10f3701fd8ab1d4bbeecf7e5cbfee71b569a1d Mon Sep 17 00:00:00 2001 From: Hans Rakers Date: Mon, 15 Dec 2025 17:21:48 +0100 Subject: [PATCH 2/5] fix: CRD migration use status for storage version migration --- main.go | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/main.go b/main.go index 686d12e4..f2512e92 100644 --- a/main.go +++ b/main.go @@ -323,28 +323,36 @@ func setupReconcilers(ctx context.Context, mgr manager.Manager) { crdMigratorConfig := map[client.Object]crdmigrator.ByObjectConfig{ &infrav1.CloudStackCluster{}: { - UseCache: true, + UseCache: true, + UseStatusForStorageVersionMigration: true, }, &infrav1.CloudStackMachine{}: { - UseCache: true, + UseCache: true, + UseStatusForStorageVersionMigration: true, }, &infrav1.CloudStackMachineTemplate{}: { - UseCache: true, + UseCache: true, + UseStatusForStorageVersionMigration: true, }, &infrav1.CloudStackClusterTemplate{}: { - UseCache: true, + UseCache: true, + UseStatusForStorageVersionMigration: false, }, &infrav1.CloudStackFailureDomain{}: { - UseCache: true, + UseCache: true, + UseStatusForStorageVersionMigration: true, }, &infrav1.CloudStackIsolatedNetwork{}: { - UseCache: true, + UseCache: true, + UseStatusForStorageVersionMigration: true, }, &infrav1.CloudStackAffinityGroup{}: { - UseCache: true, + UseCache: true, + UseStatusForStorageVersionMigration: true, }, &infrav1.CloudStackMachineStateChecker{}: { - UseCache: true, + UseCache: true, + UseStatusForStorageVersionMigration: true, }, } crdMigratorSkipPhases := []crdmigrator.Phase{} From 6c2a91399dbe9ae06dab862a432fd6f617e84b37 Mon Sep 17 00:00:00 2001 From: Hans Rakers Date: Mon, 15 Dec 2025 17:28:35 +0100 Subject: [PATCH 3/5] fix: CloudStackClusterTemplates does not have a status subresource --- config/rbac/role.yaml | 1 - main.go | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 73a61a22..602b8d67 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -89,7 +89,6 @@ rules: - infrastructure.cluster.x-k8s.io resources: - cloudstackaffinitygroups/status - - cloudstackclustertemplates/status - cloudstackisolatednetworks/status - cloudstackmachines/status - cloudstackmachinestatecheckers/status diff --git a/main.go b/main.go index f2512e92..93ef0bf6 100644 --- a/main.go +++ b/main.go @@ -201,7 +201,7 @@ func initFlags(fs *pflag.FlagSet) { // +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch;update;patch // +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions/status,verbs=get;list;watch;update;patch // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=cloudstackclusters;cloudstackmachines;cloudstackmachinetemplates;cloudstackclustertemplates;cloudstackfailuredomains;cloudstackisolatednetworks;cloudstackaffinitygroups;cloudstackmachinestatecheckers,verbs=get;list;watch;patch;update -// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=cloudstackclusters/status;cloudstackmachines/status;cloudstackmachinetemplates/status;cloudstackclustertemplates/status;cloudstackfailuredomains/status;cloudstackisolatednetworks/status;cloudstackaffinitygroups/status;cloudstackmachinestatecheckers/status,verbs=get;patch;update +// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=cloudstackclusters/status;cloudstackmachines/status;cloudstackmachinetemplates/status;cloudstackfailuredomains/status;cloudstackisolatednetworks/status;cloudstackaffinitygroups/status;cloudstackmachinestatecheckers/status,verbs=get;patch;update func main() { initFlags(pflag.CommandLine) From ecc6c433c63757628154de348d9d8bd508cf5db2 Mon Sep 17 00:00:00 2001 From: Hans Rakers Date: Mon, 15 Dec 2025 21:35:56 +0100 Subject: [PATCH 4/5] chore: add 0.11.x and 0.12.x series to the metadata.yaml --- metadata.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/metadata.yaml b/metadata.yaml index 5f4e11ce..a48fd594 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -6,6 +6,12 @@ apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 kind: Metadata releaseSeries: + - major: 0 + minor: 12 + contract: v1beta1 + - major: 0 + minor: 11 + contract: v1beta1 - major: 0 minor: 10 contract: v1beta1 From cf0377230fb172ed3bbe4e70329e538cb06ddca0 Mon Sep 17 00:00:00 2001 From: Hans Rakers Date: Mon, 15 Dec 2025 21:36:36 +0100 Subject: [PATCH 5/5] chore: Add internal folder to tilt live reload deps --- tilt-provider.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tilt-provider.json b/tilt-provider.json index 46ac7e04..32bf7603 100644 --- a/tilt-provider.json +++ b/tilt-provider.json @@ -10,7 +10,7 @@ "go.sum", "api", "cmd", - "controllers", + "internal", "pkg" ] }