Skip to content

Commit ea70663

Browse files
authored
feat: add validation for unique host variables in inventory (#2779)
This update introduces a function to ensure that internal IPv4 addresses and SSH connections are unique across all hosts in the inventory. It checks for duplicates and returns an error if any are found, enhancing the integrity of the inventory data. Signed-off-by: redscholar <blacktiledhouse@gmail.com>
1 parent 2ee14ff commit ea70663

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

pkg/web/handler/inventory.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package handler
22

33
import (
4+
"fmt"
45
"io"
56
"reflect"
67
"slices"
@@ -136,6 +137,11 @@ func (h *InventoryHandler) Patch(request *restful.Request, response *restful.Res
136137
return
137138
}
138139

140+
if err := validateUniqueHostVariables(updatedInventory); err != nil {
141+
api.HandleBadRequest(response, request, errors.Wrapf(err, "unable to patch Inventory %s/%s in the cluster: %v", namespace, inventoryName, err))
142+
return
143+
}
144+
139145
// completeInventory normalizes the inventory groups:
140146
// - Synchronizes the "kube_control_plane" group to the "etcd" group.
141147
// - Removes duplicate hosts and groups within each group.
@@ -443,3 +449,47 @@ func (h *InventoryHandler) ListHosts(request *restful.Request, response *restful
443449
results := query.DefaultList(hostTable, queryParam, less, filter)
444450
_ = response.WriteEntity(results)
445451
}
452+
453+
// validateUniqueHostVariables ensures that certain host variables are unique across all hosts in the inventory.
454+
// Specifically, it checks that:
455+
// - Each internal IPv4 address (_const.VariableIPv4) is assigned to only one host.
456+
// - Each SSH connection (the combination of ssh_host and ssh_port under the "connector" variable) is unique to a single host.
457+
func validateUniqueHostVariables(inventory *kkcorev1.Inventory) error {
458+
// Maps to track uniqueness: internal IPv4 address -> hostname, and "ssh_host:ssh_port" -> hostname
459+
internalIPv4ToHostname := make(map[string]string)
460+
sshConnectionToHostname := make(map[string]string)
461+
462+
for hostname, rawHostVars := range inventory.Spec.Hosts {
463+
hostVars := variable.Extension2Variables(rawHostVars)
464+
465+
// 1. Ensure internal IPv4 address is unique across all hosts
466+
if internalIPv4, ok := hostVars[_const.VariableIPv4].(string); ok && internalIPv4 != "" {
467+
if existingHost, found := internalIPv4ToHostname[internalIPv4]; found && existingHost != hostname {
468+
return fmt.Errorf("duplicate internal_ipv4 detected: %s is assigned to both %s and %s", internalIPv4, existingHost, hostname)
469+
}
470+
internalIPv4ToHostname[internalIPv4] = hostname
471+
}
472+
473+
// 2. Ensure SSH connection (ssh_host + ssh_port) is unique across all hosts
474+
var sshHost, sshPort string
475+
if connector, ok := hostVars[_const.VariableConnector].(map[string]any); ok {
476+
if v, ok := connector[_const.VariableConnectorHost].(string); ok {
477+
sshHost = v
478+
}
479+
switch v := connector[_const.VariableConnectorPort].(type) {
480+
case string:
481+
sshPort = v
482+
case float64:
483+
sshPort = fmt.Sprintf("%.0f", v)
484+
}
485+
}
486+
if sshHost != "" && sshPort != "" {
487+
sshKey := sshHost + ":" + sshPort
488+
if existingHost, found := sshConnectionToHostname[sshKey]; found && existingHost != hostname {
489+
return fmt.Errorf("duplicate SSH connection detected: %s is assigned to both %s and %s", sshKey, existingHost, hostname)
490+
}
491+
sshConnectionToHostname[sshKey] = hostname
492+
}
493+
}
494+
return nil
495+
}

0 commit comments

Comments
 (0)