mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
build: move e2e dependencies into e2e/go.mod
Several packages are only used while running the e2e suite. These packages are less important to update, as the they can not influence the final executable that is part of the Ceph-CSI container-image. By moving these dependencies out of the main Ceph-CSI go.mod, it is easier to identify if a reported CVE affects Ceph-CSI, or only the testing (like most of the Kubernetes CVEs). Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
committed by
mergify[bot]
parent
15da101b1b
commit
bec6090996
119
e2e/vendor/k8s.io/client-go/restmapper/category_expansion.go
generated
vendored
Normal file
119
e2e/vendor/k8s.io/client-go/restmapper/category_expansion.go
generated
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package restmapper
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/discovery"
|
||||
)
|
||||
|
||||
// CategoryExpander maps category strings to GroupResources.
|
||||
// Categories are classification or 'tag' of a group of resources.
|
||||
type CategoryExpander interface {
|
||||
Expand(category string) ([]schema.GroupResource, bool)
|
||||
}
|
||||
|
||||
// SimpleCategoryExpander implements CategoryExpander interface
|
||||
// using a static mapping of categories to GroupResource mapping.
|
||||
type SimpleCategoryExpander struct {
|
||||
Expansions map[string][]schema.GroupResource
|
||||
}
|
||||
|
||||
// Expand fulfills CategoryExpander
|
||||
func (e SimpleCategoryExpander) Expand(category string) ([]schema.GroupResource, bool) {
|
||||
ret, ok := e.Expansions[category]
|
||||
return ret, ok
|
||||
}
|
||||
|
||||
// discoveryCategoryExpander struct lets a REST Client wrapper (discoveryClient) to retrieve list of APIResourceList,
|
||||
// and then convert to fallbackExpander
|
||||
type discoveryCategoryExpander struct {
|
||||
discoveryClient discovery.DiscoveryInterface
|
||||
}
|
||||
|
||||
// NewDiscoveryCategoryExpander returns a category expander that makes use of the "categories" fields from
|
||||
// the API, found through the discovery client. In case of any error or no category found (which likely
|
||||
// means we're at a cluster prior to categories support, fallback to the expander provided.
|
||||
func NewDiscoveryCategoryExpander(client discovery.DiscoveryInterface) CategoryExpander {
|
||||
if client == nil {
|
||||
panic("Please provide discovery client to shortcut expander")
|
||||
}
|
||||
return discoveryCategoryExpander{discoveryClient: client}
|
||||
}
|
||||
|
||||
// Expand fulfills CategoryExpander
|
||||
func (e discoveryCategoryExpander) Expand(category string) ([]schema.GroupResource, bool) {
|
||||
// Get all supported resources for groups and versions from server, if no resource found, fallback anyway.
|
||||
_, apiResourceLists, _ := e.discoveryClient.ServerGroupsAndResources()
|
||||
if len(apiResourceLists) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
discoveredExpansions := map[string][]schema.GroupResource{}
|
||||
for _, apiResourceList := range apiResourceLists {
|
||||
gv, err := schema.ParseGroupVersion(apiResourceList.GroupVersion)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// Collect GroupVersions by categories
|
||||
for _, apiResource := range apiResourceList.APIResources {
|
||||
if categories := apiResource.Categories; len(categories) > 0 {
|
||||
for _, category := range categories {
|
||||
groupResource := schema.GroupResource{
|
||||
Group: gv.Group,
|
||||
Resource: apiResource.Name,
|
||||
}
|
||||
discoveredExpansions[category] = append(discoveredExpansions[category], groupResource)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret, ok := discoveredExpansions[category]
|
||||
return ret, ok
|
||||
}
|
||||
|
||||
// UnionCategoryExpander implements CategoryExpander interface.
|
||||
// It maps given category string to union of expansions returned by all the CategoryExpanders in the list.
|
||||
type UnionCategoryExpander []CategoryExpander
|
||||
|
||||
// Expand fulfills CategoryExpander
|
||||
func (u UnionCategoryExpander) Expand(category string) ([]schema.GroupResource, bool) {
|
||||
ret := []schema.GroupResource{}
|
||||
ok := false
|
||||
|
||||
// Expand the category for each CategoryExpander in the list and merge/combine the results.
|
||||
for _, expansion := range u {
|
||||
curr, currOk := expansion.Expand(category)
|
||||
|
||||
for _, currGR := range curr {
|
||||
found := false
|
||||
for _, existing := range ret {
|
||||
if existing == currGR {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
ret = append(ret, currGR)
|
||||
}
|
||||
}
|
||||
ok = ok || currOk
|
||||
}
|
||||
|
||||
return ret, ok
|
||||
}
|
338
e2e/vendor/k8s.io/client-go/restmapper/discovery.go
generated
vendored
Normal file
338
e2e/vendor/k8s.io/client-go/restmapper/discovery.go
generated
vendored
Normal file
@ -0,0 +1,338 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package restmapper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/discovery"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// APIGroupResources is an API group with a mapping of versions to
|
||||
// resources.
|
||||
type APIGroupResources struct {
|
||||
Group metav1.APIGroup
|
||||
// A mapping of version string to a slice of APIResources for
|
||||
// that version.
|
||||
VersionedResources map[string][]metav1.APIResource
|
||||
}
|
||||
|
||||
// NewDiscoveryRESTMapper returns a PriorityRESTMapper based on the discovered
|
||||
// groups and resources passed in.
|
||||
func NewDiscoveryRESTMapper(groupResources []*APIGroupResources) meta.RESTMapper {
|
||||
unionMapper := meta.MultiRESTMapper{}
|
||||
|
||||
var groupPriority []string
|
||||
// /v1 is special. It should always come first
|
||||
resourcePriority := []schema.GroupVersionResource{{Group: "", Version: "v1", Resource: meta.AnyResource}}
|
||||
kindPriority := []schema.GroupVersionKind{{Group: "", Version: "v1", Kind: meta.AnyKind}}
|
||||
|
||||
for _, group := range groupResources {
|
||||
groupPriority = append(groupPriority, group.Group.Name)
|
||||
|
||||
// Make sure the preferred version comes first
|
||||
if len(group.Group.PreferredVersion.Version) != 0 {
|
||||
preferred := group.Group.PreferredVersion.Version
|
||||
if _, ok := group.VersionedResources[preferred]; ok {
|
||||
resourcePriority = append(resourcePriority, schema.GroupVersionResource{
|
||||
Group: group.Group.Name,
|
||||
Version: group.Group.PreferredVersion.Version,
|
||||
Resource: meta.AnyResource,
|
||||
})
|
||||
|
||||
kindPriority = append(kindPriority, schema.GroupVersionKind{
|
||||
Group: group.Group.Name,
|
||||
Version: group.Group.PreferredVersion.Version,
|
||||
Kind: meta.AnyKind,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for _, discoveryVersion := range group.Group.Versions {
|
||||
resources, ok := group.VersionedResources[discoveryVersion.Version]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// Add non-preferred versions after the preferred version, in case there are resources that only exist in those versions
|
||||
if discoveryVersion.Version != group.Group.PreferredVersion.Version {
|
||||
resourcePriority = append(resourcePriority, schema.GroupVersionResource{
|
||||
Group: group.Group.Name,
|
||||
Version: discoveryVersion.Version,
|
||||
Resource: meta.AnyResource,
|
||||
})
|
||||
|
||||
kindPriority = append(kindPriority, schema.GroupVersionKind{
|
||||
Group: group.Group.Name,
|
||||
Version: discoveryVersion.Version,
|
||||
Kind: meta.AnyKind,
|
||||
})
|
||||
}
|
||||
|
||||
gv := schema.GroupVersion{Group: group.Group.Name, Version: discoveryVersion.Version}
|
||||
versionMapper := meta.NewDefaultRESTMapper([]schema.GroupVersion{gv})
|
||||
|
||||
for _, resource := range resources {
|
||||
scope := meta.RESTScopeNamespace
|
||||
if !resource.Namespaced {
|
||||
scope = meta.RESTScopeRoot
|
||||
}
|
||||
|
||||
// if we have a slash, then this is a subresource and we shouldn't create mappings for those.
|
||||
if strings.Contains(resource.Name, "/") {
|
||||
continue
|
||||
}
|
||||
|
||||
plural := gv.WithResource(resource.Name)
|
||||
singular := gv.WithResource(resource.SingularName)
|
||||
// this is for legacy resources and servers which don't list singular forms. For those we must still guess.
|
||||
if len(resource.SingularName) == 0 {
|
||||
_, singular = meta.UnsafeGuessKindToResource(gv.WithKind(resource.Kind))
|
||||
}
|
||||
|
||||
versionMapper.AddSpecific(gv.WithKind(strings.ToLower(resource.Kind)), plural, singular, scope)
|
||||
versionMapper.AddSpecific(gv.WithKind(resource.Kind), plural, singular, scope)
|
||||
// TODO this is producing unsafe guesses that don't actually work, but it matches previous behavior
|
||||
versionMapper.Add(gv.WithKind(resource.Kind+"List"), scope)
|
||||
}
|
||||
// TODO why is this type not in discovery (at least for "v1")
|
||||
versionMapper.Add(gv.WithKind("List"), meta.RESTScopeRoot)
|
||||
unionMapper = append(unionMapper, versionMapper)
|
||||
}
|
||||
}
|
||||
|
||||
for _, group := range groupPriority {
|
||||
resourcePriority = append(resourcePriority, schema.GroupVersionResource{
|
||||
Group: group,
|
||||
Version: meta.AnyVersion,
|
||||
Resource: meta.AnyResource,
|
||||
})
|
||||
kindPriority = append(kindPriority, schema.GroupVersionKind{
|
||||
Group: group,
|
||||
Version: meta.AnyVersion,
|
||||
Kind: meta.AnyKind,
|
||||
})
|
||||
}
|
||||
|
||||
return meta.PriorityRESTMapper{
|
||||
Delegate: unionMapper,
|
||||
ResourcePriority: resourcePriority,
|
||||
KindPriority: kindPriority,
|
||||
}
|
||||
}
|
||||
|
||||
// GetAPIGroupResources uses the provided discovery client to gather
|
||||
// discovery information and populate a slice of APIGroupResources.
|
||||
func GetAPIGroupResources(cl discovery.DiscoveryInterface) ([]*APIGroupResources, error) {
|
||||
gs, rs, err := cl.ServerGroupsAndResources()
|
||||
if rs == nil || gs == nil {
|
||||
return nil, err
|
||||
// TODO track the errors and update callers to handle partial errors.
|
||||
}
|
||||
rsm := map[string]*metav1.APIResourceList{}
|
||||
for _, r := range rs {
|
||||
rsm[r.GroupVersion] = r
|
||||
}
|
||||
|
||||
var result []*APIGroupResources
|
||||
for _, group := range gs {
|
||||
groupResources := &APIGroupResources{
|
||||
Group: *group,
|
||||
VersionedResources: make(map[string][]metav1.APIResource),
|
||||
}
|
||||
for _, version := range group.Versions {
|
||||
resources, ok := rsm[version.GroupVersion]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
groupResources.VersionedResources[version.Version] = resources.APIResources
|
||||
}
|
||||
result = append(result, groupResources)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DeferredDiscoveryRESTMapper is a RESTMapper that will defer
|
||||
// initialization of the RESTMapper until the first mapping is
|
||||
// requested.
|
||||
type DeferredDiscoveryRESTMapper struct {
|
||||
initMu sync.Mutex
|
||||
delegate meta.RESTMapper
|
||||
cl discovery.CachedDiscoveryInterface
|
||||
}
|
||||
|
||||
// NewDeferredDiscoveryRESTMapper returns a
|
||||
// DeferredDiscoveryRESTMapper that will lazily query the provided
|
||||
// client for discovery information to do REST mappings.
|
||||
func NewDeferredDiscoveryRESTMapper(cl discovery.CachedDiscoveryInterface) *DeferredDiscoveryRESTMapper {
|
||||
return &DeferredDiscoveryRESTMapper{
|
||||
cl: cl,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DeferredDiscoveryRESTMapper) getDelegate() (meta.RESTMapper, error) {
|
||||
d.initMu.Lock()
|
||||
defer d.initMu.Unlock()
|
||||
|
||||
if d.delegate != nil {
|
||||
return d.delegate, nil
|
||||
}
|
||||
|
||||
groupResources, err := GetAPIGroupResources(d.cl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.delegate = NewDiscoveryRESTMapper(groupResources)
|
||||
return d.delegate, nil
|
||||
}
|
||||
|
||||
// Reset resets the internally cached Discovery information and will
|
||||
// cause the next mapping request to re-discover.
|
||||
func (d *DeferredDiscoveryRESTMapper) Reset() {
|
||||
klog.V(5).Info("Invalidating discovery information")
|
||||
|
||||
d.initMu.Lock()
|
||||
defer d.initMu.Unlock()
|
||||
|
||||
d.cl.Invalidate()
|
||||
d.delegate = nil
|
||||
}
|
||||
|
||||
// KindFor takes a partial resource and returns back the single match.
|
||||
// It returns an error if there are multiple matches.
|
||||
func (d *DeferredDiscoveryRESTMapper) KindFor(resource schema.GroupVersionResource) (gvk schema.GroupVersionKind, err error) {
|
||||
del, err := d.getDelegate()
|
||||
if err != nil {
|
||||
return schema.GroupVersionKind{}, err
|
||||
}
|
||||
gvk, err = del.KindFor(resource)
|
||||
if err != nil && !d.cl.Fresh() {
|
||||
d.Reset()
|
||||
gvk, err = d.KindFor(resource)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// KindsFor takes a partial resource and returns back the list of
|
||||
// potential kinds in priority order.
|
||||
func (d *DeferredDiscoveryRESTMapper) KindsFor(resource schema.GroupVersionResource) (gvks []schema.GroupVersionKind, err error) {
|
||||
del, err := d.getDelegate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gvks, err = del.KindsFor(resource)
|
||||
if len(gvks) == 0 && !d.cl.Fresh() {
|
||||
d.Reset()
|
||||
gvks, err = d.KindsFor(resource)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ResourceFor takes a partial resource and returns back the single
|
||||
// match. It returns an error if there are multiple matches.
|
||||
func (d *DeferredDiscoveryRESTMapper) ResourceFor(input schema.GroupVersionResource) (gvr schema.GroupVersionResource, err error) {
|
||||
del, err := d.getDelegate()
|
||||
if err != nil {
|
||||
return schema.GroupVersionResource{}, err
|
||||
}
|
||||
gvr, err = del.ResourceFor(input)
|
||||
if err != nil && !d.cl.Fresh() {
|
||||
d.Reset()
|
||||
gvr, err = d.ResourceFor(input)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ResourcesFor takes a partial resource and returns back the list of
|
||||
// potential resource in priority order.
|
||||
func (d *DeferredDiscoveryRESTMapper) ResourcesFor(input schema.GroupVersionResource) (gvrs []schema.GroupVersionResource, err error) {
|
||||
del, err := d.getDelegate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gvrs, err = del.ResourcesFor(input)
|
||||
if len(gvrs) == 0 && !d.cl.Fresh() {
|
||||
d.Reset()
|
||||
gvrs, err = d.ResourcesFor(input)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// RESTMapping identifies a preferred resource mapping for the
|
||||
// provided group kind.
|
||||
func (d *DeferredDiscoveryRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (m *meta.RESTMapping, err error) {
|
||||
del, err := d.getDelegate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m, err = del.RESTMapping(gk, versions...)
|
||||
if err != nil && !d.cl.Fresh() {
|
||||
d.Reset()
|
||||
m, err = d.RESTMapping(gk, versions...)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// RESTMappings returns the RESTMappings for the provided group kind
|
||||
// in a rough internal preferred order. If no kind is found, it will
|
||||
// return a NoResourceMatchError.
|
||||
func (d *DeferredDiscoveryRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) (ms []*meta.RESTMapping, err error) {
|
||||
del, err := d.getDelegate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ms, err = del.RESTMappings(gk, versions...)
|
||||
if len(ms) == 0 && !d.cl.Fresh() {
|
||||
d.Reset()
|
||||
ms, err = d.RESTMappings(gk, versions...)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ResourceSingularizer converts a resource name from plural to
|
||||
// singular (e.g., from pods to pod).
|
||||
func (d *DeferredDiscoveryRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
|
||||
del, err := d.getDelegate()
|
||||
if err != nil {
|
||||
return resource, err
|
||||
}
|
||||
singular, err = del.ResourceSingularizer(resource)
|
||||
if err != nil && !d.cl.Fresh() {
|
||||
d.Reset()
|
||||
singular, err = d.ResourceSingularizer(resource)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *DeferredDiscoveryRESTMapper) String() string {
|
||||
del, err := d.getDelegate()
|
||||
if err != nil {
|
||||
return fmt.Sprintf("DeferredDiscoveryRESTMapper{%v}", err)
|
||||
}
|
||||
return fmt.Sprintf("DeferredDiscoveryRESTMapper{\n\t%v\n}", del)
|
||||
}
|
||||
|
||||
// Make sure it satisfies the interface
|
||||
var _ meta.ResettableRESTMapper = &DeferredDiscoveryRESTMapper{}
|
211
e2e/vendor/k8s.io/client-go/restmapper/shortcut.go
generated
vendored
Normal file
211
e2e/vendor/k8s.io/client-go/restmapper/shortcut.go
generated
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package restmapper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/discovery"
|
||||
)
|
||||
|
||||
// shortcutExpander is a RESTMapper that can be used for Kubernetes resources. It expands the resource first, then invokes the wrapped
|
||||
type shortcutExpander struct {
|
||||
RESTMapper meta.RESTMapper
|
||||
|
||||
discoveryClient discovery.DiscoveryInterface
|
||||
|
||||
warningHandler func(string)
|
||||
}
|
||||
|
||||
var _ meta.ResettableRESTMapper = shortcutExpander{}
|
||||
|
||||
// NewShortcutExpander wraps a restmapper in a layer that expands shortcuts found via discovery
|
||||
func NewShortcutExpander(delegate meta.RESTMapper, client discovery.DiscoveryInterface, warningHandler func(string)) meta.RESTMapper {
|
||||
return shortcutExpander{RESTMapper: delegate, discoveryClient: client, warningHandler: warningHandler}
|
||||
}
|
||||
|
||||
// KindFor fulfills meta.RESTMapper
|
||||
func (e shortcutExpander) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) {
|
||||
// expandResourceShortcut works with current API resources as read from discovery cache.
|
||||
// In case of new CRDs this means we potentially don't have current state of discovery.
|
||||
// In the current wiring in k8s.io/cli-runtime/pkg/genericclioptions/config_flags.go#toRESTMapper,
|
||||
// we are using DeferredDiscoveryRESTMapper which on KindFor failure will clear the
|
||||
// cache and fetch all data from a cluster (see k8s.io/client-go/restmapper/discovery.go#KindFor).
|
||||
// Thus another call to expandResourceShortcut, after a NoMatchError should successfully
|
||||
// read Kind to the user or an error.
|
||||
gvk, err := e.RESTMapper.KindFor(e.expandResourceShortcut(resource))
|
||||
if meta.IsNoMatchError(err) {
|
||||
return e.RESTMapper.KindFor(e.expandResourceShortcut(resource))
|
||||
}
|
||||
return gvk, err
|
||||
}
|
||||
|
||||
// KindsFor fulfills meta.RESTMapper
|
||||
func (e shortcutExpander) KindsFor(resource schema.GroupVersionResource) ([]schema.GroupVersionKind, error) {
|
||||
return e.RESTMapper.KindsFor(e.expandResourceShortcut(resource))
|
||||
}
|
||||
|
||||
// ResourcesFor fulfills meta.RESTMapper
|
||||
func (e shortcutExpander) ResourcesFor(resource schema.GroupVersionResource) ([]schema.GroupVersionResource, error) {
|
||||
return e.RESTMapper.ResourcesFor(e.expandResourceShortcut(resource))
|
||||
}
|
||||
|
||||
// ResourceFor fulfills meta.RESTMapper
|
||||
func (e shortcutExpander) ResourceFor(resource schema.GroupVersionResource) (schema.GroupVersionResource, error) {
|
||||
return e.RESTMapper.ResourceFor(e.expandResourceShortcut(resource))
|
||||
}
|
||||
|
||||
// ResourceSingularizer fulfills meta.RESTMapper
|
||||
func (e shortcutExpander) ResourceSingularizer(resource string) (string, error) {
|
||||
return e.RESTMapper.ResourceSingularizer(e.expandResourceShortcut(schema.GroupVersionResource{Resource: resource}).Resource)
|
||||
}
|
||||
|
||||
// RESTMapping fulfills meta.RESTMapper
|
||||
func (e shortcutExpander) RESTMapping(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) {
|
||||
return e.RESTMapper.RESTMapping(gk, versions...)
|
||||
}
|
||||
|
||||
// RESTMappings fulfills meta.RESTMapper
|
||||
func (e shortcutExpander) RESTMappings(gk schema.GroupKind, versions ...string) ([]*meta.RESTMapping, error) {
|
||||
return e.RESTMapper.RESTMappings(gk, versions...)
|
||||
}
|
||||
|
||||
// getShortcutMappings returns a set of tuples which holds short names for resources.
|
||||
// First the list of potential resources will be taken from the API server.
|
||||
// Next we will append the hardcoded list of resources - to be backward compatible with old servers.
|
||||
// NOTE that the list is ordered by group priority.
|
||||
func (e shortcutExpander) getShortcutMappings() ([]*metav1.APIResourceList, []resourceShortcuts, error) {
|
||||
res := []resourceShortcuts{}
|
||||
// get server resources
|
||||
// This can return an error *and* the results it was able to find. We don't need to fail on the error.
|
||||
_, apiResList, err := e.discoveryClient.ServerGroupsAndResources()
|
||||
if err != nil {
|
||||
klog.V(1).Infof("Error loading discovery information: %v", err)
|
||||
}
|
||||
for _, apiResources := range apiResList {
|
||||
gv, err := schema.ParseGroupVersion(apiResources.GroupVersion)
|
||||
if err != nil {
|
||||
klog.V(1).Infof("Unable to parse groupversion = %s due to = %s", apiResources.GroupVersion, err.Error())
|
||||
continue
|
||||
}
|
||||
for _, apiRes := range apiResources.APIResources {
|
||||
for _, shortName := range apiRes.ShortNames {
|
||||
rs := resourceShortcuts{
|
||||
ShortForm: schema.GroupResource{Group: gv.Group, Resource: shortName},
|
||||
LongForm: schema.GroupResource{Group: gv.Group, Resource: apiRes.Name},
|
||||
}
|
||||
res = append(res, rs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return apiResList, res, nil
|
||||
}
|
||||
|
||||
// expandResourceShortcut will return the expanded version of resource
|
||||
// (something that a pkg/api/meta.RESTMapper can understand), if it is
|
||||
// indeed a shortcut. If no match has been found, we will match on group prefixing.
|
||||
// Lastly we will return resource unmodified.
|
||||
func (e shortcutExpander) expandResourceShortcut(resource schema.GroupVersionResource) schema.GroupVersionResource {
|
||||
// get the shortcut mappings and return on first match.
|
||||
if allResources, shortcutResources, err := e.getShortcutMappings(); err == nil {
|
||||
// avoid expanding if there's an exact match to a full resource name
|
||||
for _, apiResources := range allResources {
|
||||
gv, err := schema.ParseGroupVersion(apiResources.GroupVersion)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if len(resource.Group) != 0 && resource.Group != gv.Group {
|
||||
continue
|
||||
}
|
||||
for _, apiRes := range apiResources.APIResources {
|
||||
if resource.Resource == apiRes.Name {
|
||||
return resource
|
||||
}
|
||||
if resource.Resource == apiRes.SingularName {
|
||||
return resource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
found := false
|
||||
var rsc schema.GroupVersionResource
|
||||
warnedAmbiguousShortcut := make(map[schema.GroupResource]bool)
|
||||
for _, item := range shortcutResources {
|
||||
if len(resource.Group) != 0 && resource.Group != item.ShortForm.Group {
|
||||
continue
|
||||
}
|
||||
if resource.Resource == item.ShortForm.Resource {
|
||||
if found {
|
||||
if item.LongForm.Group == rsc.Group && item.LongForm.Resource == rsc.Resource {
|
||||
// It is common and acceptable that group/resource has multiple
|
||||
// versions registered in cluster. This does not introduce ambiguity
|
||||
// in terms of shortname usage.
|
||||
continue
|
||||
}
|
||||
if !warnedAmbiguousShortcut[item.LongForm] {
|
||||
if e.warningHandler != nil {
|
||||
e.warningHandler(fmt.Sprintf("short name %q could also match lower priority resource %s", resource.Resource, item.LongForm.String()))
|
||||
}
|
||||
warnedAmbiguousShortcut[item.LongForm] = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
rsc.Resource = item.LongForm.Resource
|
||||
rsc.Group = item.LongForm.Group
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if found {
|
||||
return rsc
|
||||
}
|
||||
|
||||
// we didn't find exact match so match on group prefixing. This allows autoscal to match autoscaling
|
||||
if len(resource.Group) == 0 {
|
||||
return resource
|
||||
}
|
||||
for _, item := range shortcutResources {
|
||||
if !strings.HasPrefix(item.ShortForm.Group, resource.Group) {
|
||||
continue
|
||||
}
|
||||
if resource.Resource == item.ShortForm.Resource {
|
||||
resource.Resource = item.LongForm.Resource
|
||||
resource.Group = item.LongForm.Group
|
||||
return resource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resource
|
||||
}
|
||||
|
||||
func (e shortcutExpander) Reset() {
|
||||
meta.MaybeResetRESTMapper(e.RESTMapper)
|
||||
}
|
||||
|
||||
// ResourceShortcuts represents a structure that holds the information how to
|
||||
// transition from resource's shortcut to its full name.
|
||||
type resourceShortcuts struct {
|
||||
ShortForm schema.GroupResource
|
||||
LongForm schema.GroupResource
|
||||
}
|
Reference in New Issue
Block a user