feat(firstboot): SkipFormation flag — bm-bootstrap owns cluster formation

Add SkipFormation bool to firstboot.Config. When set, the cluster
formation block (spx admin init/join) is replaced with a no-op echo,
leaving formation to the provisioning controller.

Wired through: autoinstall reads SPINIFEX_SKIP_FORMATION=1 from env,
install.go passes it to firstboot.Config. spinifex-init.sh parses the
kernel cmdline param and exports it. boot-handler.go hardcodes
SPINIFEX_SKIP_FORMATION=1 so all bare-metal CI nodes skip formation —
bm-bootstrap.sh always runs spx admin init/join with the correct
--nodes N from nodes.json, enabling proper multi-node formation.
This commit is contained in:
joshsiv-mulga
2026-05-14 16:57:54 +10:00
parent 9fd89ec1ad
commit fba2103133
4 changed files with 16 additions and 0 deletions
+4
View File
@@ -151,6 +151,10 @@ func buildConfig() (*install.Config, error) {
cfg.JoinAddr = joinAddr
}
if os.Getenv("SPINIFEX_SKIP_FORMATION") == "1" {
cfg.SkipFormation = true
}
return cfg, nil
}
+7
View File
@@ -52,6 +52,10 @@ type Config struct {
// and network failures are swallowed so the install is not gated on
// controller reachability.
InstallCallback string
// SkipFormation skips spx admin init/join. Used when a provisioning
// controller (e.g. bm-bootstrap.sh) owns cluster formation and will call
// spx admin init/join itself with the correct multi-node parameters.
SkipFormation bool
}
// Write drops the firstboot script and systemd unit into root, which should be
@@ -232,6 +236,9 @@ fi
}
func buildClusterCmd(cfg Config) string {
if cfg.SkipFormation {
return `echo "[firstboot] cluster formation skipped — provisioning controller will handle it"`
}
emailFlag := ""
if cfg.Email != "" {
// shellEscapeSingle keeps the email safe if it ever contains a
+4
View File
@@ -55,6 +55,10 @@ type Config struct {
// JoinAddr is the primary node address (host:port) when ClusterRole is "join".
JoinAddr string
// SkipFormation skips spx admin init/join in firstboot; the provisioning
// controller (e.g. bm-bootstrap.sh) owns cluster formation instead.
SkipFormation bool
// CA certificate (PEM), optional.
HasCACert bool
CACert string
+1
View File
@@ -696,6 +696,7 @@ func (c *Config) toFirstbootConfig() firstboot.Config {
JoinAddr: c.JoinAddr,
Email: c.Email,
InstallCallback: strings.TrimSpace(os.Getenv("SPINIFEX_INSTALL_CALLBACK")),
SkipFormation: c.SkipFormation,
}
}