Skip to content

Extend maxlength linter to support kubernetes declarative validation markers - #245

Open
itzPranshul wants to merge 1 commit into
kubernetes-sigs:mainfrom
itzPranshul:extend-maxlength
Open

Extend maxlength linter to support kubernetes declarative validation markers #245
itzPranshul wants to merge 1 commit into
kubernetes-sigs:mainfrom
itzPranshul:extend-maxlength

Conversation

@itzPranshul

Copy link
Copy Markdown
Contributor

This PR extends the maxlength linter to support kubernetes DV markers:

  • +k8s:maxLength for string types
  • +k8s:maxBytes for []byte types (aligning with DV byte counting semantics)
  • +k8s:maxItems for slices and arrays
  • +k8s:maxProperties for map[string]V types

Key chages:

  • Added support for +k8s:enum and +k8s:format to exempt string fields from requiring maximum lengths.
  • Introduced MaxLengthConfig to specify whether the linter should prefer kubebuilder or k8s DV markers
  • Upgraded the analyzer to struct-based implementation NewConfigurableInitializer.
  • added dedicated tests to validate all new DV marker scenarios.

Fixes #223

@k8s-ci-robot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

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

Details 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 added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels May 6, 2026
@itzPranshul
itzPranshul force-pushed the extend-maxlength branch 2 times, most recently from 0730e76 to 92b1b98 Compare May 6, 2026 07:36
@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why do you edit this file?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Those were accidental changes introduced by my local environment while addressing the lint issues.I have reverted them. Sorry about that!

Comment thread pkg/analysis/maxlength/analyzer_test.go Outdated

// TestMaxLength_DVMarkers tests that the linter (default config) accepts DV
// markers as satisfying the max-length/max-items/max-properties constraints.
func TestMaxLength_DVMarkers(t *testing.T) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This test looks duplicating TestMaxLength. Why did you add this test ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've removed it now

Comment thread pkg/analysis/maxlength/analyzer_test.go Outdated
Comment on lines +51 to +60
ci, ok := maxlength.Initializer().(initializer.ConfigurableAnalyzerInitializer)
if !ok {
t.Fatal("maxlength.Initializer() does not implement ConfigurableAnalyzerInitializer")
}

a, err := ci.Init(&maxlength.MaxLengthConfig{
PreferredMaxLengthMarker: markers.K8sMaxLengthMarker,
PreferredMaxItemsMarker: markers.K8sMaxItemsMarker,
PreferredMaxPropertiesMarker: markers.K8sMaxPropertiesMarker,
})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
ci, ok := maxlength.Initializer().(initializer.ConfigurableAnalyzerInitializer)
if !ok {
t.Fatal("maxlength.Initializer() does not implement ConfigurableAnalyzerInitializer")
}
a, err := ci.Init(&maxlength.MaxLengthConfig{
PreferredMaxLengthMarker: markers.K8sMaxLengthMarker,
PreferredMaxItemsMarker: markers.K8sMaxItemsMarker,
PreferredMaxPropertiesMarker: markers.K8sMaxPropertiesMarker,
})
ci, err := maxlength.Initializer().Initialize(&maxlength.MaxLengthConfig{
PreferredMaxLengthMarker: markers.K8sMaxLengthMarker,
PreferredMaxItemsMarker: markers.K8sMaxItemsMarker,
PreferredMaxPropertiesMarker: markers.K8sMaxPropertiesMarker,
})

I like this style.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated.

Comment thread pkg/analysis/maxlength/analyzer_test.go Outdated
Comment on lines +65 to +70
// Run only against c.go-style testdata when DV markers are preferred.
// The want-comments in a.go cite kubebuilder markers; for this run we use a
// separate package that has no want-comments (happy-path only).
// For now we verify the analyzer initialises and runs without panicking.
_ = a
_ = testdata

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why don't you test dv-style marker?
If you don't test dv-style, we can't confirm this implementation works correctly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've Added a new testdata/src/b/b.go with the analyzer initialized in DV preferred mode.

DV-style markers are now tested across two layers:

  1. Acceptance in default (Kubebuilder-preferred) config - verifies that +k8s markers suppress diagnostics even when the linter is configured to prefer kubebuilder markers.
    2.End to end DV-preferred config

All tests pass. Thanks for the review!

@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 24, 2026
MapWithNoMaxProperties map[string]string // want `field DVMaxLength.MapWithNoMaxProperties must have a maximum properties, add kubebuilder:validation:MaxProperties marker`

// Non-string-keyed map — should NOT lint.
// DV +k8s:maxProperties only supports string-keyed maps; linter mirrors this constraint.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What about +kubebuilder:validation:maxProperties?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The restriction actually applies to both. I've updated the comments to be generic so it's clear why it's skipped in both modes.

Comment on lines +65 to +66
// +k8s:maxLength (counts chars) is not the correct DV tag for []byte;
// +k8s:maxBytes (counts bytes) should be used instead.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What's the parsing doing for these comments, they look like markers? Maybe remove the + at the beginning?

Comment thread pkg/analysis/maxlength/analyzer.go Outdated
Comment on lines +195 to +199
// DV +k8s:maxProperties only supports string-keyed maps.
// Skip non-string-keyed maps (e.g. map[int]string) to avoid false positives.
if keyIdent, ok := mapType.Key.(*ast.Ident); !ok || keyIdent.Name != "string" {
return
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Won't this break CRD use cases? Or are non string keyed maps not possible in CRDs?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

As far as I understood, non-string-keyed maps are not valid CRD fields. So, this will not break CRD use case

Comment thread pkg/analysis/maxlength/analyzer.go Outdated
Comment on lines +269 to +270
// needsByteSliceMaxLength is like needsStringMaxLength but enforces that for DV markers,
// +k8s:maxBytes is used instead of +k8s:maxLength (which counts characters).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How does this work for CRDs though where there is no byte length check, it is always character based?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

For CRDs, the linter remains character-based and only-handles byte based validation +k8s:maxBytes when explicitly configured for DV.

OpenAPI v3 does not have native byte-length constraints; instead, byte[] fields are represented as base64-encoded json strings, so the linter expects +kubebuilder :validation:MaxLength for []byte fields for CRDs

@kubernetes-prow kubernetes-prow Bot added the do-not-merge/invalid-commit-message Indicates that a PR should not merge because it has an invalid commit message. label Jul 5, 2026
@kubernetes-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

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

Details 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

@kubernetes-prow kubernetes-prow Bot removed the do-not-merge/invalid-commit-message Indicates that a PR should not merge because it has an invalid commit message. label Jul 5, 2026
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. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[declarative-validation] Add support for DV markers to the maxlength linter.

4 participants