2 Copyright 2014 The Kubernetes Authors.
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
8 http://www.apache.org/licenses/LICENSE-2.0
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.
23 "k8s.io/apimachinery/pkg/runtime/schema"
24 utilerrors "k8s.io/apimachinery/pkg/util/errors"
27 // MultiRESTMapper is a wrapper for multiple RESTMappers.
28 type MultiRESTMapper []RESTMapper
30 func (m MultiRESTMapper) String() string {
33 currString := fmt.Sprintf("%v", t)
34 splitStrings := strings.Split(currString, "\n")
35 nested = append(nested, strings.Join(splitStrings, "\n\t"))
38 return fmt.Sprintf("MultiRESTMapper{\n\t%s\n}", strings.Join(nested, "\n\t"))
41 // ResourceSingularizer converts a REST resource name from plural to singular (e.g., from pods to pod)
42 // This implementation supports multiple REST schemas and return the first match.
43 func (m MultiRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
45 singular, err = t.ResourceSingularizer(resource)
53 func (m MultiRESTMapper) ResourcesFor(resource schema.GroupVersionResource) ([]schema.GroupVersionResource, error) {
54 allGVRs := []schema.GroupVersionResource{}
56 gvrs, err := t.ResourcesFor(resource)
57 // ignore "no match" errors, but any other error percolates back up
58 if IsNoMatchError(err) {
65 // walk the existing values to de-dup
66 for _, curr := range gvrs {
68 for _, existing := range allGVRs {
76 allGVRs = append(allGVRs, curr)
81 if len(allGVRs) == 0 {
82 return nil, &NoResourceMatchError{PartialResource: resource}
88 func (m MultiRESTMapper) KindsFor(resource schema.GroupVersionResource) (gvk []schema.GroupVersionKind, err error) {
89 allGVKs := []schema.GroupVersionKind{}
91 gvks, err := t.KindsFor(resource)
92 // ignore "no match" errors, but any other error percolates back up
93 if IsNoMatchError(err) {
100 // walk the existing values to de-dup
101 for _, curr := range gvks {
103 for _, existing := range allGVKs {
104 if curr == existing {
111 allGVKs = append(allGVKs, curr)
116 if len(allGVKs) == 0 {
117 return nil, &NoResourceMatchError{PartialResource: resource}
123 func (m MultiRESTMapper) ResourceFor(resource schema.GroupVersionResource) (schema.GroupVersionResource, error) {
124 resources, err := m.ResourcesFor(resource)
126 return schema.GroupVersionResource{}, err
128 if len(resources) == 1 {
129 return resources[0], nil
132 return schema.GroupVersionResource{}, &AmbiguousResourceError{PartialResource: resource, MatchingResources: resources}
135 func (m MultiRESTMapper) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) {
136 kinds, err := m.KindsFor(resource)
138 return schema.GroupVersionKind{}, err
144 return schema.GroupVersionKind{}, &AmbiguousResourceError{PartialResource: resource, MatchingKinds: kinds}
147 // RESTMapping provides the REST mapping for the resource based on the
148 // kind and version. This implementation supports multiple REST schemas and
149 // return the first match.
150 func (m MultiRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (*RESTMapping, error) {
151 allMappings := []*RESTMapping{}
154 for _, t := range m {
155 currMapping, err := t.RESTMapping(gk, versions...)
156 // ignore "no match" errors, but any other error percolates back up
157 if IsNoMatchError(err) {
161 errors = append(errors, err)
165 allMappings = append(allMappings, currMapping)
168 // if we got exactly one mapping, then use it even if other requested failed
169 if len(allMappings) == 1 {
170 return allMappings[0], nil
172 if len(allMappings) > 1 {
173 var kinds []schema.GroupVersionKind
174 for _, m := range allMappings {
175 kinds = append(kinds, m.GroupVersionKind)
177 return nil, &AmbiguousKindError{PartialKind: gk.WithVersion(""), MatchingKinds: kinds}
180 return nil, utilerrors.NewAggregate(errors)
182 return nil, &NoKindMatchError{GroupKind: gk, SearchedVersions: versions}
185 // RESTMappings returns all possible RESTMappings for the provided group kind, or an error
186 // if the type is not recognized.
187 func (m MultiRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) ([]*RESTMapping, error) {
188 var allMappings []*RESTMapping
191 for _, t := range m {
192 currMappings, err := t.RESTMappings(gk, versions...)
193 // ignore "no match" errors, but any other error percolates back up
194 if IsNoMatchError(err) {
198 errors = append(errors, err)
201 allMappings = append(allMappings, currMappings...)
204 return nil, utilerrors.NewAggregate(errors)
206 if len(allMappings) == 0 {
207 return nil, &NoKindMatchError{GroupKind: gk, SearchedVersions: versions}
209 return allMappings, nil