diff --git a/pkg/client/unversioned/client.go b/pkg/client/unversioned/client.go index 778ac013c78..53bf188ede8 100644 --- a/pkg/client/unversioned/client.go +++ b/pkg/client/unversioned/client.go @@ -46,6 +46,7 @@ type Interface interface { PersistentVolumesInterface PersistentVolumeClaimsNamespacer ComponentStatusesInterface + Experimental() ExperimentalInterface } func (c *Client) ReplicationControllers(namespace string) ReplicationControllerInterface { @@ -122,6 +123,7 @@ type APIStatus interface { // Client is the implementation of a Kubernetes client. type Client struct { *RESTClient + *ExperimentalClient } // ServerVersion retrieves and parses the server's version. @@ -192,3 +194,7 @@ func IsTimeout(err error) bool { } return false } + +func (c *Client) Experimental() ExperimentalInterface { + return c.ExperimentalClient +} diff --git a/pkg/client/unversioned/client_test.go b/pkg/client/unversioned/client_test.go index d4100cc9296..5671518704f 100644 --- a/pkg/client/unversioned/client_test.go +++ b/pkg/client/unversioned/client_test.go @@ -54,7 +54,6 @@ type Response struct { type testClient struct { *Client - *ExperimentalClient Request testRequest Response Response Error bool @@ -87,16 +86,6 @@ func (c *testClient) Setup() *testClient { Version: version, }) } - if c.ExperimentalClient == nil { - version := c.Version - if len(version) == 0 { - version = testapi.Version() - } - c.ExperimentalClient = NewExperimentalOrDie(&Config{ - Host: c.server.URL, - Version: version, - }) - } c.QueryValidator = map[string]func(string, string) bool{} return c } diff --git a/pkg/client/unversioned/daemon_test.go b/pkg/client/unversioned/daemon_test.go index 1a30c1b3725..42ee7a75ce1 100644 --- a/pkg/client/unversioned/daemon_test.go +++ b/pkg/client/unversioned/daemon_test.go @@ -55,7 +55,7 @@ func TestListDaemons(t *testing.T) { }, }, } - receivedControllerList, err := c.Setup().Daemons(ns).List(labels.Everything()) + receivedControllerList, err := c.Setup().Experimental().Daemons(ns).List(labels.Everything()) c.Validate(t, receivedControllerList, err) } @@ -80,14 +80,14 @@ func TestGetDaemon(t *testing.T) { }, }, } - receivedController, err := c.Setup().Daemons(ns).Get("foo") + receivedController, err := c.Setup().Experimental().Daemons(ns).Get("foo") c.Validate(t, receivedController, err) } func TestGetDaemonWithNoName(t *testing.T) { ns := api.NamespaceDefault c := &testClient{Error: true} - receivedPod, err := c.Setup().Daemons(ns).Get("") + receivedPod, err := c.Setup().Experimental().Daemons(ns).Get("") if (err != nil) && (err.Error() != nameRequiredError) { t.Errorf("Expected error: %v, but got %v", nameRequiredError, err) } @@ -118,7 +118,7 @@ func TestUpdateDaemon(t *testing.T) { }, }, } - receivedController, err := c.Setup().Daemons(ns).Update(requestController) + receivedController, err := c.Setup().Experimental().Daemons(ns).Update(requestController) c.Validate(t, receivedController, err) } @@ -128,7 +128,7 @@ func TestDeleteDaemon(t *testing.T) { Request: testRequest{Method: "DELETE", Path: testapi.ResourcePath(getDCResourceName(), ns, "foo"), Query: buildQueryValues(nil)}, Response: Response{StatusCode: 200}, } - err := c.Setup().Daemons(ns).Delete("foo") + err := c.Setup().Experimental().Daemons(ns).Delete("foo") c.Validate(t, nil, err) } @@ -155,6 +155,6 @@ func TestCreateDaemon(t *testing.T) { }, }, } - receivedController, err := c.Setup().Daemons(ns).Create(requestController) + receivedController, err := c.Setup().Experimental().Daemons(ns).Create(requestController) c.Validate(t, receivedController, err) } diff --git a/pkg/client/unversioned/experimental.go b/pkg/client/unversioned/experimental.go index d2fff69f985..bd30ace7d8b 100644 --- a/pkg/client/unversioned/experimental.go +++ b/pkg/client/unversioned/experimental.go @@ -119,9 +119,7 @@ func NewExperimentalOrDie(c *Config) *ExperimentalClient { } func setExperimentalDefaults(config *Config) error { - if config.Prefix == "" { - config.Prefix = "/experimental" - } + config.Prefix = "/experimental" if config.UserAgent == "" { config.UserAgent = DefaultKubernetesUserAgent() } diff --git a/pkg/client/unversioned/helper.go b/pkg/client/unversioned/helper.go index ac09a0924c9..cae4fafc38e 100644 --- a/pkg/client/unversioned/helper.go +++ b/pkg/client/unversioned/helper.go @@ -139,7 +139,12 @@ func New(c *Config) (*Client, error) { if err != nil { return nil, err } - return &Client{client}, nil + experimentalConfig := *c + experimentalClient, err := NewExperimental(&experimentalConfig) + if err != nil { + return nil, err + } + return &Client{RESTClient: client, ExperimentalClient: experimentalClient}, nil } // MatchesServerVersion queries the server to compares the build version diff --git a/pkg/client/unversioned/horizontalpodautoscaler_test.go b/pkg/client/unversioned/horizontalpodautoscaler_test.go index 23ff02d8eed..d1fdd5aa16b 100644 --- a/pkg/client/unversioned/horizontalpodautoscaler_test.go +++ b/pkg/client/unversioned/horizontalpodautoscaler_test.go @@ -49,7 +49,7 @@ func TestHorizontalPodAutoscalerCreate(t *testing.T) { Response: Response{StatusCode: 200, Body: &horizontalPodAutoscaler}, } - response, err := c.Setup().HorizontalPodAutoscalers(ns).Create(&horizontalPodAutoscaler) + response, err := c.Setup().Experimental().HorizontalPodAutoscalers(ns).Create(&horizontalPodAutoscaler) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -74,7 +74,7 @@ func TestHorizontalPodAutoscalerGet(t *testing.T) { Response: Response{StatusCode: 200, Body: horizontalPodAutoscaler}, } - response, err := c.Setup().HorizontalPodAutoscalers(ns).Get("abc") + response, err := c.Setup().Experimental().HorizontalPodAutoscalers(ns).Get("abc") c.Validate(t, response, err) } @@ -99,7 +99,7 @@ func TestHorizontalPodAutoscalerList(t *testing.T) { }, Response: Response{StatusCode: 200, Body: horizontalPodAutoscalerList}, } - response, err := c.Setup().HorizontalPodAutoscalers(ns).List(labels.Everything(), fields.Everything()) + response, err := c.Setup().Experimental().HorizontalPodAutoscalers(ns).List(labels.Everything(), fields.Everything()) c.Validate(t, response, err) } @@ -116,7 +116,7 @@ func TestHorizontalPodAutoscalerUpdate(t *testing.T) { Request: testRequest{Method: "PUT", Path: testapi.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc"), Query: buildQueryValues(nil)}, Response: Response{StatusCode: 200, Body: horizontalPodAutoscaler}, } - response, err := c.Setup().HorizontalPodAutoscalers(ns).Update(horizontalPodAutoscaler) + response, err := c.Setup().Experimental().HorizontalPodAutoscalers(ns).Update(horizontalPodAutoscaler) c.Validate(t, response, err) } @@ -126,7 +126,7 @@ func TestHorizontalPodAutoscalerDelete(t *testing.T) { Request: testRequest{Method: "DELETE", Path: testapi.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "foo"), Query: buildQueryValues(nil)}, Response: Response{StatusCode: 200}, } - err := c.Setup().HorizontalPodAutoscalers(ns).Delete("foo", nil) + err := c.Setup().Experimental().HorizontalPodAutoscalers(ns).Delete("foo", nil) c.Validate(t, nil, err) } @@ -138,6 +138,6 @@ func TestHorizontalPodAutoscalerWatch(t *testing.T) { Query: url.Values{"resourceVersion": []string{}}}, Response: Response{StatusCode: 200}, } - _, err := c.Setup().HorizontalPodAutoscalers(api.NamespaceAll).Watch(labels.Everything(), fields.Everything(), "") + _, err := c.Setup().Experimental().HorizontalPodAutoscalers(api.NamespaceAll).Watch(labels.Everything(), fields.Everything(), "") c.Validate(t, nil, err) } diff --git a/pkg/client/unversioned/testclient/fake_daemons.go b/pkg/client/unversioned/testclient/fake_daemons.go index 382d62f3922..8b0b3bc8014 100644 --- a/pkg/client/unversioned/testclient/fake_daemons.go +++ b/pkg/client/unversioned/testclient/fake_daemons.go @@ -27,7 +27,7 @@ import ( // FakeDaemons implements DaemonInterface. Meant to be embedded into a struct to get a default // implementation. This makes faking out just the method you want to test easier. type FakeDaemons struct { - Fake *Fake + Fake *FakeExperimental Namespace string } diff --git a/pkg/client/unversioned/testclient/testclient.go b/pkg/client/unversioned/testclient/testclient.go index 5814fb5cb1e..2773890482b 100644 --- a/pkg/client/unversioned/testclient/testclient.go +++ b/pkg/client/unversioned/testclient/testclient.go @@ -171,10 +171,6 @@ func (c *Fake) ReplicationControllers(namespace string) client.ReplicationContro return &FakeReplicationControllers{Fake: c, Namespace: namespace} } -func (c *Fake) Daemons(namespace string) client.DaemonInterface { - return &FakeDaemons{Fake: c, Namespace: namespace} -} - func (c *Fake) Nodes() client.NodeInterface { return &FakeNodes{Fake: c} } @@ -219,6 +215,10 @@ func (c *Fake) Namespaces() client.NamespaceInterface { return &FakeNamespaces{Fake: c} } +func (c *Fake) Experimental() client.ExperimentalInterface { + return &FakeExperimental{c} +} + func (c *Fake) ServerVersion() (*version.Info, error) { action := ActionImpl{} action.Verb = "get" @@ -241,3 +241,23 @@ func (c *Fake) ServerAPIVersions() (*api.APIVersions, error) { func (c *Fake) ComponentStatuses() client.ComponentStatusInterface { return &FakeComponentStatuses{Fake: c} } + +type FakeExperimental struct { + *Fake +} + +func (c *FakeExperimental) Daemons(namespace string) client.DaemonInterface { + return &FakeDaemons{Fake: c, Namespace: namespace} +} + +func (c *FakeExperimental) HorizontalPodAutoscalers(namespace string) client.HorizontalPodAutoscalerInterface { + panic("unimplemented") +} + +func (c *FakeExperimental) Scales(namespace string) client.ScaleInterface { + panic("unimplemented") +} + +func (c *FakeExperimental) Deployments(namespace string) client.DeploymentInterface { + panic("unimplemented") +} diff --git a/pkg/kubectl/cmd/apiversions.go b/pkg/kubectl/cmd/apiversions.go index 032c3b597bb..9694f0e4d7b 100644 --- a/pkg/kubectl/cmd/apiversions.go +++ b/pkg/kubectl/cmd/apiversions.go @@ -58,12 +58,8 @@ func RunApiVersions(f *cmdutil.Factory, w io.Writer) error { } var expAPIVersions *api.APIVersions - showExpVersions := false - expClient, err := f.ExperimentalClient() - if err == nil { - expAPIVersions, err = expClient.ServerAPIVersions() - showExpVersions = err == nil - } + expAPIVersions, err = client.Experimental().ServerAPIVersions() + showExpVersions := (err == nil) fmt.Fprintf(w, "Available Server Api Versions: %#v\n", *apiVersions) if showExpVersions { diff --git a/pkg/kubectl/cmd/util/clientcache.go b/pkg/kubectl/cmd/util/clientcache.go index 49253b7e3da..c43fcca264e 100644 --- a/pkg/kubectl/cmd/util/clientcache.go +++ b/pkg/kubectl/cmd/util/clientcache.go @@ -89,28 +89,3 @@ func (c *ClientCache) ClientForVersion(version string) (*client.Client, error) { c.clients[config.Version] = client return client, nil } - -type ExperimentalClientCache struct { - loader clientcmd.ClientConfig - client *client.ExperimentalClient - err error - init bool -} - -func NewExperimentalClientCache(loader clientcmd.ClientConfig) *ExperimentalClientCache { - return &ExperimentalClientCache{loader: loader} -} - -func (cc *ExperimentalClientCache) Client() (*client.ExperimentalClient, error) { - if cc.init { - return cc.client, cc.err - } - cfg, err := cc.loader.ClientConfig() - if err != nil { - cc.err = err - } else { - cc.client, cc.err = client.NewExperimental(cfg) - } - cc.init = true - return cc.client, cc.err -} diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index 4b4c6dea9bc..3c16f49f4a5 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -17,7 +17,6 @@ limitations under the License. package util import ( - "errors" "flag" "fmt" "io" @@ -57,8 +56,6 @@ type Factory struct { Object func() (meta.RESTMapper, runtime.ObjectTyper) // Returns a client for accessing Kubernetes resources or an error. Client func() (*client.Client, error) - // Returns a client for accessing experimental Kubernetes resources or an error. - ExperimentalClient func() (*client.ExperimentalClient, error) // Returns a client.Config for accessing the Kubernetes server. ClientConfig func() (*client.Config, error) // Returns a RESTClient for working with the specified RESTMapping or an error. This is intended @@ -110,28 +107,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { } clients := NewClientCache(clientConfig) - expClients := NewExperimentalClientCache(clientConfig) - noClientErr := errors.New("could not get client") - getBothClients := func(group string, version string) (*client.Client, *client.ExperimentalClient, error) { - switch group { - case "api": - client, err := clients.ClientForVersion(version) - return client, nil, err - - case "experimental": - client, err := clients.ClientForVersion(version) - if err != nil { - return nil, nil, err - } - expClient, err := expClients.Client() - if err != nil { - return nil, nil, err - } - return client, expClient, err - } - return nil, nil, noClientErr - } return &Factory{ clients: clients, flags: flags, @@ -147,30 +123,20 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { Client: func() (*client.Client, error) { return clients.ClientForVersion("") }, - ExperimentalClient: func() (*client.ExperimentalClient, error) { - return expClients.Client() - }, ClientConfig: func() (*client.Config, error) { return clients.ClientConfigForVersion("") }, RESTClient: func(mapping *meta.RESTMapping) (resource.RESTClient, error) { group, err := api.RESTMapper.GroupForResource(mapping.Resource) + client, err := clients.ClientForVersion(mapping.APIVersion) if err != nil { return nil, err } switch group { case "api": - client, err := clients.ClientForVersion(mapping.APIVersion) - if err != nil { - return nil, err - } return client.RESTClient, nil case "experimental": - client, err := expClients.Client() - if err != nil { - return nil, err - } - return client.RESTClient, nil + return client.ExperimentalClient.RESTClient, nil } return nil, fmt.Errorf("unable to get RESTClient for resource '%s'", mapping.Resource) }, @@ -179,11 +145,11 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { if err != nil { return nil, err } - client, expClient, err := getBothClients(group, mapping.APIVersion) + client, err := clients.ClientForVersion(mapping.APIVersion) if err != nil { return nil, err } - if describer, ok := kubectl.DescriberFor(mapping.Kind, client, expClient); ok { + if describer, ok := kubectl.DescriberFor(group, mapping.Kind, client); ok { return describer, nil } return nil, fmt.Errorf("no description has been implemented for %q", mapping.Kind) @@ -235,26 +201,18 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { return meta.NewAccessor().Labels(object) }, Scaler: func(mapping *meta.RESTMapping) (kubectl.Scaler, error) { - group, err := api.RESTMapper.GroupForResource(mapping.Resource) - if err != nil { - return nil, err - } - client, _, err := getBothClients(group, mapping.APIVersion) + client, err := clients.ClientForVersion(mapping.APIVersion) if err != nil { return nil, err } return kubectl.ScalerFor(mapping.Kind, kubectl.NewScalerClient(client)) }, Reaper: func(mapping *meta.RESTMapping) (kubectl.Reaper, error) { - group, err := api.RESTMapper.GroupForResource(mapping.Resource) + client, err := clients.ClientForVersion(mapping.APIVersion) if err != nil { return nil, err } - client, expClient, err := getBothClients(group, mapping.APIVersion) - if err != nil { - return nil, err - } - return kubectl.ReaperFor(mapping.Kind, client, expClient) + return kubectl.ReaperFor(mapping.Kind, client) }, Validator: func(validate bool) (validation.Schema, error) { if validate { @@ -262,8 +220,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { if err != nil { return nil, err } - expClient, _ := expClients.Client() - return &clientSwaggerSchema{client, expClient, api.Scheme}, nil + return &clientSwaggerSchema{client, client.ExperimentalClient, api.Scheme}, nil } return validation.NullSchema{}, nil }, diff --git a/pkg/kubectl/describe.go b/pkg/kubectl/describe.go index b1a5ccf9680..d47c2f4fb4b 100644 --- a/pkg/kubectl/describe.go +++ b/pkg/kubectl/describe.go @@ -82,12 +82,9 @@ func describerMap(c *client.Client) map[string]Describer { return m } -func expDescriberMap(c *client.Client, exp *client.ExperimentalClient) map[string]Describer { +func expDescriberMap(c *client.Client) map[string]Describer { return map[string]Describer{ - "HorizontalPodAutoscaler": &HorizontalPodAutoscalerDescriber{ - client: c, - experimental: exp, - }, + "HorizontalPodAutoscaler": &HorizontalPodAutoscalerDescriber{c}, } } @@ -104,16 +101,17 @@ func DescribableResources() []string { // Describer returns the default describe functions for each of the standard // Kubernetes types. -func DescriberFor(kind string, c *client.Client, ec *client.ExperimentalClient) (Describer, bool) { +func DescriberFor(group string, kind string, c *client.Client) (Describer, bool) { var f Describer var ok bool - if c != nil { + switch group { + case "api": f, ok = describerMap(c)[kind] + case "experimental": + f, ok = expDescriberMap(c)[kind] } - if !ok && c != nil && ec != nil { - f, ok = expDescriberMap(c, ec)[kind] - } + return f, ok } @@ -1153,12 +1151,11 @@ func describeNode(node *api.Node, pods []*api.Pod, events *api.EventList) (strin // HorizontalPodAutoscalerDescriber generates information about a horizontal pod autoscaler. type HorizontalPodAutoscalerDescriber struct { - client *client.Client - experimental *client.ExperimentalClient + client *client.Client } func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string) (string, error) { - hpa, err := d.experimental.HorizontalPodAutoscalers(namespace).Get(name) + hpa, err := d.client.Experimental().HorizontalPodAutoscalers(namespace).Get(name) if err != nil { return "", err } diff --git a/pkg/kubectl/stop.go b/pkg/kubectl/stop.go index 7cf92bf20d4..bca8ff277d9 100644 --- a/pkg/kubectl/stop.go +++ b/pkg/kubectl/stop.go @@ -52,7 +52,7 @@ func IsNoSuchReaperError(err error) bool { return ok } -func ReaperFor(kind string, c client.Interface, ec *client.ExperimentalClient) (Reaper, error) { +func ReaperFor(kind string, c client.Interface) (Reaper, error) { switch kind { case "ReplicationController": return &ReplicationControllerReaper{c, Interval, Timeout}, nil diff --git a/pkg/kubectl/stop_test.go b/pkg/kubectl/stop_test.go index e4acce66140..705d7def237 100644 --- a/pkg/kubectl/stop_test.go +++ b/pkg/kubectl/stop_test.go @@ -365,7 +365,7 @@ func TestSimpleStop(t *testing.T) { } for _, test := range tests { fake := test.fake - reaper, err := ReaperFor(test.kind, fake, nil) + reaper, err := ReaperFor(test.kind, fake) if err != nil { t.Errorf("unexpected error: %v (%s)", err, test.test) } diff --git a/test/integration/framework/master_utils.go b/test/integration/framework/master_utils.go index d2d89b9ca95..31b7dc8275b 100644 --- a/test/integration/framework/master_utils.go +++ b/test/integration/framework/master_utils.go @@ -190,7 +190,7 @@ func RCFromManifest(fileName string) *api.ReplicationController { // StopRC stops the rc via kubectl's stop library func StopRC(rc *api.ReplicationController, restClient *client.Client) error { - reaper, err := kubectl.ReaperFor("ReplicationController", restClient, nil) + reaper, err := kubectl.ReaperFor("ReplicationController", restClient) if err != nil || reaper == nil { return err }