From a63bd1bdfa1b15b230e9d6089d87602577dffbca Mon Sep 17 00:00:00 2001 From: Daniel Smith Date: Thu, 18 Dec 2014 17:47:59 -0800 Subject: [PATCH] Remove an unneeded trip over the network when getting/listing pods. --- pkg/master/master.go | 14 ++++-- pkg/master/rest_to_nodes.go | 85 +++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 pkg/master/rest_to_nodes.go diff --git a/pkg/master/master.go b/pkg/master/master.go index 94b1ca55261..866191c00e1 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -325,6 +325,8 @@ func (m *Master) init(c *Config) { var userContexts = handlers.NewUserRequestContext() var authenticator = c.Authenticator + nodeRESTStorage := minion.NewREST(m.minionRegistry) + // TODO: Factor out the core API registration m.storage = map[string]apiserver.RESTStorage{ "pods": pod.NewREST(&pod.RESTConfig{ @@ -332,13 +334,19 @@ func (m *Master) init(c *Config) { PodCache: podCache, PodInfoGetter: c.KubeletClient, Registry: m.podRegistry, - Nodes: m.client.Nodes(), + // Note: this allows the pod rest object to directly call + // the node rest object without going through the network & + // apiserver. This arrangement should be temporary, nodes + // shouldn't really need this at all. Once we add more auth in, + // we need to consider carefully if this sort of shortcut is a + // good idea. + Nodes: RESTStorageToNodes(nodeRESTStorage).Nodes(), }), "replicationControllers": controller.NewREST(m.controllerRegistry, m.podRegistry), "services": service.NewREST(m.serviceRegistry, c.Cloud, m.minionRegistry, m.portalNet), "endpoints": endpoint.NewREST(m.endpointRegistry), - "minions": minion.NewREST(m.minionRegistry), - "nodes": minion.NewREST(m.minionRegistry), + "minions": nodeRESTStorage, + "nodes": nodeRESTStorage, "events": event.NewREST(m.eventRegistry), // TODO: should appear only in scheduler API group. diff --git a/pkg/master/rest_to_nodes.go b/pkg/master/rest_to_nodes.go new file mode 100644 index 00000000000..a86a7eea90b --- /dev/null +++ b/pkg/master/rest_to_nodes.go @@ -0,0 +1,85 @@ +/* +Copyright 2014 Google Inc. 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 master + +import ( + "errors" + + "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" + "github.com/GoogleCloudPlatform/kubernetes/pkg/client" + "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" +) + +// RESTStorageToNodes will take a RESTStorage object and return a client interface +// which will work for any use expecting a client.Nodes() interface. The advantage +// of doing this in server code is that it doesn't require an actual trip through +// the network. +// +// TODO: considering that the only difference between the various client types +// and RESTStorage type is the type of the arguments, maybe use "go generate" to +// write a specialized adaptor for every client type? +func RESTStorageToNodes(storage apiserver.RESTStorage) client.NodesInterface { + return &nodeAdaptor{storage} +} + +type nodeAdaptor struct { + storage apiserver.RESTStorage +} + +func (n *nodeAdaptor) Nodes() client.NodeInterface { + return n +} + +// Create creates a new minion. +func (n *nodeAdaptor) Create(minion *api.Node) (*api.Node, error) { + return nil, errors.New("direct creation not implemented") + // TODO: apiserver should expose newOperation to make this easier. + // the actual code that should go here would start like this: + // + // ctx := api.NewDefaultContext() + // out, err := n.storage.Create(ctx, minion) + // if err != nil { + // return nil, err + // } +} + +// List lists all the nodes in the cluster. +func (n *nodeAdaptor) List() (*api.NodeList, error) { + ctx := api.NewContext() + obj, err := n.storage.List(ctx, labels.Everything(), labels.Everything()) + if err != nil { + return nil, err + } + return obj.(*api.NodeList), nil +} + +// Get gets an existing minion +func (n *nodeAdaptor) Get(name string) (*api.Node, error) { + ctx := api.NewContext() + obj, err := n.storage.Get(ctx, name) + if err != nil { + return nil, err + } + return obj.(*api.Node), nil +} + +// Delete deletes an existing minion. +// TODO: implement +func (n *nodeAdaptor) Delete(name string) error { + return errors.New("direct deletion not implemented") +}