diff --git a/gen-apidocs/generators/api/config.go b/gen-apidocs/generators/api/config.go index 5b36a23de3..4aa5ea5fb2 100644 --- a/gen-apidocs/generators/api/config.go +++ b/gen-apidocs/generators/api/config.go @@ -816,7 +816,9 @@ func (c *Config) mapOperationsToDefinitions() error { continue } - // XXX: The TokenRequest definition has operation defined as "createCoreV1NamespacedServiceAccountToken"! + // TokenRequest is created through a ServiceAccount subresource, so its + // operation ID doesn't follow the ${group}${version}${resource} pattern + // the generic matcher below uses. if d.Name == "TokenRequest" && d.Group.String() == "authentication" && d.Version == "v1" { operationId := "createCoreV1NamespacedServiceAccountToken" if o, ok := c.Operations[operationId]; ok { @@ -830,11 +832,14 @@ func (c *Config) mapOperationsToDefinitions() error { } o.Definition = d - o.Definition.InToc = true + o.Type = ot if err := o.initExample(c); err != nil { return fmt.Errorf("failed to init example: %w", err) } oc.Operations = append(oc.Operations, o) + // Attach the category to the definition so IsTopLevelResource + // and the resource pages see this Create operation. + d.OperationCategories = append(d.OperationCategories, &oc) } continue } diff --git a/gen-apidocs/generators/api/definition.go b/gen-apidocs/generators/api/definition.go index adb366d2ba..b4931732ec 100644 --- a/gen-apidocs/generators/api/definition.go +++ b/gen-apidocs/generators/api/definition.go @@ -334,20 +334,30 @@ func (s *Definitions) FindNewestVersion(group, kind string) string { return newest } -// IsTopLevelResource returns true if this definition represents a top-level -// API resource (one that has its own List endpoint), as opposed to a -// subresource (Scale, Eviction) or utility type (Status, WatchEvent). +// 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. func (d *Definition) IsTopLevelResource() bool { for _, c := range d.OperationCategories { - if c == nil || c.Name != "Read Operations" { + if c == nil { continue } for _, op := range c.Operations { if op == nil { continue } - if op.Type.Name == "List" || op.Type.Name == "List All Namespaces" { - return true + 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 + } } } }