You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
210 lines
5.6 KiB
210 lines
5.6 KiB
/* |
|
Copyright 2014 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 meta |
|
|
|
import ( |
|
"fmt" |
|
"strings" |
|
|
|
"k8s.io/apimachinery/pkg/runtime/schema" |
|
utilerrors "k8s.io/apimachinery/pkg/util/errors" |
|
) |
|
|
|
// MultiRESTMapper is a wrapper for multiple RESTMappers. |
|
type MultiRESTMapper []RESTMapper |
|
|
|
func (m MultiRESTMapper) String() string { |
|
nested := []string{} |
|
for _, t := range m { |
|
currString := fmt.Sprintf("%v", t) |
|
splitStrings := strings.Split(currString, "\n") |
|
nested = append(nested, strings.Join(splitStrings, "\n\t")) |
|
} |
|
|
|
return fmt.Sprintf("MultiRESTMapper{\n\t%s\n}", strings.Join(nested, "\n\t")) |
|
} |
|
|
|
// ResourceSingularizer converts a REST resource name from plural to singular (e.g., from pods to pod) |
|
// This implementation supports multiple REST schemas and return the first match. |
|
func (m MultiRESTMapper) ResourceSingularizer(resource string) (singular string, err error) { |
|
for _, t := range m { |
|
singular, err = t.ResourceSingularizer(resource) |
|
if err == nil { |
|
return |
|
} |
|
} |
|
return |
|
} |
|
|
|
func (m MultiRESTMapper) ResourcesFor(resource schema.GroupVersionResource) ([]schema.GroupVersionResource, error) { |
|
allGVRs := []schema.GroupVersionResource{} |
|
for _, t := range m { |
|
gvrs, err := t.ResourcesFor(resource) |
|
// ignore "no match" errors, but any other error percolates back up |
|
if IsNoMatchError(err) { |
|
continue |
|
} |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
// walk the existing values to de-dup |
|
for _, curr := range gvrs { |
|
found := false |
|
for _, existing := range allGVRs { |
|
if curr == existing { |
|
found = true |
|
break |
|
} |
|
} |
|
|
|
if !found { |
|
allGVRs = append(allGVRs, curr) |
|
} |
|
} |
|
} |
|
|
|
if len(allGVRs) == 0 { |
|
return nil, &NoResourceMatchError{PartialResource: resource} |
|
} |
|
|
|
return allGVRs, nil |
|
} |
|
|
|
func (m MultiRESTMapper) KindsFor(resource schema.GroupVersionResource) (gvk []schema.GroupVersionKind, err error) { |
|
allGVKs := []schema.GroupVersionKind{} |
|
for _, t := range m { |
|
gvks, err := t.KindsFor(resource) |
|
// ignore "no match" errors, but any other error percolates back up |
|
if IsNoMatchError(err) { |
|
continue |
|
} |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
// walk the existing values to de-dup |
|
for _, curr := range gvks { |
|
found := false |
|
for _, existing := range allGVKs { |
|
if curr == existing { |
|
found = true |
|
break |
|
} |
|
} |
|
|
|
if !found { |
|
allGVKs = append(allGVKs, curr) |
|
} |
|
} |
|
} |
|
|
|
if len(allGVKs) == 0 { |
|
return nil, &NoResourceMatchError{PartialResource: resource} |
|
} |
|
|
|
return allGVKs, nil |
|
} |
|
|
|
func (m MultiRESTMapper) ResourceFor(resource schema.GroupVersionResource) (schema.GroupVersionResource, error) { |
|
resources, err := m.ResourcesFor(resource) |
|
if err != nil { |
|
return schema.GroupVersionResource{}, err |
|
} |
|
if len(resources) == 1 { |
|
return resources[0], nil |
|
} |
|
|
|
return schema.GroupVersionResource{}, &AmbiguousResourceError{PartialResource: resource, MatchingResources: resources} |
|
} |
|
|
|
func (m MultiRESTMapper) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { |
|
kinds, err := m.KindsFor(resource) |
|
if err != nil { |
|
return schema.GroupVersionKind{}, err |
|
} |
|
if len(kinds) == 1 { |
|
return kinds[0], nil |
|
} |
|
|
|
return schema.GroupVersionKind{}, &AmbiguousResourceError{PartialResource: resource, MatchingKinds: kinds} |
|
} |
|
|
|
// RESTMapping provides the REST mapping for the resource based on the |
|
// kind and version. This implementation supports multiple REST schemas and |
|
// return the first match. |
|
func (m MultiRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (*RESTMapping, error) { |
|
allMappings := []*RESTMapping{} |
|
errors := []error{} |
|
|
|
for _, t := range m { |
|
currMapping, err := t.RESTMapping(gk, versions...) |
|
// ignore "no match" errors, but any other error percolates back up |
|
if IsNoMatchError(err) { |
|
continue |
|
} |
|
if err != nil { |
|
errors = append(errors, err) |
|
continue |
|
} |
|
|
|
allMappings = append(allMappings, currMapping) |
|
} |
|
|
|
// if we got exactly one mapping, then use it even if other requested failed |
|
if len(allMappings) == 1 { |
|
return allMappings[0], nil |
|
} |
|
if len(allMappings) > 1 { |
|
var kinds []schema.GroupVersionKind |
|
for _, m := range allMappings { |
|
kinds = append(kinds, m.GroupVersionKind) |
|
} |
|
return nil, &AmbiguousKindError{PartialKind: gk.WithVersion(""), MatchingKinds: kinds} |
|
} |
|
if len(errors) > 0 { |
|
return nil, utilerrors.NewAggregate(errors) |
|
} |
|
return nil, &NoKindMatchError{GroupKind: gk, SearchedVersions: versions} |
|
} |
|
|
|
// RESTMappings returns all possible RESTMappings for the provided group kind, or an error |
|
// if the type is not recognized. |
|
func (m MultiRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) ([]*RESTMapping, error) { |
|
var allMappings []*RESTMapping |
|
var errors []error |
|
|
|
for _, t := range m { |
|
currMappings, err := t.RESTMappings(gk, versions...) |
|
// ignore "no match" errors, but any other error percolates back up |
|
if IsNoMatchError(err) { |
|
continue |
|
} |
|
if err != nil { |
|
errors = append(errors, err) |
|
continue |
|
} |
|
allMappings = append(allMappings, currMappings...) |
|
} |
|
if len(errors) > 0 { |
|
return nil, utilerrors.NewAggregate(errors) |
|
} |
|
if len(allMappings) == 0 { |
|
return nil, &NoKindMatchError{GroupKind: gk, SearchedVersions: versions} |
|
} |
|
return allMappings, nil |
|
}
|
|
|