From 23ecc1e79692345cd1a0b38035f6bff70f596201 Mon Sep 17 00:00:00 2001 From: Ivan Sim Date: Thu, 28 Nov 2024 18:39:31 -0800 Subject: [PATCH 1/3] Add rke2 network configuration to installer Signed-off-by: Ivan Sim --- pkg/config/config.go | 4 + .../templates/rke2-90-harvester-server.yaml | 6 +- pkg/console/constant.go | 13 + pkg/console/install_panels.go | 263 ++++++++++++++++++ 4 files changed, 283 insertions(+), 3 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index 1086ac99d..39279c4f5 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -150,6 +150,10 @@ type Install struct { VipHwAddr string `json:"vipHwAddr,omitempty"` VipMode string `json:"vipMode,omitempty"` + ClusterDNS string `json:"clusterDns,omitempty"` + ClusterPodCIDR string `json:"clusterPodCidr,omitempty"` + ClusterServiceCIDR string `json:"clusterServiceCidr,omitempty"` + ForceEFI bool `json:"forceEfi,omitempty"` Device string `json:"device,omitempty"` ConfigURL string `json:"configUrl,omitempty"` diff --git a/pkg/config/templates/rke2-90-harvester-server.yaml b/pkg/config/templates/rke2-90-harvester-server.yaml index 39077a406..01dcee0cb 100644 --- a/pkg/config/templates/rke2-90-harvester-server.yaml +++ b/pkg/config/templates/rke2-90-harvester-server.yaml @@ -1,7 +1,7 @@ cni: multus,canal -cluster-cidr: 10.52.0.0/16 -service-cidr: 10.53.0.0/16 -cluster-dns: 10.53.0.10 +cluster-cidr: {{ or .ClusterPodCIDR "10.52.0.0/16" }} +service-cidr: {{ or .ClusterServiceCIDR "10.53.0.0/16" }} +cluster-dns: {{ or .ClusterDNS "10.53.0.10" }} tls-san: - {{ .Vip }} {{- with $args := .GetKubeletArgs }} diff --git a/pkg/console/constant.go b/pkg/console/constant.go index 64368668f..9a946612c 100644 --- a/pkg/console/constant.go +++ b/pkg/console/constant.go @@ -71,6 +71,19 @@ const ( vipLabel = "VIP" askVipMethodLabel = "VIP Mode" + clusterNetworkTitle = "Configure cluster network" + clusterPodCIDRLabel = "Pod CIDR (optional) " + clusterServiceCIDRLabel = "Service CIDR (optional) " + clusterDNSLabel = "Cluster DNS IP (optional) " + clusterPodCIDRPanel = "podCIDRPanel" + clusterServiceCIDRPanel = "serviceCIDRPanel" + clusterDNSPanel = "clusterDNSPanel" + clusterNetworkNotePanel = "clusterNetworkNotePanel" + clusterNetworkDNSNotePanel = "clusterNetworkDNSNotePanel" + clusterNetworkValidatorPanel = "clusterNetworkValidatorPanel" + clusterNetworkNote = "Note: Leave blank to use the default pod CIDR 10.52.0.0/16, service CIDR 10.53.0.0/16 and cluster DNS 10.53.0.10." + clusterNetworkDNSNote = "If the service CIDR is changed, the DNS IP must be updated to be within the service CIDR." + clusterTokenCreateNote = "Note: The token is used for adding nodes to the cluster" clusterTokenJoinNote = "Note: Input the token of the existing cluster" serverURLNote = "Note: Input VIP/domain name of the management node" diff --git a/pkg/console/install_panels.go b/pkg/console/install_panels.go index cd3dbc9bc..10f5aa6d6 100644 --- a/pkg/console/install_panels.go +++ b/pkg/console/install_panels.go @@ -3,6 +3,7 @@ package console import ( "fmt" "net" + "net/netip" "os" "os/exec" "strconv" @@ -157,6 +158,7 @@ func setPanels(c *Console) error { addDiskPanel, addHostnamePanel, addNetworkPanel, + addClusterNetworkPanel, addVIPPanel, addDNSServersPanel, addNTPServersPanel, @@ -1230,6 +1232,9 @@ func addHostnamePanel(c *Console) error { prev := func(_ *gocui.Gui, _ *gocui.View) error { c.CloseElements(hostnamePanel, hostnameValidatorPanel) + if c.config.Install.Mode == config.ModeCreate { + return showClusterNetworkPage(c) + } return showNetworkPage(c) } @@ -1448,6 +1453,9 @@ func addNetworkPanel(c *Console) error { spinner.Stop(false, "") g.Update(func(_ *gocui.Gui) error { closeThisPage() + if c.config.Install.Mode == config.ModeCreate { + return showClusterNetworkPage(c) + } return showHostnamePage(c) }) } @@ -1744,6 +1752,261 @@ func addNetworkPanel(c *Console) error { return nil } +func showClusterNetworkPage(c *Console) error { + return showNext( + c, + clusterServiceCIDRPanel, + clusterDNSPanel, + clusterNetworkNotePanel, + clusterNetworkDNSNotePanel, + clusterNetworkValidatorPanel, + clusterPodCIDRPanel) +} + +func addClusterNetworkPanel(c *Console) error { + // define page navigation + closePage := func() { + c.CloseElements( + clusterPodCIDRPanel, + clusterServiceCIDRPanel, + clusterDNSPanel, + clusterNetworkNotePanel, + clusterNetworkDNSNotePanel, + clusterNetworkValidatorPanel) + } + + prevPage := func(_ *gocui.Gui, _ *gocui.View) error { + closePage() + return showNetworkPage(c) + } + + nextPage := func() error { + closePage() + return showHostnamePage(c) + } + + setLocation := createVerticalLocator(c) + + // set up the pod CIDR input panel + podCIDRInput, err := widgets.NewInput( + c.Gui, + clusterPodCIDRPanel, + clusterPodCIDRLabel, + false) + if err != nil { + return err + } + podCIDRInput.PreShow = func() error { + c.Cursor = true + podCIDRInput.Value = c.config.ClusterPodCIDR + + if err := c.setContentByName( + titlePanel, + clusterNetworkTitle); err != nil { + return err + } + + if err := c.setContentByName( + clusterNetworkNotePanel, + clusterNetworkNote); err != nil { + return err + } + + if err := c.setContentByName( + clusterNetworkDNSNotePanel, + clusterNetworkDNSNote); err != nil { + return err + } + + // reset any previous error in the validator panel before + // showing the rest of the page + return c.setContentByName(clusterNetworkValidatorPanel, "") + } + + // set up the service CIDR input panel + serviceCIDRInput, err := widgets.NewInput( + c.Gui, + clusterServiceCIDRPanel, + clusterServiceCIDRLabel, + false) + if err != nil { + return err + } + + serviceCIDRInput.PreShow = func() error { + c.Cursor = true + serviceCIDRInput.Value = c.config.ClusterServiceCIDR + return nil + } + + // set up the cluster DNS input panel + dnsInput, err := widgets.NewInput( + c.Gui, + clusterDNSPanel, + clusterDNSLabel, + false) + if err != nil { + return err + } + + dnsInput.PreShow = func() error { + c.Cursor = true + dnsInput.Value = c.config.ClusterDNS + return nil + } + + // define inputs validators + validateCIDR := func(cidr string) error { + cidr = strings.TrimSpace(cidr) + if cidr == "" { + return nil + } + + _, err := netip.ParsePrefix(cidr) + return err + } + + validateDNSIP := func(ip string) error { + ip = strings.TrimSpace(ip) + serviceCIDR, err := serviceCIDRInput.GetData() + if err != nil { + return err + } + if ip == "" && serviceCIDR == "" { + return nil + } + + // the DNS IP address must be well-formed and within the + // service CIDR + ipAddr, err := netip.ParseAddr(ip) + if err != nil { + return fmt.Errorf("Invalid cluster DNS IP: %w", err) + } + + svcNet, err := netip.ParsePrefix(serviceCIDR) + if err != nil { + return fmt.Errorf("To override the cluster DNS IP, the service CIDR must be valid: %w", err) + } + + if !svcNet.Contains(ipAddr) { + return fmt.Errorf("Invalid cluster DNS IP: %s is not in the service CIDR %s", ip, serviceCIDR) + } + + return nil + } + + // define input confirm actions + podCIDRConfirm := func(_ *gocui.Gui, _ *gocui.View) error { + podCIDR, err := podCIDRInput.GetData() + if err != nil { + return err + } + + if err := validateCIDR(podCIDR); err != nil { + c.setContentByName( + clusterNetworkValidatorPanel, + fmt.Sprintf("Invalid pod CIDR: %s", err)) + return nil + } + c.config.ClusterPodCIDR = podCIDR + + // reset any previous error in the validator panel before + // moving to the next panel + c.setContentByName(clusterNetworkValidatorPanel, "") + return showNext(c, clusterServiceCIDRPanel) + } + + serviceCIDRConfirm := func(_ *gocui.Gui, _ *gocui.View) error { + serviceCIDR, err := serviceCIDRInput.GetData() + if err != nil { + return err + } + + if err := validateCIDR(serviceCIDR); err != nil { + c.setContentByName( + clusterNetworkValidatorPanel, + fmt.Sprintf("Invalid service CIDR: %s", err)) + return nil + } + c.config.ClusterServiceCIDR = serviceCIDR + + // reset any previous error in the validator panel before + // moving to the next panel + c.setContentByName(clusterNetworkValidatorPanel, "") + return showNext(c, clusterDNSPanel) + } + + dnsConfirm := func(_ *gocui.Gui, _ *gocui.View) error { + dns, err := dnsInput.GetData() + if err != nil { + return err + } + if err := validateDNSIP(dns); err != nil { + c.setContentByName(clusterNetworkValidatorPanel, err.Error()) + return nil + } + c.config.ClusterDNS = dns + + // reset the validator panel before moving to the next page + c.setContentByName(clusterNetworkValidatorPanel, "") + return nextPage() + } + + // configure key bindings and element locations + podCIDRInput.KeyBindings = map[gocui.Key]func(*gocui.Gui, *gocui.View) error{ + gocui.KeyEsc: prevPage, + gocui.KeyArrowUp: prevPage, + gocui.KeyArrowDown: podCIDRConfirm, + gocui.KeyEnter: podCIDRConfirm, + } + setLocation(podCIDRInput, 3) + c.AddElement(clusterPodCIDRPanel, podCIDRInput) + + serviceCIDRInput.KeyBindings = map[gocui.Key]func(*gocui.Gui, *gocui.View) error{ + gocui.KeyEsc: prevPage, + gocui.KeyArrowUp: func(_ *gocui.Gui, _ *gocui.View) error { + return showNext(c, clusterPodCIDRPanel) + }, + gocui.KeyArrowDown: serviceCIDRConfirm, + gocui.KeyEnter: serviceCIDRConfirm, + } + setLocation(serviceCIDRInput, 3) + c.AddElement(clusterServiceCIDRPanel, serviceCIDRInput) + + dnsInput.KeyBindings = map[gocui.Key]func(*gocui.Gui, *gocui.View) error{ + gocui.KeyEsc: prevPage, + gocui.KeyArrowUp: func(_ *gocui.Gui, _ *gocui.View) error { + return showNext(c, clusterServiceCIDRPanel) + }, + gocui.KeyArrowDown: dnsConfirm, + gocui.KeyEnter: dnsConfirm, + } + setLocation(dnsInput, 3) + c.AddElement(clusterDNSPanel, dnsInput) + + // set up notes panels + notePanel := widgets.NewPanel(c.Gui, clusterNetworkNotePanel) + notePanel.Focus = false + setLocation(notePanel, 3) + c.AddElement(clusterNetworkNotePanel, notePanel) + + dnsNotePanel := widgets.NewPanel(c.Gui, clusterNetworkDNSNotePanel) + dnsNotePanel.Focus = false + setLocation(dnsNotePanel, 3) + c.AddElement(clusterNetworkDNSNotePanel, dnsNotePanel) + + // set up validator panel for warning and error messages + validatorPanel := widgets.NewPanel(c.Gui, clusterNetworkValidatorPanel) + validatorPanel.FgColor = gocui.ColorRed + validatorPanel.Focus = false + maxX, _ := c.Gui.Size() + validatorPanel.X1 = maxX / 8 * 6 + setLocation(validatorPanel, 3) + c.AddElement(clusterNetworkValidatorPanel, validatorPanel) + + return nil +} + func getBondModeOptions() ([]widgets.Option, error) { return []widgets.Option{ { From 0819b79e48396245675f536410bb9db13bd40f71 Mon Sep 17 00:00:00 2001 From: Ivan Sim Date: Fri, 6 Dec 2024 17:21:08 -0800 Subject: [PATCH 2/3] Declutter input panel labels Signed-off-by: Ivan Sim --- pkg/console/constant.go | 9 ++++----- pkg/console/install_panels.go | 16 ++-------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/pkg/console/constant.go b/pkg/console/constant.go index 9a946612c..a1ea13d0f 100644 --- a/pkg/console/constant.go +++ b/pkg/console/constant.go @@ -72,17 +72,16 @@ const ( askVipMethodLabel = "VIP Mode" clusterNetworkTitle = "Configure cluster network" - clusterPodCIDRLabel = "Pod CIDR (optional) " - clusterServiceCIDRLabel = "Service CIDR (optional) " - clusterDNSLabel = "Cluster DNS IP (optional) " + clusterPodCIDRLabel = "Pod CIDR" + clusterServiceCIDRLabel = "Service CIDR" + clusterDNSLabel = "Cluster DNS IP" clusterPodCIDRPanel = "podCIDRPanel" clusterServiceCIDRPanel = "serviceCIDRPanel" clusterDNSPanel = "clusterDNSPanel" clusterNetworkNotePanel = "clusterNetworkNotePanel" clusterNetworkDNSNotePanel = "clusterNetworkDNSNotePanel" clusterNetworkValidatorPanel = "clusterNetworkValidatorPanel" - clusterNetworkNote = "Note: Leave blank to use the default pod CIDR 10.52.0.0/16, service CIDR 10.53.0.0/16 and cluster DNS 10.53.0.10." - clusterNetworkDNSNote = "If the service CIDR is changed, the DNS IP must be updated to be within the service CIDR." + clusterNetworkNote = "Note: Leave blank to use the default pod CIDR 10.52.0.0/16, service CIDR 10.53.0.0/16 and cluster DNS 10.53.0.10. If the service CIDR is changed, the DNS IP must be updated to be within the service CIDR." clusterTokenCreateNote = "Note: The token is used for adding nodes to the cluster" clusterTokenJoinNote = "Note: Input the token of the existing cluster" diff --git a/pkg/console/install_panels.go b/pkg/console/install_panels.go index 10f5aa6d6..a77639e31 100644 --- a/pkg/console/install_panels.go +++ b/pkg/console/install_panels.go @@ -1758,7 +1758,6 @@ func showClusterNetworkPage(c *Console) error { clusterServiceCIDRPanel, clusterDNSPanel, clusterNetworkNotePanel, - clusterNetworkDNSNotePanel, clusterNetworkValidatorPanel, clusterPodCIDRPanel) } @@ -1771,7 +1770,6 @@ func addClusterNetworkPanel(c *Console) error { clusterServiceCIDRPanel, clusterDNSPanel, clusterNetworkNotePanel, - clusterNetworkDNSNotePanel, clusterNetworkValidatorPanel) } @@ -1812,12 +1810,6 @@ func addClusterNetworkPanel(c *Console) error { return err } - if err := c.setContentByName( - clusterNetworkDNSNotePanel, - clusterNetworkDNSNote); err != nil { - return err - } - // reset any previous error in the validator panel before // showing the rest of the page return c.setContentByName(clusterNetworkValidatorPanel, "") @@ -1987,14 +1979,10 @@ func addClusterNetworkPanel(c *Console) error { // set up notes panels notePanel := widgets.NewPanel(c.Gui, clusterNetworkNotePanel) notePanel.Focus = false - setLocation(notePanel, 3) + notePanel.Wrap = true + setLocation(notePanel, 4) c.AddElement(clusterNetworkNotePanel, notePanel) - dnsNotePanel := widgets.NewPanel(c.Gui, clusterNetworkDNSNotePanel) - dnsNotePanel.Focus = false - setLocation(dnsNotePanel, 3) - c.AddElement(clusterNetworkDNSNotePanel, dnsNotePanel) - // set up validator panel for warning and error messages validatorPanel := widgets.NewPanel(c.Gui, clusterNetworkValidatorPanel) validatorPanel.FgColor = gocui.ColorRed From 563845df3ceb39d58a031d6a6ce0978e60c9e1a3 Mon Sep 17 00:00:00 2001 From: Ivan Sim Date: Thu, 12 Dec 2024 13:07:35 -0800 Subject: [PATCH 3/3] Add CIDR settings to promote controller chart config These overridden CIDR settings will be injected into the promote.sh data in the harvester-helper config map. Signed-off-by: Ivan Sim --- pkg/config/templates/rancherd-10-harvester.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/config/templates/rancherd-10-harvester.yaml b/pkg/config/templates/rancherd-10-harvester.yaml index 6c8e5ddc1..3d99eda3c 100644 --- a/pkg/config/templates/rancherd-10-harvester.yaml +++ b/pkg/config/templates/rancherd-10-harvester.yaml @@ -202,6 +202,10 @@ resources: enabled: true kube-vip-cloud-provider: enabled: true + promote: + clusterPodCIDR: {{ or .ClusterPodCIDR "10.52.0.0/16" }} + clusterServiceCIDR: {{ or .ClusterServiceCIDR "10.53.0.0/16" }} + clusterDNS: {{ or .ClusterDNS "10.53.0.10" }} - apiVersion: management.cattle.io/v3 kind: ManagedChart metadata: