diff --git a/e2e/tcp_validation_version_downgrade_test.go b/e2e/tcp_validation_version_downgrade_test.go new file mode 100644 index 0000000..4129172 --- /dev/null +++ b/e2e/tcp_validation_version_downgrade_test.go @@ -0,0 +1,65 @@ +// Copyright 2022 Clastix Labs +// SPDX-License-Identifier: Apache-2.0 + +package e2e + +import ( + "context" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1" +) + +var _ = Describe("downgrade of a TenantControlPlane Kubernetes version", func() { + // Fill TenantControlPlane object + tcp := kamajiv1alpha1.TenantControlPlane{ + ObjectMeta: metav1.ObjectMeta{ + Name: "downgrade", + Namespace: "default", + }, + Spec: kamajiv1alpha1.TenantControlPlaneSpec{ + ControlPlane: kamajiv1alpha1.ControlPlane{ + Deployment: kamajiv1alpha1.DeploymentSpec{ + Replicas: 1, + }, + Service: kamajiv1alpha1.ServiceSpec{ + ServiceType: "ClusterIP", + }, + }, + Kubernetes: kamajiv1alpha1.KubernetesSpec{ + Version: "v1.23.0", + Kubelet: kamajiv1alpha1.KubeletSpec{ + CGroupFS: "cgroupfs", + }, + }, + }, + } + // Create a TenantControlPlane resource into the cluster + JustBeforeEach(func() { + Expect(k8sClient.Create(context.Background(), &tcp)).NotTo(HaveOccurred()) + }) + // Delete the TenantControlPlane resource after test is finished + JustAfterEach(func() { + Expect(k8sClient.Delete(context.Background(), &tcp)).Should(Succeed()) + }) + + It("should be blocked", func() { + Consistently(func() error { + tcp := tcp.DeepCopy() + + err := k8sClient.Get(context.Background(), types.NamespacedName{Name: tcp.GetName(), Namespace: tcp.GetNamespace()}, tcp) + if err != nil { + return nil + } + + tcp.Spec.Kubernetes.Version = "v1.22.0" + + return k8sClient.Update(context.Background(), tcp) + }, 10*time.Second, time.Second).ShouldNot(Succeed()) + }) +}) diff --git a/e2e/tcp_validation_version_nonlinear_test.go b/e2e/tcp_validation_version_nonlinear_test.go new file mode 100644 index 0000000..eedb4a5 --- /dev/null +++ b/e2e/tcp_validation_version_nonlinear_test.go @@ -0,0 +1,65 @@ +// Copyright 2022 Clastix Labs +// SPDX-License-Identifier: Apache-2.0 + +package e2e + +import ( + "context" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1" +) + +var _ = Describe("non-linear minor upgrade of a TenantControlPlane Kubernetes version", func() { + // Fill TenantControlPlane object + tcp := kamajiv1alpha1.TenantControlPlane{ + ObjectMeta: metav1.ObjectMeta{ + Name: "non-linear", + Namespace: "default", + }, + Spec: kamajiv1alpha1.TenantControlPlaneSpec{ + ControlPlane: kamajiv1alpha1.ControlPlane{ + Deployment: kamajiv1alpha1.DeploymentSpec{ + Replicas: 1, + }, + Service: kamajiv1alpha1.ServiceSpec{ + ServiceType: "ClusterIP", + }, + }, + Kubernetes: kamajiv1alpha1.KubernetesSpec{ + Version: "v1.23.0", + Kubelet: kamajiv1alpha1.KubeletSpec{ + CGroupFS: "cgroupfs", + }, + }, + }, + } + // Create a TenantControlPlane resource into the cluster + JustBeforeEach(func() { + Expect(k8sClient.Create(context.Background(), &tcp)).NotTo(HaveOccurred()) + }) + // Delete the TenantControlPlane resource after test is finished + JustAfterEach(func() { + Expect(k8sClient.Delete(context.Background(), &tcp)).Should(Succeed()) + }) + + It("should be blocked", func() { + Consistently(func() error { + tcp := tcp.DeepCopy() + + err := k8sClient.Get(context.Background(), types.NamespacedName{Name: tcp.GetName(), Namespace: tcp.GetNamespace()}, tcp) + if err != nil { + return nil + } + + tcp.Spec.Kubernetes.Version = "v1.25.0" + + return k8sClient.Update(context.Background(), tcp) + }, 10*time.Second, time.Second).ShouldNot(Succeed()) + }) +}) diff --git a/e2e/tcp_validation_version_unsupport_test.go b/e2e/tcp_validation_version_unsupport_test.go new file mode 100644 index 0000000..6dbe00b --- /dev/null +++ b/e2e/tcp_validation_version_unsupport_test.go @@ -0,0 +1,99 @@ +// Copyright 2022 Clastix Labs +// SPDX-License-Identifier: Apache-2.0 + +package e2e + +import ( + "context" + "fmt" + "time" + + "github.com/blang/semver" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1" + "github.com/clastix/kamaji/internal/upgrade" +) + +var _ = Describe("using an unsupported TenantControlPlane Kubernetes version", func() { + v, err := semver.Make(upgrade.KubeadmVersion[1:]) + Expect(err).ToNot(HaveOccurred()) + + unsupported, err := semver.Make(fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch+1)) + Expect(err).ToNot(HaveOccurred()) + + It("should be blocked on creation", func() { + Consistently(func() error { + tcp := kamajiv1alpha1.TenantControlPlane{ + ObjectMeta: metav1.ObjectMeta{ + Name: "non-linear-update", + Namespace: "default", + }, + Spec: kamajiv1alpha1.TenantControlPlaneSpec{ + ControlPlane: kamajiv1alpha1.ControlPlane{ + Deployment: kamajiv1alpha1.DeploymentSpec{ + Replicas: 1, + }, + Service: kamajiv1alpha1.ServiceSpec{ + ServiceType: "ClusterIP", + }, + }, + Kubernetes: kamajiv1alpha1.KubernetesSpec{ + Version: fmt.Sprintf("v%s", unsupported.String()), + Kubelet: kamajiv1alpha1.KubeletSpec{ + CGroupFS: "cgroupfs", + }, + }, + }, + } + + return k8sClient.Create(context.Background(), &tcp) + }, 10*time.Second, time.Second).ShouldNot(Succeed()) + }) + + It("should be blocked on update", func() { + tcp := kamajiv1alpha1.TenantControlPlane{ + ObjectMeta: metav1.ObjectMeta{ + Name: "non-linear-update", + Namespace: "default", + }, + Spec: kamajiv1alpha1.TenantControlPlaneSpec{ + ControlPlane: kamajiv1alpha1.ControlPlane{ + Deployment: kamajiv1alpha1.DeploymentSpec{ + Replicas: 1, + }, + Service: kamajiv1alpha1.ServiceSpec{ + ServiceType: "ClusterIP", + }, + }, + Kubernetes: kamajiv1alpha1.KubernetesSpec{ + Version: fmt.Sprintf("v%s", v.String()), + Kubelet: kamajiv1alpha1.KubeletSpec{ + CGroupFS: "cgroupfs", + }, + }, + }, + } + + Expect(k8sClient.Create(context.Background(), &tcp)).ToNot(HaveOccurred()) + defer func() { + Expect(k8sClient.Delete(context.Background(), &tcp)).ToNot(HaveOccurred()) + }() + + Consistently(func() error { + tcp := tcp.DeepCopy() + + err := k8sClient.Get(context.Background(), types.NamespacedName{Name: tcp.GetName(), Namespace: tcp.GetNamespace()}, tcp) + if err != nil { + return nil + } + + tcp.Spec.Kubernetes.Version = fmt.Sprintf("v%s", unsupported.String()) + + return k8sClient.Create(context.Background(), tcp) + }, 10*time.Second, time.Second).ShouldNot(Succeed()) + }) +})