diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go b/staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go index 982081f05bb..53816ee3db7 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go @@ -120,12 +120,22 @@ func (o *ExplainOptions) Run(args []string) error { recursive := o.Recursive apiVersionString := o.APIVersion - // TODO: After we figured out the new syntax to separate group and resource, allow - // the users to use it in explain (kubectl explain ). - // Refer to issue #16039 for why we do this. Refer to PR #15808 that used "/" syntax. - fullySpecifiedGVR, fieldsPath, err := explain.SplitAndParseResourceRequest(args[0], o.Mapper) - if err != nil { - return err + var fullySpecifiedGVR schema.GroupVersionResource + var fieldsPath []string + var err error + if len(apiVersionString) == 0 { + fullySpecifiedGVR, fieldsPath, err = explain.SplitAndParseResourceRequestWithMatchingPrefix(args[0], o.Mapper) + if err != nil { + return err + } + } else { + // TODO: After we figured out the new syntax to separate group and resource, allow + // the users to use it in explain (kubectl explain ). + // Refer to issue #16039 for why we do this. Refer to PR #15808 that used "/" syntax. + fullySpecifiedGVR, fieldsPath, err = explain.SplitAndParseResourceRequest(args[0], o.Mapper) + if err != nil { + return err + } } gvk, _ := o.Mapper.KindFor(fullySpecifiedGVR) diff --git a/staging/src/k8s.io/kubectl/pkg/explain/explain.go b/staging/src/k8s.io/kubectl/pkg/explain/explain.go index 9d0e904bb9a..bc136a6d978 100644 --- a/staging/src/k8s.io/kubectl/pkg/explain/explain.go +++ b/staging/src/k8s.io/kubectl/pkg/explain/explain.go @@ -50,6 +50,43 @@ func SplitAndParseResourceRequest(inResource string, mapper meta.RESTMapper) (sc if err != nil { return schema.GroupVersionResource{}, nil, err } + + return gvr, fieldsPath, nil +} + +// SplitAndParseResourceRequestWithMatchingPrefix separates the users input into a model and fields +// while selecting gvr whose (resource, group) prefix matches the resource +func SplitAndParseResourceRequestWithMatchingPrefix(inResource string, mapper meta.RESTMapper) (gvr schema.GroupVersionResource, fieldsPath []string, err error) { + // ignore trailing period + inResource = strings.TrimSuffix(inResource, ".") + dotParts := strings.Split(inResource, ".") + + gvrs, err := mapper.ResourcesFor(schema.GroupVersionResource{Resource: dotParts[0]}) + if err != nil { + return schema.GroupVersionResource{}, nil, err + } + + for _, gvrItem := range gvrs { + // Find first gvr whose gr prefixes requested resource + groupResource := gvrItem.GroupResource().String() + if strings.HasPrefix(inResource, groupResource) { + resourceSuffix := inResource[len(groupResource):] + if len(resourceSuffix) > 0 { + dotParts := strings.Split(resourceSuffix, ".") + if len(dotParts) > 0 { + fieldsPath = dotParts[1:] + } + } + return gvrItem, fieldsPath, nil + } + } + + // If no match, take the first (the highest priority) gvr + if len(gvrs) > 0 { + gvr = gvrs[0] + _, fieldsPath = splitDotNotation(inResource) + } + return gvr, fieldsPath, nil }