Migrate installer to Go#139
Conversation
There was a problem hiding this comment.
Pull request overview
This PR migrates the KubeSolo installer from multiple bash scripts to a single compiled Go-based CLI (cmd/installer) with subcommands for install/uninstall/service/download/check/version.
Changes:
- Added a new Go installer CLI (cobra) that performs host detection, preflight checks, binary download/offline install, service setup, and kubeconfig merge.
- Implemented init-system service backends (systemd/OpenRC/SysV/s6/runit/upstart) plus daemon/foreground run modes.
- Added bootstrap script (
scripts/get.sh) and Makefile targets to build/test the installer across supported architectures.
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/get.sh | Adds a curl/wget bootstrap script that downloads and execs the correct installer binary per arch. |
| cmd/installer/main.go | Introduces the main cobra CLI and wires install/uninstall/service/download/check/version flows. |
| internal/installer/config/config.go | Defines installer configuration defaults and builds kubesolo CLI args. |
| internal/installer/config/config_test.go | Unit tests for Config.CmdArgs(). |
| internal/installer/detect/detect.go | Filesystem-/proc-based detection for arch/libc/init/environment and archive naming. |
| internal/installer/detect/detect_test.go | Unit tests for archive naming, arch mapping, and constants. |
| internal/installer/download/download.go | Downloads/extracts KubeSolo archives and supports offline installation. |
| internal/installer/download/download_test.go | Unit tests for tar.gz extraction, copy, and progress reader. |
| internal/installer/kubeconfig/kubeconfig.go | Waits for admin kubeconfig then merges it into the invoking user’s kubeconfig. |
| internal/installer/preflight/preflight.go | Implements ordered preflight checks (root/hostname/docker/iptables/alpine/cgroups/ports). |
| internal/installer/preflight/preflight_test.go | Tests for hostname regex, controllers, suite, and best-effort env checks. |
| internal/installer/process/process.go | Stops existing KubeSolo processes via /proc scanning and port-owner detection. |
| internal/installer/process/exec.go | Wraps command creation for potential test substitution. |
| internal/installer/process/process_test.go | Unit tests for PID parsing, min duration, ports list, and non-panicking inode parsing. |
| internal/installer/service/manager.go | Defines Manager interface, routing by init system/run mode, and template helpers. |
| internal/installer/service/systemd.go | systemd unit generation/install/uninstall and systemctl invocations. |
| internal/installer/service/openrc.go | OpenRC init script generation/install/uninstall. |
| internal/installer/service/sysvinit.go | SysV init script generation/install/uninstall plus enable/start logic. |
| internal/installer/service/s6.go | s6 service directory/scripts generation and optional supervisor activation. |
| internal/installer/service/runit.go | runit service directory/script generation and enabling via symlink. |
| internal/installer/service/upstart.go | Upstart job generation/install/uninstall via initctl. |
| internal/installer/service/daemon.go | Fallback daemon-mode runner that starts kubesolo detached and writes a PID file. |
| internal/installer/service/daemon_linux.go | Linux-specific SysProcAttr for daemon detachment. |
| internal/installer/service/daemon_other.go | Non-Linux stub to keep builds/tests working on dev machines. |
| internal/installer/service/foreground.go | Foreground run mode that executes kubesolo attached to the current TTY. |
| internal/installer/service/service_test.go | Template rendering tests and init-system routing tests for New(). |
| Makefile | Adds build/test/clean targets for the new installer binary across architectures. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 27 out of 27 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| package service | ||
|
|
||
| import "syscall" | ||
|
|
||
| // daemonSysProcAttr returns a SysProcAttr that puts the child process in its |
There was a problem hiding this comment.
daemon_linux.go is compiled on all platforms because it lacks a //go:build linux constraint. On non-Linux, both this file and daemon_other.go (//go:build !linux) will be included, causing a duplicate definition of daemonSysProcAttr and breaking macOS/Windows builds/tests. Add a Linux build tag to daemon_linux.go (and optionally the legacy // +build linux line) so only one implementation is compiled per platform.
| Long: `Control the KubeSolo system service. | ||
|
|
||
| Actions: start | stop | restart | status | logs | enable | disable`, | ||
| Args: cobra.ExactArgs(1), | ||
| ValidArgs: []string{"start", "stop", "restart", "status", "logs", "enable", "disable"}, | ||
| SilenceUsage: true, |
There was a problem hiding this comment.
service help text and ValidArgs include enable|disable, but the command only implements those for OpenRC. On SysV this will call service kubesolo enable/disable (typically invalid), and on Upstart initctl enable/disable is also not a thing. Either remove enable|disable from the advertised actions, or implement init-specific enable/disable behavior and validate actions explicitly (note: ValidArgs is used for completion; it doesn't enforce values at runtime without an Args validator).
KS-45: Go installer — replaces install.sh, kubesolo-service.sh, uninstall.sh
Rewrites the three bash installer scripts as a single compiled Go CLI binary (
cmd/installer). Built withCGO_ENABLED=0so one binary per architecture covers both glibc and musl systems, eliminating the libc split the bash scripts handle at runtime.Supported targets
linux/amd64,linux/arm64,linux/arm(armhf),linux/riscv64CLI
All flags have
KUBESOLO_*environment variable equivalents.What's new
cmd/installer/— cobra CLI entry point. Six subcommands: install (default), uninstall, service, download, check, version.uninstallremoves the service, binary, and optionally the data directory (--purge).internal/installer/config/—Configstruct and constants.CmdArgs()builds the argument list passed to the kubesolo binary using bare boolean flags (--debugnot--debug=true) to match kubesolo's flag parser.internal/installer/detect/— host detection with no subprocess calls. Detects arch, libc (musl vs glibc via/lib/ld-musl-*.so.1), init system (from filesystem landmarks — nowhich/command -v), and environment (container, SBC).internal/installer/preflight/— seven ordered checks: root, hostname RFC 1123, Docker conflict, iptables xt_comment module, nftables+iptables (Alpine only, installs viaapk addif--install-prereqs), cgroups (enables Alpine OpenRC cgroups service proactively if needed), required ports. Stop runs before preflight so ports held by an existing KubeSolo installation don't cause false failures.internal/installer/process/— stops running KubeSolo before reinstalling. Reads/proc/*/exesymlinks, SIGTERMs with exponential backoff, SIGKILLs stragglers. Port holders found via/proc/net/tcp[6]inode mapping. No dependency onlsof,ss, ornetstat.internal/installer/download/— online and offline install. Extracts by base name so nested tar paths (kubesolo-v1.1.2-linux-amd64/kubesolo) are handled correctly. Atomic install viaos.Rename; cross-device fallback (tmpfs → ext4 on Alpine) explicitlychmod 0755es the staged binary before the final rename.internal/installer/service/— seven init system backends behind a commonManagerinterface: systemd, OpenRC, SysV, s6, runit, upstart, daemon (fallback). All templates support optional proxy environment injection.daemon_linux.go/daemon_other.gosplit via build tags keeps the package compilable on macOS for local development.internal/installer/kubeconfig/— waits up to 30s for the admin kubeconfig to appear, then merges it into the real user's~/.kube/configviakubectl config view --flatten. Real user resolved in order:SUDO_USER(sudo),DOAS_USER(doas),/proc/self/loginuid(kernel login UID, preserved across any privilege escalation — reliable catch-all fordoason Alpine), fallback to current user. Source kubeconfig ischowned to the real user soKUBECONFIG=<path>in shell profiles keeps working.scripts/get.sh— bootstrap script forget.kubesolo.io. Detects arch viauname -m, downloads the correctinstaller-linux-<arch>binary, and execs it. SupportsKUBESOLO_VERSION,KUBESOLO_INSTALLER_BASE_URL, andKUBESOLO_FLAT_URLSfor version pinning and internal mirrors.Makefile— addsbuild-installer,build-installer-all,test-installer,clean-installertargets.Building