Merge pull request #118930 from atiratree/automated-cherry-pick-of-#118876-upstream-release-1.27

Automated cherry pick of #118876: kubectl explain should work for both cluster and namespace

Kubernetes-commit: 04e86095d38aec469c31c9df707796ff7bf05de3
This commit is contained in:
Kubernetes Publisher 2023-07-05 10:45:09 -07:00
commit 13f7b15bc1
6 changed files with 9234 additions and 8 deletions

4
go.mod
View File

@ -33,7 +33,7 @@ require (
k8s.io/api v0.0.0-20230705181702-64b026215965
k8s.io/apimachinery v0.0.0-20230612171306-38152d47d786
k8s.io/cli-runtime v0.0.0-20230705200247-da2c5ab289b9
k8s.io/client-go v0.0.0-20230705183358-8d8e2bc8c982
k8s.io/client-go v0.0.0-20230705183401-860d25f20e24
k8s.io/component-base v0.0.0-20230705190003-c964270bd046
k8s.io/component-helpers v0.0.0-20230705190518-e8b08838a22f
k8s.io/klog/v2 v2.90.1
@ -97,7 +97,7 @@ replace (
k8s.io/api => k8s.io/api v0.0.0-20230705181702-64b026215965
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20230612171306-38152d47d786
k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20230705200247-da2c5ab289b9
k8s.io/client-go => k8s.io/client-go v0.0.0-20230705183358-8d8e2bc8c982
k8s.io/client-go => k8s.io/client-go v0.0.0-20230705183401-860d25f20e24
k8s.io/code-generator => k8s.io/code-generator v0.0.0-20230705153058-ad209354fb6b
k8s.io/component-base => k8s.io/component-base v0.0.0-20230705190003-c964270bd046
k8s.io/component-helpers => k8s.io/component-helpers v0.0.0-20230705190518-e8b08838a22f

4
go.sum
View File

@ -545,8 +545,8 @@ k8s.io/apimachinery v0.0.0-20230612171306-38152d47d786 h1:5apbbWoKi3ZjCSWm5UKfcN
k8s.io/apimachinery v0.0.0-20230612171306-38152d47d786/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
k8s.io/cli-runtime v0.0.0-20230705200247-da2c5ab289b9 h1:BfpceTxJkpRJ241YNDPtheyf2Ru/ACrDgSHHbKuYiIE=
k8s.io/cli-runtime v0.0.0-20230705200247-da2c5ab289b9/go.mod h1:Dyr7YCfqajaLZf6BgME78H+mdgyIdE+3goKo6tXRBZU=
k8s.io/client-go v0.0.0-20230705183358-8d8e2bc8c982 h1:d+jZBdBd2n2D7k/8+fizAqZXHBtCtWYXvtrAXQTNWUI=
k8s.io/client-go v0.0.0-20230705183358-8d8e2bc8c982/go.mod h1:BuW1PoLqaULdxqGIXqc77od21c39c6Cxe+rm9KhNnvc=
k8s.io/client-go v0.0.0-20230705183401-860d25f20e24 h1:h7JwteUItQCraRMQUdOoFve+0eiAR2IvUs0sXP/xWvg=
k8s.io/client-go v0.0.0-20230705183401-860d25f20e24/go.mod h1:BuW1PoLqaULdxqGIXqc77od21c39c6Cxe+rm9KhNnvc=
k8s.io/component-base v0.0.0-20230705190003-c964270bd046 h1:OBVR0/Wl6AP93SGN8cOtRJFmyHztwGU0rn6Cfj35p2c=
k8s.io/component-base v0.0.0-20230705190003-c964270bd046/go.mod h1:iTsyaqmcZA6Cwc2WL21dLc0H8cCZZzwbklTzDQzuqvU=
k8s.io/component-helpers v0.0.0-20230705190518-e8b08838a22f h1:aJREGrqWonsPU+rz6MItpzzgWvWKLtTaThx0HBr9kkg=

View File

@ -185,6 +185,9 @@ func WithBuiltinTemplateFuncs(tmpl *template.Template) *template.Template {
return copyDict, nil
},
"list": func(values ...any) ([]any, error) {
return values, nil
},
"add": func(value, operand int) int {
return value + operand
},

File diff suppressed because it is too large Load Diff

View File

@ -2,13 +2,33 @@
{{- $prefix := (ternary "/api" (join "" "/apis/" $.GVR.Group) (not $.GVR.Group)) -}}
{{- /* Search both cluster-scoped and namespaced-scoped paths for the GVR to find its GVK */ -}}
{{- /* Looks for path /apis/<group>/<version>/<resource> or /apis/<group>/<version>/<version>/namespaces/{namespace}/<resource> */ -}}
{{- /* Also search for paths with {name} component in case the list path is missing */ -}}
{{- /* Looks for the following paths: */ -}}
{{- /* /apis/<group>/<version>/<resource> */ -}}
{{- /* /apis/<group>/<version>/<resource>/{name} */ -}}
{{- /* /apis/<group>/<version>/namespaces/{namespace}/<resource> */ -}}
{{- /* /apis/<group>/<version>/namespaces/{namespace}/<resource>/{name} */ -}}
{{- /* Also search for get verb paths in case list verb is missing */ -}}
{{- $clusterScopedSearchPath := join "/" $prefix $.GVR.Version $.GVR.Resource -}}
{{- $namespaceScopedSearchPath := join "/" $prefix $.GVR.Version "namespaces" "\\{namespace\\}" $.GVR.Resource -}}
{{- $path := or (index $.Document "paths" $clusterScopedSearchPath) (index $.Document "paths" $clusterScopedSearchPath) -}}
{{- $clusterScopedNameSearchPath := join "/" $prefix $.GVR.Version $.GVR.Resource "{name}" -}}
{{- $namespaceScopedSearchPath := join "/" $prefix $.GVR.Version "namespaces" "{namespace}" $.GVR.Resource -}}
{{- $namespaceScopedNameSearchPath := join "/" $prefix $.GVR.Version "namespaces" "{namespace}" $.GVR.Resource "{name}" -}}
{{- $gvk := "" -}}
{{- /* Pull GVK from operation */ -}}
{{- with $gvk := and $path (index $path "get" "x-kubernetes-group-version-kind") -}}
{{- range $index, $searchPath := (list $clusterScopedSearchPath $clusterScopedNameSearchPath $namespaceScopedSearchPath $namespaceScopedNameSearchPath) -}}
{{- with $resourcePathElement := index $.Document "paths" $searchPath -}}
{{- range $methodIndex, $method := (list "get" "post" "put" "patch" "delete") -}}
{{- with $resourceMethodPathElement := index $resourcePathElement $method -}}
{{- with $gvk = index $resourceMethodPathElement "x-kubernetes-group-version-kind" -}}
{{- break -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- with $gvk -}}
{{- if $gvk.group -}}
GROUP: {{ $gvk.group }}{{"\n" -}}
{{- end -}}

View File

@ -41,17 +41,46 @@ var (
//go:embed apiextensions.k8s.io_v1.json
apiextensionsJSON string
//go:embed batch.k8s.io_v1.json
batchJSON string
apiExtensionsV1OpenAPI map[string]interface{} = func() map[string]interface{} {
var res map[string]interface{}
utilruntime.Must(json.Unmarshal([]byte(apiextensionsJSON), &res))
return res
}()
apiExtensionsV1OpenAPIWithoutListVerb map[string]interface{} = func() map[string]interface{} {
var res map[string]interface{}
utilruntime.Must(json.Unmarshal([]byte(apiextensionsJSON), &res))
paths := res["paths"].(map[string]interface{})
delete(paths, "/apis/apiextensions.k8s.io/v1/customresourcedefinitions")
return res
}()
apiExtensionsV1OpenAPISpec spec3.OpenAPI = func() spec3.OpenAPI {
var res spec3.OpenAPI
utilruntime.Must(json.Unmarshal([]byte(apiextensionsJSON), &res))
return res
}()
batchV1OpenAPI map[string]interface{} = func() map[string]interface{} {
var res map[string]interface{}
utilruntime.Must(json.Unmarshal([]byte(batchJSON), &res))
return res
}()
batchV1OpenAPIWithoutListVerb map[string]interface{} = func() map[string]interface{} {
var res map[string]interface{}
utilruntime.Must(json.Unmarshal([]byte(batchJSON), &res))
paths := res["paths"].(map[string]interface{})
delete(paths, "/apis/batch/v1/jobs")
delete(paths, "/apis/batch/v1/namespaces/{namespace}/jobs")
delete(paths, "/apis/batch/v1/cronjobs")
delete(paths, "/apis/batch/v1/namespaces/{namespace}/cronjobs/{name}")
return res
}()
)
type testCase struct {
@ -143,6 +172,74 @@ func TestPlaintext(t *testing.T) {
checkContains("CustomResourceDefinition represents a resource that should be exposed"),
},
},
{
// Test basic ability to find a namespaced GVR and print its description
Name: "SchemaFoundNamespaced",
Context: v2.TemplateContext{
Document: batchV1OpenAPI,
GVR: schema.GroupVersionResource{
Group: "batch",
Version: "v1",
Resource: "jobs",
},
FieldPath: nil,
Recursive: false,
},
Checks: []check{
checkContains("Job represents the configuration of a single job"),
},
},
{
// Test basic ability to find a GVR without a list verb and print its description
Name: "SchemaFoundWithoutListVerb",
Context: v2.TemplateContext{
Document: apiExtensionsV1OpenAPIWithoutListVerb,
GVR: schema.GroupVersionResource{
Group: "apiextensions.k8s.io",
Version: "v1",
Resource: "customresourcedefinitions",
},
FieldPath: nil,
Recursive: false,
},
Checks: []check{
checkContains("CustomResourceDefinition represents a resource that should be exposed"),
},
},
{
// Test basic ability to find a namespaced GVR without a list verb and print its description
Name: "SchemaFoundNamespacedWithoutListVerb",
Context: v2.TemplateContext{
Document: batchV1OpenAPIWithoutListVerb,
GVR: schema.GroupVersionResource{
Group: "batch",
Version: "v1",
Resource: "jobs",
},
FieldPath: nil,
Recursive: false,
},
Checks: []check{
checkContains("Job represents the configuration of a single job"),
},
},
{
// Test basic ability to find a namespaced GVR without a top level list verb and print its description
Name: "SchemaFoundNamespacedWithoutTopLevelListVerb",
Context: v2.TemplateContext{
Document: batchV1OpenAPIWithoutListVerb,
GVR: schema.GroupVersionResource{
Group: "batch",
Version: "v1",
Resource: "cronjobs",
},
FieldPath: nil,
Recursive: false,
},
Checks: []check{
checkContains("CronJob represents the configuration of a single cron job"),
},
},
{
// Test that shows trying to find a non-existent field path of an existing
// schema