mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	add a PriorityRESTMapper that can choose particular group/version of a resource
This commit is contained in:
		
							
								
								
									
										173
									
								
								pkg/api/meta/priority.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								pkg/api/meta/priority.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,173 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2016 The Kubernetes Authors All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/api/unversioned"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						AnyGroup    = "*"
 | 
				
			||||||
 | 
						AnyVersion  = "*"
 | 
				
			||||||
 | 
						AnyResource = "*"
 | 
				
			||||||
 | 
						AnyKind     = "*"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PriorityRESTMapper is a wrapper for automatically choosing a particular Resource or Kind
 | 
				
			||||||
 | 
					// when multiple matches are possible
 | 
				
			||||||
 | 
					type PriorityRESTMapper struct {
 | 
				
			||||||
 | 
						// Delegate is the RESTMapper to use to locate all the Kind and Resource matches
 | 
				
			||||||
 | 
						Delegate RESTMapper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ResourcePriority is a list of priority patterns to apply to matching resources.
 | 
				
			||||||
 | 
						// The list of all matching resources is narrowed based on the patterns until only one remains.
 | 
				
			||||||
 | 
						// A pattern with no matches is skipped.  A pattern with more than one match uses its
 | 
				
			||||||
 | 
						// matches as the list to continue matching against.
 | 
				
			||||||
 | 
						ResourcePriority []unversioned.GroupVersionResource
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// KindPriority is a list of priority patterns to apply to matching kinds.
 | 
				
			||||||
 | 
						// The list of all matching kinds is narrowed based on the patterns until only one remains.
 | 
				
			||||||
 | 
						// A pattern with no matches is skipped.  A pattern with more than one match uses its
 | 
				
			||||||
 | 
						// matches as the list to continue matching against.
 | 
				
			||||||
 | 
						KindPriority []unversioned.GroupVersionKind
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m PriorityRESTMapper) String() string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("PriorityRESTMapper{\n\t%v\n\t%v\n\t%v\n}", m.ResourcePriority, m.KindPriority, m.Delegate)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ResourceFor finds all resources, then passes them through the ResourcePriority patterns to find a single matching hit.
 | 
				
			||||||
 | 
					func (m PriorityRESTMapper) ResourceFor(partiallySpecifiedResource unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error) {
 | 
				
			||||||
 | 
						originalGVRs, err := m.Delegate.ResourcesFor(partiallySpecifiedResource)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return unversioned.GroupVersionResource{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(originalGVRs) == 1 {
 | 
				
			||||||
 | 
							return originalGVRs[0], nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						remainingGVRs := append([]unversioned.GroupVersionResource{}, originalGVRs...)
 | 
				
			||||||
 | 
						for _, pattern := range m.ResourcePriority {
 | 
				
			||||||
 | 
							matchedGVRs := []unversioned.GroupVersionResource{}
 | 
				
			||||||
 | 
							for _, gvr := range remainingGVRs {
 | 
				
			||||||
 | 
								if resourceMatches(pattern, gvr) {
 | 
				
			||||||
 | 
									matchedGVRs = append(matchedGVRs, gvr)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch len(matchedGVRs) {
 | 
				
			||||||
 | 
							case 0:
 | 
				
			||||||
 | 
								// if you have no matches, then nothing matched this pattern just move to the next
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
								// one match, return
 | 
				
			||||||
 | 
								return matchedGVRs[0], nil
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								// more than one match, use the matched hits as the list moving to the next pattern.
 | 
				
			||||||
 | 
								// this way you can have a series of selection criteria
 | 
				
			||||||
 | 
								remainingGVRs = matchedGVRs
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return unversioned.GroupVersionResource{}, &AmbiguousResourceError{PartialResource: partiallySpecifiedResource, MatchingResources: originalGVRs}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// KindFor finds all kinds, then passes them through the KindPriority patterns to find a single matching hit.
 | 
				
			||||||
 | 
					func (m PriorityRESTMapper) KindFor(partiallySpecifiedResource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error) {
 | 
				
			||||||
 | 
						originalGVKs, err := m.Delegate.KindsFor(partiallySpecifiedResource)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return unversioned.GroupVersionKind{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(originalGVKs) == 1 {
 | 
				
			||||||
 | 
							return originalGVKs[0], nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						remainingGVKs := append([]unversioned.GroupVersionKind{}, originalGVKs...)
 | 
				
			||||||
 | 
						for _, pattern := range m.KindPriority {
 | 
				
			||||||
 | 
							matchedGVKs := []unversioned.GroupVersionKind{}
 | 
				
			||||||
 | 
							for _, gvr := range remainingGVKs {
 | 
				
			||||||
 | 
								if kindMatches(pattern, gvr) {
 | 
				
			||||||
 | 
									matchedGVKs = append(matchedGVKs, gvr)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch len(matchedGVKs) {
 | 
				
			||||||
 | 
							case 0:
 | 
				
			||||||
 | 
								// if you have no matches, then nothing matched this pattern just move to the next
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
								// one match, return
 | 
				
			||||||
 | 
								return matchedGVKs[0], nil
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								// more than one match, use the matched hits as the list moving to the next pattern.
 | 
				
			||||||
 | 
								// this way you can have a series of selection criteria
 | 
				
			||||||
 | 
								remainingGVKs = matchedGVKs
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return unversioned.GroupVersionKind{}, &AmbiguousResourceError{PartialResource: partiallySpecifiedResource, MatchingKinds: originalGVKs}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func resourceMatches(pattern unversioned.GroupVersionResource, resource unversioned.GroupVersionResource) bool {
 | 
				
			||||||
 | 
						if pattern.Group != AnyGroup && pattern.Group != resource.Group {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if pattern.Version != AnyVersion && pattern.Version != resource.Version {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if pattern.Resource != AnyResource && pattern.Resource != resource.Resource {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func kindMatches(pattern unversioned.GroupVersionKind, kind unversioned.GroupVersionKind) bool {
 | 
				
			||||||
 | 
						if pattern.Group != AnyGroup && pattern.Group != kind.Group {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if pattern.Version != AnyVersion && pattern.Version != kind.Version {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if pattern.Kind != AnyKind && pattern.Kind != kind.Kind {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m PriorityRESTMapper) RESTMapping(gk unversioned.GroupKind, versions ...string) (mapping *RESTMapping, err error) {
 | 
				
			||||||
 | 
						return m.Delegate.RESTMapping(gk, versions...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m PriorityRESTMapper) AliasesForResource(alias string) (aliases []string, ok bool) {
 | 
				
			||||||
 | 
						return m.Delegate.AliasesForResource(alias)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m PriorityRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
 | 
				
			||||||
 | 
						return m.Delegate.ResourceSingularizer(resource)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m PriorityRESTMapper) ResourcesFor(partiallySpecifiedResource unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error) {
 | 
				
			||||||
 | 
						return m.Delegate.ResourcesFor(partiallySpecifiedResource)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m PriorityRESTMapper) KindsFor(partiallySpecifiedResource unversioned.GroupVersionResource) (gvk []unversioned.GroupVersionKind, err error) {
 | 
				
			||||||
 | 
						return m.Delegate.KindsFor(partiallySpecifiedResource)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										206
									
								
								pkg/api/meta/priority_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								pkg/api/meta/priority_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,206 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2016 The Kubernetes Authors All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 (
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/api/unversioned"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestPriorityRESTMapperResourceForErrorHandling(t *testing.T) {
 | 
				
			||||||
 | 
						tcs := []struct {
 | 
				
			||||||
 | 
							name string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							delegate         RESTMapper
 | 
				
			||||||
 | 
							resourcePatterns []unversioned.GroupVersionResource
 | 
				
			||||||
 | 
							result           unversioned.GroupVersionResource
 | 
				
			||||||
 | 
							err              string
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:     "single hit",
 | 
				
			||||||
 | 
								delegate: fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{{Resource: "single-hit"}}},
 | 
				
			||||||
 | 
								result:   unversioned.GroupVersionResource{Resource: "single-hit"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "ambiguous match",
 | 
				
			||||||
 | 
								delegate: fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{
 | 
				
			||||||
 | 
									{Group: "one", Version: "a", Resource: "first"},
 | 
				
			||||||
 | 
									{Group: "two", Version: "b", Resource: "second"},
 | 
				
			||||||
 | 
								}},
 | 
				
			||||||
 | 
								err: "matches multiple resources",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "group selection",
 | 
				
			||||||
 | 
								delegate: fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{
 | 
				
			||||||
 | 
									{Group: "one", Version: "a", Resource: "first"},
 | 
				
			||||||
 | 
									{Group: "two", Version: "b", Resource: "second"},
 | 
				
			||||||
 | 
								}},
 | 
				
			||||||
 | 
								resourcePatterns: []unversioned.GroupVersionResource{
 | 
				
			||||||
 | 
									{Group: "one", Version: AnyVersion, Resource: AnyResource},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								result: unversioned.GroupVersionResource{Group: "one", Version: "a", Resource: "first"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "empty match continues",
 | 
				
			||||||
 | 
								delegate: fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{
 | 
				
			||||||
 | 
									{Group: "one", Version: "a", Resource: "first"},
 | 
				
			||||||
 | 
									{Group: "two", Version: "b", Resource: "second"},
 | 
				
			||||||
 | 
								}},
 | 
				
			||||||
 | 
								resourcePatterns: []unversioned.GroupVersionResource{
 | 
				
			||||||
 | 
									{Group: "fail", Version: AnyVersion, Resource: AnyResource},
 | 
				
			||||||
 | 
									{Group: "one", Version: AnyVersion, Resource: AnyResource},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								result: unversioned.GroupVersionResource{Group: "one", Version: "a", Resource: "first"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "group followed by version selection",
 | 
				
			||||||
 | 
								delegate: fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{
 | 
				
			||||||
 | 
									{Group: "one", Version: "a", Resource: "first"},
 | 
				
			||||||
 | 
									{Group: "two", Version: "b", Resource: "second"},
 | 
				
			||||||
 | 
									{Group: "one", Version: "c", Resource: "third"},
 | 
				
			||||||
 | 
								}},
 | 
				
			||||||
 | 
								resourcePatterns: []unversioned.GroupVersionResource{
 | 
				
			||||||
 | 
									{Group: "one", Version: AnyVersion, Resource: AnyResource},
 | 
				
			||||||
 | 
									{Group: AnyGroup, Version: "a", Resource: AnyResource},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								result: unversioned.GroupVersionResource{Group: "one", Version: "a", Resource: "first"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "resource selection",
 | 
				
			||||||
 | 
								delegate: fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{
 | 
				
			||||||
 | 
									{Group: "one", Version: "a", Resource: "first"},
 | 
				
			||||||
 | 
									{Group: "one", Version: "a", Resource: "second"},
 | 
				
			||||||
 | 
								}},
 | 
				
			||||||
 | 
								resourcePatterns: []unversioned.GroupVersionResource{
 | 
				
			||||||
 | 
									{Group: AnyGroup, Version: AnyVersion, Resource: "second"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								result: unversioned.GroupVersionResource{Group: "one", Version: "a", Resource: "second"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range tcs {
 | 
				
			||||||
 | 
							mapper := PriorityRESTMapper{Delegate: tc.delegate, ResourcePriority: tc.resourcePatterns}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							actualResult, actualErr := mapper.ResourceFor(unversioned.GroupVersionResource{})
 | 
				
			||||||
 | 
							if e, a := tc.result, actualResult; e != a {
 | 
				
			||||||
 | 
								t.Errorf("%s: expected %v, got %v", tc.name, e, a)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if len(tc.err) == 0 && actualErr == nil {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if len(tc.err) > 0 && actualErr == nil {
 | 
				
			||||||
 | 
								t.Errorf("%s: missing expected err: %v", tc.name, tc.err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !strings.Contains(actualErr.Error(), tc.err) {
 | 
				
			||||||
 | 
								t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestPriorityRESTMapperKindForErrorHandling(t *testing.T) {
 | 
				
			||||||
 | 
						tcs := []struct {
 | 
				
			||||||
 | 
							name string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							delegate     RESTMapper
 | 
				
			||||||
 | 
							kindPatterns []unversioned.GroupVersionKind
 | 
				
			||||||
 | 
							result       unversioned.GroupVersionKind
 | 
				
			||||||
 | 
							err          string
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:     "single hit",
 | 
				
			||||||
 | 
								delegate: fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{{Kind: "single-hit"}}},
 | 
				
			||||||
 | 
								result:   unversioned.GroupVersionKind{Kind: "single-hit"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "ambiguous match",
 | 
				
			||||||
 | 
								delegate: fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{
 | 
				
			||||||
 | 
									{Group: "one", Version: "a", Kind: "first"},
 | 
				
			||||||
 | 
									{Group: "two", Version: "b", Kind: "second"},
 | 
				
			||||||
 | 
								}},
 | 
				
			||||||
 | 
								err: "matches multiple kinds",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "group selection",
 | 
				
			||||||
 | 
								delegate: fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{
 | 
				
			||||||
 | 
									{Group: "one", Version: "a", Kind: "first"},
 | 
				
			||||||
 | 
									{Group: "two", Version: "b", Kind: "second"},
 | 
				
			||||||
 | 
								}},
 | 
				
			||||||
 | 
								kindPatterns: []unversioned.GroupVersionKind{
 | 
				
			||||||
 | 
									{Group: "one", Version: AnyVersion, Kind: AnyKind},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								result: unversioned.GroupVersionKind{Group: "one", Version: "a", Kind: "first"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "empty match continues",
 | 
				
			||||||
 | 
								delegate: fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{
 | 
				
			||||||
 | 
									{Group: "one", Version: "a", Kind: "first"},
 | 
				
			||||||
 | 
									{Group: "two", Version: "b", Kind: "second"},
 | 
				
			||||||
 | 
								}},
 | 
				
			||||||
 | 
								kindPatterns: []unversioned.GroupVersionKind{
 | 
				
			||||||
 | 
									{Group: "fail", Version: AnyVersion, Kind: AnyKind},
 | 
				
			||||||
 | 
									{Group: "one", Version: AnyVersion, Kind: AnyKind},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								result: unversioned.GroupVersionKind{Group: "one", Version: "a", Kind: "first"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "group followed by version selection",
 | 
				
			||||||
 | 
								delegate: fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{
 | 
				
			||||||
 | 
									{Group: "one", Version: "a", Kind: "first"},
 | 
				
			||||||
 | 
									{Group: "two", Version: "b", Kind: "second"},
 | 
				
			||||||
 | 
									{Group: "one", Version: "c", Kind: "third"},
 | 
				
			||||||
 | 
								}},
 | 
				
			||||||
 | 
								kindPatterns: []unversioned.GroupVersionKind{
 | 
				
			||||||
 | 
									{Group: "one", Version: AnyVersion, Kind: AnyKind},
 | 
				
			||||||
 | 
									{Group: AnyGroup, Version: "a", Kind: AnyKind},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								result: unversioned.GroupVersionKind{Group: "one", Version: "a", Kind: "first"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "kind selection",
 | 
				
			||||||
 | 
								delegate: fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{
 | 
				
			||||||
 | 
									{Group: "one", Version: "a", Kind: "first"},
 | 
				
			||||||
 | 
									{Group: "one", Version: "a", Kind: "second"},
 | 
				
			||||||
 | 
								}},
 | 
				
			||||||
 | 
								kindPatterns: []unversioned.GroupVersionKind{
 | 
				
			||||||
 | 
									{Group: AnyGroup, Version: AnyVersion, Kind: "second"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								result: unversioned.GroupVersionKind{Group: "one", Version: "a", Kind: "second"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range tcs {
 | 
				
			||||||
 | 
							mapper := PriorityRESTMapper{Delegate: tc.delegate, KindPriority: tc.kindPatterns}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							actualResult, actualErr := mapper.KindFor(unversioned.GroupVersionResource{})
 | 
				
			||||||
 | 
							if e, a := tc.result, actualResult; e != a {
 | 
				
			||||||
 | 
								t.Errorf("%s: expected %v, got %v", tc.name, e, a)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if len(tc.err) == 0 && actualErr == nil {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if len(tc.err) > 0 && actualErr == nil {
 | 
				
			||||||
 | 
								t.Errorf("%s: missing expected err: %v", tc.name, tc.err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !strings.Contains(actualErr.Error(), tc.err) {
 | 
				
			||||||
 | 
								t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -180,7 +180,16 @@ func NewTestFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return &cmdutil.Factory{
 | 
						return &cmdutil.Factory{
 | 
				
			||||||
		Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
 | 
							Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
 | 
				
			||||||
			return t.Mapper, t.Typer
 | 
								priorityRESTMapper := meta.PriorityRESTMapper{
 | 
				
			||||||
 | 
									Delegate: t.Mapper,
 | 
				
			||||||
 | 
									ResourcePriority: []unversioned.GroupVersionResource{
 | 
				
			||||||
 | 
										{Group: meta.AnyGroup, Version: "v1", Resource: meta.AnyResource},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									KindPriority: []unversioned.GroupVersionKind{
 | 
				
			||||||
 | 
										{Group: meta.AnyGroup, Version: "v1", Kind: meta.AnyKind},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return priorityRESTMapper, t.Typer
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		ClientForMapping: func(*meta.RESTMapping) (resource.RESTClient, error) {
 | 
							ClientForMapping: func(*meta.RESTMapping) (resource.RESTClient, error) {
 | 
				
			||||||
			return t.Client, t.Err
 | 
								return t.Client, t.Err
 | 
				
			||||||
@@ -212,7 +221,16 @@ func NewTestFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
 | 
				
			|||||||
func NewMixedFactory(apiClient resource.RESTClient) (*cmdutil.Factory, *testFactory, runtime.Codec) {
 | 
					func NewMixedFactory(apiClient resource.RESTClient) (*cmdutil.Factory, *testFactory, runtime.Codec) {
 | 
				
			||||||
	f, t, c := NewTestFactory()
 | 
						f, t, c := NewTestFactory()
 | 
				
			||||||
	f.Object = func() (meta.RESTMapper, runtime.ObjectTyper) {
 | 
						f.Object = func() (meta.RESTMapper, runtime.ObjectTyper) {
 | 
				
			||||||
		return meta.MultiRESTMapper{t.Mapper, testapi.Default.RESTMapper()}, runtime.MultiObjectTyper{t.Typer, api.Scheme}
 | 
							priorityRESTMapper := meta.PriorityRESTMapper{
 | 
				
			||||||
 | 
								Delegate: meta.MultiRESTMapper{t.Mapper, testapi.Default.RESTMapper()},
 | 
				
			||||||
 | 
								ResourcePriority: []unversioned.GroupVersionResource{
 | 
				
			||||||
 | 
									{Group: meta.AnyGroup, Version: "v1", Resource: meta.AnyResource},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								KindPriority: []unversioned.GroupVersionKind{
 | 
				
			||||||
 | 
									{Group: meta.AnyGroup, Version: "v1", Kind: meta.AnyKind},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return priorityRESTMapper, runtime.MultiObjectTyper{t.Typer, api.Scheme}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	f.ClientForMapping = func(m *meta.RESTMapping) (resource.RESTClient, error) {
 | 
						f.ClientForMapping = func(m *meta.RESTMapping) (resource.RESTClient, error) {
 | 
				
			||||||
		if m.ObjectConvertor == api.Scheme {
 | 
							if m.ObjectConvertor == api.Scheme {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,6 +43,7 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/pkg/apis/autoscaling"
 | 
						"k8s.io/kubernetes/pkg/apis/autoscaling"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/apis/batch"
 | 
						"k8s.io/kubernetes/pkg/apis/batch"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/apis/extensions"
 | 
						"k8s.io/kubernetes/pkg/apis/extensions"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/apis/metrics"
 | 
				
			||||||
	clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
 | 
						clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
 | 
				
			||||||
	client "k8s.io/kubernetes/pkg/client/unversioned"
 | 
						client "k8s.io/kubernetes/pkg/client/unversioned"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
 | 
						"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
 | 
				
			||||||
@@ -202,7 +203,24 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
 | 
				
			|||||||
				cmdApiVersion = *cfg.GroupVersion
 | 
									cmdApiVersion = *cfg.GroupVersion
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return kubectl.OutputVersionMapper{RESTMapper: mapper, OutputVersions: []unversioned.GroupVersion{cmdApiVersion}}, api.Scheme
 | 
								outputRESTMapper := kubectl.OutputVersionMapper{RESTMapper: mapper, OutputVersions: []unversioned.GroupVersion{cmdApiVersion}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// eventually this should allow me choose a group priority based on the order of the discovery doc, for now hardcode a given order
 | 
				
			||||||
 | 
								priorityRESTMapper := meta.PriorityRESTMapper{
 | 
				
			||||||
 | 
									Delegate: outputRESTMapper,
 | 
				
			||||||
 | 
									ResourcePriority: []unversioned.GroupVersionResource{
 | 
				
			||||||
 | 
										{Group: api.GroupName, Version: meta.AnyVersion, Resource: meta.AnyResource},
 | 
				
			||||||
 | 
										{Group: extensions.GroupName, Version: meta.AnyVersion, Resource: meta.AnyResource},
 | 
				
			||||||
 | 
										{Group: metrics.GroupName, Version: meta.AnyVersion, Resource: meta.AnyResource},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									KindPriority: []unversioned.GroupVersionKind{
 | 
				
			||||||
 | 
										{Group: api.GroupName, Version: meta.AnyVersion, Kind: meta.AnyKind},
 | 
				
			||||||
 | 
										{Group: extensions.GroupName, Version: meta.AnyVersion, Kind: meta.AnyKind},
 | 
				
			||||||
 | 
										{Group: metrics.GroupName, Version: meta.AnyVersion, Kind: meta.AnyKind},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return priorityRESTMapper, api.Scheme
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		Client: func() (*client.Client, error) {
 | 
							Client: func() (*client.Client, error) {
 | 
				
			||||||
			return clients.ClientForVersion(nil)
 | 
								return clients.ClientForVersion(nil)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user