clitools: Added ConfigureDNS

This commit is contained in:
2026-03-27 20:25:54 +08:00
parent 87aa1d4b0b
commit 848daefffe
5 changed files with 132 additions and 24 deletions

View File

@@ -4,11 +4,11 @@ BIN_DIR := bin
build: build:
mkdir -p $(BIN_DIR) mkdir -p $(BIN_DIR)
go build -o $(BIN_DIR)/ctl-$(VERSION) ./cmd/ctl GOOS=linux GOARCH=arm64 go build -o $(BIN_DIR)/ctl-linux-aarch64-$(VERSION) ./cmd/ctl/
# go build -o $(BIN_DIR)/ctl-$(VERSION) ./cmd/ctl
run: run:
go run ./cmd/ctl go run ./cmd/ctl
clean: clean:
rm -rf $(BIN_DIR) rm -rf $(BIN_DIR)

View File

@@ -12,9 +12,11 @@ type Registry struct {
func NewRegistry(ctx *node.NodeContext) *Registry { func NewRegistry(ctx *node.NodeContext) *Registry {
netCfg := node.NetworkConfig{ netCfg := node.NetworkConfig{
MgmtIface: ctx.Config.Spec.Network.ManagementIface, MgmtIface: ctx.Config.Spec.Network.ManagementIface,
MgmtAddress: ctx.Config.Spec.Network.ManagementCIDR, MgmtAddress: ctx.Config.Spec.Network.ManagementCIDR,
MgmtGateway: ctx.Config.Spec.Network.ManagementGW, MgmtGateway: ctx.Config.Spec.Network.ManagementGW,
DNSNameservers: ctx.Config.Spec.Network.DNSNameservers,
DNSSearchDomains: ctx.Config.Spec.Network.DNSSearchDomains,
} }
return &Registry{ return &Registry{
@@ -34,7 +36,7 @@ func NewRegistry(ctx *node.NodeContext) *Registry {
"allow_single_node_scheduling": node.AllowSingleNodeScheduling, "allow_single_node_scheduling": node.AllowSingleNodeScheduling,
"ensure_ip_forward": node.EnsureIPForward, "ensure_ip_forward": node.EnsureIPForward,
"configure_mgmt_interface": node.ConfigureMgmtInterface(netCfg), "configure_mgmt_interface": node.ConfigureMgmtInterface(netCfg),
"configure_dns": node.ConfigureDNS, "configure_dns": node.ConfigureDNS(netCfg),
"set_hostname_if_needed": node.SetHostnameIfNeeded, "set_hostname_if_needed": node.SetHostnameIfNeeded,
"print_summary": node.PrintSummary, "print_summary": node.PrintSummary,
"reconcile_control_plane": node.ReconcileControlPlane, "reconcile_control_plane": node.ReconcileControlPlane,

View File

@@ -1,9 +1,9 @@
package internal package internal
import ( import (
"github.com/spf13/cobra"
"undecided.project/monok8s/pkg/bootstrap" "undecided.project/monok8s/pkg/bootstrap"
"undecided.project/monok8s/pkg/config" "undecided.project/monok8s/pkg/config"
"github.com/spf13/cobra"
) )
func NewCmdInternal() *cobra.Command { func NewCmdInternal() *cobra.Command {
@@ -18,11 +18,19 @@ func NewCmdInternal() *cobra.Command {
if err != nil { if err != nil {
return err return err
} }
cfg, err := (config.Loader{}).Load(path) cfg, err := (config.Loader{}).Load(path)
if err != nil { if err != nil {
return err return err
} }
return bootstrap.NewRunner(cfg).RunNamedStep(cmd.Context(), args[0])
err = bootstrap.NewRunner(cfg).RunNamedStep(cmd.Context(), args[0])
if err != nil {
return err
}
cmd.Println("OK")
return nil
}, },
}) })
cmd.PersistentFlags().StringVarP(&configPath, "config", "c", "", "path to MonoKSConfig yaml") cmd.PersistentFlags().StringVarP(&configPath, "config", "c", "", "path to MonoKSConfig yaml")

View File

@@ -4,16 +4,19 @@ import (
"context" "context"
"fmt" "fmt"
"net" "net"
"os"
"strings" "strings"
system "undecided.project/monok8s/pkg/system"
"k8s.io/klog/v2" "k8s.io/klog/v2"
system "undecided.project/monok8s/pkg/system"
) )
type NetworkConfig struct { type NetworkConfig struct {
MgmtIface string MgmtIface string
MgmtAddress string MgmtAddress string
MgmtGateway string MgmtGateway string
DNSNameservers []string
DNSSearchDomains []string
} }
func ConfigureMgmtInterface(cfg NetworkConfig) Step { func ConfigureMgmtInterface(cfg NetworkConfig) Step {
@@ -24,18 +27,31 @@ func ConfigureMgmtInterface(cfg NetworkConfig) Step {
if strings.TrimSpace(cfg.MgmtAddress) == "" { if strings.TrimSpace(cfg.MgmtAddress) == "" {
return fmt.Errorf("mgmt address is required") return fmt.Errorf("mgmt address is required")
} }
ip, ipNet, err := net.ParseCIDR(cfg.MgmtAddress)
ip, ipNet, err := net.ParseCIDR(strings.TrimSpace(cfg.MgmtAddress))
if err != nil { if err != nil {
return fmt.Errorf("invalid mgmt address %q: %w", cfg.MgmtAddress, err) return fmt.Errorf("invalid mgmt address %q: %w", cfg.MgmtAddress, err)
} }
wantIP := ip.String()
if gw := strings.TrimSpace(cfg.MgmtGateway); gw != "" && net.ParseIP(gw) == nil { ip4 := ip.To4()
return fmt.Errorf("invalid mgmt gateway %q", gw) if ip4 == nil {
return fmt.Errorf("mgmt address must be IPv4: %q", cfg.MgmtAddress)
}
wantIP := ip4.String()
wantCIDR := fmt.Sprintf("%s/%d", wantIP, maskSize(ipNet.Mask))
if gw := strings.TrimSpace(cfg.MgmtGateway); gw != "" {
gwIP := net.ParseIP(gw)
if gwIP == nil || gwIP.To4() == nil {
return fmt.Errorf("invalid mgmt gateway %q", gw)
}
} }
if _, err := nctx.System.Run(ctx, "ip", "link", "show", "dev", cfg.MgmtIface); err != nil { if _, err := nctx.System.Run(ctx, "ip", "link", "show", "dev", cfg.MgmtIface); err != nil {
return fmt.Errorf("interface not found: %s: %w", cfg.MgmtIface, err) return fmt.Errorf("interface not found: %s: %w", cfg.MgmtIface, err)
} }
if _, err := nctx.System.Run(ctx, "ip", "link", "set", "dev", cfg.MgmtIface, "up"); err != nil { if _, err := nctx.System.Run(ctx, "ip", "link", "set", "dev", cfg.MgmtIface, "up"); err != nil {
return fmt.Errorf("failed to bring up interface %s: %w", cfg.MgmtIface, err) return fmt.Errorf("failed to bring up interface %s: %w", cfg.MgmtIface, err)
} }
@@ -44,11 +60,12 @@ func ConfigureMgmtInterface(cfg NetworkConfig) Step {
if err != nil { if err != nil {
return fmt.Errorf("failed checking existing address on %s: %w", cfg.MgmtIface, err) return fmt.Errorf("failed checking existing address on %s: %w", cfg.MgmtIface, err)
} }
if hasAddr { if hasAddr {
klog.Infof("address already present on %s: %s", cfg.MgmtIface, cfg.MgmtAddress) klog.Infof("address already present on %s: %s", cfg.MgmtIface, wantCIDR)
} else { } else {
if _, err := nctx.System.Run(ctx, "ip", "addr", "add", ipNet.String(), "dev", cfg.MgmtIface); err != nil { if _, err := nctx.System.Run(ctx, "ip", "addr", "add", wantCIDR, "dev", cfg.MgmtIface); err != nil {
return fmt.Errorf("failed assigning %s to %s: %w", ipNet.String(), cfg.MgmtIface, err) return fmt.Errorf("failed assigning %s to %s: %w", wantCIDR, cfg.MgmtIface, err)
} }
} }
@@ -57,17 +74,88 @@ func ConfigureMgmtInterface(cfg NetworkConfig) Step {
return fmt.Errorf("failed setting default route via %s dev %s: %w", gw, cfg.MgmtIface, err) return fmt.Errorf("failed setting default route via %s dev %s: %w", gw, cfg.MgmtIface, err)
} }
} }
return nil return nil
} }
} }
func maskSize(m net.IPMask) int {
ones, _ := m.Size()
return ones
}
func EnsureIPForward(ctx context.Context, n *NodeContext) error { func EnsureIPForward(ctx context.Context, n *NodeContext) error {
return system.EnsureSysctl(ctx, n.System, "net.ipv4.ip_forward", "1") return system.EnsureSysctl(ctx, n.System, "net.ipv4.ip_forward", "1")
} }
func ConfigureDNS(context.Context, *NodeContext) error { func ConfigureDNS(cfg NetworkConfig) Step {
klog.Info("configure_dns: TODO implement resolv.conf rendering") return func(context.Context, *NodeContext) error {
return nil
if len(cfg.DNSNameservers) == 0 {
return nil
}
var nameservers []string
for _, ns := range cfg.DNSNameservers {
ns = strings.TrimSpace(ns)
if ns == "" {
continue
}
if ip := net.ParseIP(ns); ip == nil {
return fmt.Errorf("invalid DNS nameserver %q", ns)
}
nameservers = append(nameservers, ns)
}
if len(nameservers) == 0 {
return fmt.Errorf("DNSNameservers is set but no valid nameservers were parsed")
}
var searchDomains []string
for _, d := range cfg.DNSSearchDomains {
d = strings.TrimSpace(d)
if d == "" {
continue
}
searchDomains = append(searchDomains, d)
}
var b strings.Builder
if len(searchDomains) > 0 {
b.WriteString("search ")
b.WriteString(strings.Join(searchDomains, " "))
b.WriteByte('\n')
}
for _, ns := range nameservers {
b.WriteString("nameserver ")
b.WriteString(ns)
b.WriteByte('\n')
}
b.WriteString("options timeout:2 attempts:3\n")
const (
resolvDir = "/etc"
tmpPath = "/etc/resolv.conf.monok8s.tmp"
resolvPath = "/etc/resolv.conf"
)
if err := os.MkdirAll(resolvDir, 0o755); err != nil {
klog.Warningf("failed to create %s for DNS config: %v; leaving %s unchanged", resolvDir, err, resolvPath)
return nil
}
if err := os.WriteFile(tmpPath, []byte(b.String()), 0o644); err != nil {
klog.Warningf("failed to write temporary DNS config %s: %v; leaving %s unchanged", tmpPath, err, resolvPath)
return nil
}
if err := os.Rename(tmpPath, resolvPath); err != nil {
_ = os.Remove(tmpPath)
klog.Warningf("failed to install DNS config at %s: %v; leaving existing DNS config unchanged", resolvPath, err)
return nil
}
return nil
}
} }
func interfaceHasIPv4(ctx context.Context, nctx *NodeContext, iface, wantIP string) (bool, error) { func interfaceHasIPv4(ctx context.Context, nctx *NodeContext, iface, wantIP string) (bool, error) {

View File

@@ -91,6 +91,12 @@ RELEASE_DEPS := \
build.env \ build.env \
makefile makefile
CLITOOLS := \
clitools/pkg \
clitools/cmd \
clitools/go.mod \
clitools/go.sum
# ---- Directory creation ------------------------------------------------------ # ---- Directory creation ------------------------------------------------------
$(PACKAGES_DIR): $(PACKAGES_DIR):
@@ -258,13 +264,17 @@ initramfs: $(INITRAMFS)
itb: $(BOARD_ITB) itb: $(BOARD_ITB)
build-base: $(BUILD_BASE_STAMP) build-base: $(BUILD_BASE_STAMP)
clitools: $(CLITOOLS)
$(MAKE) -C clitools
clean: clean:
rm -f \ rm -f \
$(BUILD_BASE_STAMP) \ $(BUILD_BASE_STAMP) \
$(KERNEL_IMAGE) \ $(KERNEL_IMAGE) \
$(INITRAMFS) \ $(INITRAMFS) \
$(BOARD_ITB) \ $(BOARD_ITB) \
$(RELEASE_IMAGE) $(RELEASE_IMAGE) \
$(CLITOOLS)
distclean: clean distclean: clean
rm -rf $(OUT_DIR) rm -rf $(OUT_DIR)
@@ -272,5 +282,5 @@ distclean: clean
pkgclean: pkgclean:
rm -rf $(PACKAGES_DIR) rm -rf $(PACKAGES_DIR)
.PHONY: release kernel initramfs itb build-base clean distclean pkgclean \ .PHONY: release kernel initramfs itb build-base clitools clean distclean pkgclean \
cluster-config cluster-defconfig cluster-print cluster-config cluster-defconfig cluster-print