metis/pkg/plan/inject_extra_test.go

128 lines
3.6 KiB
Go
Raw Normal View History

package plan
import (
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
"time"
"metis/pkg/inventory"
)
func TestFilesAndInjectWithSecretsAndOverlays(t *testing.T) {
vault := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/v1/kv/data/atlas/nodes/titan-15" {
http.NotFound(w, r)
return
}
_ = json.NewEncoder(w).Encode(map[string]any{
"data": map[string]any{
"data": map[string]any{
"cloud_init": "#cloud-config\nmanage_etc_hosts: true\n",
"k3s_token": "secret-token",
"extra": map[string]string{"foo": "bar"},
},
},
})
}))
defer vault.Close()
t.Setenv("VAULT_ADDR", vault.URL)
t.Setenv("VAULT_TOKEN", "tok")
dir := t.TempDir()
bootOverlay := filepath.Join(dir, "boot-overlay")
rootOverlay := filepath.Join(dir, "root-overlay")
if err := os.MkdirAll(filepath.Join(bootOverlay, "over"), 0o755); err != nil {
t.Fatal(err)
}
if err := os.MkdirAll(filepath.Join(rootOverlay, "etc"), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(bootOverlay, "over", "cmdline.txt"), []byte("console=tty1"), 0o644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(rootOverlay, "etc", "issue"), []byte("hello"), 0o644); err != nil {
t.Fatal(err)
}
inv := &inventory.Inventory{
Classes: []inventory.NodeClass{{
Name: "c1",
Arch: "arm64",
OS: "linux",
Image: "file:///tmp/base.img",
BootOverlay: bootOverlay,
RootOverlay: rootOverlay,
}},
Nodes: []inventory.NodeSpec{{
Name: "titan-15",
Class: "c1",
Hostname: "titan-15",
IP: "192.168.22.43",
K3sRole: "agent",
SSHUser: "atlas",
SSHAuthorized: []string{"ssh-ed25519 AAA"},
}},
}
files, err := Files(inv, "titan-15")
if err != nil {
t.Fatalf("Files: %v", err)
}
var sawSecret, sawBootOverlay, sawRootOverlay, sawCloudInit bool
for _, f := range files {
switch {
case f.Path == "etc/metis/secrets.json":
sawSecret = true
case f.Path == "over/cmdline.txt":
sawBootOverlay = true
case f.Path == "etc/issue":
sawRootOverlay = true
case f.Path == "user-data":
sawCloudInit = strings.Contains(string(f.Content), "manage_etc_hosts: true")
}
}
if !sawSecret || !sawBootOverlay || !sawRootOverlay || !sawCloudInit {
t.Fatalf("missing generated files: secret=%v boot=%v root=%v cloudinit=%v", sawSecret, sawBootOverlay, sawRootOverlay, sawCloudInit)
}
bootDir := filepath.Join(dir, "boot")
rootDir := filepath.Join(dir, "root")
if err := os.MkdirAll(bootDir, 0o755); err != nil {
t.Fatal(err)
}
if err := os.MkdirAll(rootDir, 0o755); err != nil {
t.Fatal(err)
}
if err := Inject(inv, "titan-15", bootDir, rootDir); err != nil {
t.Fatalf("Inject: %v", err)
}
if _, err := os.Stat(filepath.Join(bootDir, "over", "cmdline.txt")); err != nil {
t.Fatalf("expected boot overlay file: %v", err)
}
if _, err := os.Stat(filepath.Join(rootDir, "etc/metis/node.json")); err != nil {
t.Fatalf("expected injected rootfs file: %v", err)
}
}
func TestNextRunStale(t *testing.T) {
if !NextRunStale(time.Now().Add(-2*time.Hour), time.Hour) {
t.Fatal("expected stale run")
}
if NextRunStale(time.Now(), time.Hour) {
t.Fatal("did not expect fresh run to be stale")
}
}
func TestAllowK3sNodeLabelRules(t *testing.T) {
if allowK3sNodeLabel("agent", "node-role.kubernetes.io/worker") {
t.Fatal("agent should block node-role labels")
}
if !allowK3sNodeLabel("server", "node-role.kubernetes.io/worker") {
t.Fatal("server should allow node-role labels")
}
}