Kubernetes publisher: WithPersistentVolume name-match propagates invalid mount source name (containing dots) into StatefulSet podSpec volumes[].name
- Dominant language
- C#
- Stars
- 6.3k
- Forks
- 991
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 196
Description
Discovered while testing E2E PV durability for #16929 (issue #16999).
## Symptom
When binding a Postgres resource to a first-class `KubernetesPersistentVolumeResource` using the name-match overload, the publisher generates an invalid StatefulSet:
```
StatefulSet.apps "pg-statefulset" is invalid:
spec.template.spec.volumes[0].name: Invalid value:
"k8sdeploypvtest.apphost-d10c8f5ce6-pg-data": must not contain dots
spec.template.spec.containers[0].volumeMounts[0].name: Not found:
"k8sdeploypvtest.apphost-d10c8f5ce6-pg-data"
```
## Repro
```csharp
var pgData = k8s.AddPersistentVolume("pg-data")
.WithStorageClass("standard")
.WithCapacity("1Gi")
.WithAccessMode(PersistentVolumeAccessMode.ReadWriteOnce);
// No-arg WithDataVolume auto-generates a unique mount source name of the
// form "{AppHost}.{hash}-{name}" — e.g. "k8sdeploypvtest.apphost-d10c8f5ce6-pg-data"
var postgres = builder.AddPostgres("pg")
.WithDataVolume()
.WithPersistentVolume(pgData);
```
## Root cause
`KubernetesPersistentVolumeExtensions.WithPersistentVolume(IResourceBuilder)` matches the workload's existing `ContainerMountAnnotation` by source name and reuses that source name as the K8s `volumes[].name` ref in the podSpec. K8s requires that name to be a DNS_LABEL (lowercase, alphanumeric + dashes, no dots), but the auto-generated mount source can contain dots.
The PVC itself is named correctly (`pg-data`, the PV resource name) — only the podSpec ref is broken.
## Workaround
Pass an explicit name to `WithDataVolume("pg-data")` so it matches the PV name directly. Used by the new E2E test (`KubernetesDeployWithPersistentVolumeTests`) to unblock CI.
## Suggested fix
Normalize the mount source name to a DNS_LABEL when materializing the podSpec volume entry. The reference table built in `KubernetesPublishingContext` already has the binding-by-name, so we just need to apply something like `HelmExtensions.ToKubernetesResourceName` (or equivalent) at the podSpec-emit site.
cc @mitchdenny
Contributor guide
Assessment
This issue has not been assessed yet.