Skip to content

Commit 8fe8096

Browse files
committed
subnet: forbid subnet vpc change
Signed-off-by: Mengxin Liu <[email protected]>
1 parent dfcea35 commit 8fe8096

File tree

5 files changed

+46
-23
lines changed

5 files changed

+46
-23
lines changed

pkg/controller/controller.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ const (
5252
portGroupKey = "pg"
5353
networkPolicyKey = "np"
5454
sgKey = "sg"
55-
associatedSgKeyPrefix = "associated_sg_"
5655
sgsKey = "security_groups"
5756
u2oKey = "u2o"
5857
adminNetworkPolicyKey = "anp"
@@ -125,7 +124,6 @@ type Controller struct {
125124
subnetsLister kubeovnlister.SubnetLister
126125
subnetSynced cache.InformerSynced
127126
addOrUpdateSubnetQueue workqueue.TypedRateLimitingInterface[string]
128-
subnetLastVpcNameMap *xsync.Map[string, string]
129127
deleteSubnetQueue workqueue.TypedRateLimitingInterface[*kubeovnv1.Subnet]
130128
updateSubnetStatusQueue workqueue.TypedRateLimitingInterface[string]
131129
syncVirtualPortsQueue workqueue.TypedRateLimitingInterface[string]
@@ -431,7 +429,6 @@ func Run(ctx context.Context, config *Configuration) {
431429
subnetsLister: subnetInformer.Lister(),
432430
subnetSynced: subnetInformer.Informer().HasSynced,
433431
addOrUpdateSubnetQueue: newTypedRateLimitingQueue[string]("AddSubnet", nil),
434-
subnetLastVpcNameMap: xsync.NewMap[string, string](),
435432
deleteSubnetQueue: newTypedRateLimitingQueue[*kubeovnv1.Subnet]("DeleteSubnet", nil),
436433
updateSubnetStatusQueue: newTypedRateLimitingQueue[string]("UpdateSubnetStatus", nil),
437434
syncVirtualPortsQueue: newTypedRateLimitingQueue[string]("SyncVirtualPort", nil),

pkg/controller/subnet.go

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,6 @@ func (c *Controller) enqueueUpdateSubnet(oldObj, newObj any) {
7777
return
7878
}
7979

80-
if oldSubnet.Spec.Vpc != newSubnet.Spec.Vpc &&
81-
((oldSubnet.Spec.Vpc != "" || newSubnet.Spec.Vpc != c.config.ClusterRouter) && (oldSubnet.Spec.Vpc != c.config.ClusterRouter || newSubnet.Spec.Vpc != "")) {
82-
// recode last vpc name for subnet
83-
if oldSubnet.Spec.Vpc == "" {
84-
c.subnetLastVpcNameMap.Store(newSubnet.Name, c.config.ClusterRouter)
85-
} else {
86-
c.subnetLastVpcNameMap.Store(newSubnet.Name, oldSubnet.Spec.Vpc)
87-
}
88-
89-
c.updateVpcStatusQueue.Add(oldSubnet.Spec.Vpc)
90-
}
91-
9280
if oldSubnet.Spec.U2OInterconnection != newSubnet.Spec.U2OInterconnection {
9381
klog.Infof("enqueue update vpc %s triggered by u2o interconnection change of subnet %s", newSubnet.Spec.Vpc, key)
9482
c.addOrUpdateVpcQueue.Add(newSubnet.Spec.Vpc)
@@ -482,9 +470,9 @@ func (c *Controller) validateVpcBySubnet(subnet *kubeovnv1.Subnet) (*kubeovnv1.V
482470
klog.Errorf("failed to list vpc, %v", err)
483471
return vpc, err
484472
}
485-
lastVpcName, _ := c.subnetLastVpcNameMap.Load(subnet.Name)
473+
486474
for _, vpc := range vpcs {
487-
if (lastVpcName == "" && subnet.Spec.Vpc != vpc.Name || lastVpcName != "" && lastVpcName != vpc.Name) &&
475+
if subnet.Spec.Vpc != vpc.Name &&
488476
!vpc.Status.Default && util.IsStringsOverlap(vpc.Spec.Namespaces, subnet.Spec.Namespaces) {
489477
err = fmt.Errorf("namespaces %v are overlap with vpc '%s'", subnet.Spec.Namespaces, vpc.Name)
490478
klog.Error(err)
@@ -1035,9 +1023,6 @@ func (c *Controller) handleDeleteSubnet(subnet *kubeovnv1.Subnet) error {
10351023
}
10361024
}
10371025

1038-
// clean up subnet last vpc name cached
1039-
c.subnetLastVpcNameMap.Delete(subnet.Name)
1040-
10411026
return nil
10421027
}
10431028

pkg/util/const.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,6 @@ const (
122122
VpcEgressGatewayLabel = "ovn.kubernetes.io/vpc-egress-gateway"
123123
GenerateHashAnnotation = "ovn.kubernetes.io/generate-hash"
124124

125-
VpcLastName = "ovn.kubernetes.io/last_vpc_name"
126-
VpcLastPolicies = "ovn.kubernetes.io/last_policies"
127-
128125
ServiceExternalIPFromSubnetAnnotation = "ovn.kubernetes.io/service_external_ip_from_subnet"
129126
ServiceHealthCheck = "ovn.kubernetes.io/service_health_check"
130127

pkg/webhook/subnet.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ func (v *ValidatingHook) SubnetUpdateHook(ctx context.Context, req admission.Req
6969
return ctrlwebhook.Denied("can't update gateway of cidr when any IPs in Using")
7070
}
7171

72+
if o.Spec.Vpc != oldSubnet.Spec.Vpc {
73+
if oldSubnet.Spec.Vpc != "" || o.Spec.Vpc != util.DefaultVpc {
74+
return ctrlwebhook.Denied("vpc can only be changed from empty to ovn-cluster")
75+
}
76+
}
77+
7278
if err := util.ValidateSubnet(o); err != nil {
7379
return ctrlwebhook.Denied(err.Error())
7480
}

test/e2e/webhook/subnet/subnet.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,42 @@ var _ = framework.Describe("[group:webhook-subnet]", func() {
9090
_, err = subnetClient.SubnetInterface.Create(context.TODO(), subnet, metav1.CreateOptions{})
9191
framework.ExpectError(err, "subnet %s cidr %s is invalid", subnet.Name, subnet.Spec.CIDRBlock)
9292
})
93+
94+
framework.ConformanceIt("check subnet vpc update validation", func() {
95+
ginkgo.By("Creating subnet " + subnetName)
96+
subnet := framework.MakeSubnet(subnetName, "", cidr, "", "", "", nil, nil, nil)
97+
subnet = subnetClient.CreateSync(subnet)
98+
99+
ginkgo.By("Validating vpc can be changed from empty to ovn-cluster")
100+
modifiedSubnet := subnet.DeepCopy()
101+
modifiedSubnet.Spec.Vpc = util.DefaultVpc
102+
_, err := subnetClient.SubnetInterface.Update(context.TODO(), modifiedSubnet, metav1.UpdateOptions{})
103+
framework.ExpectNoError(err)
104+
105+
ginkgo.By("Validating vpc cannot be changed from ovn-cluster to another value")
106+
subnet = subnetClient.Get(subnetName)
107+
modifiedSubnet = subnet.DeepCopy()
108+
modifiedSubnet.Spec.Vpc = "test-vpc"
109+
_, err = subnetClient.SubnetInterface.Update(context.TODO(), modifiedSubnet, metav1.UpdateOptions{})
110+
framework.ExpectError(err, "vpc can only be changed from empty to ovn-cluster")
111+
112+
ginkgo.By("Validating vpc cannot be changed from ovn-cluster to empty")
113+
subnet = subnetClient.Get(subnetName)
114+
modifiedSubnet = subnet.DeepCopy()
115+
modifiedSubnet.Spec.Vpc = ""
116+
_, err = subnetClient.SubnetInterface.Update(context.TODO(), modifiedSubnet, metav1.UpdateOptions{})
117+
framework.ExpectError(err, "vpc can only be changed from empty to ovn-cluster")
118+
})
119+
120+
framework.ConformanceIt("check subnet vpc cannot be set to non-ovn-cluster on update", func() {
121+
ginkgo.By("Creating subnet " + subnetName + " with empty vpc")
122+
subnet := framework.MakeSubnet(subnetName, "", cidr, "", "", "", nil, nil, nil)
123+
subnet = subnetClient.CreateSync(subnet)
124+
125+
ginkgo.By("Validating vpc cannot be changed from empty to non-ovn-cluster value")
126+
modifiedSubnet := subnet.DeepCopy()
127+
modifiedSubnet.Spec.Vpc = "test-vpc"
128+
_, err := subnetClient.SubnetInterface.Update(context.TODO(), modifiedSubnet, metav1.UpdateOptions{})
129+
framework.ExpectError(err, "vpc can only be changed from empty to ovn-cluster")
130+
})
93131
})

0 commit comments

Comments
 (0)