Merge pull request #22840 from liggitt/preferred-gvk

Prefer fetched version when determining HPA group version kind
This commit is contained in:
Brian Grant 2016-03-11 00:41:39 -08:00
commit e5748a44d6
7 changed files with 65 additions and 7 deletions

View File

@ -729,6 +729,13 @@ __EOF__
kubectl autoscale -f hack/testdata/frontend-controller.yaml --save-config "${kube_flags[@]}" --max=2 kubectl autoscale -f hack/testdata/frontend-controller.yaml --save-config "${kube_flags[@]}" --max=2
# Post-Condition: hpa "frontend" has configuration annotation # Post-Condition: hpa "frontend" has configuration annotation
[[ "$(kubectl get hpa.extensions frontend -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]] [[ "$(kubectl get hpa.extensions frontend -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
# Ensure we can interact with HPA objects in lists through both the extensions/v1beta1 and autoscaling/v1 APIs
output_message=$(kubectl get hpa -o=jsonpath='{.items[0].apiVersion}' 2>&1 "${kube_flags[@]}")
kube::test::if_has_string "${output_message}" 'extensions/v1beta1'
output_message=$(kubectl get hpa.extensions -o=jsonpath='{.items[0].apiVersion}' 2>&1 "${kube_flags[@]}")
kube::test::if_has_string "${output_message}" 'extensions/v1beta1'
output_message=$(kubectl get hpa.autoscaling -o=jsonpath='{.items[0].apiVersion}' 2>&1 "${kube_flags[@]}")
kube::test::if_has_string "${output_message}" 'autoscaling/v1'
# Clean up # Clean up
# Note that we should delete hpa first, otherwise it may fight with the rc reaper. # Note that we should delete hpa first, otherwise it may fight with the rc reaper.
kubectl delete hpa frontend "${kube_flags[@]}" kubectl delete hpa frontend "${kube_flags[@]}"

View File

@ -136,7 +136,7 @@ func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), ClientMapper: resource.ClientMapperFunc(f.ClientForMapping),
Decoder: f.Decoder(true), Decoder: f.Decoder(true),
} }
hpa, err := resourceMapper.InfoForObject(object) hpa, err := resourceMapper.InfoForObject(object, nil)
if err != nil { if err != nil {
return err return err
} }

View File

@ -236,7 +236,7 @@ func RunCreateSubcommand(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer,
RESTMapper: mapper, RESTMapper: mapper,
ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), ClientMapper: resource.ClientMapperFunc(f.ClientForMapping),
} }
info, err := resourceMapper.InfoForObject(obj) info, err := resourceMapper.InfoForObject(obj, nil)
if err != nil { if err != nil {
return err return err
} }

View File

@ -212,7 +212,7 @@ func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), ClientMapper: resource.ClientMapperFunc(f.ClientForMapping),
Decoder: f.Decoder(true), Decoder: f.Decoder(true),
} }
info, err = resourceMapper.InfoForObject(object) info, err = resourceMapper.InfoForObject(object, nil)
if err != nil { if err != nil {
return err return err
} }

View File

@ -441,7 +441,7 @@ func createGeneratedObject(f *cmdutil.Factory, cmd *cobra.Command, generator kub
ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), ClientMapper: resource.ClientMapperFunc(f.ClientForMapping),
Decoder: f.Decoder(true), Decoder: f.Decoder(true),
} }
info, err := resourceMapper.InfoForObject(obj) info, err := resourceMapper.InfoForObject(obj, nil)
if err != nil { if err != nil {
return nil, "", nil, nil, err return nil, "", nil, nil, err
} }

View File

@ -21,6 +21,7 @@ import (
"reflect" "reflect"
"k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
) )
@ -85,11 +86,17 @@ func (m *Mapper) InfoForData(data []byte, source string) (*Info, error) {
// InfoForObject creates an Info object for the given Object. An error is returned // InfoForObject creates an Info object for the given Object. An error is returned
// if the object cannot be introspected. Name and namespace will be set into Info // if the object cannot be introspected. Name and namespace will be set into Info
// if the mapping's MetadataAccessor can retrieve them. // if the mapping's MetadataAccessor can retrieve them.
func (m *Mapper) InfoForObject(obj runtime.Object) (*Info, error) { func (m *Mapper) InfoForObject(obj runtime.Object, preferredGVKs []unversioned.GroupVersionKind) (*Info, error) {
groupVersionKind, err := m.ObjectKind(obj) groupVersionKinds, err := m.ObjectKinds(obj)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to get type info from the object %q: %v", reflect.TypeOf(obj), err) return nil, fmt.Errorf("unable to get type info from the object %q: %v", reflect.TypeOf(obj), err)
} }
groupVersionKind := groupVersionKinds[0]
if len(groupVersionKinds) > 1 && len(preferredGVKs) > 0 {
groupVersionKind = preferredObjectKind(groupVersionKinds, preferredGVKs)
}
mapping, err := m.RESTMapping(groupVersionKind.GroupKind(), groupVersionKind.Version) mapping, err := m.RESTMapping(groupVersionKind.GroupKind(), groupVersionKind.Version)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to recognize %v: %v", groupVersionKind, err) return nil, fmt.Errorf("unable to recognize %v: %v", groupVersionKind, err)
@ -111,3 +118,39 @@ func (m *Mapper) InfoForObject(obj runtime.Object) (*Info, error) {
ResourceVersion: resourceVersion, ResourceVersion: resourceVersion,
}, nil }, nil
} }
// preferredObjectKind picks the possibility that most closely matches the priority list in this order:
// GroupVersionKind matches (exact match)
// GroupKind matches
// Group matches
func preferredObjectKind(possibilities []unversioned.GroupVersionKind, preferences []unversioned.GroupVersionKind) unversioned.GroupVersionKind {
// Exact match
for _, priority := range preferences {
for _, possibility := range possibilities {
if possibility == priority {
return possibility
}
}
}
// GroupKind match
for _, priority := range preferences {
for _, possibility := range possibilities {
if possibility.GroupKind() == priority.GroupKind() {
return possibility
}
}
}
// Group match
for _, priority := range preferences {
for _, possibility := range possibilities {
if possibility.Group == priority.Group {
return possibility
}
}
}
// Just pick the first
return possibilities[0]
}

View File

@ -26,6 +26,7 @@ import (
"path/filepath" "path/filepath"
"k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
utilerrors "k8s.io/kubernetes/pkg/util/errors" utilerrors "k8s.io/kubernetes/pkg/util/errors"
@ -337,8 +338,15 @@ func (v FlattenListVisitor) Visit(fn VisitorFunc) error {
}{v.Mapper, v.Mapper.Decoder}); len(errs) > 0 { }{v.Mapper, v.Mapper.Decoder}); len(errs) > 0 {
return utilerrors.NewAggregate(errs) return utilerrors.NewAggregate(errs)
} }
// If we have a GroupVersionKind on the list, prioritize that when asking for info on the objects contained in the list
var preferredGVKs []unversioned.GroupVersionKind
if info.Mapping != nil && !info.Mapping.GroupVersionKind.IsEmpty() {
preferredGVKs = append(preferredGVKs, info.Mapping.GroupVersionKind)
}
for i := range items { for i := range items {
item, err := v.InfoForObject(items[i]) item, err := v.InfoForObject(items[i], preferredGVKs)
if err != nil { if err != nil {
return err return err
} }