Skip to content

Commit a1dc187

Browse files
committed
fix(runtime): keep user config writable
1 parent 4c726ae commit a1dc187

4 files changed

Lines changed: 22 additions & 10 deletions

File tree

docs/runtime.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ the PVC) is **gone**. Only mutable state lives on the volume.
3434

3535
Persistent state lives at **`/opt/data`**, the PVC mount, and `HERMES_HOME` is
3636
set to `/opt/data`. (The previous runtime used `/home/hermes/.hermes`.) The
37-
rendered `config.yaml` is mounted read-only at `/opt/data/config.yaml`.
37+
operator-rendered `config.yaml` is mounted read-only at
38+
`/etc/hermes/config.yaml`, Hermes' managed-scope location. The user/runtime
39+
configuration remains writable and persistent at `/opt/data/config.yaml` so
40+
commands such as `/sethome` can save state. Hermes merges the managed scope over
41+
the runtime file per leaf, so declarative operator values remain authoritative.
3842

3943
## Security posture and the SCC tradeoff
4044

hack/dev/hermes-upstream-validate.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ spec:
103103
- name: data
104104
mountPath: /opt/data
105105
- name: config
106-
mountPath: /opt/data/config.yaml
106+
mountPath: /etc/hermes/config.yaml
107107
subPath: config.yaml
108108
readOnly: true
109109
volumes:

internal/resources/statefulset.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,12 @@ func BuildStatefulSet(inst *hermesv1.HermesInstance, extraInits []corev1.Contain
7979
// HERMES_HOME on the upstream image is /opt/data (the persistent volume).
8080
{Name: "data", MountPath: "/opt/data"},
8181
{
82-
Name: "config",
83-
MountPath: "/opt/data/config.yaml",
82+
Name: "config",
83+
// Mount the operator-rendered config as Hermes' immutable managed scope.
84+
// The writable user config remains on the data PVC at
85+
// /opt/data/config.yaml so runtime commands such as /sethome can persist
86+
// user-owned state without replacing the managed configuration.
87+
MountPath: "/etc/hermes/config.yaml",
8488
SubPath: "config.yaml",
8589
ReadOnly: true,
8690
},

internal/resources/statefulset_test.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,17 @@ func TestBuildStatefulSet_VolumesAndMounts(t *testing.T) {
109109
sts := BuildStatefulSet(minimalInstance(), nil)
110110
c := sts.Spec.Template.Spec.Containers[0]
111111

112-
mountNames := map[string]string{}
112+
mountsByName := map[string]corev1.VolumeMount{}
113113
for _, m := range c.VolumeMounts {
114-
mountNames[m.Name] = m.MountPath
115-
}
116-
assert.Equal(t, "/opt/data", mountNames["data"], "PVC mounted at HERMES_HOME (/opt/data)")
117-
assert.Equal(t, "/opt/data/config.yaml", mountNames["config"], "configmap subPath at config.yaml")
118-
assert.Equal(t, "/tmp", mountNames["tmp"], "writable /tmp")
114+
mountsByName[m.Name] = m
115+
assert.NotEqual(t, "/opt/data/config.yaml", m.MountPath,
116+
"runtime config must remain writable on the data PVC")
117+
}
118+
assert.Equal(t, "/opt/data", mountsByName["data"].MountPath, "PVC mounted at HERMES_HOME (/opt/data)")
119+
assert.Equal(t, "/etc/hermes/config.yaml", mountsByName["config"].MountPath,
120+
"operator config is mounted as Hermes managed scope")
121+
assert.True(t, mountsByName["config"].ReadOnly, "managed config must be immutable")
122+
assert.Equal(t, "/tmp", mountsByName["tmp"].MountPath, "writable /tmp")
119123
}
120124

121125
func minimalInstance() *hermesv1.HermesInstance {

0 commit comments

Comments
 (0)