github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/api/meta/multirestmapper.go (about)

     1  /*
     2  Copyright 2014 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package meta
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  
    23  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/runtime/schema"
    24  	utilerrors "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/util/errors"
    25  )
    26  
    27  var (
    28  	_ ResettableRESTMapper = MultiRESTMapper{}
    29  )
    30  
    31  // MultiRESTMapper is a wrapper for multiple RESTMappers.
    32  type MultiRESTMapper []RESTMapper
    33  
    34  func (m MultiRESTMapper) String() string {
    35  	nested := make([]string, 0, len(m))
    36  	for _, t := range m {
    37  		currString := fmt.Sprintf("%v", t)
    38  		splitStrings := strings.Split(currString, "\n")
    39  		nested = append(nested, strings.Join(splitStrings, "\n\t"))
    40  	}
    41  
    42  	return fmt.Sprintf("MultiRESTMapper{\n\t%s\n}", strings.Join(nested, "\n\t"))
    43  }
    44  
    45  // ResourceSingularizer converts a REST resource name from plural to singular (e.g., from pods to pod)
    46  // This implementation supports multiple REST schemas and return the first match.
    47  func (m MultiRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
    48  	for _, t := range m {
    49  		singular, err = t.ResourceSingularizer(resource)
    50  		if err == nil {
    51  			return
    52  		}
    53  	}
    54  	return
    55  }
    56  
    57  func (m MultiRESTMapper) ResourcesFor(resource schema.GroupVersionResource) ([]schema.GroupVersionResource, error) {
    58  	allGVRs := []schema.GroupVersionResource{}
    59  	for _, t := range m {
    60  		gvrs, err := t.ResourcesFor(resource)
    61  		// ignore "no match" errors, but any other error percolates back up
    62  		if IsNoMatchError(err) {
    63  			continue
    64  		}
    65  		if err != nil {
    66  			return nil, err
    67  		}
    68  
    69  		// walk the existing values to de-dup
    70  		for _, curr := range gvrs {
    71  			found := false
    72  			for _, existing := range allGVRs {
    73  				if curr == existing {
    74  					found = true
    75  					break
    76  				}
    77  			}
    78  
    79  			if !found {
    80  				allGVRs = append(allGVRs, curr)
    81  			}
    82  		}
    83  	}
    84  
    85  	if len(allGVRs) == 0 {
    86  		return nil, &NoResourceMatchError{PartialResource: resource}
    87  	}
    88  
    89  	return allGVRs, nil
    90  }
    91  
    92  func (m MultiRESTMapper) KindsFor(resource schema.GroupVersionResource) (gvk []schema.GroupVersionKind, err error) {
    93  	allGVKs := []schema.GroupVersionKind{}
    94  	for _, t := range m {
    95  		gvks, err := t.KindsFor(resource)
    96  		// ignore "no match" errors, but any other error percolates back up
    97  		if IsNoMatchError(err) {
    98  			continue
    99  		}
   100  		if err != nil {
   101  			return nil, err
   102  		}
   103  
   104  		// walk the existing values to de-dup
   105  		for _, curr := range gvks {
   106  			found := false
   107  			for _, existing := range allGVKs {
   108  				if curr == existing {
   109  					found = true
   110  					break
   111  				}
   112  			}
   113  
   114  			if !found {
   115  				allGVKs = append(allGVKs, curr)
   116  			}
   117  		}
   118  	}
   119  
   120  	if len(allGVKs) == 0 {
   121  		return nil, &NoResourceMatchError{PartialResource: resource}
   122  	}
   123  
   124  	return allGVKs, nil
   125  }
   126  
   127  func (m MultiRESTMapper) ResourceFor(resource schema.GroupVersionResource) (schema.GroupVersionResource, error) {
   128  	resources, err := m.ResourcesFor(resource)
   129  	if err != nil {
   130  		return schema.GroupVersionResource{}, err
   131  	}
   132  	if len(resources) == 1 {
   133  		return resources[0], nil
   134  	}
   135  
   136  	return schema.GroupVersionResource{}, &AmbiguousResourceError{PartialResource: resource, MatchingResources: resources}
   137  }
   138  
   139  func (m MultiRESTMapper) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) {
   140  	kinds, err := m.KindsFor(resource)
   141  	if err != nil {
   142  		return schema.GroupVersionKind{}, err
   143  	}
   144  	if len(kinds) == 1 {
   145  		return kinds[0], nil
   146  	}
   147  
   148  	return schema.GroupVersionKind{}, &AmbiguousResourceError{PartialResource: resource, MatchingKinds: kinds}
   149  }
   150  
   151  // RESTMapping provides the REST mapping for the resource based on the
   152  // kind and version. This implementation supports multiple REST schemas and
   153  // return the first match.
   154  func (m MultiRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (*RESTMapping, error) {
   155  	allMappings := []*RESTMapping{}
   156  	errors := []error{}
   157  
   158  	for _, t := range m {
   159  		currMapping, err := t.RESTMapping(gk, versions...)
   160  		// ignore "no match" errors, but any other error percolates back up
   161  		if IsNoMatchError(err) {
   162  			continue
   163  		}
   164  		if err != nil {
   165  			errors = append(errors, err)
   166  			continue
   167  		}
   168  
   169  		allMappings = append(allMappings, currMapping)
   170  	}
   171  
   172  	// if we got exactly one mapping, then use it even if other requested failed
   173  	if len(allMappings) == 1 {
   174  		return allMappings[0], nil
   175  	}
   176  	if len(allMappings) > 1 {
   177  		var kinds []schema.GroupVersionKind
   178  		for _, m := range allMappings {
   179  			kinds = append(kinds, m.GroupVersionKind)
   180  		}
   181  		return nil, &AmbiguousKindError{PartialKind: gk.WithVersion(""), MatchingKinds: kinds}
   182  	}
   183  	if len(errors) > 0 {
   184  		return nil, utilerrors.NewAggregate(errors)
   185  	}
   186  	return nil, &NoKindMatchError{GroupKind: gk, SearchedVersions: versions}
   187  }
   188  
   189  // RESTMappings returns all possible RESTMappings for the provided group kind, or an error
   190  // if the type is not recognized.
   191  func (m MultiRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) ([]*RESTMapping, error) {
   192  	var allMappings []*RESTMapping
   193  	var errors []error
   194  
   195  	for _, t := range m {
   196  		currMappings, err := t.RESTMappings(gk, versions...)
   197  		// ignore "no match" errors, but any other error percolates back up
   198  		if IsNoMatchError(err) {
   199  			continue
   200  		}
   201  		if err != nil {
   202  			errors = append(errors, err)
   203  			continue
   204  		}
   205  		allMappings = append(allMappings, currMappings...)
   206  	}
   207  	if len(errors) > 0 {
   208  		return nil, utilerrors.NewAggregate(errors)
   209  	}
   210  	if len(allMappings) == 0 {
   211  		return nil, &NoKindMatchError{GroupKind: gk, SearchedVersions: versions}
   212  	}
   213  	return allMappings, nil
   214  }
   215  
   216  func (m MultiRESTMapper) Reset() {
   217  	for _, t := range m {
   218  		MaybeResetRESTMapper(t)
   219  	}
   220  }