mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-19 19:01:42 +00:00
5f8ee0b5a2
In the PXE path SPINIFEX_INSTALL_CALLBACK arrives on the iPXE kernel cmdline but was never threaded into the firstboot script, so firstboot never curled the controller's /done endpoint. The flag stayed on disk, the node re-entered the install loop on the next PXE boot. Fix: read SPINIFEX_INSTALL_CALLBACK from the live-environment env in toFirstbootConfig and embed a best-effort curl into the generated firstboot script, fired once after the success marker is written. Interactive and USB-stick installs are unaffected (env var absent -> callbackBlock is empty, no curl injected).
101 lines
2.4 KiB
Go
101 lines
2.4 KiB
Go
package firstboot
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func makeRootDirs(t *testing.T, root string) {
|
|
t.Helper()
|
|
for _, d := range []string{
|
|
"usr/local/bin",
|
|
"etc/systemd/system",
|
|
"etc/systemd/system/multi-user.target.wants",
|
|
} {
|
|
if err := os.MkdirAll(filepath.Join(root, d), 0o755); err != nil {
|
|
t.Fatalf("mkdir %s: %v", d, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWriteScriptNoCallbackWhenEmpty(t *testing.T) {
|
|
root := t.TempDir()
|
|
makeRootDirs(t, root)
|
|
|
|
cfg := Config{Hostname: "test-node", ClusterRole: "init"}
|
|
if err := Write(root, cfg); err != nil {
|
|
t.Fatalf("Write: %v", err)
|
|
}
|
|
|
|
script, err := os.ReadFile(filepath.Join(root, "usr/local/bin/spinifex-firstboot.sh"))
|
|
if err != nil {
|
|
t.Fatalf("read script: %v", err)
|
|
}
|
|
if strings.Contains(string(script), "curl") {
|
|
t.Error("script should not contain curl when InstallCallback is empty")
|
|
}
|
|
}
|
|
|
|
func TestWriteScriptEmbedsCurlWhenCallbackSet(t *testing.T) {
|
|
root := t.TempDir()
|
|
makeRootDirs(t, root)
|
|
|
|
const callbackURL = "http://192.168.1.12/boot/done?mac=aa:bb:cc:dd:ee:ff"
|
|
cfg := Config{
|
|
Hostname: "test-node",
|
|
ClusterRole: "init",
|
|
InstallCallback: callbackURL,
|
|
}
|
|
if err := Write(root, cfg); err != nil {
|
|
t.Fatalf("Write: %v", err)
|
|
}
|
|
|
|
script, err := os.ReadFile(filepath.Join(root, "usr/local/bin/spinifex-firstboot.sh"))
|
|
if err != nil {
|
|
t.Fatalf("read script: %v", err)
|
|
}
|
|
content := string(script)
|
|
|
|
if !strings.Contains(content, "curl") {
|
|
t.Error("script missing curl command")
|
|
}
|
|
if !strings.Contains(content, callbackURL) {
|
|
t.Errorf("script missing callback URL %q", callbackURL)
|
|
}
|
|
}
|
|
|
|
func TestWriteScriptCallbackAfterDoneMarker(t *testing.T) {
|
|
root := t.TempDir()
|
|
makeRootDirs(t, root)
|
|
|
|
const callbackURL = "http://192.168.1.12/boot/done?mac=aa:bb:cc:dd:ee:ff"
|
|
cfg := Config{
|
|
Hostname: "node1",
|
|
ClusterRole: "init",
|
|
InstallCallback: callbackURL,
|
|
}
|
|
if err := Write(root, cfg); err != nil {
|
|
t.Fatalf("Write: %v", err)
|
|
}
|
|
|
|
script, err := os.ReadFile(filepath.Join(root, "usr/local/bin/spinifex-firstboot.sh"))
|
|
if err != nil {
|
|
t.Fatalf("read script: %v", err)
|
|
}
|
|
content := string(script)
|
|
|
|
doneIdx := strings.Index(content, "touch \"$DONE_MARKER\"")
|
|
curlIdx := strings.Index(content, "curl")
|
|
if doneIdx < 0 {
|
|
t.Fatal("done marker not found in script")
|
|
}
|
|
if curlIdx < 0 {
|
|
t.Fatal("curl not found in script")
|
|
}
|
|
if curlIdx < doneIdx {
|
|
t.Error("curl must appear after done marker write")
|
|
}
|
|
}
|