@@ -28,6 +28,7 @@ import (
2828 // +kubebuilder:scaffold:imports
2929 "github.com/spf13/pflag"
3030
31+ apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
3132 "k8s.io/apimachinery/pkg/runtime"
3233 utilruntime "k8s.io/apimachinery/pkg/util/runtime"
3334 clientgoscheme "k8s.io/client-go/kubernetes/scheme"
@@ -39,9 +40,11 @@ import (
3940 ctrl "sigs.k8s.io/controller-runtime"
4041 "sigs.k8s.io/controller-runtime/pkg/cache"
4142 "sigs.k8s.io/controller-runtime/pkg/client"
43+ "sigs.k8s.io/controller-runtime/pkg/controller"
4244 "sigs.k8s.io/controller-runtime/pkg/webhook"
4345
4446 clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2"
47+ "sigs.k8s.io/cluster-api/controllers/crdmigrator"
4548 "sigs.k8s.io/cluster-api/util/flags"
4649
4750 powervsinfrav1beta2 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/powervs/v1beta2"
@@ -60,19 +63,21 @@ import (
6063)
6164
6265var (
63- watchNamespace string
64- enableLeaderElection bool
65- healthAddr string
66- syncPeriod time.Duration
67- managerOptions = flags.ManagerOptions {}
68- logOptions = logs .NewOptions ()
69- webhookPort int
70- webhookCertDir string
71- watchFilterValue string
72- disableHTTP2 bool
73-
7466 scheme = runtime .NewScheme ()
7567 setupLog = ctrl .Log .WithName ("setup" )
68+
69+ // flags.
70+ watchNamespace string
71+ enableLeaderElection bool
72+ healthAddr string
73+ syncPeriod time.Duration
74+ managerOptions = flags.ManagerOptions {}
75+ logOptions = logs .NewOptions ()
76+ webhookPort int
77+ webhookCertDir string
78+ watchFilterValue string
79+ disableHTTP2 bool
80+ skipCRDMigrationPhases []string
7681)
7782
7883func init () {
@@ -84,10 +89,13 @@ func init() {
8489 utilruntime .Must (vpcinfrav1beta1 .AddToScheme (scheme ))
8590 utilruntime .Must (vpcinfrav1 .AddToScheme (scheme ))
8691 utilruntime .Must (clusterv1 .AddToScheme (scheme ))
92+ utilruntime .Must (apiextensionsv1 .AddToScheme (scheme ))
8793 // +kubebuilder:scaffold:scheme
8894}
8995
9096func initFlags (fs * pflag.FlagSet ) {
97+ logsv1 .AddFlags (logOptions , fs )
98+
9199 fs .BoolVar (
92100 & enableLeaderElection ,
93101 "leader-elect" ,
@@ -136,15 +144,26 @@ func initFlags(fs *pflag.FlagSet) {
136144 "The webhook server port the manager will listen on." ,
137145 )
138146
139- fs .StringVar (& webhookCertDir , "webhook-cert-dir" , "/tmp/k8s-webhook-server/serving-certs/" ,
147+ fs .StringVar (& webhookCertDir ,
148+ "webhook-cert-dir" ,
149+ "/tmp/k8s-webhook-server/serving-certs/" ,
140150 "The webhook certificate directory, where the server should find the TLS certificate and key." )
141151
142- fs .StringVar (& watchFilterValue , "watch-filter" , "" ,
152+ fs .StringVar (& watchFilterValue ,
153+ "watch-filter" ,
154+ "" ,
143155 fmt .Sprintf ("Label value that the controller watches to reconcile cluster-api objects. Label key is always %s. If unspecified, the controller watches for all cluster-api objects." , clusterv1 .WatchLabel ))
144- fs .BoolVar (& disableHTTP2 , "disable-http2" , true , "http/2 should be disabled due to its vulnerabilities. More specifically, disabling http/2 will" +
145- " prevent from being vulnerable to the HTTP/2 Stream Cancellation and Rapid Reset CVEs." )
146156
147- logsv1 .AddFlags (logOptions , fs )
157+ fs .BoolVar (& disableHTTP2 ,
158+ "disable-http2" ,
159+ true ,
160+ "http/2 should be disabled due to its vulnerabilities. More specifically, disabling http/2 will prevent from being vulnerable to the HTTP/2 Stream Cancellation and Rapid Reset CVEs." )
161+
162+ fs .StringSliceVar (& skipCRDMigrationPhases ,
163+ "skip-crd-migration-phases" ,
164+ []string {},
165+ "List of CRD migration phases to skip. Valid values are: StorageVersionMigration, CleanupManagedFields." )
166+
148167 flags .AddManagerOptions (fs , & managerOptions )
149168}
150169
@@ -166,6 +185,11 @@ func validateFlags() error {
166185// Add RBAC for the authorized diagnostics endpoint.
167186// +kubebuilder:rbac:groups=authentication.k8s.io,resources=tokenreviews,verbs=create
168187// +kubebuilder:rbac:groups=authorization.k8s.io,resources=subjectaccessreviews,verbs=create
188+ // ADD CRD RBAC for CRD Migrator.
189+ // +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch
190+ // +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions;customresourcedefinitions/status,verbs=update;patch,resourceNames=ibmpowervsclusters.infrastructure.cluster.x-k8s.io;ibmpowervsclustertemplates.infrastructure.cluster.x-k8s.io;ibmpowervsmachines.infrastructure.cluster.x-k8s.io;ibmpowervsmachinetemplates.infrastructure.cluster.x-k8s.io;ibmpowervsimages.infrastructure.cluster.x-k8s.io
191+ // ADD CR RBAC for CRD Migrator.
192+ // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=ibmpowervsclustertemplates,verbs=get;list;watch;patch;update
169193
170194func main () {
171195 initFlags (pflag .CommandLine )
@@ -268,6 +292,32 @@ func main() {
268292}
269293
270294func setupReconcilers (ctx context.Context , mgr ctrl.Manager , serviceEndpoint []endpoints.ServiceEndpoint ) {
295+ // Note: The kubebuilder RBAC markers above has to be kept in sync
296+ // with the CRDs that should be migrated by this provider.
297+ crdMigratorConfig := map [client.Object ]crdmigrator.ByObjectConfig {
298+ & powervsinfrav1.IBMPowerVSCluster {}: {UseCache : true , UseStatusForStorageVersionMigration : true },
299+ & powervsinfrav1.IBMPowerVSClusterTemplate {}: {UseCache : false },
300+ & powervsinfrav1.IBMPowerVSMachine {}: {UseCache : true , UseStatusForStorageVersionMigration : true },
301+ & powervsinfrav1.IBMPowerVSMachineTemplate {}: {UseCache : false },
302+ & powervsinfrav1.IBMPowerVSImage {}: {UseCache : true , UseStatusForStorageVersionMigration : true },
303+ }
304+
305+ crdMigratorSkipPhases := []crdmigrator.Phase {}
306+ for _ , p := range skipCRDMigrationPhases {
307+ crdMigratorSkipPhases = append (crdMigratorSkipPhases , crdmigrator .Phase (p ))
308+ }
309+ if err := (& crdmigrator.CRDMigrator {
310+ Client : mgr .GetClient (),
311+ APIReader : mgr .GetAPIReader (),
312+ SkipCRDMigrationPhases : crdMigratorSkipPhases ,
313+ Config : crdMigratorConfig ,
314+ // The CRDMigrator is run with only concurrency 1 to ensure we don't overwhelm the apiserver by patching a
315+ // lot of CRs concurrently.
316+ }).SetupWithManager (ctx , mgr , controller.Options {MaxConcurrentReconciles : 1 }); err != nil {
317+ setupLog .Error (err , "Unable to create controller" , "controller" , "CRDMigrator" )
318+ os .Exit (1 )
319+ }
320+
271321 if err := (& controllers.IBMVPCClusterReconciler {
272322 Client : mgr .GetClient (),
273323 Log : ctrl .Log .WithName ("controllers" ).WithName ("IBMVPCCluster" ),
0 commit comments