|
| 1 | +package hermes |
| 2 | + |
| 3 | +import ( |
| 4 | + "os" |
| 5 | + "path/filepath" |
| 6 | + "testing" |
| 7 | + |
| 8 | + "github.com/ObolNetwork/obol-stack/internal/agentruntime" |
| 9 | +) |
| 10 | + |
| 11 | +// TestSyncRuntimeFiles_RestoresContainerOwnership guards the regression where |
| 12 | +// syncRuntimeFiles chowned the Hermes home dir to the host UID (for host-side |
| 13 | +// config/skill writes) but never handed ownership back to the container UID. |
| 14 | +// On legacy hostPath PVs the kubelet does not re-apply fsGroup, so the missing |
| 15 | +// chown-back left .hermes owned by the host user and the non-root pod's init |
| 16 | +// container died with "mkdir: cannot create directory '/data/.hermes': |
| 17 | +// Permission denied" on the next sync/restart (e.g. after `obol model setup`). |
| 18 | +func TestSyncRuntimeFiles_RestoresContainerOwnership(t *testing.T) { |
| 19 | + cfg, _ := walletImportTestConfig(t, "obol-agent") |
| 20 | + calls := stubVolumeOwnership(t) |
| 21 | + |
| 22 | + if err := syncRuntimeFiles(cfg, "obol-agent", []byte("model_list: []\n"), newTestUI()); err != nil { |
| 23 | + t.Fatalf("syncRuntimeFiles: %v", err) |
| 24 | + } |
| 25 | + |
| 26 | + // Must restore ownership, and only after the host-side writes (ensure first). |
| 27 | + if len(*calls) != 2 || (*calls)[0] != "ensureVolumeWritable" || (*calls)[1] != "fixRuntimeVolumeOwnership" { |
| 28 | + t.Fatalf("expected [ensureVolumeWritable, fixRuntimeVolumeOwnership], got %v", *calls) |
| 29 | + } |
| 30 | + |
| 31 | + // Sanity: the config was actually written to the home dir. |
| 32 | + home := agentruntime.HomePath(cfg, agentruntime.Hermes, "obol-agent") |
| 33 | + if _, err := os.Stat(filepath.Join(home, "config.yaml")); err != nil { |
| 34 | + t.Fatalf("config.yaml not written: %v", err) |
| 35 | + } |
| 36 | +} |
0 commit comments