feat: Phase 7 — SeedService, SecretsService, ProvisioningService + ssh Provisioner
Seed ingest/export moves behind ports.SeedRepository (SeedRepo in the postgres adapter; knowledge ingest absorbed from internal/knowledge, package deleted). pct_create flow (defaults, template/VMID/gateway pre-flights, pct create, graph registration) moves from httpapi's approved-execution path into app.ProvisioningService + the ssh provisioner adapter; CLI seed/export/secret become adapters over the services. EntityCreateInput gains EnrolledAt. Plan status corrected: phases 0-7 shipped, 8 + 9 gates open. VERSION 0.34.1.
This commit is contained in:
98
internal/core/app/seed_test.go
Normal file
98
internal/core/app/seed_test.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/dtoro/oikos/internal/core/ports/portstest"
|
||||
)
|
||||
|
||||
func writeSeedFile(t *testing.T, dir, name, content string) {
|
||||
t.Helper()
|
||||
if err := os.WriteFile(filepath.Join(dir, name), []byte(content), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSeedServiceIngestOrder(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeSeedFile(t, dir, "ontology.yaml", "a: 1")
|
||||
writeSeedFile(t, dir, "inventory.yaml", "b: 2")
|
||||
writeSeedFile(t, dir, "policy.yaml", "c: 3")
|
||||
writeSeedFile(t, dir, "knowledge.yaml", "d: 4")
|
||||
|
||||
repo := portstest.NewSeedRepo()
|
||||
if err := NewSeedService(repo).Ingest(context.Background(), dir); err != nil {
|
||||
t.Fatalf("Ingest: %v", err)
|
||||
}
|
||||
|
||||
want := []string{"ontology.yaml", "inventory.yaml", "policy.yaml", "knowledge.yaml"}
|
||||
if len(repo.Order) != len(want) {
|
||||
t.Fatalf("ingested %v, want %v", repo.Order, want)
|
||||
}
|
||||
for i, f := range want {
|
||||
if repo.Order[i] != f {
|
||||
t.Errorf("order[%d] = %s, want %s", i, repo.Order[i], f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSeedServiceKnowledgeOptional(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeSeedFile(t, dir, "ontology.yaml", "a: 1")
|
||||
writeSeedFile(t, dir, "inventory.yaml", "b: 2")
|
||||
writeSeedFile(t, dir, "policy.yaml", "c: 3")
|
||||
|
||||
repo := portstest.NewSeedRepo()
|
||||
if err := NewSeedService(repo).Ingest(context.Background(), dir); err != nil {
|
||||
t.Fatalf("Ingest without knowledge seed: %v", err)
|
||||
}
|
||||
for _, f := range repo.Order {
|
||||
if f == "knowledge.yaml" {
|
||||
t.Error("knowledge.yaml must be skipped when absent")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSeedServiceMissingStructuralSeedFails(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeSeedFile(t, dir, "ontology.yaml", "a: 1")
|
||||
// inventory.yaml and policy.yaml absent — both are required.
|
||||
|
||||
repo := portstest.NewSeedRepo()
|
||||
err := NewSeedService(repo).Ingest(context.Background(), dir)
|
||||
if err == nil {
|
||||
t.Fatal("missing inventory seed must fail the ingest")
|
||||
}
|
||||
if repo.Order[len(repo.Order)-1] != "ontology.yaml" {
|
||||
t.Errorf("ingest stopped at %v, want ontology.yaml only", repo.Order)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSeedServiceIngestErrorPropagates(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeSeedFile(t, dir, "ontology.yaml", "a: 1")
|
||||
writeSeedFile(t, dir, "inventory.yaml", "b: 2")
|
||||
|
||||
repo := portstest.NewSeedRepo()
|
||||
repo.IngestErr["inventory.yaml"] = errors.New("entity bad: unknown type")
|
||||
err := NewSeedService(repo).Ingest(context.Background(), dir)
|
||||
if err == nil || !errors.Is(err, repo.IngestErr["inventory.yaml"]) {
|
||||
t.Fatalf("got %v, want ingest error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSeedServiceExport(t *testing.T) {
|
||||
repo := portstest.NewSeedRepo()
|
||||
repo.ExportFiles = map[string][]byte{"ontology.yaml": []byte("x")}
|
||||
files, err := NewSeedService(repo).Export(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("Export: %v", err)
|
||||
}
|
||||
if string(files["ontology.yaml"]) != "x" {
|
||||
t.Errorf("export = %v", files)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user