mirror of
https://github.com/kubesphere/kubekey.git
synced 2025-12-25 17:12:50 +00:00
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:
parent
2ee14ff614
commit
ea70663492
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue