Skip to content

Commit 7a141b0

Browse files
pbasovs3rj1k
authored andcommitted
Allow changing DNSNameservers in subnet config for OpenstackCluster
1 parent c11ea4b commit 7a141b0

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
@@ -139,6 +139,62 @@ func (*openStackClusterWebhook) ValidateUpdate(_ context.Context, oldObjRaw, new
139139
newObj.Spec.ManagedSecurityGroups.AllowAllInClusterTraffic = false
140140
}
141141

142+
// Allow changes only to DNSNameservers in ManagedSubnets spec
143+
if newObj.Spec.ManagedSubnets != nil && oldObj.Spec.ManagedSubnets != nil {
144+
// Check if any fields other than DNSNameservers have changed
145+
if len(oldObj.Spec.ManagedSubnets) != len(newObj.Spec.ManagedSubnets) {
146+
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "managedSubnets"), "cannot add or remove subnets"))
147+
} else {
148+
// Build maps of subnets by CIDR
149+
oldSubnetMap := make(map[string]infrav1.SubnetSpec)
150+
newSubnetMap := make(map[string]infrav1.SubnetSpec)
151+
152+
for _, subnet := range oldObj.Spec.ManagedSubnets {
153+
oldSubnetMap[subnet.CIDR] = subnet
154+
}
155+
156+
// Check if all new subnets have matching old subnets with the same CIDR
157+
for _, newSubnet := range newObj.Spec.ManagedSubnets {
158+
oldSubnet, exists := oldSubnetMap[newSubnet.CIDR]
159+
if !exists {
160+
allErrs = append(allErrs, field.Forbidden(
161+
field.NewPath("spec", "managedSubnets"),
162+
fmt.Sprintf("cannot change subnet CIDR from existing value to %s", newSubnet.CIDR),
163+
))
164+
continue
165+
}
166+
167+
// Check if AllocationPools have changed
168+
if !reflect.DeepEqual(oldSubnet.AllocationPools, newSubnet.AllocationPools) {
169+
allErrs = append(allErrs, field.Forbidden(
170+
field.NewPath("spec", "managedSubnets").Child("allocationPools"),
171+
"cannot modify allocation pools in existing subnet",
172+
))
173+
}
174+
175+
newSubnetMap[newSubnet.CIDR] = newSubnet
176+
}
177+
178+
// Create modified copies of the subnets with DNSNameservers cleared
179+
oldSubnets := make([]infrav1.SubnetSpec, 0, len(oldObj.Spec.ManagedSubnets))
180+
newSubnets := make([]infrav1.SubnetSpec, 0, len(newObj.Spec.ManagedSubnets))
181+
for _, subnet := range oldObj.Spec.ManagedSubnets {
182+
subnetCopy := subnet
183+
subnetCopy.DNSNameservers = nil
184+
oldSubnets = append(oldSubnets, subnetCopy)
185+
186+
if newSubnet, exists := newSubnetMap[subnet.CIDR]; exists {
187+
newSubnetCopy := newSubnet
188+
newSubnetCopy.DNSNameservers = nil
189+
newSubnets = append(newSubnets, newSubnetCopy)
190+
}
191+
}
192+
193+
oldObj.Spec.ManagedSubnets = oldSubnets
194+
newObj.Spec.ManagedSubnets = newSubnets
195+
}
196+
}
197+
142198
// Allow changes on AllowedCIDRs
143199
if newObj.Spec.APIServerLoadBalancer != nil && oldObj.Spec.APIServerLoadBalancer != nil {
144200
oldObj.Spec.APIServerLoadBalancer.AllowedCIDRs = []string{}

0 commit comments

Comments
 (0)