Merge pull request #3133 from smarterclayton/remove_request_path

Introduce Resource/ResourceName/Prefix/Suffix options to RESTClient
This commit is contained in:
Daniel Smith 2014-12-30 15:33:11 -08:00
commit 6156526d92
21 changed files with 347 additions and 138 deletions

View File

@ -332,7 +332,7 @@ func TestNetwork(c *client.Client) bool {
const maxAttempts = 60 const maxAttempts = 60
for i := 0; i < maxAttempts; i++ { for i := 0; i < maxAttempts; i++ {
time.Sleep(time.Second) time.Sleep(time.Second)
body, err := c.Get().Path("proxy").Path("services").Path(svc.Name).Path("status").Do().Raw() body, err := c.Get().Prefix("proxy").Resource("services").Name(svc.Name).Suffix("status").Do().Raw()
if err != nil { if err != nil {
glog.Infof("Attempt %v/%v: service/pod still starting. (error: '%v')", i, maxAttempts, err) glog.Infof("Attempt %v/%v: service/pod still starting. (error: '%v')", i, maxAttempts, err)
continue continue
@ -344,7 +344,7 @@ func TestNetwork(c *client.Client) bool {
case "running": case "running":
glog.Infof("Attempt %v/%v: test still running", i, maxAttempts) glog.Infof("Attempt %v/%v: test still running", i, maxAttempts)
case "fail": case "fail":
if body, err := c.Get().Path("proxy").Path("services").Path(svc.Name).Path("read").Do().Raw(); err != nil { if body, err := c.Get().Prefix("proxy").Resource("services").Name(svc.Name).Suffix("read").Do().Raw(); err != nil {
glog.Infof("Failed on attempt %v. Cleaning up. Error reading details: %v", i, err) glog.Infof("Failed on attempt %v. Cleaning up. Error reading details: %v", i, err)
} else { } else {
glog.Infof("Failed on attempt %v. Cleaning up. Details:\n%v", i, string(body)) glog.Infof("Failed on attempt %v. Cleaning up. Details:\n%v", i, string(body))
@ -353,7 +353,7 @@ func TestNetwork(c *client.Client) bool {
} }
} }
if body, err := c.Get().Path("proxy").Path("services").Path(svc.Name).Path("read").Do().Raw(); err != nil { if body, err := c.Get().Prefix("proxy").Resource("services").Name(svc.Name).Suffix("read").Do().Raw(); err != nil {
glog.Infof("Timed out. Cleaning up. Error reading details: %v", err) glog.Infof("Timed out. Cleaning up. Error reading details: %v", err)
} else { } else {
glog.Infof("Timed out. Cleaning up. Details:\n%v", string(body)) glog.Infof("Timed out. Cleaning up. Details:\n%v", string(body))
@ -472,12 +472,11 @@ func TestClusterDNS(c *client.Client) bool {
failed = []string{} failed = []string{}
for _, name := range namesToResolve { for _, name := range namesToResolve {
_, err := c.Get(). _, err := c.Get().
Path("proxy"). Prefix("proxy").
Resource("pods").
Namespace("default"). Namespace("default").
Path("pods"). Name(pod.Name).
Path(pod.Name). Suffix("results", name).
Path("results").
Path(name).
Do().Raw() Do().Raw()
if err != nil { if err != nil {
failed = append(failed, name) failed = append(failed, name)

View File

@ -279,7 +279,7 @@ func runAPIVersionsTest(c *client.Client) {
func runSelfLinkTest(c *client.Client) { func runSelfLinkTest(c *client.Client) {
var svc api.Service var svc api.Service
err := c.Post().Path("services").Body( err := c.Post().Resource("services").Body(
&api.Service{ &api.Service{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: "selflinktest", Name: "selflinktest",
@ -305,7 +305,7 @@ func runSelfLinkTest(c *client.Client) {
} }
var svcList api.ServiceList var svcList api.ServiceList
err = c.Get().Path("services").Do().Into(&svcList) err = c.Get().Resource("services").Do().Into(&svcList)
if err != nil { if err != nil {
glog.Fatalf("Failed listing services: %v", err) glog.Fatalf("Failed listing services: %v", err)
} }
@ -338,7 +338,7 @@ func runSelfLinkTest(c *client.Client) {
func runAtomicPutTest(c *client.Client) { func runAtomicPutTest(c *client.Client) {
var svc api.Service var svc api.Service
err := c.Post().Path("services").Body( err := c.Post().Resource("services").Body(
&api.Service{ &api.Service{
TypeMeta: api.TypeMeta{ TypeMeta: api.TypeMeta{
APIVersion: latest.Version, APIVersion: latest.Version,
@ -377,8 +377,8 @@ func runAtomicPutTest(c *client.Client) {
glog.Infof("Starting to update (%s, %s)", l, v) glog.Infof("Starting to update (%s, %s)", l, v)
var tmpSvc api.Service var tmpSvc api.Service
err := c.Get(). err := c.Get().
Path("services"). Resource("services").
Path(svc.Name). Name(svc.Name).
Do(). Do().
Into(&tmpSvc) Into(&tmpSvc)
if err != nil { if err != nil {
@ -391,7 +391,7 @@ func runAtomicPutTest(c *client.Client) {
tmpSvc.Spec.Selector[l] = v tmpSvc.Spec.Selector[l] = v
} }
glog.Infof("Posting update (%s, %s)", l, v) glog.Infof("Posting update (%s, %s)", l, v)
err = c.Put().Path("services").Path(svc.Name).Body(&tmpSvc).Do().Error() err = c.Put().Resource("services").Name(svc.Name).Body(&tmpSvc).Do().Error()
if err != nil { if err != nil {
if errors.IsConflict(err) { if errors.IsConflict(err) {
glog.Infof("Conflict: (%s, %s)", l, v) glog.Infof("Conflict: (%s, %s)", l, v)
@ -408,7 +408,7 @@ func runAtomicPutTest(c *client.Client) {
}(label, value) }(label, value)
} }
wg.Wait() wg.Wait()
if err := c.Get().Path("services").Path(svc.Name).Do().Into(&svc); err != nil { if err := c.Get().Resource("services").Name(svc.Name).Do().Into(&svc); err != nil {
glog.Fatalf("Failed getting atomicService after writers are complete: %v", err) glog.Fatalf("Failed getting atomicService after writers are complete: %v", err)
} }
if !reflect.DeepEqual(testLabels, labels.Set(svc.Spec.Selector)) { if !reflect.DeepEqual(testLabels, labels.Set(svc.Spec.Selector)) {
@ -422,7 +422,7 @@ func runMasterServiceTest(client *client.Client) {
var svcList api.ServiceList var svcList api.ServiceList
err := client.Get(). err := client.Get().
Namespace("default"). Namespace("default").
Path("services"). Resource("services").
Do(). Do().
Into(&svcList) Into(&svcList)
if err != nil { if err != nil {
@ -443,8 +443,8 @@ func runMasterServiceTest(client *client.Client) {
var ep api.Endpoints var ep api.Endpoints
err := client.Get(). err := client.Get().
Namespace("default"). Namespace("default").
Path("endpoints"). Resource("endpoints").
Path("kubernetes"). Name("kubernetes").
Do(). Do().
Into(&ep) Into(&ep)
if err != nil { if err != nil {
@ -460,8 +460,8 @@ func runMasterServiceTest(client *client.Client) {
var ep api.Endpoints var ep api.Endpoints
err := client.Get(). err := client.Get().
Namespace("default"). Namespace("default").
Path("endpoints"). Resource("endpoints").
Path("kubernetes-ro"). Name("kubernetes-ro").
Do(). Do().
Into(&ep) Into(&ep)
if err != nil { if err != nil {

View File

@ -378,7 +378,7 @@ func executeAPIRequest(ctx api.Context, method string, c *client.Client) bool {
glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>", method, prettyWireStorage()) glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>", method, prettyWireStorage())
} }
case "update": case "update":
obj, err := c.Verb("GET").Namespace(api.Namespace(ctx)).Path(path).Do().Get() obj, err := c.Verb("GET").Namespace(api.Namespace(ctx)).Suffix(path).Do().Get()
if err != nil { if err != nil {
glog.Fatalf("error obtaining resource version for update: %v", err) glog.Fatalf("error obtaining resource version for update: %v", err)
} }
@ -404,7 +404,7 @@ func executeAPIRequest(ctx api.Context, method string, c *client.Client) bool {
return false return false
} }
r := c.Verb(verb).Namespace(api.Namespace(ctx)).Path(path) r := c.Verb(verb).Namespace(api.Namespace(ctx)).Suffix(path)
if len(*selector) > 0 { if len(*selector) > 0 {
r.ParseSelectorParam("labels", *selector) r.ParseSelectorParam("labels", *selector)
} }

View File

@ -53,14 +53,14 @@ func newEndpoints(c *Client, namespace string) *endpoints {
// Create creates a new endpoint. // Create creates a new endpoint.
func (c *endpoints) Create(endpoints *api.Endpoints) (*api.Endpoints, error) { func (c *endpoints) Create(endpoints *api.Endpoints) (*api.Endpoints, error) {
result := &api.Endpoints{} result := &api.Endpoints{}
err := c.r.Post().Namespace(c.ns).Path("endpoints").Body(endpoints).Do().Into(result) err := c.r.Post().Namespace(c.ns).Resource("endpoints").Body(endpoints).Do().Into(result)
return result, err return result, err
} }
// List takes a selector, and returns the list of endpoints that match that selector // List takes a selector, and returns the list of endpoints that match that selector
func (c *endpoints) List(selector labels.Selector) (result *api.EndpointsList, err error) { func (c *endpoints) List(selector labels.Selector) (result *api.EndpointsList, err error) {
result = &api.EndpointsList{} result = &api.EndpointsList{}
err = c.r.Get().Namespace(c.ns).Path("endpoints").SelectorParam("labels", selector).Do().Into(result) err = c.r.Get().Namespace(c.ns).Resource("endpoints").SelectorParam("labels", selector).Do().Into(result)
return return
} }
@ -71,16 +71,16 @@ func (c *endpoints) Get(name string) (result *api.Endpoints, err error) {
} }
result = &api.Endpoints{} result = &api.Endpoints{}
err = c.r.Get().Namespace(c.ns).Path("endpoints").Path(name).Do().Into(result) err = c.r.Get().Namespace(c.ns).Resource("endpoints").Name(name).Do().Into(result)
return return
} }
// Watch returns a watch.Interface that watches the requested endpoints for a service. // Watch returns a watch.Interface that watches the requested endpoints for a service.
func (c *endpoints) Watch(label, field labels.Selector, resourceVersion string) (watch.Interface, error) { func (c *endpoints) Watch(label, field labels.Selector, resourceVersion string) (watch.Interface, error) {
return c.r.Get(). return c.r.Get().
Path("watch"). Prefix("watch").
Namespace(c.ns). Namespace(c.ns).
Path("endpoints"). Resource("endpoints").
Param("resourceVersion", resourceVersion). Param("resourceVersion", resourceVersion).
SelectorParam("labels", label). SelectorParam("labels", label).
SelectorParam("fields", field). SelectorParam("fields", field).
@ -94,8 +94,8 @@ func (c *endpoints) Update(endpoints *api.Endpoints) (*api.Endpoints, error) {
} }
err := c.r.Put(). err := c.r.Put().
Namespace(c.ns). Namespace(c.ns).
Path("endpoints"). Resource("endpoints").
Path(endpoints.Name). Name(endpoints.Name).
Body(endpoints). Body(endpoints).
Do(). Do().
Into(result) Into(result)

View File

@ -66,7 +66,7 @@ func (e *events) Create(event *api.Event) (*api.Event, error) {
result := &api.Event{} result := &api.Event{}
err := e.client.Post(). err := e.client.Post().
Namespace(event.Namespace). Namespace(event.Namespace).
Path("events"). Resource("events").
Body(event). Body(event).
Do(). Do().
Into(result) Into(result)
@ -78,7 +78,7 @@ func (e *events) List(label, field labels.Selector) (*api.EventList, error) {
result := &api.EventList{} result := &api.EventList{}
err := e.client.Get(). err := e.client.Get().
Namespace(e.namespace). Namespace(e.namespace).
Path("events"). Resource("events").
SelectorParam("labels", label). SelectorParam("labels", label).
SelectorParam("fields", field). SelectorParam("fields", field).
Do(). Do().
@ -95,8 +95,8 @@ func (e *events) Get(name string) (*api.Event, error) {
result := &api.Event{} result := &api.Event{}
err := e.client.Get(). err := e.client.Get().
Namespace(e.namespace). Namespace(e.namespace).
Path("events"). Resource("events").
Path(name). Name(name).
Do(). Do().
Into(result) Into(result)
return result, err return result, err
@ -105,9 +105,9 @@ func (e *events) Get(name string) (*api.Event, error) {
// Watch starts watching for events matching the given selectors. // Watch starts watching for events matching the given selectors.
func (e *events) Watch(label, field labels.Selector, resourceVersion string) (watch.Interface, error) { func (e *events) Watch(label, field labels.Selector, resourceVersion string) (watch.Interface, error) {
return e.client.Get(). return e.client.Get().
Path("watch"). Prefix("watch").
Namespace(e.namespace). Namespace(e.namespace).
Path("events"). Resource("events").
Param("resourceVersion", resourceVersion). Param("resourceVersion", resourceVersion).
SelectorParam("labels", label). SelectorParam("labels", label).
SelectorParam("fields", field). SelectorParam("fields", field).

View File

@ -55,14 +55,14 @@ func (c *nodes) resourceName() string {
// Create creates a new minion. // Create creates a new minion.
func (c *nodes) Create(minion *api.Node) (*api.Node, error) { func (c *nodes) Create(minion *api.Node) (*api.Node, error) {
result := &api.Node{} result := &api.Node{}
err := c.r.Post().Path(c.resourceName()).Body(minion).Do().Into(result) err := c.r.Post().Resource(c.resourceName()).Body(minion).Do().Into(result)
return result, err return result, err
} }
// List lists all the nodes in the cluster. // List lists all the nodes in the cluster.
func (c *nodes) List() (*api.NodeList, error) { func (c *nodes) List() (*api.NodeList, error) {
result := &api.NodeList{} result := &api.NodeList{}
err := c.r.Get().Path(c.resourceName()).Do().Into(result) err := c.r.Get().Resource(c.resourceName()).Do().Into(result)
return result, err return result, err
} }
@ -73,11 +73,11 @@ func (c *nodes) Get(name string) (*api.Node, error) {
} }
result := &api.Node{} result := &api.Node{}
err := c.r.Get().Path(c.resourceName()).Path(name).Do().Into(result) err := c.r.Get().Resource(c.resourceName()).Name(name).Do().Into(result)
return result, err return result, err
} }
// Delete deletes an existing minion. // Delete deletes an existing minion.
func (c *nodes) Delete(name string) error { func (c *nodes) Delete(name string) error {
return c.r.Delete().Path(c.resourceName()).Path(name).Do().Error() return c.r.Delete().Resource(c.resourceName()).Name(name).Do().Error()
} }

View File

@ -55,7 +55,7 @@ func newPods(c *Client, namespace string) *pods {
// ListPods takes a selector, and returns the list of pods that match that selector. // ListPods takes a selector, and returns the list of pods that match that selector.
func (c *pods) List(selector labels.Selector) (result *api.PodList, err error) { func (c *pods) List(selector labels.Selector) (result *api.PodList, err error) {
result = &api.PodList{} result = &api.PodList{}
err = c.r.Get().Namespace(c.ns).Path("pods").SelectorParam("labels", selector).Do().Into(result) err = c.r.Get().Namespace(c.ns).Resource("pods").SelectorParam("labels", selector).Do().Into(result)
return return
} }
@ -66,19 +66,19 @@ func (c *pods) Get(name string) (result *api.Pod, err error) {
} }
result = &api.Pod{} result = &api.Pod{}
err = c.r.Get().Namespace(c.ns).Path("pods").Path(name).Do().Into(result) err = c.r.Get().Namespace(c.ns).Resource("pods").Name(name).Do().Into(result)
return return
} }
// DeletePod takes the name of the pod, and returns an error if one occurs // DeletePod takes the name of the pod, and returns an error if one occurs
func (c *pods) Delete(name string) error { func (c *pods) Delete(name string) error {
return c.r.Delete().Namespace(c.ns).Path("pods").Path(name).Do().Error() return c.r.Delete().Namespace(c.ns).Resource("pods").Name(name).Do().Error()
} }
// CreatePod takes the representation of a pod. Returns the server's representation of the pod, and an error, if it occurs. // CreatePod takes the representation of a pod. Returns the server's representation of the pod, and an error, if it occurs.
func (c *pods) Create(pod *api.Pod) (result *api.Pod, err error) { func (c *pods) Create(pod *api.Pod) (result *api.Pod, err error) {
result = &api.Pod{} result = &api.Pod{}
err = c.r.Post().Namespace(c.ns).Path("pods").Body(pod).Do().Into(result) err = c.r.Post().Namespace(c.ns).Resource("pods").Body(pod).Do().Into(result)
return return
} }
@ -89,6 +89,6 @@ func (c *pods) Update(pod *api.Pod) (result *api.Pod, err error) {
err = fmt.Errorf("invalid update object, missing resource version: %v", pod) err = fmt.Errorf("invalid update object, missing resource version: %v", pod)
return return
} }
err = c.r.Put().Namespace(c.ns).Path("pods").Path(pod.Name).Body(pod).Do().Into(result) err = c.r.Put().Namespace(c.ns).Resource("pods").Name(pod.Name).Body(pod).Do().Into(result)
return return
} }

View File

@ -54,7 +54,7 @@ func newReplicationControllers(c *Client, namespace string) *replicationControll
// List takes a selector, and returns the list of replication controllers that match that selector. // List takes a selector, and returns the list of replication controllers that match that selector.
func (c *replicationControllers) List(selector labels.Selector) (result *api.ReplicationControllerList, err error) { func (c *replicationControllers) List(selector labels.Selector) (result *api.ReplicationControllerList, err error) {
result = &api.ReplicationControllerList{} result = &api.ReplicationControllerList{}
err = c.r.Get().Namespace(c.ns).Path("replicationControllers").SelectorParam("labels", selector).Do().Into(result) err = c.r.Get().Namespace(c.ns).Resource("replicationControllers").SelectorParam("labels", selector).Do().Into(result)
return return
} }
@ -65,14 +65,14 @@ func (c *replicationControllers) Get(name string) (result *api.ReplicationContro
} }
result = &api.ReplicationController{} result = &api.ReplicationController{}
err = c.r.Get().Namespace(c.ns).Path("replicationControllers").Path(name).Do().Into(result) err = c.r.Get().Namespace(c.ns).Resource("replicationControllers").Name(name).Do().Into(result)
return return
} }
// Create creates a new replication controller. // Create creates a new replication controller.
func (c *replicationControllers) Create(controller *api.ReplicationController) (result *api.ReplicationController, err error) { func (c *replicationControllers) Create(controller *api.ReplicationController) (result *api.ReplicationController, err error) {
result = &api.ReplicationController{} result = &api.ReplicationController{}
err = c.r.Post().Namespace(c.ns).Path("replicationControllers").Body(controller).Do().Into(result) err = c.r.Post().Namespace(c.ns).Resource("replicationControllers").Body(controller).Do().Into(result)
return return
} }
@ -83,21 +83,21 @@ func (c *replicationControllers) Update(controller *api.ReplicationController) (
err = fmt.Errorf("invalid update object, missing resource version: %v", controller) err = fmt.Errorf("invalid update object, missing resource version: %v", controller)
return return
} }
err = c.r.Put().Namespace(c.ns).Path("replicationControllers").Path(controller.Name).Body(controller).Do().Into(result) err = c.r.Put().Namespace(c.ns).Resource("replicationControllers").Name(controller.Name).Body(controller).Do().Into(result)
return return
} }
// Delete deletes an existing replication controller. // Delete deletes an existing replication controller.
func (c *replicationControllers) Delete(name string) error { func (c *replicationControllers) Delete(name string) error {
return c.r.Delete().Namespace(c.ns).Path("replicationControllers").Path(name).Do().Error() return c.r.Delete().Namespace(c.ns).Resource("replicationControllers").Name(name).Do().Error()
} }
// Watch returns a watch.Interface that watches the requested controllers. // Watch returns a watch.Interface that watches the requested controllers.
func (c *replicationControllers) Watch(label, field labels.Selector, resourceVersion string) (watch.Interface, error) { func (c *replicationControllers) Watch(label, field labels.Selector, resourceVersion string) (watch.Interface, error) {
return c.r.Get(). return c.r.Get().
Path("watch"). Prefix("watch").
Namespace(c.ns). Namespace(c.ns).
Path("replicationControllers"). Resource("replicationControllers").
Param("resourceVersion", resourceVersion). Param("resourceVersion", resourceVersion).
SelectorParam("labels", label). SelectorParam("labels", label).
SelectorParam("fields", field). SelectorParam("fields", field).

View File

@ -89,16 +89,22 @@ type Request struct {
// whether to poll. // whether to poll.
poller PollFunc poller PollFunc
// accessible via method setters // If true, put ns/<namespace> in path; if false, add "?namespace=<namespace>" as a query parameter
namespaceInPath bool
// generic components accessible via method setters
path string path string
subpath string
params map[string]string params map[string]string
// structural elements of the request that are part of the Kubernetes API conventions
namespace string
resource string
resourceName string
selector labels.Selector selector labels.Selector
sync bool sync bool
timeout time.Duration timeout time.Duration
// If true, put ns/<namespace> in path; if false, add "?namespace=<namespace>" as a query parameter
namespaceInPath bool
// output // output
err error err error
body io.Reader body io.Reader
@ -116,12 +122,50 @@ func NewRequest(client HTTPClient, verb string, baseURL *url.URL, codec runtime.
} }
} }
// Path appends an item to the request path. You must call Path at least once. // Prefix adds segments to the relative beginning to the request path. These
func (r *Request) Path(item string) *Request { // items will be placed before the optional Namespace, Resource, or Name sections.
// Setting AbsPath will clear any previously set Prefix segments
func (r *Request) Prefix(segments ...string) *Request {
if r.err != nil { if r.err != nil {
return r return r
} }
r.path = path.Join(r.path, item) r.path = path.Join(r.path, path.Join(segments...))
return r
}
// Suffix appends segments to the end of the path. These items will be placed after the prefix and optional
// Namespace, Resource, or Name sections.
func (r *Request) Suffix(segments ...string) *Request {
if r.err != nil {
return r
}
r.subpath = path.Join(r.subpath, path.Join(segments...))
return r
}
// Resource sets the resource to access (<resource>/[ns/<namespace>/]<name>)
func (r *Request) Resource(resource string) *Request {
if r.err != nil {
return r
}
if len(r.resource) != 0 {
r.err = fmt.Errorf("resource already set to %q, cannot change to %q", r.resource, resource)
return r
}
r.resource = resource
return r
}
// Name sets the name of a resource to access (<resource>/[ns/<namespace>/]<name>)
func (r *Request) Name(resourceName string) *Request {
if r.err != nil {
return r
}
if len(r.resourceName) != 0 {
r.err = fmt.Errorf("resource name already set to %q, cannot change to %q", r.resourceName, resourceName)
return r
}
r.resourceName = resourceName
return r return r
} }
@ -134,29 +178,31 @@ func (r *Request) Sync(sync bool) *Request {
return r return r
} }
// Namespace applies the namespace scope to a request // Namespace applies the namespace scope to a request (<resource>/[ns/<namespace>/]<name>)
func (r *Request) Namespace(namespace string) *Request { func (r *Request) Namespace(namespace string) *Request {
if r.err != nil { if r.err != nil {
return r return r
} }
if len(r.namespace) != 0 {
if len(namespace) > 0 { r.err = fmt.Errorf("namespace already set to %q, cannot change to %q", r.namespace, namespace)
if r.namespaceInPath { return r
return r.Path("ns").Path(namespace)
} else {
return r.setParam("namespace", namespace)
}
} }
r.namespace = namespace
return r return r
} }
// AbsPath overwrites an existing path with the path parameter. // AbsPath overwrites an existing path with the segments provided. Trailing slashes are preserved
func (r *Request) AbsPath(path string) *Request { // when a single segment is passed.
func (r *Request) AbsPath(segments ...string) *Request {
if r.err != nil { if r.err != nil {
return r return r
} }
r.path = path if len(segments) == 1 {
// preserve any trailing slashes for legacy behavior
r.path = segments[0]
} else {
r.path = path.Join(segments...)
}
return r return r
} }
@ -273,13 +319,30 @@ func (r *Request) Poller(poller PollFunc) *Request {
} }
func (r *Request) finalURL() string { func (r *Request) finalURL() string {
p := r.path
if r.namespaceInPath {
p = path.Join(p, "ns", r.namespace)
}
if len(r.resource) != 0 {
p = path.Join(p, r.resource)
}
// Join trims trailing slashes, so preserve r.path's trailing slash for backwards compat if nothing was changed
if len(r.resourceName) != 0 || len(r.subpath) != 0 {
p = path.Join(p, r.resourceName, r.subpath)
}
finalURL := *r.baseURL finalURL := *r.baseURL
finalURL.Path = r.path finalURL.Path = p
query := url.Values{} query := url.Values{}
for key, value := range r.params { for key, value := range r.params {
query.Add(key, value) query.Add(key, value)
} }
if !r.namespaceInPath && len(r.namespace) > 0 {
query.Add("namespace", r.namespace)
}
// sync and timeout are handled specially here, to allow setting them // sync and timeout are handled specially here, to allow setting them
// in any order. // in any order.
if r.sync { if r.sync {
@ -452,13 +515,12 @@ func (r *Request) transformResponse(resp *http.Response, req *http.Request) ([]b
switch resp.StatusCode { switch resp.StatusCode {
case http.StatusConflict: case http.StatusConflict:
if req.Method == "POST" { if req.Method == "POST" {
// TODO: add Resource() and ResourceName() as Request methods so that we can set these err = errors.NewAlreadyExists(r.resource, r.resourceName)
err = errors.NewAlreadyExists("", "")
} else { } else {
err = errors.NewConflict("", "", err) err = errors.NewConflict(r.resource, r.resourceName, err)
} }
case http.StatusNotFound: case http.StatusNotFound:
err = errors.NewNotFound("", "") err = errors.NewNotFound(r.resource, r.resourceName)
case http.StatusBadRequest: case http.StatusBadRequest:
err = errors.NewBadRequest(err.Error()) err = errors.NewBadRequest(err.Error())
} }

View File

@ -32,6 +32,7 @@ import (
"time" "time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
apierrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
@ -54,9 +55,12 @@ func TestRequestWithErrorWontChange(t *testing.T) {
SelectorParam("labels", labels.Set{"a": "b"}.AsSelector()). SelectorParam("labels", labels.Set{"a": "b"}.AsSelector()).
UintParam("uint", 1). UintParam("uint", 1).
AbsPath("/abs"). AbsPath("/abs").
Path("test"). Prefix("test").
Suffix("testing").
ParseSelectorParam("foo", "a=b"). ParseSelectorParam("foo", "a=b").
Namespace("new"). Namespace("new").
Resource("foos").
Name("bars").
NoPoll(). NoPoll().
Body("foo"). Body("foo").
Poller(skipPolling). Poller(skipPolling).
@ -70,6 +74,74 @@ func TestRequestWithErrorWontChange(t *testing.T) {
} }
} }
func TestRequestPreservesBaseTrailingSlash(t *testing.T) {
r := &Request{baseURL: &url.URL{}, path: "/path/"}
if s := r.finalURL(); s != "/path/" {
t.Errorf("trailing slash should be preserved: %s", s)
}
}
func TestRequestAbsPathPreservesTrailingSlash(t *testing.T) {
r := (&Request{baseURL: &url.URL{}}).AbsPath("/foo/")
if s := r.finalURL(); s != "/foo/" {
t.Errorf("trailing slash should be preserved: %s", s)
}
}
func TestRequestAbsPathJoins(t *testing.T) {
r := (&Request{baseURL: &url.URL{}}).AbsPath("foo/bar", "baz")
if s := r.finalURL(); s != "foo/bar/baz" {
t.Errorf("trailing slash should be preserved: %s", s)
}
}
func TestRequestSetsNamespace(t *testing.T) {
r := (&Request{
baseURL: &url.URL{
Path: "/",
},
}).Namespace("foo")
if r.namespace == "" {
t.Errorf("namespace should be set: %#v", r)
}
if s := r.finalURL(); s != "?namespace=foo" {
t.Errorf("namespace should be in params: %s", s)
}
r = (&Request{
baseURL: &url.URL{
Path: "/",
},
namespaceInPath: true,
}).Namespace("foo")
if s := r.finalURL(); s != "ns/foo" {
t.Errorf("namespace should be in path: %s", s)
}
}
func TestRequestOrdersNamespaceInPath(t *testing.T) {
r := (&Request{
baseURL: &url.URL{},
path: "/test/",
namespaceInPath: true,
}).Name("bar").Resource("baz").Namespace("foo")
if s := r.finalURL(); s != "/test/ns/foo/baz/bar" {
t.Errorf("namespace should be in order in path: %s", s)
}
}
func TestRequestSetTwiceError(t *testing.T) {
if (&Request{}).Name("bar").Name("baz").err == nil {
t.Errorf("setting name twice should result in error")
}
if (&Request{}).Namespace("bar").Namespace("baz").err == nil {
t.Errorf("setting namespace twice should result in error")
}
if (&Request{}).Resource("bar").Resource("baz").err == nil {
t.Errorf("setting resource twice should result in error")
}
}
func TestRequestParseSelectorParam(t *testing.T) { func TestRequestParseSelectorParam(t *testing.T) {
r := (&Request{}).ParseSelectorParam("foo", "a") r := (&Request{}).ParseSelectorParam("foo", "a")
if r.err == nil || r.params != nil { if r.err == nil || r.params != nil {
@ -133,6 +205,9 @@ func TestTransformResponse(t *testing.T) {
{Response: &http.Response{StatusCode: 201}, Data: []byte{}, Created: true}, {Response: &http.Response{StatusCode: 201}, Data: []byte{}, Created: true},
{Response: &http.Response{StatusCode: 199}, Error: true}, {Response: &http.Response{StatusCode: 199}, Error: true},
{Response: &http.Response{StatusCode: 500}, Error: true}, {Response: &http.Response{StatusCode: 500}, Error: true},
{Response: &http.Response{StatusCode: 422}, Error: true},
{Response: &http.Response{StatusCode: 409}, Error: true},
{Response: &http.Response{StatusCode: 404}, Error: true},
{Response: &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewReader(invalid))}, Data: invalid}, {Response: &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewReader(invalid))}, Data: invalid},
{Response: &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewReader(invalid))}, Data: invalid}, {Response: &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewReader(invalid))}, Data: invalid},
} }
@ -155,6 +230,80 @@ func TestTransformResponse(t *testing.T) {
} }
} }
func TestTransformUnstructuredError(t *testing.T) {
testCases := []struct {
Req *http.Request
Res *http.Response
Resource string
Name string
ErrFn func(error) bool
}{
{
Resource: "foo",
Name: "bar",
Req: &http.Request{
Method: "POST",
},
Res: &http.Response{
StatusCode: http.StatusConflict,
Body: ioutil.NopCloser(bytes.NewReader(nil)),
},
ErrFn: apierrors.IsAlreadyExists,
},
{
Resource: "foo",
Name: "bar",
Req: &http.Request{
Method: "PUT",
},
Res: &http.Response{
StatusCode: http.StatusConflict,
Body: ioutil.NopCloser(bytes.NewReader(nil)),
},
ErrFn: apierrors.IsConflict,
},
{
Resource: "foo",
Name: "bar",
Req: &http.Request{},
Res: &http.Response{
StatusCode: http.StatusNotFound,
Body: ioutil.NopCloser(bytes.NewReader(nil)),
},
ErrFn: apierrors.IsNotFound,
},
{
Req: &http.Request{},
Res: &http.Response{
StatusCode: http.StatusBadRequest,
Body: ioutil.NopCloser(bytes.NewReader(nil)),
},
ErrFn: apierrors.IsBadRequest,
},
}
for _, testCase := range testCases {
r := &Request{
codec: latest.Codec,
resourceName: testCase.Name,
resource: testCase.Resource,
}
_, _, err := r.transformResponse(testCase.Res, testCase.Req)
if !testCase.ErrFn(err) {
t.Errorf("unexpected error: %v", err)
continue
}
if len(testCase.Name) != 0 && !strings.Contains(err.Error(), testCase.Name) {
t.Errorf("unexpected error string: %s", err)
}
if len(testCase.Resource) != 0 && !strings.Contains(err.Error(), testCase.Resource) {
t.Errorf("unexpected error string: %s", err)
}
}
}
type clientFunc func(req *http.Request) (*http.Response, error) type clientFunc func(req *http.Request) (*http.Response, error)
func (f clientFunc) Do(req *http.Request) (*http.Response, error) { func (f clientFunc) Do(req *http.Request) (*http.Response, error) {
@ -333,8 +482,8 @@ func TestDoRequestNewWay(t *testing.T) {
defer testServer.Close() defer testServer.Close()
c := NewOrDie(&Config{Host: testServer.URL, Version: "v1beta2", Username: "user", Password: "pass"}) c := NewOrDie(&Config{Host: testServer.URL, Version: "v1beta2", Username: "user", Password: "pass"})
obj, err := c.Verb("POST"). obj, err := c.Verb("POST").
Path("foo/bar"). Prefix("foo", "bar").
Path("baz"). Suffix("baz").
ParseSelectorParam("labels", "name=foo"). ParseSelectorParam("labels", "name=foo").
Timeout(time.Second). Timeout(time.Second).
Body([]byte(reqBody)). Body([]byte(reqBody)).
@ -367,8 +516,9 @@ func TestDoRequestNewWayReader(t *testing.T) {
testServer := httptest.NewServer(&fakeHandler) testServer := httptest.NewServer(&fakeHandler)
c := NewOrDie(&Config{Host: testServer.URL, Version: "v1beta1", Username: "user", Password: "pass"}) c := NewOrDie(&Config{Host: testServer.URL, Version: "v1beta1", Username: "user", Password: "pass"})
obj, err := c.Verb("POST"). obj, err := c.Verb("POST").
Path("foo/bar"). Resource("bar").
Path("baz"). Name("baz").
Prefix("foo").
SelectorParam("labels", labels.Set{"name": "foo"}.AsSelector()). SelectorParam("labels", labels.Set{"name": "foo"}.AsSelector()).
Sync(true). Sync(true).
Timeout(time.Second). Timeout(time.Second).
@ -403,8 +553,9 @@ func TestDoRequestNewWayObj(t *testing.T) {
testServer := httptest.NewServer(&fakeHandler) testServer := httptest.NewServer(&fakeHandler)
c := NewOrDie(&Config{Host: testServer.URL, Version: "v1beta2", Username: "user", Password: "pass"}) c := NewOrDie(&Config{Host: testServer.URL, Version: "v1beta2", Username: "user", Password: "pass"})
obj, err := c.Verb("POST"). obj, err := c.Verb("POST").
Path("foo/bar"). Suffix("baz").
Path("baz"). Name("bar").
Resource("foo").
SelectorParam("labels", labels.Set{"name": "foo"}.AsSelector()). SelectorParam("labels", labels.Set{"name": "foo"}.AsSelector()).
Timeout(time.Second). Timeout(time.Second).
Body(reqObj). Body(reqObj).
@ -453,8 +604,7 @@ func TestDoRequestNewWayFile(t *testing.T) {
c := NewOrDie(&Config{Host: testServer.URL, Version: "v1beta1", Username: "user", Password: "pass"}) c := NewOrDie(&Config{Host: testServer.URL, Version: "v1beta1", Username: "user", Password: "pass"})
wasCreated := true wasCreated := true
obj, err := c.Verb("POST"). obj, err := c.Verb("POST").
Path("foo/bar"). Prefix("foo/bar", "baz").
Path("baz").
ParseSelectorParam("labels", "name=foo"). ParseSelectorParam("labels", "name=foo").
Timeout(time.Second). Timeout(time.Second).
Body(file.Name()). Body(file.Name()).
@ -496,8 +646,7 @@ func TestWasCreated(t *testing.T) {
c := NewOrDie(&Config{Host: testServer.URL, Version: "v1beta1", Username: "user", Password: "pass"}) c := NewOrDie(&Config{Host: testServer.URL, Version: "v1beta1", Username: "user", Password: "pass"})
wasCreated := false wasCreated := false
obj, err := c.Verb("PUT"). obj, err := c.Verb("PUT").
Path("foo/bar"). Prefix("foo/bar", "baz").
Path("baz").
ParseSelectorParam("labels", "name=foo"). ParseSelectorParam("labels", "name=foo").
Timeout(time.Second). Timeout(time.Second).
Body(reqBodyExpected). Body(reqBodyExpected).
@ -541,7 +690,7 @@ func TestVerbs(t *testing.T) {
func TestAbsPath(t *testing.T) { func TestAbsPath(t *testing.T) {
expectedPath := "/bar/foo" expectedPath := "/bar/foo"
c := NewOrDie(&Config{}) c := NewOrDie(&Config{})
r := c.Post().Path("/foo").AbsPath(expectedPath) r := c.Post().Prefix("/foo").AbsPath(expectedPath)
if r.path != expectedPath { if r.path != expectedPath {
t.Errorf("unexpected path: %s, expected %s", r.path, expectedPath) t.Errorf("unexpected path: %s, expected %s", r.path, expectedPath)
} }
@ -792,7 +941,7 @@ func TestWatch(t *testing.T) {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
watching, err := s.Get().Path("path/to/watch/thing").Watch() watching, err := s.Get().Prefix("path/to/watch/thing").Watch()
if err != nil { if err != nil {
t.Fatalf("Unexpected error") t.Fatalf("Unexpected error")
} }
@ -841,7 +990,7 @@ func TestStream(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
readCloser, err := s.Get().Path("path/to/stream/thing").Stream() readCloser, err := s.Get().Prefix("path/to/stream/thing").Stream()
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }

View File

@ -59,7 +59,9 @@ type RESTClient struct {
// NewRESTClient creates a new RESTClient. This client performs generic REST functions // NewRESTClient creates a new RESTClient. This client performs generic REST functions
// such as Get, Put, Post, and Delete on specified paths. Codec controls encoding and // such as Get, Put, Post, and Delete on specified paths. Codec controls encoding and
// decoding of responses from the server. // decoding of responses from the server. If the namespace should be specified as part
// of the path (after the resource), set namespaceInPath to true, otherwise it will be
// passed as "namespace" in the query string.
func NewRESTClient(baseURL *url.URL, c runtime.Codec, namespaceInPath bool) *RESTClient { func NewRESTClient(baseURL *url.URL, c runtime.Codec, namespaceInPath bool) *RESTClient {
base := *baseURL base := *baseURL
if !strings.HasSuffix(base.Path, "/") { if !strings.HasSuffix(base.Path, "/") {
@ -129,7 +131,7 @@ func (c *RESTClient) Delete() *Request {
// PollFor makes a request to do a single poll of the completion of the given operation. // PollFor makes a request to do a single poll of the completion of the given operation.
func (c *RESTClient) Operation(name string) *Request { func (c *RESTClient) Operation(name string) *Request {
return c.Get().Path("operations").Path(name).Sync(false).NoPoll() return c.Get().Resource("operations").Name(name).Sync(false).NoPoll()
} }
func (c *RESTClient) DefaultPoll(name string) (*Request, bool) { func (c *RESTClient) DefaultPoll(name string) (*Request, bool) {

View File

@ -137,7 +137,7 @@ func TestDoRequestAccepted(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
body, err := c.Get().Path("test").Do().Raw() body, err := c.Get().Prefix("test").Do().Raw()
if err == nil { if err == nil {
t.Fatalf("Unexpected non-error") t.Fatalf("Unexpected non-error")
} }
@ -171,7 +171,7 @@ func TestDoRequestAcceptedSuccess(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
body, err := c.Get().Path("test").Do().Raw() body, err := c.Get().Prefix("test").Do().Raw()
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@ -231,7 +231,7 @@ func TestDoRequestCreated(t *testing.T) {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
created := false created := false
body, err := c.Get().Path("test").Do().WasCreated(&created).Raw() body, err := c.Get().Prefix("test").Do().WasCreated(&created).Raw()
if err != nil { if err != nil {
t.Errorf("Unexpected error %#v", err) t.Errorf("Unexpected error %#v", err)
} }

View File

@ -54,7 +54,7 @@ func newServices(c *Client, namespace string) *services {
// List takes a selector, and returns the list of services that match that selector // List takes a selector, and returns the list of services that match that selector
func (c *services) List(selector labels.Selector) (result *api.ServiceList, err error) { func (c *services) List(selector labels.Selector) (result *api.ServiceList, err error) {
result = &api.ServiceList{} result = &api.ServiceList{}
err = c.r.Get().Namespace(c.ns).Path("services").SelectorParam("labels", selector).Do().Into(result) err = c.r.Get().Namespace(c.ns).Resource("services").SelectorParam("labels", selector).Do().Into(result)
return return
} }
@ -65,14 +65,14 @@ func (c *services) Get(name string) (result *api.Service, err error) {
} }
result = &api.Service{} result = &api.Service{}
err = c.r.Get().Namespace(c.ns).Path("services").Path(name).Do().Into(result) err = c.r.Get().Namespace(c.ns).Resource("services").Name(name).Do().Into(result)
return return
} }
// Create creates a new service. // Create creates a new service.
func (c *services) Create(svc *api.Service) (result *api.Service, err error) { func (c *services) Create(svc *api.Service) (result *api.Service, err error) {
result = &api.Service{} result = &api.Service{}
err = c.r.Post().Namespace(c.ns).Path("services").Body(svc).Do().Into(result) err = c.r.Post().Namespace(c.ns).Resource("services").Body(svc).Do().Into(result)
return return
} }
@ -83,21 +83,21 @@ func (c *services) Update(svc *api.Service) (result *api.Service, err error) {
err = fmt.Errorf("invalid update object, missing resource version: %v", svc) err = fmt.Errorf("invalid update object, missing resource version: %v", svc)
return return
} }
err = c.r.Put().Namespace(c.ns).Path("services").Path(svc.Name).Body(svc).Do().Into(result) err = c.r.Put().Namespace(c.ns).Resource("services").Name(svc.Name).Body(svc).Do().Into(result)
return return
} }
// Delete deletes an existing service. // Delete deletes an existing service.
func (c *services) Delete(name string) error { func (c *services) Delete(name string) error {
return c.r.Delete().Namespace(c.ns).Path("services").Path(name).Do().Error() return c.r.Delete().Namespace(c.ns).Resource("services").Name(name).Do().Error()
} }
// Watch returns a watch.Interface that watches the requested services. // Watch returns a watch.Interface that watches the requested services.
func (c *services) Watch(label, field labels.Selector, resourceVersion string) (watch.Interface, error) { func (c *services) Watch(label, field labels.Selector, resourceVersion string) (watch.Interface, error) {
return c.r.Get(). return c.r.Get().
Path("watch"). Prefix("watch").
Namespace(c.ns). Namespace(c.ns).
Path("services"). Resource("services").
Param("resourceVersion", resourceVersion). Param("resourceVersion", resourceVersion).
SelectorParam("labels", label). SelectorParam("labels", label).
SelectorParam("fields", field). SelectorParam("fields", field).

View File

@ -80,7 +80,7 @@ func CreateObject(client RESTClientPoster, mapping *meta.RESTMapping, obj runtim
} }
// TODO: This should be using RESTHelper // TODO: This should be using RESTHelper
err = client.Post().Path(mapping.Resource).Namespace(namespace).Body(obj).Do().Error() err = client.Post().Resource(mapping.Resource).Namespace(namespace).Body(obj).Do().Error()
if err != nil { if err != nil {
return errs.NewFieldInvalid(name, obj, err.Error()) return errs.NewFieldInvalid(name, obj, err.Error())
} }

View File

@ -37,7 +37,7 @@ func ValidateObject(data []byte, c *client.Client) error {
schemaData, err := c.RESTClient.Get(). schemaData, err := c.RESTClient.Get().
AbsPath("/swaggerapi/api"). AbsPath("/swaggerapi/api").
Path(apiVersion.(string)). Prefix(apiVersion.(string)).
Do(). Do().
Raw() Raw()
if err != nil { if err != nil {

View File

@ -183,8 +183,7 @@ func (c *clientSwaggerSchema) ValidateBytes(data []byte) error {
return err return err
} }
schemaData, err := c.c.RESTClient.Get(). schemaData, err := c.c.RESTClient.Get().
AbsPath("/swaggerapi/api"). AbsPath("/swaggerapi/api", version).
Path(version).
Do(). Do().
Raw() Raw()
if err != nil { if err != nil {

View File

@ -70,12 +70,10 @@ Examples:
} }
readCloser, err := client.RESTClient.Get(). readCloser, err := client.RESTClient.Get().
Path("proxy/minions"). Prefix("proxy").
Path(pod.Status.Host). Resource("minions").
Path("containerLogs"). Name(pod.Status.Host).
Path(namespace). Suffix("containerLogs", namespace, podID, container).
Path(podID).
Path(container).
Param("follow", strconv.FormatBool(follow)). Param("follow", strconv.FormatBool(follow)).
Stream() Stream()
checkErr(err) checkErr(err)

View File

@ -47,18 +47,18 @@ func NewRESTHelper(client RESTClient, mapping *meta.RESTMapping) *RESTHelper {
} }
func (m *RESTHelper) Get(namespace, name string, selector labels.Selector) (runtime.Object, error) { func (m *RESTHelper) Get(namespace, name string, selector labels.Selector) (runtime.Object, error) {
return m.RESTClient.Get().Namespace(namespace).Path(m.Resource).Path(name).SelectorParam("labels", selector).Do().Get() return m.RESTClient.Get().Resource(m.Resource).Namespace(namespace).Name(name).SelectorParam("labels", selector).Do().Get()
} }
func (m *RESTHelper) List(namespace string, selector labels.Selector) (runtime.Object, error) { func (m *RESTHelper) List(namespace string, selector labels.Selector) (runtime.Object, error) {
return m.RESTClient.Get().Path(m.Resource).Namespace(namespace).Path("").SelectorParam("labels", selector).Do().Get() return m.RESTClient.Get().Resource(m.Resource).Namespace(namespace).SelectorParam("labels", selector).Do().Get()
} }
func (m *RESTHelper) Watch(namespace, resourceVersion string, labelSelector, fieldSelector labels.Selector) (watch.Interface, error) { func (m *RESTHelper) Watch(namespace, resourceVersion string, labelSelector, fieldSelector labels.Selector) (watch.Interface, error) {
return m.RESTClient.Get(). return m.RESTClient.Get().
Path("watch"). Prefix("watch").
Namespace(namespace). Namespace(namespace).
Path(m.Resource). Resource(m.Resource).
Param("resourceVersion", resourceVersion). Param("resourceVersion", resourceVersion).
SelectorParam("labels", labelSelector). SelectorParam("labels", labelSelector).
SelectorParam("fields", fieldSelector). SelectorParam("fields", fieldSelector).
@ -66,7 +66,7 @@ func (m *RESTHelper) Watch(namespace, resourceVersion string, labelSelector, fie
} }
func (m *RESTHelper) Delete(namespace, name string) error { func (m *RESTHelper) Delete(namespace, name string) error {
return m.RESTClient.Delete().Namespace(namespace).Path(m.Resource).Path(name).Do().Error() return m.RESTClient.Delete().Namespace(namespace).Resource(m.Resource).Name(name).Do().Error()
} }
func (m *RESTHelper) Create(namespace string, modify bool, data []byte) error { func (m *RESTHelper) Create(namespace string, modify bool, data []byte) error {
@ -98,8 +98,8 @@ func (m *RESTHelper) Create(namespace string, modify bool, data []byte) error {
return createResource(m.RESTClient, m.Resource, namespace, data) return createResource(m.RESTClient, m.Resource, namespace, data)
} }
func createResource(c RESTClient, resourcePath, namespace string, data []byte) error { func createResource(c RESTClient, resource, namespace string, data []byte) error {
return c.Post().Namespace(namespace).Path(resourcePath).Body(data).Do().Error() return c.Post().Namespace(namespace).Resource(resource).Body(data).Do().Error()
} }
func (m *RESTHelper) Update(namespace, name string, overwrite bool, data []byte) error { func (m *RESTHelper) Update(namespace, name string, overwrite bool, data []byte) error {
@ -119,7 +119,7 @@ func (m *RESTHelper) Update(namespace, name string, overwrite bool, data []byte)
} }
if version == "" && overwrite { if version == "" && overwrite {
// Retrieve the current version of the object to overwrite the server object // Retrieve the current version of the object to overwrite the server object
serverObj, err := c.Get().Path(m.Resource).Path(name).Do().Get() serverObj, err := c.Get().Resource(m.Resource).Name(name).Do().Get()
if err != nil { if err != nil {
// The object does not exist, but we want it to be created // The object does not exist, but we want it to be created
return updateResource(c, m.Resource, namespace, name, data) return updateResource(c, m.Resource, namespace, name, data)
@ -141,6 +141,6 @@ func (m *RESTHelper) Update(namespace, name string, overwrite bool, data []byte)
return updateResource(c, m.Resource, namespace, name, data) return updateResource(c, m.Resource, namespace, name, data)
} }
func updateResource(c RESTClient, resourcePath, namespace, name string, data []byte) error { func updateResource(c RESTClient, resource, namespace, name string, data []byte) error {
return c.Put().Namespace(namespace).Path(resourcePath).Path(name).Body(data).Do().Error() return c.Put().Namespace(namespace).Resource(resource).Name(name).Body(data).Do().Error()
} }

View File

@ -287,7 +287,7 @@ func TestRESTHelperUpdate(t *testing.T) {
} }
parts := splitPath(req.URL.Path) parts := splitPath(req.URL.Path)
if parts[1] != "bar" { if parts[1] != "bar" {
t.Errorf("url doesn't contain namespace: %#v", req) t.Errorf("url doesn't contain namespace: %#v", req.URL)
return false return false
} }
if parts[2] != "foo" { if parts[2] != "foo" {

File diff suppressed because one or more lines are too long

View File

@ -139,7 +139,7 @@ type listWatch struct {
func (lw *listWatch) List() (runtime.Object, error) { func (lw *listWatch) List() (runtime.Object, error) {
return lw.client. return lw.client.
Get(). Get().
Path(lw.resource). Resource(lw.resource).
SelectorParam("fields", lw.fieldSelector). SelectorParam("fields", lw.fieldSelector).
Do(). Do().
Get() Get()
@ -148,8 +148,8 @@ func (lw *listWatch) List() (runtime.Object, error) {
func (lw *listWatch) Watch(resourceVersion string) (watch.Interface, error) { func (lw *listWatch) Watch(resourceVersion string) (watch.Interface, error) {
return lw.client. return lw.client.
Get(). Get().
Path("watch"). Prefix("watch").
Path(lw.resource). Resource(lw.resource).
SelectorParam("fields", lw.fieldSelector). SelectorParam("fields", lw.fieldSelector).
Param("resourceVersion", resourceVersion). Param("resourceVersion", resourceVersion).
Watch() Watch()
@ -195,7 +195,7 @@ func (factory *ConfigFactory) createMinionLW() *listWatch {
// pollMinions lists all minions and returns an enumerator for cache.Poller. // pollMinions lists all minions and returns an enumerator for cache.Poller.
func (factory *ConfigFactory) pollMinions() (cache.Enumerator, error) { func (factory *ConfigFactory) pollMinions() (cache.Enumerator, error) {
list := &api.NodeList{} list := &api.NodeList{}
err := factory.Client.Get().Path("minions").Do().Into(list) err := factory.Client.Get().Resource("minions").Do().Into(list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -215,7 +215,7 @@ func (factory *ConfigFactory) makeDefaultErrorFunc(backoff *podBackoff, podQueue
backoff.wait(podID) backoff.wait(podID)
// Get the pod again; it may have changed/been scheduled already. // Get the pod again; it may have changed/been scheduled already.
pod = &api.Pod{} pod = &api.Pod{}
err := factory.Client.Get().Namespace(podNamespace).Path("pods").Path(podID).Do().Into(pod) err := factory.Client.Get().Namespace(podNamespace).Resource("pods").Name(podID).Do().Into(pod)
if err != nil { if err != nil {
glog.Errorf("Error getting pod %v for retry: %v; abandoning", podID, err) glog.Errorf("Error getting pod %v for retry: %v; abandoning", podID, err)
return return
@ -288,7 +288,7 @@ type binder struct {
func (b *binder) Bind(binding *api.Binding) error { func (b *binder) Bind(binding *api.Binding) error {
glog.V(2).Infof("Attempting to bind %v to %v", binding.PodID, binding.Host) glog.V(2).Infof("Attempting to bind %v to %v", binding.PodID, binding.Host)
ctx := api.WithNamespace(api.NewContext(), binding.Namespace) ctx := api.WithNamespace(api.NewContext(), binding.Namespace)
return b.Post().Namespace(api.Namespace(ctx)).Path("bindings").Body(binding).Do().Error() return b.Post().Namespace(api.Namespace(ctx)).Resource("bindings").Body(binding).Do().Error()
} }
type clock interface { type clock interface {