deploy-image: image reference is parsed by hand and produces invalid version labels
Background
The scaffolded controller builds the app.kubernetes.io/version label like this:
imageTag = strings.Split(image, ":")[1] At create api, the plugin checks that --image is not empty. It does not check the format. The --image-container-port flag next to it is validated.
PR #5962 reports the panic this causes and proposes reading only an explicit tag after the last path slash. The gap is real. The open point is whether to fix the parsing or the design.
The problem
Splitting on : does not match the structure of an image reference. The following results come from validation.IsValidLabelValue:
| Image | Split(image, ":")[1] |
Result |
|---|---|---|
example.com/image:test |
test |
valid |
busybox |
— | panic, index out of range |
localhost:5000/busybox |
5000/busybox |
invalid label value |
localhost:5000/busybox:v1 |
5000/busybox |
invalid label value |
busybox@sha256:7b3cca… |
64 characters | invalid, over 63 bytes |
busybox:_dev |
_dev |
invalid, must start with an alphanumeric character |
There are two distinct problems:
- A tagless image is valid and common. The first reconcile panics.
- A valid image tag is not always a valid label value. Tags allow 128 characters and can start with
_. Label values allow 63 characters and must start and end with an alphanumeric character. Correct tag extraction still produces objects that the API server rejects.
app.kubernetes.io/version is one of the recommended labels. When there is no version to state, the convention is to omit the label rather than set it to an empty string.
Proposed direction
Validate the input where the plugin receives it
--image is user input, and the plugin accepts it unchecked. Validate it at create api, alongside --image-container-port. The command then fails while the user is still typing it, rather than at the first reconcile in a cluster.
Open question: how strict should the check be? Reject any value that is not a valid image reference, or accept the value and warn only when the tag cannot become a label value?
Parse the reference correctly, or drop the derived label
Splitting on : cannot be corrected by patching it. Either apply the canonical rules — registry, repository, tag, digest — or stop deriving the label from the image.
Decide what the reconcile does when no usable version exists
- Omit the label. This matches the convention, and is silent.
- Omit the label and report it on the resource status. This is the preference expressed on #5962.
- Fail the reconcile. This is too strict, because a tagless image is legitimate.
If the controller reports it on status, follow the conventions the scaffold already uses:
- Set a
metav1.Conditionthroughmeta.SetStatusCondition. - Use a CamelCase
Reason, for exampleInvalidImageReference. - Write a
Messagethat names the image and explains why no version was derived. - Set
ObservedGeneration. - Reuse the
AvailableorDegradedtypes. A missing version label does not make the workload unavailable, so a third type is unlikely to be justified. - Set
ObservedGeneration. - Reuse the
AvailableorDegradedtypes. A missing version label does not make the workload unavailable, so a third type is unlikely to be justified.
Tests
Input validation belongs in the plugin tests, alongside the existing --image-container-port cases. It does not belong in the scaffolded controller test.
The scaffolded controller test covers reconcile behaviour. It currently hardcodes example.com/image:test and asserts only the Available condition. It never inspects the Deployment labels, which is why the panic in #5962 went unnoticed.
Add coverage for:
- A tagged image reconciles, and the Deployment carries
app.kubernetes.io/versionwith the tag. busyboxreconciles without panicking, and the version label is absent rather than empty.- A tag that is not a valid label value behaves the same way.
- The expected condition
Reason, if the controller reports the problem on status.
These tests are scaffolded into every user's project, so they also serve as the example of how to test a controller.
References
- PR #5962
- Recommended labels
- Labels and selectors: syntax and character set
pkg/plugins/golang/deploy-image/v1alpha1/scaffolds/internal/templates/controllers/controller.go
Source: kubernetes-sigs/kubebuilder