Skip to content

gen-apidocs: include create-only resources in the generated ToC - #473

Open
abhinav-phi wants to merge 2 commits into
kubernetes-sigs:masterfrom
abhinav-phi:fix-create-only-resources-missing-from-toc
Open

abhinav-phi wants to merge 2 commits into
kubernetes-sigs:masterfrom
abhinav-phi:fix-create-only-resources-missing-from-toc

Conversation

@abhinav-phi

Copy link
Copy Markdown

Problem

With --auto-detect, IsTopLevelResource only recognized definitions that have a List operation ("Read Operations" category, List/List All Namespaces). Resources that only support Create were therefore never classified as top-level, and buildGroupBasedCategories dropped them entirely — their API group's category/directory and per-resource pages were never emitted.

This silently dropped two whole groups from the generated navigation (kubernetes/website#57313):

  • authentication.k8s.io: TokenRequest, TokenReview, SelfSubjectReview
  • authorization.k8s.io review types: SubjectAccessReview, LocalSubjectAccessReview, SelfSubjectAccessReview, SelfSubjectRulesReview

Both groups are listed on the generated group-versions.md page but had no pages. Up to the v1.35 docs these pages existed (e.g. /docs/reference/kubernetes-api/authentication-resources/token-request-v1/); the migration to the markdown backend removed them because the generator no longer produced them. Verified against the v1.36 spec: baseline run produces no authentication/ or authorization/ directory.

Fix

  1. IsTopLevelResource also accepts a top-level Create operation ("Write Operations" category, Create type) as evidence of a top-level resource.
  2. In the TokenRequest special case (its operation is createCoreV1NamespacedServiceAccountToken, mapped in mapOperationsToDefinitions), the category was constructed and the operation linked, but the category was never appended to d.OperationCategories, and o.Type was never set — so even with fix 1 alone TokenRequest would still fail the check. Attach the category (with the typed operation) to the definition.

Result

With --auto-detect --backend=hugo-md on the v1.36 spec:

  • authentication/: _index.md, token-request-v1.md, token-review-v1.md, self-subject-review-v1.md
  • authorization/: _index.md, subject-access-review-v1.md, local-subject-access-review-v1.md, self-subject-access-review-v1.md, self-subject-rules-review-v1.md

matching the per-group structure of the other groups. The group _index/weights of existing groups shift by two steps (Authentication and Authorization now occupy their alphabetical slots); all page content of existing resources is unchanged.

Notes

  • TestWriteOperationGolden / TestWriteOperationGoldenHugoMode fail on master at this commit (checked without this change) because the checked-in operation-list-hugo.golden.md predates the pipe-table formatting of 7e8927c; the failures are unrelated to this diff (identical failures before/after). Happy to refresh goldens in a separate PR.
  • Downstream effect for kubernetes/website: after this lands, make apimd-hugo && copyapimd restores the missing group directories. The new resource pages for authentication/authorization land in content/en/docs/reference/kubernetes-api/authentication/ and .../authorization/.
  • Fixes Authentication v1 API reference has disappeared from navigation as of 1.36 kubernetes/website#57313 (together with a website-side commit syncing the regenerated content, coming separately).

IsTopLevelResource only recognized resources with a List operation, so
group-based ToC generation (auto-detect) skipped resources that only
support Create. This dropped the authentication.k8s.io group (TokenRequest,
TokenReview, SelfSubjectReview) and the authorization.k8s.io review types
(SubjectAccessReview and friends) from the generated navigation: their
group directories and category pages were never emitted, even though the
group-versions page lists them.

Treat a top-level Create operation as evidence of a top-level resource as
well. For TokenRequest this also required attaching the Write Operations
category to the definition in the special case that maps it to the
createCoreV1NamespacedServiceAccountToken operation (the category was
built and the operation linked, but never appended to
OperationCategories, so the operation type stayed empty and the
definition still failed the check).

With --auto-detect --backend=hugo-md on the v1.36 spec this emits
authentication/ (token-request-v1, token-review-v1,
self-subject-review-v1) and authorization/ (subject-access-review-v1,
local-subject-access-review-v1, self-subject-access-review-v1,
self-subject-rules-review-v1), matching the pages published up to the
v1.35 docs.

Signed-off-by: abhinav-phi <alpha9coder@gmail.com>
@kubernetes-prow kubernetes-prow Bot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Sep 4, 2026
@kubernetes-prow

Copy link
Copy Markdown
Contributor

Welcome @abhinav-phi!

It looks like this is your first PR to kubernetes-sigs/reference-docs 🎉. Please refer to our pull request process documentation to help your PR have a smooth ride to approval.

You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. Here is the bot commands documentation.

You can also check if kubernetes-sigs/reference-docs has its own contribution guidelines.

You may want to refer to our testing guide if you run into trouble with your tests not passing.

If you are having difficulty getting your pull request seen, please follow the recommended escalation practices. Also, for tips and tricks in the contribution process you may want to read the Kubernetes contributor cheat sheet. We want to make sure your contribution gets all the attention it needs!

Thank you, and welcome to Kubernetes. 😃

@kubernetes-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: abhinav-phi
Once this PR has been reviewed and has the lgtm label, please assign natalisucks 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 added the size/S Denotes a PR that changes 10-29 lines, ignoring generated files. label Sep 4, 2026

@Caesarsage Caesarsage left a comment

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.

Nice find, the dropped OperationCategory is easy to miss. I reproduced your result on the v1.37 spec: both groups come back, 162 pages either way.

Have you copied the output into k/website and built it locally?

https://deploy-preview-57160--kubernetes-io-main-staging.netlify.app/docs/contribute/generate-ref-docs/release-generation/

Mine failed with 18 REF_NOT_FOUND errors. Three of the admission-policy pages relref the definitions/ pages you're removing, so the website change needs to go in at the same time as this one.

While you're there, look at the page you just created, authentication/token-request-v1.md. Its request body and all three responses link to the CSI driver page instead of to itself. There are two different TokenRequest kinds, authentication.v1 and storage.v1, and the link map in markdown.go is keyed on the kind name alone, so one overwrites the other. Same thing makes Pod's eviction op point at the wrong Eviction today. So this needs a fix in markdown.go as well. That can be a follow-up PR, but please hold this one until it lands.

Last thing: the golden tests pass on your base. That golden came in with #460, which you're already on, so that note in the description can go.

Left a few smaller things inline.

// API resource (one that has its own List endpoint), as opposed to a
// subresource (Scale, Eviction) or utility type (Status, WatchEvent).
// Some resources, such as TokenRequest and the SubjectAccessReview family,
// only support Create; they are top-level resources too.

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.

The first sentence is now the opposite of what the function does, and Binding (a pods/binding subresource) gets promoted by this change, so the "as opposed to a subresource" part doesn't hold either.

Suggested change
// only support Create; they are top-level resources too.
// IsTopLevelResource reports whether this definition is a top-level API
// resource, as opposed to a utility type (Status, WatchEvent) or a field type
// that never appears on the wire by itself.
//
// A List endpoint is the usual marker, but create-only resources such as
// TokenRequest and the SubjectAccessReview family qualify too.

Comment on lines +356 to +368
for _, c := range d.OperationCategories {
if c == nil || c.Name != "Write Operations" {
continue
}
for _, op := range c.Operations {
if op == nil {
continue
}
if op.Type.Name == "Create" {
return true
}
}
}

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.

Suggested change
for _, c := range d.OperationCategories {
if c == nil || c.Name != "Write Operations" {
continue
}
for _, op := range c.Operations {
if op == nil {
continue
}
if op.Type.Name == "Create" {
return true
}
}
}

There is no need for this extra loop.

This can be one pass instead of walking OperationCategories twice, same conditions, same result:

for _, c := range d.OperationCategories {
		if c == nil {
			continue
		}
		for _, op := range c.Operations {
			if op == nil {
				continue
			}
			switch c.Name {
			case "Read Operations":
				if op.Type.Name == "List" || op.Type.Name == "List All Namespaces" {
					return true
				}
			case "Write Operations":
				if op.Type.Name == "Create" {
					return true
				}
			}
		}
	}
	return false

Comment thread gen-apidocs/generators/api/config.go Outdated
@@ -831,10 +831,14 @@ func (c *Config) mapOperationsToDefinitions() error {

o.Definition = d
o.Definition.InToc = true

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.

Now that the category is attached and buildGroupBasedCategories marks the definition, this line is redundant and it's the other half of what broke TokenRequest in the first place: it told writeDefinitions to skip the page while the missing category kept it out of the ToC, so it fell through both. Worth dropping so the fix reads on its own.

Comment thread gen-apidocs/generators/api/config.go Outdated

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.

nit: Since you're here, this XXX: reads like a bug marker but it's just describing the operation ID. Something like "TokenRequest is created through a ServiceAccount subresource, so its operation ID doesn't follow the ${group}${version}${resource} pattern the generic matcher below uses" would save the next person a detour

- IsTopLevelResource: single pass over OperationCategories with a switch,
  and a doc comment that no longer claims List-only resources are excluded
- TokenRequest special case: drop the redundant o.Definition.InToc line;
  attaching the Write Operations category is what places the definition
- Reword the XXX comment to explain why TokenRequest's operation ID does
  not match the generic pattern

Signed-off-by: abhinav-phi <alpha9coder@gmail.com>
@kubernetes-prow kubernetes-prow Bot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed size/S Denotes a PR that changes 10-29 lines, ignoring generated files. labels Sep 7, 2026
@abhinav-phi

Copy link
Copy Markdown
Author

Thanks @Caesarsage for the quick review and for reproducing it on the v1.37 spec — all four suggestions are applied in 9cecf0f:

  • IsTopLevelResource is now a single pass with a switch, and the doc comment no longer claims List-only resources are excluded (I re-verified the regenerated output after the rework: authentication/ and authorization/ still come out with the same pages, and Binding is still promoted to a resource page, consistent with the v1.35 docs where workload-resources/binding-v1 existed).
  • Dropped the redundant o.Definition.InToc = true — agreed, attaching the category is what places the definition, and the stray flag was exactly what made TokenRequest fall through both writeDefinitions and the ToC before.
  • Reworded the XXX: comment to explain the operation-ID mismatch.

To answer your question: I did not copy the output into k/website and build it there. Two reasons:

  1. Format drift between reference-docs master and the site. The content committed on kubernetes/website main still matches the hugo-md output as of the backend switch (May 13): import: string front matter, HTML tables, no preamble shortcodes. Master's output today (after 31032f6) emits code_import:, {{< api-object-preamble >}} and friends — and none of those shortcodes are defined in kubernetes/website's layouts (or docsy), so pasting master-format pages today would break the Hugo build. I checked this while preparing the link-repair PR (Repair links to the removed authentication-resources API reference pages kubernetes/website#57414), which fixes the 16 stranded inbound links in the meantime; the full page restore should ride the next scheduled regen once the shortcode templates land on the site side (issue Emit API reference as structured Hugo shortcodes instead of HTML tables #440 territory).

  2. A pre-existing nondeterminism I hit while diffing runs (not from this change — reproduces on master without it, verified by stashing): two consecutive runs of --backend=hugo-md can differ in the core vs events category weights (130/140 swap in _index.md front matter) and in the ref-link disambiguation of the colliding event-v1.md filenames ({{< ref "event-v1#Event" >}} vs {{< ref "../events/event-v1#Event" >}} in core/event-v1.md). Looks like a map-iteration-order dependency in the link map / weight assignment when two groups have same-named filenames. Worth a follow-up issue since it will make every website regen PR noisy — happy to file and take a stab at it if you agree.

@abhinav-phi

Copy link
Copy Markdown
Author

@Caesarsage all four of your suggestions are applied in 9cecf0f (single-pass switch + corrected doc comment, redundant InToc dropped, XXX: comment reworded). I re-ran --backend=hugo-md on the v1.36 spec after the rework — authentication/ and authorization/ still emit with the same page set as before, so behavior is unchanged.

Could I ask for a re-review when you have a moment? Happy to iterate on anything else.

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/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Authentication v1 API reference has disappeared from navigation as of 1.36

2 participants