github.com/aclisp/heapster@v0.19.2-0.20160613100040-51756f899a96/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/multirestmapper.go (about)

     1  /*
     2  Copyright 2014 The Kubernetes Authors All rights reserved.
     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  	"k8s.io/kubernetes/pkg/api/unversioned"
    24  	utilerrors "k8s.io/kubernetes/pkg/util/errors"
    25  	"k8s.io/kubernetes/pkg/util/sets"
    26  )
    27  
    28  // MultiRESTMapper is a wrapper for multiple RESTMappers.
    29  type MultiRESTMapper []RESTMapper
    30  
    31  func (m MultiRESTMapper) String() string {
    32  	nested := []string{}
    33  	for _, t := range m {
    34  		currString := fmt.Sprintf("%v", t)
    35  		splitStrings := strings.Split(currString, "\n")
    36  		nested = append(nested, strings.Join(splitStrings, "\n\t"))
    37  	}
    38  
    39  	return fmt.Sprintf("MultiRESTMapper{\n\t%s\n}", strings.Join(nested, "\n\t"))
    40  }
    41  
    42  // ResourceSingularizer converts a REST resource name from plural to singular (e.g., from pods to pod)
    43  // This implementation supports multiple REST schemas and return the first match.
    44  func (m MultiRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
    45  	for _, t := range m {
    46  		singular, err = t.ResourceSingularizer(resource)
    47  		if err == nil {
    48  			return
    49  		}
    50  	}
    51  	return
    52  }
    53  
    54  func (m MultiRESTMapper) ResourcesFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error) {
    55  	allGVRs := []unversioned.GroupVersionResource{}
    56  	for _, t := range m {
    57  		gvrs, err := t.ResourcesFor(resource)
    58  		// ignore "no match" errors, but any other error percolates back up
    59  		if IsNoResourceMatchError(err) {
    60  			continue
    61  		}
    62  		if err != nil {
    63  			return nil, err
    64  		}
    65  
    66  		// walk the existing values to de-dup
    67  		for _, curr := range gvrs {
    68  			found := false
    69  			for _, existing := range allGVRs {
    70  				if curr == existing {
    71  					found = true
    72  					break
    73  				}
    74  			}
    75  
    76  			if !found {
    77  				allGVRs = append(allGVRs, curr)
    78  			}
    79  		}
    80  	}
    81  
    82  	if len(allGVRs) == 0 {
    83  		return nil, &NoResourceMatchError{PartialResource: resource}
    84  	}
    85  
    86  	return allGVRs, nil
    87  }
    88  
    89  func (m MultiRESTMapper) KindsFor(resource unversioned.GroupVersionResource) (gvk []unversioned.GroupVersionKind, err error) {
    90  	allGVKs := []unversioned.GroupVersionKind{}
    91  	for _, t := range m {
    92  		gvks, err := t.KindsFor(resource)
    93  		// ignore "no match" errors, but any other error percolates back up
    94  		if IsNoResourceMatchError(err) {
    95  			continue
    96  		}
    97  		if err != nil {
    98  			return nil, err
    99  		}
   100  
   101  		// walk the existing values to de-dup
   102  		for _, curr := range gvks {
   103  			found := false
   104  			for _, existing := range allGVKs {
   105  				if curr == existing {
   106  					found = true
   107  					break
   108  				}
   109  			}
   110  
   111  			if !found {
   112  				allGVKs = append(allGVKs, curr)
   113  			}
   114  		}
   115  	}
   116  
   117  	if len(allGVKs) == 0 {
   118  		return nil, &NoResourceMatchError{PartialResource: resource}
   119  	}
   120  
   121  	return allGVKs, nil
   122  }
   123  
   124  func (m MultiRESTMapper) ResourceFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error) {
   125  	resources, err := m.ResourcesFor(resource)
   126  	if err != nil {
   127  		return unversioned.GroupVersionResource{}, err
   128  	}
   129  	if len(resources) == 1 {
   130  		return resources[0], nil
   131  	}
   132  
   133  	return unversioned.GroupVersionResource{}, &AmbiguousResourceError{PartialResource: resource, MatchingResources: resources}
   134  }
   135  
   136  func (m MultiRESTMapper) KindFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error) {
   137  	kinds, err := m.KindsFor(resource)
   138  	if err != nil {
   139  		return unversioned.GroupVersionKind{}, err
   140  	}
   141  	if len(kinds) == 1 {
   142  		return kinds[0], nil
   143  	}
   144  
   145  	return unversioned.GroupVersionKind{}, &AmbiguousResourceError{PartialResource: resource, MatchingKinds: kinds}
   146  }
   147  
   148  // RESTMapping provides the REST mapping for the resource based on the
   149  // kind and version. This implementation supports multiple REST schemas and
   150  // return the first match.
   151  func (m MultiRESTMapper) RESTMapping(gk unversioned.GroupKind, versions ...string) (*RESTMapping, error) {
   152  	allMappings := []*RESTMapping{}
   153  	errors := []error{}
   154  
   155  	for _, t := range m {
   156  		currMapping, err := t.RESTMapping(gk, versions...)
   157  		// ignore "no match" errors, but any other error percolates back up
   158  		if IsNoResourceMatchError(err) {
   159  			continue
   160  		}
   161  		if err != nil {
   162  			errors = append(errors, err)
   163  			continue
   164  		}
   165  
   166  		allMappings = append(allMappings, currMapping)
   167  	}
   168  
   169  	// if we got exactly one mapping, then use it even if other requested failed
   170  	if len(allMappings) == 1 {
   171  		return allMappings[0], nil
   172  	}
   173  	if len(allMappings) > 1 {
   174  		return nil, fmt.Errorf("multiple matches found for %v in %v", gk, versions)
   175  	}
   176  	if len(errors) > 0 {
   177  		return nil, utilerrors.NewAggregate(errors)
   178  	}
   179  	return nil, fmt.Errorf("no match found for %v in %v", gk, versions)
   180  }
   181  
   182  // AliasesForResource finds the first alias response for the provided mappers.
   183  func (m MultiRESTMapper) AliasesForResource(alias string) ([]string, bool) {
   184  	seenAliases := sets.NewString()
   185  	allAliases := []string{}
   186  	handled := false
   187  
   188  	for _, t := range m {
   189  		if currAliases, currOk := t.AliasesForResource(alias); currOk {
   190  			for _, currAlias := range currAliases {
   191  				if !seenAliases.Has(currAlias) {
   192  					allAliases = append(allAliases, currAlias)
   193  					seenAliases.Insert(currAlias)
   194  				}
   195  			}
   196  			handled = true
   197  		}
   198  	}
   199  	return allAliases, handled
   200  }