package bootstrap import ( "context" "fmt" "k8s.io/klog/v2" 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: "ConfigureHostname", Name: "Configure hostname", Desc: "Set system hostname according to cluster configuration", }, { RegKey: "ConfigureMgmtInterface", Name: "Configure management interface", Desc: "Configure management network interface, IP address, and gateway", }, { RegKey: "ConfigureDNS", Name: "Configure DNS", Desc: "Set system DNS resolver configuration for cluster and external access", }, { RegKey: "EnsureIPForward", Name: "Ensure IP forwarding", Desc: "Enable kernel IP forwarding required for pod networking", }, { RegKey: "ConfigureDefaultCNI", Name: "Configure default CNI", Desc: "Install or configure default container networking (CNI bridge, IPAM, etc.)", }, { RegKey: "StartCRIO", Name: "Start CRI-O runtime", Desc: "Start container runtime and verify it is ready for Kubernetes workloads", }, { RegKey: "ValidateRequiredImagesPresent", Name: "Validate required images", Desc: "Ensure all required Kubernetes images are present or available locally", }, { RegKey: "ValidateNodeIPAndAPIServerReachability", Name: "Validate Node IP and wether API Server is available", Desc: "Verify the local ip address with the api server advertise address. Contact remote api server", }, { RegKey: "DetectLocalClusterState", Name: "Detect local cluster state", Desc: "Inspect local node to determine existing Kubernetes membership and configuration", }, { RegKey: "ClassifyBootstrapAction", Name: "Classify bootstrap action", Desc: "Decide whether to init, join, upgrade, or reconcile based on local state and desired version", }, { RegKey: "RunKubeadmInit", Name: "Run kubeadm init", Desc: "Initialize a new Kubernetes control plane using kubeadm", }, { RegKey: "RunKubeadmJoin", Name: "Run kubeadm join", Desc: "Join node to existing cluster as worker or control-plane", }, { RegKey: "WaitForExistingClusterIfNeeded", Name: "Wait for existing cluster", Desc: "Block until control plane is reachable when joining or reconciling an existing cluster", }, { RegKey: "ReconcileControlPlane", Name: "Reconcile control plane", Desc: "Ensure control plane components match desired state without full reinitialization", }, { RegKey: "ReconcileWorker", Name: "Reconcile worker node", Desc: "Reconcile the worker node", }, { RegKey: "CheckForVersionSkew", Name: "Check for version skew", Desc: "Validate wether version satisfy the requirements againts current cluster if any", }, { RegKey: "RunKubeadmUpgradeApply", Name: "Run kubeadm upgrade apply", Desc: "Upgrade control plane components using kubeadm", }, { RegKey: "RunKubeadmUpgradeNode", Name: "Run kubeadm upgrade node", Desc: "Upgrade node components (kubelet, config) to match control plane", }, { RegKey: "ApplyLocalNodeMetadataIfPossible", Name: "Apply node metadata", Desc: "Apply labels/annotations to the local node if API server is reachable", }, }, } } 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) } } klog.Info("All steps completed successfully") 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 }