Extend Volume type beyond HostPath-only
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 2.2k
- Forks
- 300
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 184
Description
Summary
The operator defines a custom Volume type that only supports HostPath mounts. Users cannot mount ConfigMaps, Secrets, EmptyDir, or PVCs as volumes in MCP server containers. HostPath is generally discouraged in production Kubernetes due to node-affinity and security concerns.
Current custom type (cmd/thv-operator/api/v1alpha1/mcpserver_types.go, lines ~381-399)
type Volume struct {
Name string `json:"name"`
HostPath string `json:"hostPath"`
MountPath string `json:"mountPath"`
ReadOnly bool `json:"readOnly,omitempty"`
}
Controller usage (cmd/thv-operator/controllers/mcpserver_controller.go, lines ~1150-1166)
The controller hardcodes corev1.HostPathVolumeSource:
for _, v := range m.Spec.Volumes {
volumes = append(volumes, corev1.Volume{
Name: v.Name,
VolumeSource: corev1.VolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: v.HostPath,
},
},
})
}
Why this matters
- HostPath ties pods to specific nodes and is a security risk (host filesystem access)
- Users cannot mount Secrets as files (common for TLS certs, credentials)
- Users cannot mount ConfigMaps as configuration files
- Users cannot use EmptyDir for scratch space or sidecar communication
- Users cannot mount PVCs for persistent data
PodTemplateSpeccan work around this but common volume patterns should be first-class
What to change
Option A (recommended): Extend the custom Volume type
Replace the single HostPath field with multiple optional source fields, enforced by a CEL mutual exclusivity rule:
// +kubebuilder:validation:XValidation:rule="(has(self.hostPath) ? 1 : 0) + (has(self.configMap) ? 1 : 0) + (has(self.secret) ? 1 : 0) + (has(self.emptyDir) ? 1 : 0) + (has(self.persistentVolumeClaim) ? 1 : 0) == 1",message="exactly one volume source must be specified"
type Volume struct {
// Name is the name of the volume
// +kubebuilder:validation:Required
Name string `json:"name"`
// MountPath is the path in the container to mount to
// +kubebuilder:validation:Required
MountPath string `json:"mountPath"`
// ReadOnly specifies whether the volume should be mounted read-only
// +kubebuilder:default=false
// +optional
ReadOnly bool `json:"readOnly,omitempty"`
// HostPath mounts a path from the host node's filesystem
// +optional
HostPath *string `json:"hostPath,omitempty"`
// ConfigMap mounts a ConfigMap as files
// +optional
ConfigMap *corev1.ConfigMapVolumeSource `json:"configMap,omitempty"`
// Secret mounts a Secret as files
// +optional
Secret *corev1.SecretVolumeSource `json:"secret,omitempty"`
// EmptyDir provides an empty directory for scratch space
// +optional
EmptyDir *corev1.EmptyDirVolumeSource `json:"emptyDir,omitempty"`
// PersistentVolumeClaim mounts a PVC
// +optional
PersistentVolumeClaim *corev1.PersistentVolumeClaimVolumeSource `json:"persistentVolumeClaim,omitempty"`
}
Controller update (cmd/thv-operator/controllers/mcpserver_controller.go)
Replace the hardcoded HostPath conversion (~lines 1150-1166) with a switch/if-chain that creates the appropriate corev1.VolumeSource based on which field is set.
Tests
Update test files that construct Volume{Name: "x", HostPath: "/path", MountPath: "/mnt"} to use the new pointer field: Volume{Name: "x", HostPath: ptr("/path"), MountPath: "/mnt"}. Add test cases for ConfigMap and Secret volume sources.
Option B (simpler alternative)
Remove the custom Volume type entirely and direct users to PodTemplateSpec for all volume needs. Document this as the intended pattern. This is less user-friendly but avoids maintaining a custom volume abstraction.
Regenerate and verify
task gen
task crdref-gen
task lint-fix
task lint
task test
Notes
- The
HostPathfield changes fromstring(required) to*string(optional) — this is a breaking change for existing manifests but acceptable forv1alpha1. - The CEL rule ensures exactly one source is set, preventing ambiguous configurations.
Generated with Claude Code
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with Volume in cmd/thv-operator/api/v1alpha1/mcpserver_types.go and its conversion in cmd/thv-operator/controllers/mcpserver_controller.go around lines 1150-1166. Review existing Volume constructions and tests, then implement the selected volume-source approach, add ConfigMap and Secret coverage, run task gen and task crdref-gen, and verify with task lint and task test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, kubernetes
- Domain
- backend, devops, infrastructure
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100