move category expansion out of restmapper

This commit is contained in:
deads2k
2017-03-24 08:02:10 -04:00
parent f4986235c7
commit 8895f314b4
51 changed files with 298 additions and 245 deletions

View File

@@ -189,6 +189,8 @@ type ObjectMappingFactory interface {
// Returns interfaces for dealing with arbitrary
// runtime.Unstructured. This performs API calls to discover types.
UnstructuredObject() (meta.RESTMapper, runtime.ObjectTyper, error)
// Returns interface for expanding categories like `all`.
CategoryExpander() resource.CategoryExpander
// Returns a RESTClient for working with the specified RESTMapping or an error. This is intended
// for working with arbitrary resources and is not guaranteed to point to a Kubernetes APIServer.
ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error)

View File

@@ -126,6 +126,7 @@ func (f *ring2Factory) PrintObject(cmd *cobra.Command, mapper meta.RESTMapper, o
func (f *ring2Factory) NewBuilder() *resource.Builder {
mapper, typer := f.objectMappingFactory.Object()
categoryExpander := f.objectMappingFactory.CategoryExpander()
return resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.objectMappingFactory.ClientForMapping), f.clientAccessFactory.Decoder(true))
return resource.NewBuilder(mapper, categoryExpander, typer, resource.ClientMapperFunc(f.objectMappingFactory.ClientForMapping), f.clientAccessFactory.Decoder(true))
}

View File

@@ -105,6 +105,20 @@ func (f *ring1Factory) UnstructuredObject() (meta.RESTMapper, runtime.ObjectType
return expander, typer, err
}
func (f *ring1Factory) CategoryExpander() resource.CategoryExpander {
var categoryExpander resource.CategoryExpander
categoryExpander = resource.LegacyCategoryExpander
discoveryClient, err := f.clientAccessFactory.DiscoveryClient()
if err == nil {
// wrap with discovery based filtering
categoryExpander, err = resource.NewDiscoveryFilteredExpander(categoryExpander, discoveryClient)
// you only have an error on missing discoveryClient, so this shouldn't fail. Check anyway.
CheckErr(err)
}
return categoryExpander
}
func (f *ring1Factory) ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) {
cfg, err := f.clientAccessFactory.ClientConfig()
if err != nil {

View File

@@ -740,12 +740,12 @@ func TestDiscoveryReplaceAliases(t *testing.T) {
{
name: "all-replacement",
arg: "all",
expected: "pods,replicationcontrollers,services,statefulsets,horizontalpodautoscalers,jobs,deployments,replicasets",
expected: "pods,replicationcontrollers,services,statefulsets.apps,horizontalpodautoscalers.autoscaling,jobs.batch,deployments.extensions,replicasets.extensions",
},
{
name: "alias-in-comma-separated-arg",
arg: "all,secrets",
expected: "pods,replicationcontrollers,services,statefulsets,horizontalpodautoscalers,jobs,deployments,replicasets,secrets",
expected: "pods,replicationcontrollers,services,statefulsets.apps,horizontalpodautoscalers.autoscaling,jobs.batch,deployments.extensions,replicasets.extensions,secrets",
},
}
@@ -754,7 +754,7 @@ func TestDiscoveryReplaceAliases(t *testing.T) {
if err != nil {
t.Fatalf("Unable to create shortcut expander, err = %s", err.Error())
}
b := resource.NewBuilder(mapper, api.Scheme, fakeClient(), testapi.Default.Codec())
b := resource.NewBuilder(mapper, resource.LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec())
for _, test := range tests {
replaced := b.ReplaceAliases(test.arg)

View File

@@ -21,6 +21,7 @@ import (
"strings"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/discovery"
@@ -31,8 +32,6 @@ import (
type shortcutExpander struct {
RESTMapper meta.RESTMapper
All []schema.GroupResource
discoveryClient discovery.DiscoveryInterface
}
@@ -42,33 +41,7 @@ func NewShortcutExpander(delegate meta.RESTMapper, client discovery.DiscoveryInt
if client == nil {
return shortcutExpander{}, errors.New("Please provide discovery client to shortcut expander")
}
return shortcutExpander{All: UserResources, RESTMapper: delegate, discoveryClient: client}, nil
}
func (e shortcutExpander) getAll() []schema.GroupResource {
// Check if we have access to server resources
apiResources, err := e.discoveryClient.ServerResources()
if err != nil {
return e.All
}
availableResources, err := discovery.GroupVersionResources(apiResources)
if err != nil {
return e.All
}
availableAll := []schema.GroupResource{}
for _, requestedResource := range e.All {
for availableResource := range availableResources {
if requestedResource.Group == availableResource.Group &&
requestedResource.Resource == availableResource.Resource {
availableAll = append(availableAll, requestedResource)
break
}
}
}
return availableAll
return shortcutExpander{RESTMapper: delegate, discoveryClient: client}, nil
}
func (e shortcutExpander) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) {
@@ -99,38 +72,6 @@ func (e shortcutExpander) RESTMappings(gk schema.GroupKind, versions ...string)
return e.RESTMapper.RESTMappings(gk, versions...)
}
// UserResources are the resource names that apply to the primary, user facing resources used by
// client tools. They are in deletion-first order - dependent resources should be last.
// Should remain exported in order to expose a current list of resources to downstream
// composition that wants to build on the concept of 'all' for their CLIs.
var UserResources = []schema.GroupResource{
{Group: "", Resource: "pods"},
{Group: "", Resource: "replicationcontrollers"},
{Group: "", Resource: "services"},
{Group: "apps", Resource: "statefulsets"},
{Group: "autoscaling", Resource: "horizontalpodautoscalers"},
{Group: "batch", Resource: "jobs"},
{Group: "extensions", Resource: "deployments"},
{Group: "extensions", Resource: "replicasets"},
}
// AliasesForResource returns whether a resource has an alias or not
func (e shortcutExpander) AliasesForResource(resource string) ([]string, bool) {
if strings.ToLower(resource) == "all" {
var resources []schema.GroupResource
if resources = e.getAll(); len(resources) == 0 {
resources = UserResources
}
aliases := []string{}
for _, r := range resources {
aliases = append(aliases, r.Resource)
}
return aliases, true
}
expanded := e.expandResourceShortcut(schema.GroupVersionResource{Resource: resource}).Resource
return []string{expanded}, (expanded != resource)
}
// getShortcutMappings returns a set of tuples which holds short names for resources.
// First the list of potential resources will be taken from the API server.
// Next we will append the hardcoded list of resources - to be backward compatible with old servers.

View File

@@ -17,7 +17,6 @@ limitations under the License.
package util
import (
"strings"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -29,43 +28,25 @@ func TestReplaceAliases(t *testing.T) {
tests := []struct {
name string
arg string
expected string
expected schema.GroupVersionResource
srvRes []*metav1.APIResourceList
}{
{
name: "no-replacement",
arg: "service",
expected: "service",
srvRes: []*metav1.APIResourceList{},
},
{
name: "all-replacement",
arg: "all",
expected: "pods,replicationcontrollers,services,statefulsets,horizontalpodautoscalers,jobs,deployments,replicasets",
srvRes: []*metav1.APIResourceList{},
},
{
name: "alias-in-comma-separated-arg",
arg: "all,secrets",
expected: "pods,replicationcontrollers,services,statefulsets,horizontalpodautoscalers,jobs,deployments,replicasets,secrets",
srvRes: []*metav1.APIResourceList{},
},
{
name: "rc-resolves-to-replicationcontrollers",
arg: "rc",
expected: "replicationcontrollers",
expected: schema.GroupVersionResource{Resource: "replicationcontrollers"},
srvRes: []*metav1.APIResourceList{},
},
{
name: "storageclasses-no-replacement",
arg: "storageclasses",
expected: "storageclasses",
expected: schema.GroupVersionResource{Resource: "storageclasses"},
srvRes: []*metav1.APIResourceList{},
},
{
name: "hpa-priority",
arg: "hpa",
expected: "superhorizontalpodautoscalers",
expected: schema.GroupVersionResource{Resource: "superhorizontalpodautoscalers"},
srvRes: []*metav1.APIResourceList{
{
GroupVersion: "autoscaling/v1",
@@ -96,16 +77,12 @@ func TestReplaceAliases(t *testing.T) {
}
for _, test := range tests {
resources := []string{}
ds.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) {
return test.srvRes, nil
}
for _, arg := range strings.Split(test.arg, ",") {
curr, _ := mapper.AliasesForResource(arg)
resources = append(resources, curr...)
}
if strings.Join(resources, ",") != test.expected {
t.Errorf("%s: unexpected argument: expected %s, got %s", test.name, test.expected, resources)
actual := mapper.expandResourceShortcut(schema.GroupVersionResource{Resource: test.arg})
if actual != test.expected {
t.Errorf("%s: unexpected argument: expected %s, got %s", test.name, test.expected, actual)
}
}
}