Skip to content

Commit 39cc4d4

Browse files
committed
add ValidateDelete method in virtualIPStrategy to prevent vip deletion
1 parent 75cef8a commit 39cc4d4

File tree

5 files changed

+105
-17
lines changed

5 files changed

+105
-17
lines changed

client-go/openapi/zz_generated.openapi.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/controllers/networking/networkinterface_ephemeralvirtualip_controller.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,10 @@ func (r *NetworkInterfaceEphemeralVirtualIPReconciler) ephemeralNetworkInterface
7777
annotations.SetDefaultEphemeralManagedBy(virtualIP)
7878
if ephemeral.VirtualIPTemplate.Spec.ReclaimPolicy != networkingv1alpha1.ReclaimPolicyTypeRetain {
7979
_ = ctrl.SetControllerReference(nic, virtualIP, r.Scheme())
80-
virtualIP.Spec.TargetRef = &commonv1alpha1.LocalUIDReference{
81-
Name: nic.Name,
82-
UID: nic.UID,
83-
}
80+
}
81+
virtualIP.Spec.TargetRef = &commonv1alpha1.LocalUIDReference{
82+
Name: nic.Name,
83+
UID: nic.UID,
8484
}
8585
res[virtualIPName] = virtualIP
8686
return res

internal/controllers/networking/networkinterface_ephemeralvirtualip_controller_test.go

Lines changed: 83 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ var _ = Describe("NetworkInterfaceEphemeralVirtualIP", func() {
7878
})),
7979
))
8080
})
81-
It("should verify ownerRef is set for ephemeral virtual IPs based on ReclaimPolicy", func(ctx SpecContext) {
82-
By("creating a network interface with an ephemeral virtual IP")
81+
It("should verify ownerRef is updated based on ReclaimPolicyType for ephemeral virtualIP", func(ctx SpecContext) {
82+
By("creating a network interface with an ephemeral virtual IP having ReclaimPolicyType Retain")
8383
vipSrc := networkingv1alpha1.VirtualIPSource{
8484
Ephemeral: &networkingv1alpha1.EphemeralVirtualIPSource{
8585
VirtualIPTemplate: &networkingv1alpha1.VirtualIPTemplateSpec{
@@ -110,28 +110,103 @@ var _ = Describe("NetworkInterfaceEphemeralVirtualIP", func() {
110110
}
111111
Expect(k8sClient.Create(ctx, nic)).To(Succeed())
112112

113-
By("waiting for the virtual IP to exist")
113+
By("waiting for the virtual IP to exist with empty OwnerRef")
114114
vip := &networkingv1alpha1.VirtualIP{
115115
ObjectMeta: metav1.ObjectMeta{
116116
Namespace: ns.Name,
117117
Name: networkingv1alpha1.NetworkInterfaceVirtualIPName(nic.Name, vipSrc),
118118
},
119119
}
120-
Eventually(Get(vip)).Should(Succeed())
121-
By("Verifying OwnerRef is not set for ephemeral virtualIP when reclaim policy is retain")
122-
Eventually(Object(vip)).Should(HaveField("ObjectMeta.OwnerReferences", BeEmpty()))
120+
Eventually(Object(vip)).Should(SatisfyAll(
121+
HaveField("ObjectMeta.OwnerReferences", BeEmpty()),
122+
HaveField("Spec", networkingv1alpha1.VirtualIPSpec{
123+
Type: networkingv1alpha1.VirtualIPTypePublic,
124+
IPFamily: corev1.IPv4Protocol,
125+
TargetRef: &commonv1alpha1.LocalUIDReference{
126+
Name: nic.Name,
127+
UID: nic.UID,
128+
},
129+
}),
130+
))
123131

124-
By("Updating reclaim policy to delete")
132+
By("Updating reclaim policy to Delete")
125133
baseNic := nic.DeepCopy()
126134
nic.Spec.VirtualIP.Ephemeral.VirtualIPTemplate.Spec.ReclaimPolicy = networkingv1alpha1.ReclaimPolicyTypeDelete
127135
Expect(k8sClient.Patch(ctx, nic, client.MergeFrom(baseNic))).To(Succeed())
128-
By("Verifying OwnerRef is updated for ephemeral virtualIP")
136+
137+
By("Verifying ephemeral virtualIP is updated with OwnerRef after updating the ReclaimPolicyTypeDelete")
129138
Eventually(Object(vip)).Should(HaveField("ObjectMeta.OwnerReferences", ConsistOf(MatchFields(IgnoreExtras, Fields{
130139
"APIVersion": Equal(networkingv1alpha1.SchemeGroupVersion.String()),
131140
"Kind": Equal("NetworkInterface"),
132141
"Name": Equal(nic.Name),
133142
})),
134143
))
144+
145+
})
146+
147+
It("should verify ephemeral virutalIP is not deleted having ReclaimPolicyType Retain with nic deletion", func(ctx SpecContext) {
148+
By("creating a network interface with an ephemeral virtual IP")
149+
vipSrc := networkingv1alpha1.VirtualIPSource{
150+
Ephemeral: &networkingv1alpha1.EphemeralVirtualIPSource{
151+
VirtualIPTemplate: &networkingv1alpha1.VirtualIPTemplateSpec{
152+
Spec: networkingv1alpha1.EphemeralVirtualIPSpec{
153+
ReclaimPolicy: networkingv1alpha1.ReclaimPolicyTypeRetain,
154+
VirtualIPSpec: networkingv1alpha1.VirtualIPSpec{
155+
Type: networkingv1alpha1.VirtualIPTypePublic,
156+
IPFamily: corev1.IPv4Protocol,
157+
},
158+
},
159+
},
160+
},
161+
}
162+
nic := &networkingv1alpha1.NetworkInterface{
163+
ObjectMeta: metav1.ObjectMeta{
164+
Namespace: ns.Name,
165+
GenerateName: "nic-",
166+
},
167+
Spec: networkingv1alpha1.NetworkInterfaceSpec{
168+
NetworkRef: corev1.LocalObjectReference{Name: "my-network"},
169+
IPs: []networkingv1alpha1.IPSource{
170+
{
171+
Value: commonv1alpha1.MustParseNewIP("10.0.0.1"),
172+
},
173+
},
174+
VirtualIP: &vipSrc,
175+
},
176+
}
177+
Expect(k8sClient.Create(ctx, nic)).To(Succeed())
178+
179+
By("waiting for the virtual IP to exist")
180+
vip := &networkingv1alpha1.VirtualIP{
181+
ObjectMeta: metav1.ObjectMeta{
182+
Namespace: ns.Name,
183+
Name: networkingv1alpha1.NetworkInterfaceVirtualIPName(nic.Name, vipSrc),
184+
},
185+
}
186+
Eventually(Object(vip)).Should(SatisfyAll(
187+
HaveField("ObjectMeta.OwnerReferences", BeEmpty()),
188+
HaveField("Spec", networkingv1alpha1.VirtualIPSpec{
189+
Type: networkingv1alpha1.VirtualIPTypePublic,
190+
IPFamily: corev1.IPv4Protocol,
191+
TargetRef: &commonv1alpha1.LocalUIDReference{
192+
Name: nic.Name,
193+
UID: nic.UID,
194+
},
195+
}),
196+
))
197+
198+
By("deleting nic")
199+
Expect(k8sClient.Delete(ctx, nic)).To(Succeed())
200+
201+
By("ensuring the nic is deleted")
202+
nicKey := client.ObjectKey{Namespace: ns.Name, Name: nic.Name}
203+
err := k8sClient.Get(ctx, nicKey, nic)
204+
Expect(apierrors.IsNotFound(err)).To(BeTrue())
205+
206+
By("ensuring the virtualIP still exists after the nic is deleted")
207+
vipKey := client.ObjectKey{Namespace: ns.Name, Name: vip.Name}
208+
Expect(k8sClient.Get(ctx, vipKey, vip)).To(Succeed())
209+
135210
})
136211

137212
It("should delete undesired virtual IPs for a network interface", func(ctx SpecContext) {

internal/controllers/networking/virtualip_release_controller_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ var _ = Describe("VirtualIPReleaseReconciler", func() {
1919

2020
It("should release virtual IPs whose owner is gone", func(ctx SpecContext) {
2121
By("creating a virtual IP referencing an owner that does not exist")
22-
nic := &networkingv1alpha1.VirtualIP{
22+
vip := &networkingv1alpha1.VirtualIP{
2323
ObjectMeta: metav1.ObjectMeta{
2424
Namespace: ns.Name,
25-
GenerateName: "nic-",
25+
GenerateName: "vip-",
2626
},
2727
Spec: networkingv1alpha1.VirtualIPSpec{
2828
Type: networkingv1alpha1.VirtualIPTypePublic,
@@ -33,9 +33,9 @@ var _ = Describe("VirtualIPReleaseReconciler", func() {
3333
},
3434
},
3535
}
36-
Expect(k8sClient.Create(ctx, nic)).To(Succeed())
36+
Expect(k8sClient.Create(ctx, vip)).To(Succeed())
3737

3838
By("waiting for the virtual IP to be released")
39-
Eventually(Object(nic)).Should(HaveField("Spec.TargetRef", BeNil()))
39+
Eventually(Object(vip)).Should(HaveField("Spec.TargetRef", BeNil()))
4040
})
4141
})

internal/registry/networking/virtualip/strategy.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,19 @@ func (virtualIPStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Ob
8383
return validation.ValidateVirtualIPUpdate(newVirtualIP, oldVirtualIP)
8484
}
8585

86+
func (virtualIPStrategy) ValidateDelete(ctx context.Context, obj runtime.Object) field.ErrorList {
87+
virtualIP := obj.(*networking.VirtualIP)
88+
var allerr field.ErrorList
89+
// Check if the VirtualIP has a TargetRef set
90+
if virtualIP.Spec.TargetRef != nil {
91+
// Return a validation error preventing deletion
92+
err := field.Forbidden(field.NewPath("spec", "targetRef"), "deletion is not allowed while TargetRef is set")
93+
allerr = append(allerr, err)
94+
}
95+
return allerr
96+
97+
}
98+
8699
func (virtualIPStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
87100
return nil
88101
}

0 commit comments

Comments
 (0)