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>
This commit is contained in:
liujian 2025-09-28 16:14:05 +08:00 committed by GitHub
parent 2ee14ff614
commit ea70663492
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,6 +1,7 @@
package handler
import (
"fmt"
"io"
"reflect"
"slices"
@ -136,6 +137,11 @@ func (h *InventoryHandler) Patch(request *restful.Request, response *restful.Res
return
}
if err := validateUniqueHostVariables(updatedInventory); err != nil {
api.HandleBadRequest(response, request, errors.Wrapf(err, "unable to patch Inventory %s/%s in the cluster: %v", namespace, inventoryName, err))
return
}
// completeInventory normalizes the inventory groups:
// - Synchronizes the "kube_control_plane" group to the "etcd" group.
// - Removes duplicate hosts and groups within each group.
@ -443,3 +449,47 @@ func (h *InventoryHandler) ListHosts(request *restful.Request, response *restful
results := query.DefaultList(hostTable, queryParam, less, filter)
_ = response.WriteEntity(results)
}
// validateUniqueHostVariables ensures that certain host variables are unique across all hosts in the inventory.
// Specifically, it checks that:
// - Each internal IPv4 address (_const.VariableIPv4) is assigned to only one host.
// - Each SSH connection (the combination of ssh_host and ssh_port under the "connector" variable) is unique to a single host.
func validateUniqueHostVariables(inventory *kkcorev1.Inventory) error {
// Maps to track uniqueness: internal IPv4 address -> hostname, and "ssh_host:ssh_port" -> hostname
internalIPv4ToHostname := make(map[string]string)
sshConnectionToHostname := make(map[string]string)
for hostname, rawHostVars := range inventory.Spec.Hosts {
hostVars := variable.Extension2Variables(rawHostVars)
// 1. Ensure internal IPv4 address is unique across all hosts
if internalIPv4, ok := hostVars[_const.VariableIPv4].(string); ok && internalIPv4 != "" {
if existingHost, found := internalIPv4ToHostname[internalIPv4]; found && existingHost != hostname {
return fmt.Errorf("duplicate internal_ipv4 detected: %s is assigned to both %s and %s", internalIPv4, existingHost, hostname)
}
internalIPv4ToHostname[internalIPv4] = hostname
}
// 2. Ensure SSH connection (ssh_host + ssh_port) is unique across all hosts
var sshHost, sshPort string
if connector, ok := hostVars[_const.VariableConnector].(map[string]any); ok {
if v, ok := connector[_const.VariableConnectorHost].(string); ok {
sshHost = v
}
switch v := connector[_const.VariableConnectorPort].(type) {
case string:
sshPort = v
case float64:
sshPort = fmt.Sprintf("%.0f", v)
}
}
if sshHost != "" && sshPort != "" {
sshKey := sshHost + ":" + sshPort
if existingHost, found := sshConnectionToHostname[sshKey]; found && existingHost != hostname {
return fmt.Errorf("duplicate SSH connection detected: %s is assigned to both %s and %s", sshKey, existingHost, hostname)
}
sshConnectionToHostname[sshKey] = hostname
}
}
return nil
}