kubectl explain: detect resource group in case there are two or more groups discovered
Assume the following CRDs exist (ordered by priority, the first is the highest): - authentications.migration.k8s.io (K=Authentications, G=migration.k8s.io) - authentications.metal3.io (K=Authentications, G=metal3.io) - authentications.whereabouts.cni.cncf.io (K=Authentications, G=whereabouts.cni.cncf.io) - authentications.snapshot.storage.k8s.io (K=Authentications, G=snapshot.storage.k8s.io) In case 'kubectl explain authentications' is ran, the highest priority definition (in this case authentications.migration.k8s.io) is returned. In case a user wants to explain authentication CRD of a different group, --api-version flag has to be set alongside to point to a specific group and version. E.g. --api-version=metal3.io/v1 This PR allows to dismiss --api-version flag and perform a prefix check to select a resource (e.g. CRD) whose (resource, group) pair fully prefixes requested resource. E.g. running 'kubectl explain authentications.metal3.io' will return description of authentications.metal3.io. The same holds for optional field path. I.e. 'kubectl explain authentications.metal3.io.spec' will return description of spec field of authentications.metal3.io.spec. In case no resource match is found, the search falls back to selecting the highest priority gvr that matches the resource. In case --api-version is set, no prefix matching is performed. To cover cases such as 'kubectl explain authentications.metal3.io --api-version=authentications.metal3.io/v1' where fields path coincide with the resource fully specified name (to access .metal3.io field of authentications.metal3.io). Kubernetes-commit: 30674db1595e3a24273ceb71cbfe67bb300ad951
This commit is contained in:
parent
808c4936d4
commit
ba75977126
|
@ -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 <group><syntax><resource>).
|
||||
// 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 <group><syntax><resource>).
|
||||
// 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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue