package node import ( "context" "fmt" "net" "strings" "time" "k8s.io/klog/v2" ) func ValidateNetworkRequirements(ctx context.Context, nct *NodeContext) error { requireLocalIP := func(wantedIP string) error { wantedIP = strings.TrimSpace(wantedIP) if wantedIP == "" { return fmt.Errorf("API server advertise address is required") } ip := net.ParseIP(wantedIP) if ip == nil { return fmt.Errorf("invalid API server advertise address %q", wantedIP) } ifaces, err := net.Interfaces() if err != nil { return fmt.Errorf("list interfaces: %w", err) } for _, iface := range ifaces { addrs, err := iface.Addrs() if err != nil { continue } for _, addr := range addrs { var got net.IP switch v := addr.(type) { case *net.IPNet: got = v.IP case *net.IPAddr: got = v.IP } if got != nil && got.Equal(ip) { return nil } } } return fmt.Errorf("required local IP is not present on any interface: %s", wantedIP) } checkAPIServerReachable := func(endpoint string) error { endpoint = strings.TrimSpace(endpoint) if endpoint == "" { return fmt.Errorf("API server endpoint is required") } host, port, err := net.SplitHostPort(endpoint) if err != nil { return fmt.Errorf("invalid API server endpoint %q: %w", endpoint, err) } if strings.TrimSpace(host) == "" || strings.TrimSpace(port) == "" { return fmt.Errorf("invalid API server endpoint %q", endpoint) } klog.Infof("checking API server reachability: %s:%s", host, port) var lastErr error for i := 0; i < 20; i++ { d := net.Dialer{Timeout: 1 * time.Second} conn, err := d.DialContext(ctx, "tcp", endpoint) if err == nil { _ = conn.Close() klog.Infof("API server is reachable") return nil } lastErr = err select { case <-ctx.Done(): return ctx.Err() case <-time.After(1 * time.Second): } } return fmt.Errorf("cannot reach API server at %s: %w", endpoint, lastErr) } cfg := nct.Config.Spec switch strings.TrimSpace(cfg.ClusterRole) { case "control-plane": if err := requireLocalIP(cfg.APIServerAdvertiseAddress); err != nil { return err } case "worker": if err := requireLocalIP(cfg.APIServerAdvertiseAddress); err != nil { return err } if err := checkAPIServerReachable(cfg.APIServerEndpoint); err != nil { return err } default: return fmt.Errorf("Incorrect ClusterRole: %s", cfg.ClusterRole) } return nil } func CheckUpgradePrereqs(context.Context, *NodeContext) error { klog.Info("check_upgrade_prereqs: TODO implement kubeadm version / skew checks") return nil }