package ns import ( "os" "path/filepath" "strings" "testing" ) func writeNSMd(t *testing.T, path, content string) { t.Helper() if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { t.Fatalf("mkdir: %v", err) } if err := os.WriteFile(path, []byte(content), 0o644); err != nil { t.Fatalf("write %s: %v", path, err) } } const validNSMd = `--- kind: Namespace name: prod parents: ["_defaults"] inherits_env: true inherits_secrets: true quota: cpu: 4 acl: admin: ops --- # Prod namespace This body is ignored. ` func TestParseNSMdValid(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "ns.md") writeNSMd(t, path, validNSMd) cfg, err := ParseNSMd(path) if err != nil { t.Fatalf("ParseNSMd: %v", err) } if cfg.Name != "prod" { t.Errorf("name = %q, want prod", cfg.Name) } if !eqSlice(cfg.Parents, []string{"_defaults"}) { t.Errorf("parents = %v, want [_defaults]", cfg.Parents) } if !cfg.InheritsEnv || !cfg.InheritsSecrets { t.Errorf("inherits_env=%v inherits_secrets=%v, want both true", cfg.InheritsEnv, cfg.InheritsSecrets) } } func TestParseNSMdMissingFrontmatter(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "ns.md") writeNSMd(t, path, "# just a body, no frontmatter\n") _, err := ParseNSMd(path) if err == nil { t.Fatal("expected missing frontmatter error, got nil") } if !strings.Contains(err.Error(), "missing frontmatter") { t.Errorf("error = %q, want contains 'missing frontmatter'", err.Error()) } } func TestParseNSMdEmptyFrontmatter(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "ns.md") writeNSMd(t, path, "---\n---\nbody\n") _, err := ParseNSMd(path) if err == nil { t.Fatal("expected error for empty frontmatter, got nil") } } func TestParseNSMdWrongKind(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "ns.md") writeNSMd(t, path, "---\nkind: Job\nname: x\n---\n") _, err := ParseNSMd(path) if err == nil { t.Fatal("expected wrong-kind error, got nil") } if !strings.Contains(err.Error(), "not \"Namespace\"") { t.Errorf("error = %q, want contains 'is not \"Namespace\"'", err.Error()) } } func TestParseNSMdMissingKind(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "ns.md") writeNSMd(t, path, "---\nname: x\n---\n") _, err := ParseNSMd(path) if err == nil { t.Fatal("expected missing kind error, got nil") } if !strings.Contains(err.Error(), "missing kind") { t.Errorf("error = %q, want contains 'missing kind'", err.Error()) } } func TestParseNSMdMissingName(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "ns.md") writeNSMd(t, path, "---\nkind: Namespace\n---\n") _, err := ParseNSMd(path) if err == nil { t.Fatal("expected missing name error, got nil") } if !strings.Contains(err.Error(), "missing name") { t.Errorf("error = %q, want contains 'missing name'", err.Error()) } } func TestParseNSMdParentsUnquoted(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "ns.md") writeNSMd(t, path, "---\nkind: Namespace\nname: x\nparents: [a, b]\n---\n") cfg, err := ParseNSMd(path) if err != nil { t.Fatalf("ParseNSMd: %v", err) } if !eqSlice(cfg.Parents, []string{"a", "b"}) { t.Errorf("parents = %v, want [a b]", cfg.Parents) } } func TestParseNSMdParentsEmpty(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "ns.md") writeNSMd(t, path, "---\nkind: Namespace\nname: x\nparents: []\n---\n") cfg, err := ParseNSMd(path) if err != nil { t.Fatalf("ParseNSMd: %v", err) } if len(cfg.Parents) != 0 { t.Errorf("parents = %v, want empty", cfg.Parents) } } func TestParseNSMdInheritsFalse(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "ns.md") writeNSMd(t, path, "---\nkind: Namespace\nname: x\ninherits_env: false\ninherits_secrets: no\n---\n") cfg, err := ParseNSMd(path) if err != nil { t.Fatalf("ParseNSMd: %v", err) } if cfg.InheritsEnv { t.Errorf("inherits_env should be false") } if cfg.InheritsSecrets { t.Errorf("inherits_secrets should be false") } } func TestParseNSMdMissingFile(t *testing.T) { _, err := ParseNSMd(filepath.Join(t.TempDir(), "nope.md")) if err == nil { t.Fatal("expected error for missing file") } } func TestParseNSMdDirHappy(t *testing.T) { root := t.TempDir() writeNSMd(t, filepath.Join(root, "_defaults", "ns.md"), "---\nkind: Namespace\nname: _defaults\n---\n") writeNSMd(t, filepath.Join(root, "prod", "ns.md"), validNSMd) cfgs, err := ParseNSMdDir(root) if err != nil { t.Fatalf("ParseNSMdDir: %v", err) } if _, ok := cfgs["_defaults"]; !ok { t.Errorf("missing _defaults in %v", cfgs) } if _, ok := cfgs["prod"]; !ok { t.Errorf("missing prod in %v", cfgs) } } func TestParseNSMdDirMissingDefaults(t *testing.T) { root := t.TempDir() writeNSMd(t, filepath.Join(root, "prod", "ns.md"), validNSMd) _, err := ParseNSMdDir(root) if err == nil { t.Fatal("expected missing _defaults error, got nil") } if !strings.Contains(err.Error(), "_defaults") { t.Errorf("error = %q, want contains _defaults", err.Error()) } } func TestParseNSMdDirSkipsCluster(t *testing.T) { root := t.TempDir() writeNSMd(t, filepath.Join(root, "_defaults", "ns.md"), "---\nkind: Namespace\nname: _defaults\n---\n") // cluster/ contains a ns.md-shaped file but must be skipped. writeNSMd(t, filepath.Join(root, "cluster", "ns.md"), "---\nkind: Namespace\nname: cluster\n---\n") cfgs, err := ParseNSMdDir(root) if err != nil { t.Fatalf("ParseNSMdDir: %v", err) } if _, ok := cfgs["cluster"]; ok { t.Errorf("cluster should be skipped, present in %v", cfgs) } } func TestParseNSMdDirNoFiles(t *testing.T) { root := t.TempDir() _, err := ParseNSMdDir(root) if err == nil { t.Fatal("expected missing _defaults error on empty dir, got nil") } } func TestParseNSMdDirNotADir(t *testing.T) { tmp := t.TempDir() // Create a file with the same name as the expected root dir. root := filepath.Join(tmp, "notadir") writeNSMd(t, root, "x") _, err := ParseNSMdDir(root) if err == nil { t.Fatal("expected error for non-dir root") } }