Skip to content

Commit 3a86f18

Browse files
committed
Implement CRD migration
Signed-off-by: Stefan Büringer [email protected]
1 parent d5fc2e3 commit 3a86f18

File tree

7 files changed

+146
-3
lines changed

7 files changed

+146
-3
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ IMPORT_BOSS_VER := v0.28.1
190190
IMPORT_BOSS := $(abspath $(TOOLS_BIN_DIR)/$(IMPORT_BOSS_BIN))
191191
IMPORT_BOSS_PKG := k8s.io/code-generator/cmd/import-boss
192192

193-
CAPI_HACK_TOOLS_VER := 065f159469f356c029c7fdef92cce1d2e4b0ebc6 # Note: this a commit ID of from CAPI main, supposed to be in v1.10
193+
CAPI_HACK_TOOLS_VER := c9261b079e0bb619a1b23c5a034c660e5660deb7 # Note: this a commit ID of from CAPI main, supposed to be in v1.10
194194

195195
BOSKOSCTL_BIN := boskosctl
196196
BOSKOSCTL := $(abspath $(TOOLS_BIN_DIR)/$(BOSKOSCTL_BIN))

config/rbac/role.yaml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,45 @@ rules:
5555
- services/status
5656
verbs:
5757
- get
58+
- apiGroups:
59+
- apiextensions.k8s.io
60+
resources:
61+
- customresourcedefinitions
62+
verbs:
63+
- get
64+
- list
65+
- watch
66+
- apiGroups:
67+
- apiextensions.k8s.io
68+
resourceNames:
69+
- providerserviceaccounts.vmware.infrastructure.cluster.x-k8s.io
70+
- vsphereclusters.vmware.infrastructure.cluster.x-k8s.io
71+
- vsphereclustertemplates.vmware.infrastructure.cluster.x-k8s.io
72+
- vspheremachines.vmware.infrastructure.cluster.x-k8s.io
73+
- vspheremachinetemplates.vmware.infrastructure.cluster.x-k8s.io
74+
resources:
75+
- customresourcedefinitions
76+
- customresourcedefinitions/status
77+
verbs:
78+
- patch
79+
- update
80+
- apiGroups:
81+
- apiextensions.k8s.io
82+
resourceNames:
83+
- vsphereclusteridentities.infrastructure.cluster.x-k8s.io
84+
- vsphereclusters.infrastructure.cluster.x-k8s.io
85+
- vsphereclustertemplates.infrastructure.cluster.x-k8s.io
86+
- vspheredeploymentzones.infrastructure.cluster.x-k8s.io
87+
- vspherefailuredomains.infrastructure.cluster.x-k8s.io
88+
- vspheremachines.infrastructure.cluster.x-k8s.io
89+
- vspheremachinetemplates.infrastructure.cluster.x-k8s.io
90+
- vspherevms.infrastructure.cluster.x-k8s.io
91+
resources:
92+
- customresourcedefinitions
93+
- customresourcedefinitions/status
94+
verbs:
95+
- patch
96+
- update
5897
- apiGroups:
5998
- authentication.k8s.io
6099
resources:
@@ -141,10 +180,13 @@ rules:
141180
- apiGroups:
142181
- infrastructure.cluster.x-k8s.io
143182
resources:
183+
- vsphereclustertemplates
144184
- vspheremachinetemplates
145185
verbs:
146186
- get
147187
- list
188+
- patch
189+
- update
148190
- watch
149191
- apiGroups:
150192
- ipam.cluster.x-k8s.io
@@ -242,6 +284,8 @@ rules:
242284
verbs:
243285
- get
244286
- list
287+
- patch
288+
- update
245289
- watch
246290
- apiGroups:
247291
- vmware.infrastructure.cluster.x-k8s.io

controllers/vmware/serviceaccount_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ import (
5252
"sigs.k8s.io/cluster-api-provider-vsphere/pkg/util"
5353
)
5454

55-
// +kubebuilder:rbac:groups=vmware.infrastructure.cluster.x-k8s.io,resources=providerserviceaccounts,verbs=get;list;watch;
55+
// +kubebuilder:rbac:groups=vmware.infrastructure.cluster.x-k8s.io,resources=providerserviceaccounts,verbs=get;list;watch;patch;update
5656
// +kubebuilder:rbac:groups=vmware.infrastructure.cluster.x-k8s.io,resources=providerserviceaccounts/status,verbs=get;update;patch
5757
// +kubebuilder:rbac:groups="",resources=serviceaccounts,verbs=get;list;watch;create;update;patch;delete
5858
// +kubebuilder:rbac:groups="",resources=secrets,verbs=get

main.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import (
4242
"k8s.io/utils/ptr"
4343
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
4444
"sigs.k8s.io/cluster-api/controllers/clustercache"
45+
"sigs.k8s.io/cluster-api/controllers/crdmigrator"
4546
"sigs.k8s.io/cluster-api/controllers/remote"
4647
"sigs.k8s.io/cluster-api/util/apiwarnings"
4748
capiflags "sigs.k8s.io/cluster-api/util/flags"
@@ -93,6 +94,7 @@ var (
9394
vSphereVMConcurrency int
9495
vSphereClusterIdentityConcurrency int
9596
vSphereDeploymentZoneConcurrency int
97+
skipCRDMigrationPhases []string
9698

9799
managerOptions = capiflags.ManagerOptions{}
98100

@@ -187,6 +189,9 @@ func InitFlags(fs *pflag.FlagSet) {
187189
fs.BoolVar(&enableContentionProfiling, "contention-profiling", false,
188190
"Enable block profiling.")
189191

192+
fs.StringArrayVar(&skipCRDMigrationPhases, "skip-crd-migration-phases", []string{},
193+
"List of CRD migration phases to skip. Valid values are: StorageVersionMigration, CleanupManagedFields.")
194+
190195
fs.DurationVar(&syncPeriod, "sync-period", defaultSyncPeriod,
191196
"The minimum interval at which watched resources are reconciled (e.g. 15m)")
192197

@@ -225,6 +230,14 @@ func InitFlags(fs *pflag.FlagSet) {
225230
// Add RBAC for the authorized diagnostics endpoint.
226231
// +kubebuilder:rbac:groups=authentication.k8s.io,resources=tokenreviews,verbs=create
227232
// +kubebuilder:rbac:groups=authorization.k8s.io,resources=subjectaccessreviews,verbs=create
233+
// ADD CRD RBAC for CRD Migrator.
234+
// +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch
235+
// govmomi
236+
// +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions;customresourcedefinitions/status,verbs=update;patch,resourceNames=vsphereclusters.infrastructure.cluster.x-k8s.io;vsphereclustertemplates.infrastructure.cluster.x-k8s.io;vspheremachines.infrastructure.cluster.x-k8s.io;vspheremachinetemplates.infrastructure.cluster.x-k8s.io;vspherevms.infrastructure.cluster.x-k8s.io;vsphereclusteridentities.infrastructure.cluster.x-k8s.io;vspheredeploymentzones.infrastructure.cluster.x-k8s.io;vspherefailuredomains.infrastructure.cluster.x-k8s.io
237+
// supervisor
238+
// +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions;customresourcedefinitions/status,verbs=update;patch,resourceNames=vsphereclusters.vmware.infrastructure.cluster.x-k8s.io;vsphereclustertemplates.vmware.infrastructure.cluster.x-k8s.io;vspheremachines.vmware.infrastructure.cluster.x-k8s.io;vspheremachinetemplates.vmware.infrastructure.cluster.x-k8s.io;providerserviceaccounts.vmware.infrastructure.cluster.x-k8s.io
239+
// govmomi CRs
240+
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=vspheremachinetemplates;vsphereclustertemplates,verbs=get;list;watch;patch;update
228241

229242
func main() {
230243
InitFlags(pflag.CommandLine)
@@ -317,6 +330,43 @@ func main() {
317330
setupLog.Info(fmt.Sprintf("CRD for %s not loaded, skipping.", supervisorGVR.String()))
318331
}
319332

333+
// Note: The kubebuilder RBAC markers above has to be kept in sync
334+
// with the CRDs that should be migrated by this provider.
335+
crdMigratorConfig := map[client.Object]crdmigrator.ByObjectConfig{}
336+
if isGovmomiCRDLoaded {
337+
crdMigratorConfig[&infrav1.VSphereCluster{}] = crdmigrator.ByObjectConfig{UseCache: true}
338+
crdMigratorConfig[&infrav1.VSphereClusterTemplate{}] = crdmigrator.ByObjectConfig{UseCache: false}
339+
crdMigratorConfig[&infrav1.VSphereMachine{}] = crdmigrator.ByObjectConfig{UseCache: true}
340+
crdMigratorConfig[&infrav1.VSphereMachineTemplate{}] = crdmigrator.ByObjectConfig{UseCache: true}
341+
crdMigratorConfig[&infrav1.VSphereVM{}] = crdmigrator.ByObjectConfig{UseCache: true}
342+
crdMigratorConfig[&infrav1.VSphereClusterIdentity{}] = crdmigrator.ByObjectConfig{UseCache: true}
343+
crdMigratorConfig[&infrav1.VSphereDeploymentZone{}] = crdmigrator.ByObjectConfig{UseCache: true}
344+
crdMigratorConfig[&infrav1.VSphereFailureDomain{}] = crdmigrator.ByObjectConfig{UseCache: true}
345+
}
346+
if isSupervisorCRDLoaded {
347+
crdMigratorConfig[&vmwarev1.VSphereCluster{}] = crdmigrator.ByObjectConfig{UseCache: true}
348+
crdMigratorConfig[&vmwarev1.VSphereClusterTemplate{}] = crdmigrator.ByObjectConfig{UseCache: false}
349+
crdMigratorConfig[&vmwarev1.VSphereMachine{}] = crdmigrator.ByObjectConfig{UseCache: true}
350+
crdMigratorConfig[&vmwarev1.VSphereMachineTemplate{}] = crdmigrator.ByObjectConfig{UseCache: true}
351+
crdMigratorConfig[&vmwarev1.ProviderServiceAccount{}] = crdmigrator.ByObjectConfig{UseCache: true}
352+
}
353+
354+
crdMigratorSkipPhases := []crdmigrator.Phase{}
355+
for _, p := range skipCRDMigrationPhases {
356+
crdMigratorSkipPhases = append(crdMigratorSkipPhases, crdmigrator.Phase(p))
357+
}
358+
if err := (&crdmigrator.CRDMigrator{
359+
Client: mgr.GetClient(),
360+
APIReader: mgr.GetAPIReader(),
361+
SkipCRDMigrationPhases: crdMigratorSkipPhases,
362+
Config: crdMigratorConfig,
363+
// The CRDMigrator is run with only concurrency 1 to ensure we don't overwhelm the apiserver by patching a
364+
// lot of CRs concurrently.
365+
}).SetupWithManager(ctx, mgr, concurrency(1)); err != nil {
366+
setupLog.Error(err, "Unable to create controller", "controller", "CRDMigrator")
367+
os.Exit(1)
368+
}
369+
320370
return nil
321371
}
322372

pkg/manager/manager.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
vmoprv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha2"
2727
ncpv1 "github.com/vmware-tanzu/vm-operator/external/ncp/api/v1alpha1"
2828
"gopkg.in/fsnotify.v1"
29+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2930
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
3031
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
3132
bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
@@ -54,6 +55,7 @@ func New(ctx context.Context, opts Options) (Manager, error) {
5455
// Ensure the default options are set.
5556
opts.defaults()
5657

58+
_ = apiextensionsv1.AddToScheme(opts.Scheme)
5759
_ = clientgoscheme.AddToScheme(opts.Scheme)
5860
_ = clusterv1.AddToScheme(opts.Scheme)
5961
_ = infrav1alpha3.AddToScheme(opts.Scheme)

test/e2e/clusterctl_upgrade_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@ package e2e
1919
import (
2020
"context"
2121
"fmt"
22+
"strings"
2223

2324
. "github.com/onsi/ginkgo/v2"
2425
. "github.com/onsi/gomega"
26+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
27+
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
28+
clusterctlcluster "sigs.k8s.io/cluster-api/cmd/clusterctl/client/cluster"
2529
capi_e2e "sigs.k8s.io/cluster-api/test/e2e"
2630
"sigs.k8s.io/cluster-api/test/framework"
2731
"sigs.k8s.io/cluster-api/test/framework/clusterctl"
@@ -67,6 +71,15 @@ var _ = Describe("When testing clusterctl upgrades using ClusterClass (CAPV 1.12
6771
InitWithInfrastructureProviders: []string{fmt.Sprintf(providerVSpherePrefix, capvStableRelease)},
6872
InitWithRuntimeExtensionProviders: testSpecificSettingsGetter().RuntimeExtensionProviders,
6973
InitWithIPAMProviders: []string{},
74+
Upgrades: []capi_e2e.ClusterctlUpgradeSpecInputUpgrade{
75+
{ // Upgrade to latest v1beta1.
76+
Contract: clusterv1.GroupVersion.Version,
77+
PostUpgrade: func(proxy framework.ClusterProxy, namespace, clusterName string) {
78+
framework.ValidateCRDMigration(ctx, proxy, namespace, clusterName,
79+
crdShouldBeMigrated, clusterctlcluster.FilterClusterObjectsWithNameFilter(clusterName))
80+
},
81+
},
82+
},
7083
// InitWithKubernetesVersion should be the highest kubernetes version supported by the init Cluster API version.
7184
// This is to guarantee that both, the old and new CAPI version, support the defined version.
7285
// Ensure all Kubernetes versions used here are covered in patch-vsphere-template.yaml
@@ -112,6 +125,15 @@ var _ = Describe("When testing clusterctl upgrades using ClusterClass (CAPV 1.12
112125
InitWithInfrastructureProviders: []string{fmt.Sprintf(providerVSpherePrefix, capvStableRelease)},
113126
InitWithRuntimeExtensionProviders: testSpecificSettingsGetter().RuntimeExtensionProviders,
114127
InitWithIPAMProviders: []string{},
128+
Upgrades: []capi_e2e.ClusterctlUpgradeSpecInputUpgrade{
129+
{ // Upgrade to latest v1beta1.
130+
Contract: clusterv1.GroupVersion.Version,
131+
PostUpgrade: func(proxy framework.ClusterProxy, namespace, clusterName string) {
132+
framework.ValidateCRDMigration(ctx, proxy, namespace, clusterName,
133+
crdShouldBeMigrated, clusterctlcluster.FilterClusterObjectsWithNameFilter(clusterName))
134+
},
135+
},
136+
},
115137
// InitWithKubernetesVersion should be the highest kubernetes version supported by the init Cluster API version.
116138
// This is to guarantee that both, the old and new CAPI version, support the defined version.
117139
// Ensure all Kubernetes versions used here are covered in patch-vsphere-template.yaml
@@ -157,6 +179,15 @@ var _ = Describe("When testing clusterctl upgrades using ClusterClass (CAPV 1.11
157179
InitWithInfrastructureProviders: []string{fmt.Sprintf(providerVSpherePrefix, capvStableRelease)},
158180
InitWithRuntimeExtensionProviders: testSpecificSettingsGetter().RuntimeExtensionProviders,
159181
InitWithIPAMProviders: []string{},
182+
Upgrades: []capi_e2e.ClusterctlUpgradeSpecInputUpgrade{
183+
{ // Upgrade to latest v1beta1.
184+
Contract: clusterv1.GroupVersion.Version,
185+
PostUpgrade: func(proxy framework.ClusterProxy, namespace, clusterName string) {
186+
framework.ValidateCRDMigration(ctx, proxy, namespace, clusterName,
187+
crdShouldBeMigrated, clusterctlcluster.FilterClusterObjectsWithNameFilter(clusterName))
188+
},
189+
},
190+
},
160191
// InitWithKubernetesVersion should be the highest kubernetes version supported by the init Cluster API version.
161192
// This is to guarantee that both, the old and new CAPI version, support the defined version.
162193
// Ensure all Kubernetes versions used here are covered in patch-vsphere-template.yaml
@@ -202,6 +233,15 @@ var _ = Describe("When testing clusterctl upgrades using ClusterClass (CAPV 1.10
202233
InitWithInfrastructureProviders: []string{fmt.Sprintf(providerVSpherePrefix, capvStableRelease)},
203234
InitWithRuntimeExtensionProviders: testSpecificSettingsGetter().RuntimeExtensionProviders,
204235
InitWithIPAMProviders: []string{},
236+
Upgrades: []capi_e2e.ClusterctlUpgradeSpecInputUpgrade{
237+
{ // Upgrade to latest v1beta1.
238+
Contract: clusterv1.GroupVersion.Version,
239+
PostUpgrade: func(proxy framework.ClusterProxy, namespace, clusterName string) {
240+
framework.ValidateCRDMigration(ctx, proxy, namespace, clusterName,
241+
crdShouldBeMigrated, clusterctlcluster.FilterClusterObjectsWithNameFilter(clusterName))
242+
},
243+
},
244+
},
205245
// InitWithKubernetesVersion should be the highest kubernetes version supported by the init Cluster API version.
206246
// This is to guarantee that both, the old and new CAPI version, support the defined version.
207247
// Ensure all Kubernetes versions used here are covered in patch-vsphere-template.yaml
@@ -233,3 +273,8 @@ func kindManagementClusterNewClusterProxyFunc(name string, kubeconfigPath string
233273
}
234274
return framework.NewClusterProxy(name, kubeconfigPath, initScheme())
235275
}
276+
277+
func crdShouldBeMigrated(crd apiextensionsv1.CustomResourceDefinition) bool {
278+
return strings.HasSuffix(crd.Name, ".infrastructure.cluster.x-k8s.io") && // govmomi & supervisor
279+
!strings.HasSuffix(crd.Name, ".vcsim.infrastructure.cluster.x-k8s.io") // !vcsim
280+
}

test/e2e/e2e_suite_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,9 @@ var _ = SynchronizedAfterSuite(func() {
318318

319319
case VCSimTestTarget:
320320
// Cleanup the vcsim address manager
321-
Expect(vcsimAddressManager.Teardown(ctx)).To(Succeed())
321+
if vcsimAddressManager != nil {
322+
Expect(vcsimAddressManager.Teardown(ctx)).To(Succeed())
323+
}
322324

323325
// cleanup the vcsim server
324326
Expect(vspherevcsim.Delete(ctx, bootstrapClusterProxy.GetClient(), skipCleanup)).To(Succeed())

0 commit comments

Comments
 (0)