...

Text file src/k8s.io/kubectl/pkg/explain/v2/templates/plaintext.tmpl

Documentation: k8s.io/kubectl/pkg/explain/v2/templates

     1{{- /* Determine if Path for requested GVR is at /api or /apis based on emptiness of group */ -}}
     2{{- $prefix := (ternary "/api" (join "" "/apis/" $.GVR.Group) (not $.GVR.Group)) -}}
     3
     4{{- /* Search both cluster-scoped and namespaced-scoped paths for the GVR to find its GVK */ -}}
     5{{- /* Also search for paths with {name} component in case the list path is missing */ -}}
     6{{- /* Looks for the following paths: */ -}}
     7{{- /* /apis/<group>/<version>/<resource> */ -}}
     8{{- /* /apis/<group>/<version>/<resource>/{name} */ -}}
     9{{- /* /apis/<group>/<version>/namespaces/{namespace}/<resource> */ -}}
    10{{- /* /apis/<group>/<version>/namespaces/{namespace}/<resource>/{name} */ -}}
    11{{- /* Also search for get verb paths in case list verb is missing */ -}}
    12{{- $clusterScopedSearchPath :=  join "/" $prefix $.GVR.Version $.GVR.Resource -}}
    13{{- $clusterScopedNameSearchPath :=  join "/" $prefix $.GVR.Version $.GVR.Resource "{name}" -}}
    14{{- $namespaceScopedSearchPath := join "/" $prefix $.GVR.Version "namespaces" "{namespace}" $.GVR.Resource -}}
    15{{- $namespaceScopedNameSearchPath := join "/" $prefix $.GVR.Version "namespaces" "{namespace}" $.GVR.Resource "{name}" -}}
    16{{- $gvk := "" -}}
    17
    18{{- /* Pull GVK from operation */ -}}
    19{{- range $index, $searchPath := (list $clusterScopedSearchPath $clusterScopedNameSearchPath $namespaceScopedSearchPath $namespaceScopedNameSearchPath) -}}
    20    {{- with $resourcePathElement := index $.Document "paths" $searchPath -}}
    21        {{- range $methodIndex, $method := (list "get" "post" "put" "patch" "delete") -}}
    22            {{- with $resourceMethodPathElement := index $resourcePathElement $method -}}
    23                {{- with $gvk = index $resourceMethodPathElement "x-kubernetes-group-version-kind" -}}
    24                    {{- break -}}
    25                {{- end -}}
    26            {{- end -}}
    27        {{- end -}}
    28    {{- end -}}
    29{{- end -}}
    30
    31{{- with $gvk -}}
    32    {{- if $gvk.group -}}
    33        GROUP:      {{ $gvk.group }}{{"\n" -}}
    34    {{- end -}}
    35    KIND:       {{ $gvk.kind}}{{"\n" -}}
    36    VERSION:    {{ $gvk.version }}{{"\n" -}}
    37    {{- "\n" -}}
    38
    39    {{- with include "schema" (dict "gvk" $gvk "Document" $.Document "FieldPath" $.FieldPath "Recursive" $.Recursive) -}}
    40        {{- . -}}
    41    {{- else -}}
    42        {{- throw "error: GVK %v not found in OpenAPI schema" $gvk -}}
    43    {{- end -}}
    44{{- else -}}
    45    {{- throw "error: GVR (%v) not found in OpenAPI schema" $.GVR.String -}}
    46{{- end -}}
    47{{- "\n" -}}
    48
    49{{- /*
    50Finds a schema with the given GVK and prints its explain output or empty string
    51if GVK was not found
    52
    53Takes dictionary as argument with keys:
    54    gvk: openapiv3 JSON schema
    55    Document: entire doc
    56    FieldPath: field path to follow
    57    Recursive: print recursive
    58*/ -}}
    59{{- define "schema" -}}
    60    {{- /* Find definition with this GVK by filtering out the components/schema with the given x-kubernetes-group-version-kind */ -}}
    61    {{- range index $.Document "components" "schemas" -}}
    62        {{- if contains (index . "x-kubernetes-group-version-kind") $.gvk -}}
    63            {{- with include "output" (set $ "schema" .) -}}
    64                {{- . -}}
    65            {{- else -}}
    66                {{- $fieldName := (index $.FieldPath (sub (len $.FieldPath) 1)) -}}
    67                {{- throw "error: field \"%v\" does not exist" $fieldName}}
    68            {{- end -}}
    69            {{- break -}}
    70        {{- end -}}
    71    {{- end -}}
    72{{- end -}}
    73
    74{{- /*
    75Follows FieldPath until the FieldPath is empty. Then prints field name and field 
    76list of resultant schema. If field path is not found. Prints nothing.
    77Example output:
    78
    79FIELD: spec
    80
    81DESCRIPTION:
    82    <template "description">
    83
    84FIELDS:
    85    <template "fieldList">
    86
    87Takes dictionary as argument with keys:
    88    schema: openapiv3 JSON schema
    89    history: map[string]int
    90    Document: entire doc
    91    FieldPath: field path to follow
    92    Recursive: print recursive
    93*/ -}}
    94{{- define "output" -}}
    95    {{- $refString := or (index $.schema "$ref") "" -}}
    96    {{- $nextContext := set $ "history" (set $.history $refString 1) -}}
    97    {{- $resolved := or (resolveRef $refString $.Document) $.schema -}}
    98    {{- if not $.FieldPath -}}
    99        DESCRIPTION:{{- "\n" -}}
   100        {{- or (include "description" (dict "schema" $resolved "Document" $.Document)) "<empty>" | wrap 76 | indent 4 -}}{{- "\n" -}}
   101        {{- with include "fieldList" (dict "schema" $resolved "level" 1 "Document" $.Document "Recursive" $.Recursive) -}}
   102            FIELDS:{{- "\n" -}}
   103            {{- . -}}
   104        {{- end -}}
   105    {{- else if and $refString (index $.history $refString) -}}
   106        {{- /* Stop and do nothing. Hit a cycle */ -}}
   107    {{- else if and $resolved.properties (index $resolved.properties (first $.FieldPath)) -}}
   108        {{- /* Schema has this property directly. Traverse to next schema */ -}}
   109        {{- $subschema := index $resolved.properties (first $.FieldPath) -}}
   110        {{- if eq 1 (len $.FieldPath) -}}
   111            {{- /* TODO: The original explain would say RESOURCE instead of FIELD here under some circumstances */ -}}
   112            FIELD: {{first $.FieldPath}} <{{ template "typeGuess" (dict "schema" $subschema "Document" $.Document) }}>{{"\n"}}
   113            {{- template "extractEnum" (dict "schema" $subschema "Document" $.Document "isLongView" true "limit" -1) -}}{{"\n"}}
   114            {{- "\n" -}}
   115        {{- end -}}
   116
   117        {{- template "output" (set $nextContext "history" (dict) "FieldPath" (slice $.FieldPath 1) "schema" $subschema ) -}}
   118    {{- else if $resolved.items -}}
   119        {{- /* If the schema is an array then traverse the array item fields */ -}}
   120        {{- template "output" (set $nextContext "schema" $resolved.items) -}}
   121    {{- else if $resolved.additionalProperties -}}
   122        {{- /* If the schema is a map then traverse the map item fields */ -}}
   123        {{- template "output" (set $nextContext "schema" $resolved.additionalProperties) -}}
   124    {{- else -}}
   125        {{- /* Last thing to try is all the alternatives in the allOf case */ -}}
   126        {{- /* Stop when one of the alternatives has an output at all */ -}}
   127        {{- range $index, $subschema := $resolved.allOf -}}
   128            {{- with include "output" (set $nextContext "schema" $subschema) -}}
   129                {{- . -}}
   130                {{- break -}}
   131            {{- end -}}
   132        {{- end -}}
   133    {{- end -}}
   134{{- end -}}
   135
   136{{- /*
   137Prints list of fields of a given open api schema in following form:
   138
   139field1 <type> -required-
   140    DESCRIPTION
   141
   142field2 <type> -required-
   143    DESCRIPTION
   144
   145or if Recursive is enabled:
   146field1 <type> -required-
   147    subfield1 <type>
   148        subsubfield1 <type>
   149        subsubfield2 <type>
   150    subfield2 <type>
   151field2 <type> -required-
   152    subfield1 <type>
   153    subfield2 <type>
   154
   155Follows refs for field traversal. If there are cycles in the schema, they are
   156detected and traversal ends.
   157
   158Takes dictionary as argument with keys:
   159    schema: openapiv3 JSON schema
   160    level: indentation level
   161    history: map[string]int containing all ref names so far
   162    Document: entire doc
   163    Recursive: print recursive
   164*/ -}}
   165{{- define "fieldList" -}}
   166    {{- /* Resolve schema if it is a ref */}}
   167    {{- /* If this is a ref seen before, then ignore it */}}
   168    {{- $refString := or (index $.schema "$ref") "" }}
   169    {{- if and $refString (index (or $.history (dict)) $refString) -}}
   170        {{- /* Do nothing for cycle */}}
   171    {{- else -}}
   172        {{- $nextContext := set $ "history" (set $.history $refString 1) -}}
   173        {{- $resolved := or (resolveRef $refString $.Document) $.schema -}}
   174        {{- range $k, $v := $resolved.properties -}}
   175            {{- template "fieldDetail" (dict "name" $k "schema" $resolved "short" $.Recursive "level" $.level "Document" $.Document) -}}
   176            {{- if $.Recursive -}}
   177                {{- /* Check if we already know about this element */}}
   178                {{- template "fieldList" (set $nextContext "schema" $v "level" (add $.level 1)) -}}
   179            {{- end -}}
   180        {{- end -}}
   181        {{- range $resolved.allOf -}}
   182            {{- template "fieldList" (set $nextContext "schema" .)}}
   183        {{- end -}}
   184        {{- if $resolved.items}}{{- template "fieldList" (set $nextContext "schema" $resolved.items)}}{{end}}
   185        {{- if $resolved.additionalProperties}}{{- template "fieldList" (set $nextContext "schema" $resolved.additionalProperties)}}{{end}}
   186    {{- end -}}
   187{{- end -}}
   188
   189
   190{{- /*
   191
   192Prints a single field of the given schema
   193Optionally prints in a one-line style
   194
   195Takes dictionary as argument with keys:
   196    schema: openapiv3 JSON schema which contains the field
   197    name: name of field
   198    short: limit printing to a single-line summary
   199    level: indentation amount
   200    Document: openapi document
   201*/ -}}
   202{{- define "fieldDetail" -}}
   203    {{- $level := or $.level 0 -}}
   204    {{- $indentAmount := mul $level 2 -}}
   205    {{- $fieldSchema := index $.schema.properties $.name -}}
   206    {{- $.name | indent $indentAmount -}}{{"\t"}}<{{ template "typeGuess" (dict "schema" $fieldSchema "Document" $.Document) }}>
   207    {{- if contains $.schema.required $.name}} -required-{{- end -}}
   208    {{- template "extractEnum" (dict "schema" $fieldSchema "Document" $.Document "isLongView" false "limit" 4 "indentAmount" $indentAmount) -}}
   209    {{- "\n" -}}
   210    {{- if not $.short -}}
   211        {{- or $fieldSchema.description "<no description>" | wrap (sub 78 $indentAmount) | indent (add $indentAmount 2) -}}{{- "\n" -}}
   212        {{- "\n" -}}
   213    {{- end -}}
   214{{- end -}}
   215
   216{{- /*
   217
   218Prints the description of the given OpenAPI v3 schema. Also walks through all
   219sibling schemas to the provided schema and prints the description of those schemas
   220too
   221
   222Takes dictionary as argument with keys:
   223    schema: openapiv3 JSON schema
   224    Document: document to resolve refs within
   225*/ -}}
   226{{- define "description" -}}
   227    {{- with or (resolveRef (index $.schema "$ref") $.Document) $.schema -}}
   228        {{- if .description -}}
   229            {{- .description -}}
   230            {{- "\n" -}}
   231        {{- end -}}
   232        {{- range .allOf -}}
   233            {{- template "description" (set $ "schema" .)}}
   234        {{- end -}}
   235        {{- if .items -}}
   236            {{- template "description" (set $ "schema" .items) -}}
   237        {{- end -}}
   238        {{- if .additionalProperties -}}
   239            {{- template "description" (set $ "schema" .additionalProperties) -}}
   240        {{- end -}}
   241    {{- end -}}
   242{{- end -}}
   243
   244{{- /* Renders a shortstring representing an interpretation of what is the "type"
   245        of a subschema e.g.:
   246
   247        `string` `number`, `Object`, `[]Object`, `map[string]string`, etc.
   248
   249    Serves as a more helpful type hint than raw typical openapi `type` field
   250
   251Takes dictionary as argument with keys:
   252    schema: openapiv3 JSON schema
   253    Document: openapi document
   254*/ -}}
   255{{- define "typeGuess" -}}
   256    {{- with $.schema -}}
   257        {{- if .items -}}
   258            []{{template "typeGuess" (set $ "schema" .items)}}
   259        {{- else if .additionalProperties -}}
   260            map[string]{{template "typeGuess" (set $ "schema" .additionalProperties)}}
   261        {{- else if and .allOf (not .properties) (eq (len .allOf) 1) -}}
   262            {{- /* If allOf has a single element and there are no direct
   263                properties on the schema, defer to the allOf */ -}}
   264            {{- template "typeGuess" (set $ "schema" (first .allOf)) -}}
   265        {{- else if index . "$ref"}}
   266            {{- /* Parse the #!/components/schemas/io.k8s.Kind string into just the Kind name */ -}}
   267            {{- $ref := index . "$ref" -}}
   268            {{- /* Look up ref schema to see primitive type. Only put the ref type name if it is an object. */ -}}
   269            {{- $refSchema := resolveRef $ref $.Document -}}
   270            {{- if (or (not $refSchema) (or (not $refSchema.type) (eq $refSchema.type "object"))) -}}
   271                {{- $name := split $ref "/" | last -}}
   272                {{- or (split $name "." | last) "Object" -}}
   273            {{- else if $refSchema.type -}}
   274                {{- or $refSchema.type "Object" -}}
   275            {{- else -}}
   276                {{- or .type "Object" -}}
   277            {{- end -}}
   278        {{- else -}}
   279            {{/* Old explain used capitalized "Object". Just follow suit */}}
   280            {{- if eq .type "object" -}}Object
   281            {{- else -}}{{- or .type "Object" -}}{{- end -}}
   282        {{- end -}}
   283    {{- else -}}
   284        {{- fail "expected schema argument to subtemplate 'typeguess'" -}}
   285    {{- end -}}
   286{{- end -}}
   287
   288{{- /* Check if there is any enum returns it in this format e.g.:
   289
   290    ENUM: "", BlockDevice, CharDevice, Directory
   291    enum: "", BlockDevice, CharDevice, Directory
   292
   293    Can change the style of enum in future by modifying this function
   294
   295Takes dictionary as argument with keys:
   296    schema: openapiv3 JSON schema
   297    Document: openapi document
   298    isLongView: (boolean) Simple view: long list of all fields. Long view: all details of one field
   299    limit: (int) truncate the amount of enums that can be printed in simple view, -1 means all items
   300    indentAmount: intent of the beginning enum line in longform view
   301*/ -}}
   302{{- define "extractEnum" -}}
   303    {{- with $.schema -}}
   304        {{- if .enum -}}
   305            {{- $enumLen := len .enum -}}
   306            {{- $limit := or $.limit -1 -}}
   307            {{- if eq $.isLongView false -}}
   308                {{- "\n" -}}
   309                {{- "" | indent $.indentAmount -}}
   310                {{- "enum: " -}}
   311            {{- else -}}
   312                {{- "ENUM:" -}}
   313            {{- end -}}
   314            {{- range $index, $element := .enum -}}
   315                {{- /* Prints , ....  and return the range when it goes over the limit */ -}}
   316                {{- if and (gt $limit -1) (ge $index $limit) -}}
   317                    {{- ", ...." -}}
   318                    {{- break -}}
   319                {{- end -}}
   320                {{- /* Use to reflect "" when we see empty string */ -}}
   321                {{- $elementType := printf "%T" $element -}}
   322                {{- /* Print out either `, ` or `\n    ` based of the view */ -}}
   323                {{- /* Simple view */ -}}
   324                {{- if and (gt $index 0) (eq $.isLongView false) -}}
   325                    {{- ", " -}}
   326                {{- /* Long view */ -}}
   327                {{- else if eq $.isLongView true -}}
   328                    {{- "\n" -}}{{- "" | indent 4 -}}
   329                {{- end -}}
   330                {{- /* Convert empty string to `""` for more clarification */ -}}
   331                {{- if and (eq "string" $elementType) (eq $element "") -}}
   332                    {{- `""` -}}
   333                {{- else -}}
   334                    {{- $element -}}
   335                {{- end -}}
   336        {{- end -}}
   337        {{- end -}}
   338    {{- end -}}
   339{{- end -}}

View as plain text