4c2e59cf3f
Root cause: orca job run <example>.md failed with fork/exec: no such
file or directory on every example. Two compounding problems:
1. workloadToTaskSpecs (internal/cli/job.go:340) passed the entire
runtime.command string (e.g. "/usr/bin/httpd -f /etc/orca/web-app/
httpd.conf") as a single binary path to exec.Command, which then
looked for a file literally named "/usr/bin/httpd -f ..." and
failed. The v0.9 markdown parser stores command: as a raw string;
the legacy HCL path had separate command+args fields. Fix: add
splitCommand helper that splits on strings.Fields into binary+args,
with /bin/true fallback for empty commands.
2. The example commands referenced binaries that don't exist on a bare
Linux machine (/usr/bin/httpd, postgres, api-server, fluent-bit).
Fix: rewrite the 5 example runtime.command values to use /bin/sleep
3600 (long-running services) or /bin/echo (one-shot job) so they
run out-of-the-box. Each file has a Production substitution note
showing the real binary to use in deployment.
Verified: orca job run examples/full-stack/worker.md now succeeds
(exit 0). All 4 services (web-app, api, log-shipper, postgres) start
correctly (task started, pid assigned). 12 new unit tests pass
(splitCommand: 7 cases, workloadToTaskSpecs: 5 cases). All 5 example
jobspecs still parse + validate (gate C-20). make lint clean.
---ci---
project: orca
phase: 6
milestone: v0.10
status: execute
decisions:
- id: D-195
decision: split command string via strings.Fields in workloadToTaskSpecs
rationale: exec.Command expects binary path + args as separate elements;
the v0.9 markdown parser stores command: as a single string with no
args field (unlike legacy HCL). strings.Fields is dep-free and handles
multiple spaces/tabs. Shell quoting (single/double quotes inside the
command) is not handled — examples avoid sh -c with quoted strings.
confidence: 0.95
alternatives: [shellquote.Split from mvdan/sh (adds dependency)]
lessons:
- The v0.9 markdown jobspec path needs the same command+args split that
the legacy HCL path had via separate command/args fields. The parser
stores command: as a raw string; the CLI must split it before passing
to exec.Command.
- Example jobspecs should use /bin/sleep and /bin/echo (binaries that
exist on every Linux machine) so they run out-of-the-box. Descriptive
production commands belong in a comment block, not in runtime.command.
---/ci---
51 lines
1.2 KiB
Markdown
51 lines
1.2 KiB
Markdown
---
|
|
kind: Service
|
|
name: web-app
|
|
count: 3
|
|
runtime:
|
|
one_of: process
|
|
command: /bin/sleep 3600
|
|
ports:
|
|
- name: http
|
|
port: 8080
|
|
restart:
|
|
mode: service
|
|
attempts: 5
|
|
delay: 2s
|
|
update:
|
|
strategy: rolling
|
|
max_parallel: 1
|
|
min_healthy_time: 10s
|
|
healthy_deadline: 2m
|
|
service:
|
|
name: web-app
|
|
port: 8080
|
|
health:
|
|
check_type: http
|
|
interval: 5s
|
|
timeout: 1s
|
|
unhealthy_threshold: 2
|
|
constraints:
|
|
- node.role == "web"
|
|
affinity:
|
|
- target: zone == "a"
|
|
weight: 80
|
|
lifecycle:
|
|
post_start:
|
|
- /bin/sh -c 'echo cache warmed'
|
|
pre_stop:
|
|
- /bin/sh -c 'sleep 5'
|
|
- /bin/sh -c 'echo draining web-app'
|
|
---
|
|
# Web App
|
|
|
|
Frontend web application serving HTTP on port 8080 via Unix socket.
|
|
Three replicas with rolling updates, anti-affinity for zone spreading,
|
|
and lifecycle hooks for cache warm-up and graceful drain.
|
|
|
|
> **Production substitution**: this example uses `/bin/sh -c 'echo ...
|
|
> sleep 3600'` so it runs out-of-the-box on any Linux machine. In a
|
|
> real deployment, replace the `runtime.command` with your actual
|
|
> binary, e.g. `/usr/bin/httpd -f /etc/orca/web-app/httpd.conf`, and
|
|
> replace the lifecycle hooks with your real scripts
|
|
> (`/usr/local/bin/warm-cache.sh`, `/usr/local/bin/drain.sh`). |