Skip to content

Commit 3d128f7

Browse files
pbasovs3rj1k
authored andcommitted
Allow changing DNSNameservers in subnet config for OpenstackCluster
1 parent d884dd5 commit 3d128f7

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

pkg/cloud/services/networking/network.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ func (s *Service) ReconcileSubnet(openStackCluster *infrav1.OpenStackCluster, cl
201201
} else if len(subnetList) == 1 {
202202
subnet = &subnetList[0]
203203
s.scope.Logger().V(6).Info("Reusing existing subnet", "name", subnet.Name, "id", subnet.ID)
204+
205+
if err := s.updateSubnetDNSNameservers(openStackCluster, subnet); err != nil {
206+
return err
207+
}
204208
}
205209

206210
openStackCluster.Status.Network.Subnets = []infrav1.Subnet{
@@ -248,6 +252,44 @@ func (s *Service) createSubnet(openStackCluster *infrav1.OpenStackCluster, clust
248252
return subnet, nil
249253
}
250254

255+
// updateSubnetDNSNameservers updates the DNS nameservers for an existing subnet if they differ from the desired configuration.
256+
func (s *Service) updateSubnetDNSNameservers(openStackCluster *infrav1.OpenStackCluster, subnet *subnets.Subnet) error {
257+
// Picking the first managed subnet since we only support one for now
258+
desiredNameservers := openStackCluster.Spec.ManagedSubnets[0].DNSNameservers
259+
currentNameservers := subnet.DNSNameservers
260+
261+
needsUpdate := false
262+
if len(desiredNameservers) != len(currentNameservers) {
263+
needsUpdate = true
264+
} else {
265+
for i, ns := range desiredNameservers {
266+
if i >= len(currentNameservers) || ns != currentNameservers[i] {
267+
needsUpdate = true
268+
break
269+
}
270+
}
271+
}
272+
273+
if needsUpdate {
274+
s.scope.Logger().Info("Updating subnet DNS nameservers", "id", subnet.ID, "from", currentNameservers, "to", desiredNameservers)
275+
276+
updateOpts := subnets.UpdateOpts{
277+
DNSNameservers: &desiredNameservers,
278+
}
279+
280+
updatedSubnet, err := s.client.UpdateSubnet(subnet.ID, updateOpts)
281+
if err != nil {
282+
record.Warnf(openStackCluster, "FailedUpdateSubnet", "Failed to update DNS nameservers for subnet %s: %v", subnet.ID, err)
283+
return err
284+
}
285+
286+
*subnet = *updatedSubnet
287+
record.Eventf(openStackCluster, "SuccessfulUpdateSubnet", "Updated DNS nameservers for subnet %s", subnet.ID)
288+
}
289+
290+
return nil
291+
}
292+
251293
func (s *Service) getNetworkByName(networkName string) (networks.Network, error) {
252294
opts := networks.ListOpts{
253295
Name: networkName,

pkg/webhooks/openstackcluster_webhook.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,62 @@ func (*openStackClusterWebhook) ValidateUpdate(_ context.Context, oldObjRaw, new
193193
newObj.Spec.ManagedSecurityGroups.AllowAllInClusterTraffic = false
194194
}
195195

196+
// Allow changes only to DNSNameservers in ManagedSubnets spec
197+
if newObj.Spec.ManagedSubnets != nil && oldObj.Spec.ManagedSubnets != nil {
198+
// Check if any fields other than DNSNameservers have changed
199+
if len(oldObj.Spec.ManagedSubnets) != len(newObj.Spec.ManagedSubnets) {
200+
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "managedSubnets"), "cannot add or remove subnets"))
201+
} else {
202+
// Build maps of subnets by CIDR
203+
oldSubnetMap := make(map[string]infrav1.SubnetSpec)
204+
newSubnetMap := make(map[string]infrav1.SubnetSpec)
205+
206+
for _, subnet := range oldObj.Spec.ManagedSubnets {
207+
oldSubnetMap[subnet.CIDR] = subnet
208+
}
209+
210+
// Check if all new subnets have matching old subnets with the same CIDR
211+
for _, newSubnet := range newObj.Spec.ManagedSubnets {
212+
oldSubnet, exists := oldSubnetMap[newSubnet.CIDR]
213+
if !exists {
214+
allErrs = append(allErrs, field.Forbidden(
215+
field.NewPath("spec", "managedSubnets"),
216+
fmt.Sprintf("cannot change subnet CIDR from existing value to %s", newSubnet.CIDR),
217+
))
218+
continue
219+
}
220+
221+
// Check if AllocationPools have changed
222+
if !reflect.DeepEqual(oldSubnet.AllocationPools, newSubnet.AllocationPools) {
223+
allErrs = append(allErrs, field.Forbidden(
224+
field.NewPath("spec", "managedSubnets").Child("allocationPools"),
225+
"cannot modify allocation pools in existing subnet",
226+
))
227+
}
228+
229+
newSubnetMap[newSubnet.CIDR] = newSubnet
230+
}
231+
232+
// Create modified copies of the subnets with DNSNameservers cleared
233+
oldSubnets := make([]infrav1.SubnetSpec, 0, len(oldObj.Spec.ManagedSubnets))
234+
newSubnets := make([]infrav1.SubnetSpec, 0, len(newObj.Spec.ManagedSubnets))
235+
for _, subnet := range oldObj.Spec.ManagedSubnets {
236+
subnetCopy := subnet
237+
subnetCopy.DNSNameservers = nil
238+
oldSubnets = append(oldSubnets, subnetCopy)
239+
240+
if newSubnet, exists := newSubnetMap[subnet.CIDR]; exists {
241+
newSubnetCopy := newSubnet
242+
newSubnetCopy.DNSNameservers = nil
243+
newSubnets = append(newSubnets, newSubnetCopy)
244+
}
245+
}
246+
247+
oldObj.Spec.ManagedSubnets = oldSubnets
248+
newObj.Spec.ManagedSubnets = newSubnets
249+
}
250+
}
251+
196252
// Allow changes on AllowedCIDRs
197253
if newObj.Spec.APIServerLoadBalancer != nil && oldObj.Spec.APIServerLoadBalancer != nil {
198254
oldObj.Spec.APIServerLoadBalancer.AllowedCIDRs = []string{}

0 commit comments

Comments
 (0)