package plan import ( "reflect" "strings" "testing" "metis/pkg/config" "metis/pkg/secrets" ) func TestNodeSecretHelpers(t *testing.T) { if got := effectiveAtlasPassword(nil); got != "" { t.Fatalf("effectiveAtlasPassword(nil) = %q", got) } sec := &secrets.NodeSecrets{AtlasPassword: "atlas-pass"} if got := effectiveAtlasPassword(sec); got != "atlas-pass" { t.Fatalf("effectiveAtlasPassword = %q", got) } if got := firstNonEmptyString("", " value ", "ignored"); got != "value" { t.Fatalf("firstNonEmptyString = %q", got) } if !hasNodePasswords(&secrets.NodeSecrets{RootPassword: "root-pass"}) { t.Fatal("expected root password to count as password material") } if hasNodePasswords(&secrets.NodeSecrets{}) { t.Fatal("empty node secrets should not count as password material") } debug := redactedSecretsForImage(&secrets.NodeSecrets{Extra: map[string]string{"b": "2", "a": "1"}}) if !reflect.DeepEqual(debug["extra_keys"], []string{"a", "b"}) { t.Fatalf("redactedSecretsForImage extra_keys = %#v", debug) } } func TestNodeSecretsFromEnvAndMergeNodeSecrets(t *testing.T) { t.Setenv("METIS_NODE_ATLAS_PASSWORD", "atlas-pass") t.Setenv("METIS_NODE_ROOT_PASSWORD", "root-pass") envSecrets := nodeSecretsFromEnv() if envSecrets == nil || envSecrets.RootPassword != "root-pass" || envSecrets.AtlasPassword != "atlas-pass" { t.Fatalf("nodeSecretsFromEnv = %#v", envSecrets) } merged := mergeNodeSecrets(&secrets.NodeSecrets{ AtlasPassword: "base-atlas", K3sToken: "base-token", CloudInit: "base-cloud", Extra: map[string]string{"base": "1"}, }, &secrets.NodeSecrets{ AtlasPassword: "override-atlas", RootPassword: "override-root", K3sToken: "override-token", CloudInit: "override-cloud", Extra: map[string]string{"override": "2"}, }) if merged.K3sToken != "override-token" || merged.CloudInit != "override-cloud" || merged.AtlasPassword != "override-atlas" || merged.RootPassword != "override-root" { t.Fatalf("mergeNodeSecrets = %#v", merged) } if merged.Extra["base"] != "1" || merged.Extra["override"] != "2" { t.Fatalf("mergeNodeSecrets extras = %#v", merged.Extra) } if got := mergeNodeSecrets(nil, envSecrets); got.RootPassword != "root-pass" { t.Fatalf("mergeNodeSecrets nil base = %#v", got) } if got := mergeNodeSecrets(envSecrets, nil); got.AtlasPassword != "atlas-pass" { t.Fatalf("mergeNodeSecrets nil override = %#v", got) } t.Setenv("METIS_NODE_ATLAS_PASSWORD", "") t.Setenv("METIS_NODE_ROOT_PASSWORD", "") if got := nodeSecretsFromEnv(); got != nil { t.Fatalf("expected empty env secrets to collapse to nil, got %#v", got) } } func TestFirstbootEnvContentIncludesPasswords(t *testing.T) { cfg := &config.NodeConfig{ Hostname: "titan-15", SSHUser: "atlas", K3s: config.K3sConfig{Version: "v1.31.5+k3s1"}, } content := firstbootEnvContent(cfg, &secrets.NodeSecrets{ AtlasPassword: "atlas-pass", RootPassword: "root-pass", }) if !reflect.DeepEqual(parseEnvLines(content), map[string]string{ "METIS_HOSTNAME": "'titan-15'", "METIS_SSH_USER": "'atlas'", "METIS_ATLAS_USER": "'atlas'", "METIS_K3S_VERSION": "'v1.31.5+k3s1'", "METIS_ATLAS_PASSWORD": "'atlas-pass'", "METIS_ROOT_PASSWORD": "'root-pass'", }) { t.Fatalf("firstbootEnvContent = %q", content) } } func parseEnvLines(raw string) map[string]string { result := map[string]string{} for _, line := range strings.Split(strings.TrimSpace(raw), "\n") { parts := strings.SplitN(line, "=", 2) if len(parts) != 2 { continue } result[parts[0]] = parts[1] } return result }