2c26a6d54f
P03 — full-stack example with ingress configured (REQ-094; gate C-20). examples/full-stack/: - web-app.md: kind Service, process runtime, 3 replicas, Unix socket (default R-007), rolling update, constraints (node.role==web), affinity (zone==a weight 80), lifecycle hooks (post_start/pre_stop). - api.md: kind Service, process runtime, 2 replicas, TCP opt-in (service.bind: 127.0.0.1, R-007), canary update with manual promote, constraints (node.role==api, node.cpus>=2), env vars. - worker.md: kind Job, process runtime, one-shot, timeout 300s, env vars, lifecycle hooks (register/drain). - log-shipper.md: kind Service (DaemonSet workaround — parser gap), process runtime, constraints (node.role==logs), env vars. Notes the v0.9 parser gap (schedule: block not wired) in a callout. - postgres.md: kind Service, process runtime, 1 replica, blue-green update, volumes with replication (replicate:peer-b,peer-c via Syncthing), constraints (node.role==db, node.cpus>=4, node.memory>=8192). - rendered/: Traefik dynamic YAML (web-app, api) + systemd units (web-app, api, log-shipper) showing what Orca generates on target nodes. - README.md: end-to-end walkthrough (init -> node join -> capacity set -> ns create -> job run -> list --watch -> inspect rendered -> verify ingress -> drain/rollback). Cross-links to docs/ingress.md. - examples_test.go: Go test that parses + validates all 5 jobspecs against the current parser and schema validators (gate C-20). All 5 jobspecs pass jobspec.ParseFile + schema.ValidatorFor(kind). ---ci--- project: orca phase: 3 milestone: v0.10 status: execute ---/ci---
61 lines
1.6 KiB
Go
61 lines
1.6 KiB
Go
package fullstack_test
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"git.cloudinit.dev/coreci/orca/internal/jobspec"
|
|
"git.cloudinit.dev/coreci/orca/internal/spec/schema"
|
|
)
|
|
|
|
// TestExamplesValidate parses and validates every jobspec in
|
|
// examples/full-stack/ against the current parser and schema validators
|
|
// (gate C-20, REQ-094). This ensures the example jobspecs use only
|
|
// fields that exist in the current WorkloadSpec struct and pass the
|
|
// per-kind validators.
|
|
func TestExamplesValidate(t *testing.T) {
|
|
dir := filepath.Join("..", "..", "examples", "full-stack")
|
|
entries, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
t.Fatalf("read examples dir: %v", err)
|
|
}
|
|
for _, e := range entries {
|
|
if e.IsDir() {
|
|
continue
|
|
}
|
|
name := e.Name()
|
|
// Skip README.md and other non-jobspec markdown files.
|
|
if name == "README.md" {
|
|
continue
|
|
}
|
|
ext := filepath.Ext(name)
|
|
if ext != ".md" && ext != ".yaml" && ext != ".yml" {
|
|
continue
|
|
}
|
|
t.Run(name, func(t *testing.T) {
|
|
path := filepath.Join(dir, name)
|
|
spec, err := jobspec.ParseFile(path)
|
|
if err != nil {
|
|
t.Fatalf("ParseFile %s: %v", name, err)
|
|
}
|
|
if spec == nil {
|
|
t.Fatalf("ParseFile %s: spec is nil", name)
|
|
}
|
|
if spec.Kind == "" {
|
|
t.Fatalf("ParseFile %s: kind is empty", name)
|
|
}
|
|
if spec.Name == "" {
|
|
t.Fatalf("ParseFile %s: name is empty", name)
|
|
}
|
|
validator, err := schema.ValidatorFor(spec.Kind)
|
|
if err != nil {
|
|
t.Fatalf("ValidatorFor %s (kind %s): %v", name, spec.Kind, err)
|
|
}
|
|
if err := validator.Validate(spec); err != nil {
|
|
t.Fatalf("Validate %s: %v", name, err)
|
|
}
|
|
})
|
|
}
|
|
}
|