60b0357eb6
P0c — Kind-specific schema validators + Layer 4 emitter interface.
Schemas (internal/spec/schema/schema.go, REQ-074):
- Validator interface with JobValidator, ServiceValidator, DaemonSetValidator.
JobValidator: count=1, no service block, optional schedule/timeout.
ServiceValidator: ports required, count>=1, restart+update+runtime required.
DaemonSetValidator: schedule mode required, no ports (D-175), no count.
ValidatorFor(kind) dispatcher. 96.2% coverage.
Emitter interface (internal/emitter/emitter.go, REQ-074, I-B-002):
- File{Path,Content,Mode}, Emitter interface { Render(spec,node) []File },
Registry keyed by kind:runtime, Register + Render lookup. 100% coverage.
Systemd stub (internal/emitter/systemd.go):
- SystemdEmitter for process runtime. Renders minimal [Service] unit at
/etc/systemd/system/orca-v1-alloc-<name>.service (orca-v1- prefix per
dual-write window REQ-090 — no overlap with v0.8 daemon's orca-<job>).
Flock test fix: TestFlock_concurrentBlocks rewritten to use non-blocking
tryFlockEx (LOCK_NB) instead of a leaked blocking goroutine. Eliminates
the temp-dir cleanup race.
20 packages pass, 20 bats pass, gofmt clean, verify-reqs 90 consistent.
---ci---
project: orca
phase: P0c
milestone: v0.9
status: execute
---/ci---
36 lines
982 B
Go
36 lines
982 B
Go
package security
|
|
|
|
import (
|
|
"os"
|
|
"syscall"
|
|
)
|
|
|
|
// Flock acquires an exclusive advisory lock on the file at path, creating it
|
|
// if missing. Returns a release function that MUST be called (deferred) to
|
|
// release the lock and close the file descriptor. Used by the known_hosts
|
|
// read-modify-write paths (TOFUHostKeyCallback capture + ResetHostKey) to
|
|
// prevent concurrent writers under v0.9's parallel SSH fan-out (REQ-063,
|
|
// deferred P1 from REVIEW_v0.8 A2).
|
|
func Flock(path string) (release func(), err error) {
|
|
f, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0o600)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := syscall.Flock(int(f.Fd()), syscall.LOCK_EX); err != nil {
|
|
f.Close()
|
|
return nil, err
|
|
}
|
|
return func() {
|
|
_ = syscall.Flock(int(f.Fd()), syscall.LOCK_UN)
|
|
_ = f.Close()
|
|
}, nil
|
|
}
|
|
|
|
func tryFlockEx(fd int) error {
|
|
return syscall.Flock(fd, syscall.LOCK_EX|syscall.LOCK_NB)
|
|
}
|
|
|
|
func releaseFlock(fd int) error {
|
|
return syscall.Flock(fd, syscall.LOCK_UN)
|
|
}
|