Skip to content

Commit

Permalink
Stop serving v1alpha3 API types
Browse files Browse the repository at this point in the history
Signed-off-by: killianmuldoon <kmuldoon@vmware.com>
  • Loading branch information
killianmuldoon committed May 16, 2023
1 parent 36511e7 commit 7059d02
Show file tree
Hide file tree
Showing 41 changed files with 143 additions and 40 deletions.
2 changes: 2 additions & 0 deletions api/v1alpha3/cluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ func (v APIEndpoint) String() string {
// ANCHOR_END: APIEndpoint

// +kubebuilder:object:root=true
// +kubebuilder:unservedversion
// +kubebuilder:resource:path=clusters,shortName=cl,scope=Namespaced,categories=cluster-api
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="Cluster status such as Pending/Provisioning/Provisioned/Deleting/Failed"
Expand All @@ -224,6 +225,7 @@ func (c *Cluster) SetConditions(conditions Conditions) {
}

// +kubebuilder:object:root=true
// +kubebuilder:unservedversion

// ClusterList contains a list of Cluster.
type ClusterList struct {
Expand Down
1 change: 1 addition & 0 deletions api/v1alpha3/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ limitations under the License.
// +k8s:conversion-gen=sigs.k8s.io/cluster-api/api/v1beta1
//
// Deprecated: This package will be removed in one of the next releases.
// +kubebuilder:unservedversion
package v1alpha3
2 changes: 2 additions & 0 deletions api/v1alpha3/machine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ type Bootstrap struct {
// ANCHOR_END: Bootstrap

// +kubebuilder:object:root=true
// +kubebuilder:unservedversion
// +kubebuilder:resource:path=machines,shortName=ma,scope=Namespaced,categories=cluster-api
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="ProviderID",type="string",JSONPath=".spec.providerID",description="Provider ID"
Expand Down Expand Up @@ -266,6 +267,7 @@ func (m *Machine) SetConditions(conditions Conditions) {
}

// +kubebuilder:object:root=true
// +kubebuilder:unservedversion

// MachineList contains a list of Machine.
//
Expand Down
2 changes: 2 additions & 0 deletions api/v1alpha3/machinedeployment_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ func (md *MachineDeploymentStatus) GetTypedPhase() MachineDeploymentPhase {
}

// +kubebuilder:object:root=true
// +kubebuilder:unservedversion
// +kubebuilder:resource:path=machinedeployments,shortName=md,scope=Namespaced,categories=cluster-api
// +kubebuilder:subresource:status
// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector
Expand All @@ -262,6 +263,7 @@ type MachineDeployment struct {
}

// +kubebuilder:object:root=true
// +kubebuilder:unservedversion

// MachineDeploymentList contains a list of MachineDeployment.
//
Expand Down
2 changes: 2 additions & 0 deletions api/v1alpha3/machinehealthcheck_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ type MachineHealthCheckStatus struct {
// ANCHOR_END: MachineHealthCheckStatus

// +kubebuilder:object:root=true
// +kubebuilder:unservedversion
// +kubebuilder:resource:path=machinehealthchecks,shortName=mhc;mhcs,scope=Namespaced,categories=cluster-api
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="MaxUnhealthy",type="string",JSONPath=".spec.maxUnhealthy",description="Maximum number of unhealthy machines allowed"
Expand Down Expand Up @@ -145,6 +146,7 @@ func (m *MachineHealthCheck) SetConditions(conditions Conditions) {
}

// +kubebuilder:object:root=true
// +kubebuilder:unservedversion

// MachineHealthCheckList contains a list of MachineHealthCheck.
//
Expand Down
2 changes: 2 additions & 0 deletions api/v1alpha3/machineset_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ func (m *MachineSet) Validate() field.ErrorList {
}

// +kubebuilder:object:root=true
// +kubebuilder:unservedversion
// +kubebuilder:resource:path=machinesets,shortName=ms,scope=Namespaced,categories=cluster-api
// +kubebuilder:subresource:status
// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector
Expand All @@ -204,6 +205,7 @@ type MachineSet struct {
}

// +kubebuilder:object:root=true
// +kubebuilder:unservedversion

// MachineSetList contains a list of MachineSet.
//
Expand Down
4 changes: 4 additions & 0 deletions api/v1alpha3/webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import (
)

func TestClusterConversion(t *testing.T) {
t.Skipf("v1alpha3 is no longer served see: https://cluster-api.sigs.k8s.io/contributing#removal-of-v1alpha3--v1alpha4-apiversions")

g := NewWithT(t)
ns, err := env.CreateNamespace(ctx, fmt.Sprintf("conversion-webhook-%s", util.RandomString(5)))
g.Expect(err).ToNot(HaveOccurred())
Expand All @@ -48,6 +50,7 @@ func TestClusterConversion(t *testing.T) {
}

func TestMachineSetConversion(t *testing.T) {
t.Skipf("v1alpha3 is no longer served see: https://cluster-api.sigs.k8s.io/contributing#removal-of-v1alpha3--v1alpha4-apiversions")
g := NewWithT(t)
ns, err := env.CreateNamespace(ctx, fmt.Sprintf("conversion-webhook-%s", util.RandomString(5)))
g.Expect(err).ToNot(HaveOccurred())
Expand Down Expand Up @@ -75,6 +78,7 @@ func TestMachineSetConversion(t *testing.T) {
}

func TestMachineDeploymentConversion(t *testing.T) {
t.Skipf("v1alpha3 is no longer served see: https://cluster-api.sigs.k8s.io/contributing#removal-of-v1alpha3--v1alpha4-apiversions")
g := NewWithT(t)
ns, err := env.CreateNamespace(ctx, fmt.Sprintf("conversion-webhook-%s", util.RandomString(5)))
g.Expect(err).ToNot(HaveOccurred())
Expand Down
2 changes: 2 additions & 0 deletions bootstrap/kubeadm/api/v1alpha3/kubeadmconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ type KubeadmConfigStatus struct {
}

// +kubebuilder:object:root=true
// +kubebuilder:unservedversion
// +kubebuilder:resource:path=kubeadmconfigs,scope=Namespaced,categories=cluster-api
// +kubebuilder:subresource:status

Expand All @@ -157,6 +158,7 @@ func (c *KubeadmConfig) SetConditions(conditions clusterv1alpha3.Conditions) {
}

// +kubebuilder:object:root=true
// +kubebuilder:unservedversion

// KubeadmConfigList contains a list of KubeadmConfig.
//
Expand Down
2 changes: 2 additions & 0 deletions bootstrap/kubeadm/api/v1alpha3/kubeadmconfigtemplate_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type KubeadmConfigTemplateResource struct {
}

// +kubebuilder:object:root=true
// +kubebuilder:unservedversion
// +kubebuilder:resource:path=kubeadmconfigtemplates,scope=Namespaced,categories=cluster-api

// KubeadmConfigTemplate is the Schema for the kubeadmconfigtemplates API.
Expand All @@ -44,6 +45,7 @@ type KubeadmConfigTemplate struct {
}

// +kubebuilder:object:root=true
// +kubebuilder:unservedversion

// KubeadmConfigTemplateList contains a list of KubeadmConfigTemplate.
//
Expand Down
2 changes: 2 additions & 0 deletions bootstrap/kubeadm/api/v1alpha3/webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
)

func TestKubeadmConfigConversion(t *testing.T) {
t.Skipf("v1alpha3 is no longer served see: https://cluster-api.sigs.k8s.io/contributing#removal-of-v1alpha3--v1alpha4-apiversions")
g := NewWithT(t)
ns, err := env.CreateNamespace(ctx, fmt.Sprintf("conversion-webhook-%s", util.RandomString(5)))
g.Expect(err).ToNot(HaveOccurred())
Expand All @@ -49,6 +50,7 @@ func TestKubeadmConfigConversion(t *testing.T) {
}

func TestKubeadmConfigTemplateConversion(t *testing.T) {
t.Skipf("v1alpha3 is no longer served see: https://cluster-api.sigs.k8s.io/contributing#removal-of-v1alpha3--v1alpha4-apiversions")
g := NewWithT(t)
ns, err := env.CreateNamespace(ctx, fmt.Sprintf("conversion-webhook-%s", util.RandomString(5)))
g.Expect(err).ToNot(HaveOccurred())
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 8 additions & 7 deletions cmd/clusterctl/client/cluster/crd_migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,18 @@ func (m *crdMigrator) Run(ctx context.Context, objs []unstructured.Unstructured)
}

// run migrates CRs of a new CRD.
// This is necessary when the new CRD drops a version which
// was previously used as a storage version.
// This is necessary when the new CRD drops or stops serving
// a version which was previously used as a storage version.
func (m *crdMigrator) run(ctx context.Context, newCRD *apiextensionsv1.CustomResourceDefinition) (bool, error) {
log := logf.Log

// Gets the list of version supported by the new CRD. If a version is listed but not served it is not considered supported.
newVersions := sets.Set[string]{}
servedVersions := sets.Set[string]{}
for _, version := range newCRD.Spec.Versions {
newVersions.Insert(version.Name)
if version.Served {
newVersions.Insert(version.Name)
servedVersions.Insert(version.Name)
}
}

Expand Down Expand Up @@ -107,10 +109,9 @@ func (m *crdMigrator) run(ctx context.Context, newCRD *apiextensionsv1.CustomRes
}

currentStatusStoredVersions := sets.Set[string]{}.Insert(currentCRD.Status.StoredVersions...)

// If the new CRD still contains all current stored versions, nothing to do
// as no previous storage version will be dropped.
if newVersions.HasAll(currentStatusStoredVersions.UnsortedList()...) {
if servedVersions.HasAll(currentStatusStoredVersions.UnsortedList()...) {
log.V(2).Info("CRD migration check passed", "name", newCRD.Name)
return false, nil
}
Expand All @@ -122,8 +123,8 @@ func (m *crdMigrator) run(ctx context.Context, newCRD *apiextensionsv1.CustomRes
// This way we can make sure that all CR objects are now stored in the current storage version.
// Alternatively, we would have to figure out which objects are stored in which version but this information is not
// exposed by the apiserver.
storedVersionsToDelete := currentStatusStoredVersions.Difference(newVersions)
storedVersionsToPreserve := currentStatusStoredVersions.Intersection(newVersions)
storedVersionsToDelete := currentStatusStoredVersions.Difference(servedVersions)
storedVersionsToPreserve := currentStatusStoredVersions.Intersection(servedVersions)
log.Info("CR migration required", "kind", newCRD.Spec.Names.Kind, "storedVersionsToDelete", strings.Join(sets.List(storedVersionsToDelete), ","), "storedVersionsToPreserve", strings.Join(sets.List(storedVersionsToPreserve), ","))

if err := m.migrateResourcesForCRD(ctx, currentCRD, currentStorageVersion); err != nil {
Expand Down
89 changes: 75 additions & 14 deletions cmd/clusterctl/client/cluster/crd_migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func Test_CRDMigrator(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
{Name: "v1alpha1"}, // No storage version as storage is not set.
{Name: "v1alpha1", Served: true}, // No storage version as storage is not set.
},
},
Status: apiextensionsv1.CustomResourceDefinitionStatus{StoredVersions: []string{"v1alpha1"}},
Expand All @@ -61,7 +61,7 @@ func Test_CRDMigrator(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
{Name: "v1alpha1"},
{Name: "v1alpha1", Served: true},
},
},
},
Expand All @@ -74,7 +74,7 @@ func Test_CRDMigrator(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
{Name: "v1alpha1", Storage: true},
{Name: "v1alpha1", Storage: true, Served: true},
},
},
Status: apiextensionsv1.CustomResourceDefinitionStatus{StoredVersions: []string{"v1alpha1"}},
Expand All @@ -83,7 +83,7 @@ func Test_CRDMigrator(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
{Name: "v1alpha1", Storage: true},
{Name: "v1alpha1", Storage: true, Served: true},
},
},
},
Expand All @@ -95,7 +95,7 @@ func Test_CRDMigrator(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
{Name: "v1alpha1", Storage: true},
{Name: "v1alpha1", Storage: true, Served: true},
},
},
Status: apiextensionsv1.CustomResourceDefinitionStatus{StoredVersions: []string{"v1alpha1"}},
Expand All @@ -104,8 +104,8 @@ func Test_CRDMigrator(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
{Name: "v1beta1", Storage: true}, // v1beta1 is being added
{Name: "v1alpha1"}, // v1alpha1 still exists
{Name: "v1beta1", Storage: true, Served: true}, // v1beta1 is being added
{Name: "v1alpha1", Served: true}, // v1alpha1 still exists
},
},
},
Expand All @@ -117,7 +117,7 @@ func Test_CRDMigrator(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
{Name: "v1alpha1", Storage: true},
{Name: "v1alpha1", Storage: true, Served: true},
},
},
Status: apiextensionsv1.CustomResourceDefinitionStatus{StoredVersions: []string{"v1alpha1"}},
Expand All @@ -126,14 +126,14 @@ func Test_CRDMigrator(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
{Name: "v1", Storage: true}, // CRD is jumping to v1, but dropping current storage version without allowing migration.
{Name: "v1", Storage: true, Served: true}, // CRD is jumping to v1, but dropping current storage version without allowing migration.
},
},
},
wantErr: true,
},
{
name: "Migrate",
name: "Migrate CRs if their storage version is removed from the CRD",
CRs: []unstructured.Unstructured{
{
Object: map[string]interface{}{
Expand Down Expand Up @@ -172,8 +172,8 @@ func Test_CRDMigrator(t *testing.T) {
Group: "foo",
Names: apiextensionsv1.CustomResourceDefinitionNames{Kind: "Foo", ListKind: "FooList"},
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
{Name: "v1beta1", Storage: true},
{Name: "v1alpha1"},
{Name: "v1beta1", Storage: true, Served: true},
{Name: "v1alpha1", Served: true},
},
},
Status: apiextensionsv1.CustomResourceDefinitionStatus{StoredVersions: []string{"v1beta1", "v1alpha1"}},
Expand All @@ -184,15 +184,76 @@ func Test_CRDMigrator(t *testing.T) {
Group: "foo",
Names: apiextensionsv1.CustomResourceDefinitionNames{Kind: "Foo", ListKind: "FooList"},
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
{Name: "v1", Storage: true}, // v1 is being added
{Name: "v1beta1"}, // v1beta1 still there (required for migration)
{Name: "v1", Storage: true, Served: true}, // v1 is being added
{Name: "v1beta1", Served: true}, // v1beta1 still there (required for migration)
// v1alpha1 is being dropped
},
},
},
wantStoredVersions: []string{"v1beta1"}, // v1alpha1 should be dropped from current CRD's stored versions
wantIsMigrated: true,
},
{
name: "Migrate if the CR if their storage version is no longer served by the CRD",
CRs: []unstructured.Unstructured{
{
Object: map[string]interface{}{
"apiVersion": "foo/v1beta1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "cr1",
"namespace": metav1.NamespaceDefault,
},
},
},
{
Object: map[string]interface{}{
"apiVersion": "foo/v1beta1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "cr2",
"namespace": metav1.NamespaceDefault,
},
},
},
{
Object: map[string]interface{}{
"apiVersion": "foo/v1beta1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "cr3",
"namespace": metav1.NamespaceDefault,
},
},
},
},
currentCRD: &apiextensionsv1.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
Group: "foo",
Names: apiextensionsv1.CustomResourceDefinitionNames{Kind: "Foo", ListKind: "FooList"},
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
{Name: "v1beta1", Storage: true, Served: true},
{Name: "v1alpha1", Served: true},
},
},
Status: apiextensionsv1.CustomResourceDefinitionStatus{StoredVersions: []string{"v1beta1", "v1alpha1"}},
},
newCRD: &apiextensionsv1.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
Group: "foo",
Names: apiextensionsv1.CustomResourceDefinitionNames{Kind: "Foo", ListKind: "FooList"},
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
{Name: "v1", Storage: true, Served: true}, // v1 is being added
{Name: "v1beta1", Served: true}, // v1beta1 still there (required for migration)
{Name: "v1alpha1", Served: false}, // v1alpha1 is no longer being served
},
},
},
wantStoredVersions: []string{"v1beta1"}, // v1alpha1 should be dropped from current CRD's stored versions
wantIsMigrated: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
Loading

0 comments on commit 7059d02

Please sign in to comment.