Skip to content

[DRAFT] Add kubeapi linter #3905

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

rikatz
Copy link

@rikatz rikatz commented Jul 7, 2025

What type of PR is this?
/kind test

What this PR does / why we need it: This PR is an attempt to add kube-api-linter as part of gw-api pipelines

NONE

@k8s-ci-robot k8s-ci-robot added release-note-none Denotes a PR that doesn't merit a release note. kind/test cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Jul 7, 2025
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: rikatz
Once this PR has been reviewed and has the lgtm label, please assign thockin for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot requested review from mlavacca and robscott July 7, 2025 21:26
@k8s-ci-robot k8s-ci-robot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Jul 7, 2025
@k8s-ci-robot
Copy link
Contributor

@rikatz: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-gateway-api-verify c26b5e5 link true /test pull-gateway-api-verify

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Copy link
Member

@robscott robscott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very cool, thanks @rikatz!

- "nophase" # Phase fields are discouraged by the Kube API conventions, use conditions instead.
- "optionalfields" # Ensure that all fields marked as optional adhere to being pointers and
# having the `omitempty` value in their `json` tag where appropriate.
- "optionalorrequired" # Every field should be marked as `+optional` or `+required`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I disagree with this one, or at the very least would rather start with this off. I'd always treated "required" as default and "optional" as the only thing that needed to be clearly specified.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some background on why this is important

Recent updates to the kubernetes API conventions have requested new fields added are either optional or required explicitly.

We've also come to realise that previous advice around omitempty was incorrect, and that all fields, no matter required or optional, should have omitempty to create consistent required/optional behaviour between fields.

This creates an issue for previous tooling that assumes that anything with omitempty, if it isn't tagged explicitly, is optional.

To quote the paragraph:

Note that for backward compatibility, any field that has the omitempty struct tag, and is not explicitly marked as +required, will be considered to be optional. This is expected to change in the future, and new fields should explicitly set either an +optional or +required comment tag.

It is also very easy to add a package level optional marker (you are using Kubebuilder markers?) to switch the default from optional to required, which can then go unnoticed in future reviews, leaving folks creating APIs where they think a field is required, but actually, it is optional.

There are also going to be other rules (optionalfields/requiredfields) that help to get serialization right, that depend on being marked explicitly, so you wouldn't be able to benefit from these if you chose not to explicitly mark required fields.

- "duplicatemarkers" # Ensure there are no exact duplicate markers. for types and fields.
- "integers" # Ensure only int32 and int64 are used for integers.
- "jsontags" # Ensure every field has a json tag.
- "maxlength" # Ensure all strings and arrays have maximum lengths/maximum items.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is not particularly useful when there's already a corresponding regex that ensures a max length (the case with our duration types).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have an example of a field?

One of the key reasons for setting upper bounds on fields is to allow accurate cost estimates for CEL rules. CEL has a number of exceptions within it where it knows the correct maximum length (e.g. it can determine from a list of enums what the maximum length is) and the linter implements the same exceptions (so it won't ask for maxlength on an enum).

For regexes, I don't think CEL would have a way to know (assuming you're using pattern) what the maximum length is, and as such, to enable future CEL rules on the field, it is best practice to set a maximum length, even if that duplicates something already in the regex.

Note also that while it's not implemented yet, a minimumlength rule is also planned. For example, most required string fields would not expect "" to be a valid value, and as such should be setting a minimum length to prevent this. If you have any thoughts regaring this or other rules I'm all ears, trying to gather feedback as much as possible at the moment and make this something that is really useful for the community.

lintersConfig:
conditions:
isFirstField: Warn # Require conditions to be the first field in the status struct.
usePatchStrategy: Forbid # Require conditions to be the first field in the status struct.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment on this one isn't right, this one is about the patch markers which don't work for CRDs

destination: ./bin
plugins:
- module: 'sigs.k8s.io/kube-api-linter'
version: 'main'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend to pin a specific commit. While we are still in the "early days" we haven't yet committed to producing actual releases, and I'm concerned that if you track main, we might break you accidentally.

In paritcular, I know that we need to rework how requiredfields works after recent discussion with upstream API reviewers, so that one will probably be surprising if it suddenly starts reporting issues

@shaneutt shaneutt self-requested a review July 8, 2025 11:13
@shaneutt shaneutt self-assigned this Jul 8, 2025
@shaneutt shaneutt moved this to Review in Release v1.4.0 Jul 8, 2025
@shaneutt shaneutt added this to the v1.4.0 milestone Jul 8, 2025
Copy link
Member

@shaneutt shaneutt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appreciate the work on the kubeapi linter, and am in favor of adding it here as I imagine it will help us out a lot.

- "integers" # Ensure only int32 and int64 are used for integers.
- "jsontags" # Ensure every field has a json tag.
- "maxlength" # Ensure all strings and arrays have maximum lengths/maximum items.
- "nobools" # Bools do not evolve over time, should use enums instead.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JoelSpeed would this preclude the flat boolean we're considering using for CORS here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/test release-note-none Denotes a PR that doesn't merit a release note. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.
Projects
Status: Review
Development

Successfully merging this pull request may close these issues.

5 participants