Skip to content

requiredfields/optionalfields: false positive on metav1.Time and corev1.LocalObjectReference with omitzero #249

Description

@muraee

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedDenotes an issue that needs help from a contributor. Must meet "help wanted" guidelines.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions