penguin/monok8s

k8s image for Mono Gateway Dev Kit

clitools/pkg/bootstrap/runner.go

raw ยท 5224 bytes

package bootstrap

import (
	"context"
	"fmt"

	monov1alpha1 "undecided.project/monok8s/pkg/apis/monok8s/v1alpha1"
	"undecided.project/monok8s/pkg/node"
	"undecided.project/monok8s/pkg/system"
)

type Runner struct {
	NodeCtx  *node.NodeContext
	Registry *Registry

	initSteps []StepInfo
}

type StepInfo struct {
	RegKey string
	Name   string
	Desc   string
}

type StepSelection struct {
	Indices []int // 1-based
}

func NewRunner(cfg *monov1alpha1.MonoKSConfig) *Runner {
	runnerCfg := system.RunnerConfig{}
	nctx := &node.NodeContext{
		Config:       cfg,
		SystemRunner: system.NewRunner(runnerCfg),
	}
	return &Runner{
		NodeCtx:  nctx,
		Registry: NewRegistry(nctx),
		initSteps: []StepInfo{
			{
				RegKey: "configure_hostname",
				Name:   "Configure hostname",
				Desc:   "Set system hostname according to cluster configuration",
			},
			{
				RegKey: "configure_mgmt_interface",
				Name:   "Configure management interface",
				Desc:   "Configure management network interface, IP address, and gateway",
			},
			{
				RegKey: "configure_dns",
				Name:   "Configure DNS",
				Desc:   "Set system DNS resolver configuration for cluster and external access",
			},
			{
				RegKey: "ensure_ip_forward",
				Name:   "Ensure IP forwarding",
				Desc:   "Enable kernel IP forwarding required for pod networking",
			},
			{
				RegKey: "configure_default_cni",
				Name:   "Configure default CNI",
				Desc:   "Install or configure default container networking (CNI bridge, IPAM, etc.)",
			},
			{
				RegKey: "start_crio",
				Name:   "Start CRI-O runtime",
				Desc:   "Start container runtime and verify it is ready for Kubernetes workloads",
			},
			{
				RegKey: "validate_required_images",
				Name:   "Validate required images",
				Desc:   "Ensure all required Kubernetes images are present or available locally",
			},
			{
				RegKey: "validate_network_requirements",
				Name:   "Validate network requirements",
				Desc:   "Ensure required kernel networking features (iptables/nftables, bridge, forwarding) are available",
			},
			{
				RegKey: "detect_local_cluster_state",
				Name:   "Detect local cluster state",
				Desc:   "Inspect local node to determine existing Kubernetes membership and configuration",
			},
			{
				RegKey: "classify_bootstrap_action",
				Name:   "Classify bootstrap action",
				Desc:   "Decide whether to init, join, upgrade, or reconcile based on local state and desired version",
			},
			{
				RegKey: "wait_for_existing_cluster_if_needed",
				Name:   "Wait for existing cluster",
				Desc:   "Block until control plane is reachable when joining or reconciling an existing cluster",
			},
			{
				RegKey: "generate_kubeadm_config",
				Name:   "Generate kubeadm config",
				Desc:   "Render kubeadm configuration for init, join, or upgrade operations",
			},
			{
				RegKey: "apply_local_node_metadata_if_possible",
				Name:   "Apply node metadata",
				Desc:   "Apply labels/annotations to the local node if API server is reachable",
			},
			{
				RegKey: "allow_single_node_scheduling",
				Name:   "Allow single-node scheduling",
				Desc:   "Remove control-plane taints to allow workloads on single-node clusters",
			},
			{
				RegKey: "reconcile_control_plane",
				Name:   "Reconcile control plane",
				Desc:   "Ensure control plane components match desired state without full reinitialization",
			},
			{
				RegKey: "check_upgrade_prereqs",
				Name:   "Check upgrade prerequisites",
				Desc:   "Validate cluster state and version compatibility before upgrade",
			},
			{
				RegKey: "run_kubeadm_upgrade_apply",
				Name:   "Run kubeadm upgrade apply",
				Desc:   "Upgrade control plane components using kubeadm",
			},
			{
				RegKey: "run_kubeadm_init",
				Name:   "Run kubeadm init",
				Desc:   "Initialize a new Kubernetes control plane using kubeadm",
			},
			{
				RegKey: "run_kubeadm_join",
				Name:   "Run kubeadm join",
				Desc:   "Join node to existing cluster as worker or control-plane",
			},
			{
				RegKey: "reconcile_node",
				Name:   "Reconcile node state",
				Desc:   "Ensure node configuration matches desired state after join or upgrade",
			},
			{
				RegKey: "run_kubeadm_upgrade_node",
				Name:   "Run kubeadm upgrade node",
				Desc:   "Upgrade node components (kubelet, config) to match control plane",
			},
			{
				RegKey: "print_summary",
				Name:   "Print summary",
				Desc:   "Output final bootstrap summary and detected state",
			},
		},
	}
}

func (r *Runner) RunNamedStep(ctx context.Context, name string) error {
	step, err := r.Registry.Get(name)
	if err != nil {
		return err
	}
	return step(ctx, r.NodeCtx)
}

func (r *Runner) InitSteps() []StepInfo {
	return r.initSteps
}

func (r *Runner) Init(ctx context.Context) error {
	for i, step := range r.initSteps {
		if err := r.RunNamedStep(ctx, step.RegKey); err != nil {
			return fmt.Errorf("step %d (%s): %w", i+1, step.Name, err)
		}
	}
	return nil
}

func (r *Runner) InitSelected(ctx context.Context, sel StepSelection) error {
	for _, idx := range sel.Indices {
		step := r.initSteps[idx-1]
		if err := r.RunNamedStep(ctx, step.RegKey); err != nil {
			return fmt.Errorf("step %d (%s): %w", idx, step.Name, err)
		}
	}
	return nil
}