|
1 | 1 | package migration_test |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "crypto/sha1" |
| 5 | + "fmt" |
| 6 | + |
4 | 7 | korifiv1alpha1 "code.cloudfoundry.org/korifi/controllers/api/v1alpha1" |
| 8 | + "code.cloudfoundry.org/korifi/controllers/coordination" |
| 9 | + bindingswebhook "code.cloudfoundry.org/korifi/controllers/webhooks/services/bindings" |
5 | 10 | "code.cloudfoundry.org/korifi/migration/migration" |
| 11 | + "code.cloudfoundry.org/korifi/tools" |
| 12 | + "code.cloudfoundry.org/korifi/tools/k8s" |
6 | 13 | "github.com/google/uuid" |
7 | 14 | . "github.com/onsi/ginkgo/v2" |
8 | 15 | . "github.com/onsi/gomega" |
| 16 | + coordinationv1 "k8s.io/api/coordination/v1" |
9 | 17 | corev1 "k8s.io/api/core/v1" |
| 18 | + k8serrors "k8s.io/apimachinery/pkg/api/errors" |
| 19 | + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
10 | 20 | "sigs.k8s.io/controller-runtime/pkg/client" |
11 | 21 | ) |
12 | 22 |
|
13 | 23 | var _ = Describe("Executor", func() { |
14 | | - Describe("CFRoute", test(&korifiv1alpha1.CFRoute{ |
15 | | - Spec: korifiv1alpha1.CFRouteSpec{ |
16 | | - Host: "example", |
17 | | - Path: "/example", |
18 | | - DomainRef: corev1.ObjectReference{ |
19 | | - Name: "example.com", |
20 | | - }, |
21 | | - }, |
22 | | - })) |
23 | | - |
24 | | - Describe("CFServiceBinding", test(&korifiv1alpha1.CFServiceBinding{ |
25 | | - Spec: korifiv1alpha1.CFServiceBindingSpec{ |
26 | | - Type: "key", |
27 | | - }, |
28 | | - })) |
29 | | -}) |
30 | | - |
31 | | -func test(testObj client.Object) func() { |
32 | | - GinkgoHelper() |
33 | | - |
34 | | - return func() { |
| 24 | + Describe("CFServiceBinding Lease", func() { |
35 | 25 | var ( |
36 | | - obj client.Object |
37 | | - migrator *migration.Migrator |
| 26 | + serviceBinding *korifiv1alpha1.CFServiceBinding |
| 27 | + migrator *migration.Migrator |
| 28 | + existingLease *coordinationv1.Lease |
| 29 | + bindingsNameRegistry coordination.NameRegistry |
38 | 30 | ) |
39 | 31 |
|
40 | 32 | BeforeEach(func() { |
41 | | - migrator = migration.New(k8sClient, "abc123", 1) |
| 33 | + bindingsNameRegistry = coordination.NewNameRegistry(k8sClient, bindingswebhook.ServiceBindingEntityType) |
| 34 | + migrator = migration.New(k8sClient, "test-version", 1, bindingsNameRegistry) |
42 | 35 |
|
43 | | - obj = testObj.DeepCopyObject().(client.Object) |
| 36 | + serviceBinding = &korifiv1alpha1.CFServiceBinding{ |
| 37 | + ObjectMeta: metav1.ObjectMeta{ |
| 38 | + Namespace: testNamespace, |
| 39 | + Name: uuid.NewString(), |
| 40 | + }, |
| 41 | + Spec: korifiv1alpha1.CFServiceBindingSpec{ |
| 42 | + Type: "app", |
| 43 | + Service: corev1.ObjectReference{ |
| 44 | + Kind: "CFServiceInstance", |
| 45 | + Name: uuid.NewString(), |
| 46 | + }, |
| 47 | + AppRef: corev1.LocalObjectReference{ |
| 48 | + Name: uuid.NewString(), |
| 49 | + }, |
| 50 | + }, |
| 51 | + } |
| 52 | + Expect(k8sClient.Create(ctx, serviceBinding)).To(Succeed()) |
44 | 53 |
|
45 | | - obj.SetName(uuid.NewString()) |
46 | | - obj.SetNamespace(testNamespace) |
47 | | - Expect(k8sClient.Create(ctx, obj)).To(Succeed()) |
| 54 | + existingLeaseName := fmt.Sprintf("servicebinding::sb::%s::%s::%s", serviceBinding.Spec.AppRef.Name, serviceBinding.Spec.Service.Namespace, serviceBinding.Spec.Service.Name) |
| 55 | + existingLease = &coordinationv1.Lease{ |
| 56 | + ObjectMeta: metav1.ObjectMeta{ |
| 57 | + Namespace: testNamespace, |
| 58 | + Name: fmt.Sprintf("n-%x", sha1.Sum([]byte(existingLeaseName))), |
| 59 | + }, |
| 60 | + } |
| 61 | + Expect(k8sClient.Create(ctx, existingLease)).To(Succeed()) |
48 | 62 | }) |
49 | 63 |
|
50 | 64 | JustBeforeEach(func() { |
51 | | - Expect(migrator.Run(ctx)).To(Succeed()) |
| 65 | + err := migrator.Run(ctx) |
| 66 | + Expect(err).NotTo(HaveOccurred()) |
52 | 67 | }) |
53 | 68 |
|
54 | | - It("sets the migrated_by label", func() { |
| 69 | + It("sets the migrated-by label", func() { |
55 | 70 | Eventually(func(g Gomega) { |
56 | | - g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(obj), obj)).To(Succeed()) |
57 | | - g.Expect(obj.GetLabels()).To(HaveKeyWithValue(migration.MigratedByLabelKey, "abc123")) |
| 71 | + g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(serviceBinding), serviceBinding)).To(Succeed()) |
| 72 | + g.Expect(serviceBinding.Labels).To(HaveKeyWithValue(migration.MigratedByLabelKey, "test-version")) |
58 | 73 | }).Should(Succeed()) |
59 | 74 | }) |
60 | | - } |
61 | | -} |
| 75 | + |
| 76 | + It("deletes the existing lease", func() { |
| 77 | + Eventually(func(g Gomega) { |
| 78 | + err := k8sClient.Get(ctx, client.ObjectKeyFromObject(existingLease), existingLease) |
| 79 | + g.Expect(k8serrors.IsNotFound(err)).To(BeTrue()) |
| 80 | + }).Should(Succeed()) |
| 81 | + }) |
| 82 | + |
| 83 | + It("creates a new lease in the new format by using the service name", func() { |
| 84 | + leaseName := fmt.Sprintf("servicebinding::sb::%s::%s::%s::%s", serviceBinding.Spec.AppRef.Name, serviceBinding.Namespace, serviceBinding.Spec.Service.Name, serviceBinding.Spec.Service.Name) |
| 85 | + newLease := &coordinationv1.Lease{ |
| 86 | + ObjectMeta: metav1.ObjectMeta{ |
| 87 | + Namespace: testNamespace, |
| 88 | + Name: fmt.Sprintf("n-%x", sha1.Sum([]byte(leaseName))), |
| 89 | + }, |
| 90 | + } |
| 91 | + Eventually(func(g Gomega) { |
| 92 | + g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(newLease), newLease)).To(Succeed()) |
| 93 | + g.Expect(newLease.Annotations).To(SatisfyAll( |
| 94 | + HaveKeyWithValue(coordination.EntityTypeAnnotation, bindingswebhook.ServiceBindingEntityType), |
| 95 | + HaveKeyWithValue(coordination.NameAnnotation, fmt.Sprintf("sb::%s::%s::%s::%s", serviceBinding.Spec.AppRef.Name, serviceBinding.Namespace, serviceBinding.Spec.Service.Name, serviceBinding.Spec.Service.Name)), |
| 96 | + HaveKeyWithValue(coordination.NamespaceAnnotation, serviceBinding.Namespace), |
| 97 | + HaveKeyWithValue(coordination.OwnerNamespaceAnnotation, serviceBinding.Namespace), |
| 98 | + HaveKeyWithValue(coordination.OwnerNameAnnotation, serviceBinding.Name), |
| 99 | + )) |
| 100 | + }).Should(Succeed()) |
| 101 | + }) |
| 102 | + |
| 103 | + When("the service binding has a display name", func() { |
| 104 | + BeforeEach(func() { |
| 105 | + Expect(k8s.Patch(ctx, k8sClient, serviceBinding, func() { |
| 106 | + serviceBinding.Spec.DisplayName = tools.PtrTo(uuid.NewString()) |
| 107 | + })).To(Succeed()) |
| 108 | + }) |
| 109 | + |
| 110 | + It("creates a new lease in the new format by using the binding display name", func() { |
| 111 | + leaseName := fmt.Sprintf("servicebinding::sb::%s::%s::%s::%s", serviceBinding.Spec.AppRef.Name, serviceBinding.Namespace, serviceBinding.Spec.Service.Name, *serviceBinding.Spec.DisplayName) |
| 112 | + newLease := &coordinationv1.Lease{ |
| 113 | + ObjectMeta: metav1.ObjectMeta{ |
| 114 | + Namespace: testNamespace, |
| 115 | + Name: fmt.Sprintf("n-%x", sha1.Sum([]byte(leaseName))), |
| 116 | + }, |
| 117 | + } |
| 118 | + Eventually(func(g Gomega) { |
| 119 | + g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(newLease), newLease)).To(Succeed()) |
| 120 | + g.Expect(newLease.Annotations).To(SatisfyAll( |
| 121 | + HaveKeyWithValue(coordination.EntityTypeAnnotation, bindingswebhook.ServiceBindingEntityType), |
| 122 | + HaveKeyWithValue(coordination.NameAnnotation, fmt.Sprintf("sb::%s::%s::%s::%s", serviceBinding.Spec.AppRef.Name, serviceBinding.Namespace, serviceBinding.Spec.Service.Name, *serviceBinding.Spec.DisplayName)), |
| 123 | + HaveKeyWithValue(coordination.NamespaceAnnotation, serviceBinding.Namespace), |
| 124 | + HaveKeyWithValue(coordination.OwnerNamespaceAnnotation, serviceBinding.Namespace), |
| 125 | + HaveKeyWithValue(coordination.OwnerNameAnnotation, serviceBinding.Name), |
| 126 | + )) |
| 127 | + }).Should(Succeed()) |
| 128 | + }) |
| 129 | + }) |
| 130 | + |
| 131 | + When("the binding unique name has been already registered for that binding", func() { |
| 132 | + BeforeEach(func() { |
| 133 | + Expect(bindingsNameRegistry.RegisterName(ctx, serviceBinding.Namespace, serviceBinding.UniqueName(), serviceBinding.Namespace, serviceBinding.Name)).To(Succeed()) |
| 134 | + }) |
| 135 | + |
| 136 | + It("preserves the new unique name lease", func() { |
| 137 | + leaseName := fmt.Sprintf("servicebinding::sb::%s::%s::%s::%s", serviceBinding.Spec.AppRef.Name, serviceBinding.Namespace, serviceBinding.Spec.Service.Name, serviceBinding.Spec.Service.Name) |
| 138 | + newLease := &coordinationv1.Lease{ |
| 139 | + ObjectMeta: metav1.ObjectMeta{ |
| 140 | + Namespace: testNamespace, |
| 141 | + Name: fmt.Sprintf("n-%x", sha1.Sum([]byte(leaseName))), |
| 142 | + }, |
| 143 | + } |
| 144 | + Consistently(func(g Gomega) { |
| 145 | + g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(newLease), newLease)).To(Succeed()) |
| 146 | + }).Should(Succeed()) |
| 147 | + }) |
| 148 | + |
| 149 | + It("deletes the existing lease", func() { |
| 150 | + Eventually(func(g Gomega) { |
| 151 | + err := k8sClient.Get(ctx, client.ObjectKeyFromObject(existingLease), existingLease) |
| 152 | + g.Expect(k8serrors.IsNotFound(err)).To(BeTrue()) |
| 153 | + }).Should(Succeed()) |
| 154 | + }) |
| 155 | + }) |
| 156 | + |
| 157 | + When("the binding has been already migrated by the current version", func() { |
| 158 | + BeforeEach(func() { |
| 159 | + Expect(k8s.Patch(ctx, k8sClient, serviceBinding, func() { |
| 160 | + serviceBinding.Labels = map[string]string{ |
| 161 | + migration.MigratedByLabelKey: "test-version", |
| 162 | + } |
| 163 | + })).To(Succeed()) |
| 164 | + }) |
| 165 | + |
| 166 | + It("does not migrate again", func() { |
| 167 | + Consistently(func(g Gomega) { |
| 168 | + err := k8sClient.Get(ctx, client.ObjectKeyFromObject(existingLease), existingLease) |
| 169 | + g.Expect(err).NotTo(HaveOccurred()) |
| 170 | + }).Should(Succeed()) |
| 171 | + }) |
| 172 | + }) |
| 173 | + |
| 174 | + When("the binding has been migrated by another version", func() { |
| 175 | + BeforeEach(func() { |
| 176 | + Expect(k8s.Patch(ctx, k8sClient, serviceBinding, func() { |
| 177 | + serviceBinding.Labels = map[string]string{ |
| 178 | + migration.MigratedByLabelKey: "another-version", |
| 179 | + } |
| 180 | + })).To(Succeed()) |
| 181 | + }) |
| 182 | + |
| 183 | + It("migrates the binding", func() { |
| 184 | + Eventually(func(g Gomega) { |
| 185 | + g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(serviceBinding), serviceBinding)).To(Succeed()) |
| 186 | + g.Expect(serviceBinding.Labels).To(HaveKeyWithValue(migration.MigratedByLabelKey, "test-version")) |
| 187 | + }).Should(Succeed()) |
| 188 | + }) |
| 189 | + }) |
| 190 | + }) |
| 191 | +}) |
0 commit comments