Description
The requiredfields and optionalfields analyzers produce false positives for fields using well-known Kubernetes types like metav1.Time and corev1.LocalObjectReference when paired with omitzero.
Example
type EncryptionMigrationHistory struct {
// startedTime is when the rotation was initiated.
// +required
StartedTime metav1.Time `json:"startedTime,omitzero"`
// completionTime is when the rotation finished.
// +optional
CompletionTime metav1.Time `json:"completionTime,omitzero"`
}
type AESCBCKeyStatus struct {
// secret is a reference to the Secret containing the key.
// +required
Secret corev1.LocalObjectReference `json:"secret,omitzero"`
}
Lint output
requiredfields: field EncryptionMigrationHistory.StartedTime has a valid zero value ({}), but the validation is not complete (e.g. min properties/adding required fields). The field should be a pointer to allow the zero value to be set. If the zero value is not a valid use case, complete the validation and remove the pointer.
optionalfields: field EncryptionMigrationHistory.CompletionTime has a valid zero value ({}), but the validation is not complete (e.g. min properties/adding required fields). The field should be a pointer to allow the zero value to be set. If the zero value is not a valid use case, complete the validation and remove the pointer.
requiredfields: field AESCBCKeyStatus.Secret has a valid zero value ({}), but the validation is not complete (e.g. min properties/adding required fields). The field should be a pointer to allow the zero value to be set. If the zero value is not a valid use case, complete the validation and remove the pointer.
Why this is a false positive
The linter inspects the external struct via Go's type system, counts non-omitted fields, finds zero (because all internal fields use omitempty/omitzero), and concludes the zero value {} is "valid but validation is incomplete."
However, for well-known Kubernetes types like metav1.Time (which wraps time.Time), a zero value is never a meaningful user choice — it represents the Go zero, not a valid timestamp. Making these fields pointers solely to distinguish "zero time" from "unset" is unnecessary when omitzero already handles omission correctly.
Similarly, corev1.LocalObjectReference with a single Name field that has omitempty — the zero value {} is not a valid object reference.
Suggested fix
The linter should recognize well-known Kubernetes API types (e.g., metav1.Time, metav1.Duration, corev1.LocalObjectReference, corev1.ObjectReference, resource.Quantity) as types where the zero value is not a meaningful user input, and skip the "should be a pointer" suggestion for them. Alternatively, providing a configuration option to allowlist specific external types would also work.
Version
sigs.k8s.io/kube-api-linter v0.0.0-20260518104151-5ebe05f9440b
Description
The
requiredfieldsandoptionalfieldsanalyzers produce false positives for fields using well-known Kubernetes types likemetav1.Timeandcorev1.LocalObjectReferencewhen paired withomitzero.Example
Lint output
Why this is a false positive
The linter inspects the external struct via Go's type system, counts non-omitted fields, finds zero (because all internal fields use
omitempty/omitzero), and concludes the zero value{}is "valid but validation is incomplete."However, for well-known Kubernetes types like
metav1.Time(which wrapstime.Time), a zero value is never a meaningful user choice — it represents the Go zero, not a valid timestamp. Making these fields pointers solely to distinguish "zero time" from "unset" is unnecessary whenomitzeroalready handles omission correctly.Similarly,
corev1.LocalObjectReferencewith a singleNamefield that hasomitempty— the zero value{}is not a valid object reference.Suggested fix
The linter should recognize well-known Kubernetes API types (e.g.,
metav1.Time,metav1.Duration,corev1.LocalObjectReference,corev1.ObjectReference,resource.Quantity) as types where the zero value is not a meaningful user input, and skip the "should be a pointer" suggestion for them. Alternatively, providing a configuration option to allowlist specific external types would also work.Version