Switch watch prefixes to params

This commit is contained in:
Jordan Liggitt 2017-01-09 16:21:23 -05:00
parent e6dbe5f57e
commit 7b6ef2cedc
No known key found for this signature in database
GPG Key ID: 24E7ADF9A3B42012
12 changed files with 60 additions and 33 deletions

View File

@ -321,8 +321,8 @@ func (c *$.type|privatePlural$) UpdateStatus($.type|private$ *$.type|raw$) (resu
var watchTemplate = `
// Watch returns a $.watchInterface|raw$ that watches the requested $.type|privatePlural$.
func (c *$.type|privatePlural$) Watch(opts $.ListOptions|raw$) ($.watchInterface|raw$, error) {
opts.Watch = true
return c.client.Get().
Prefix("watch").
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|allLowercasePlural$").
VersionedParams(&opts, $.apiParameterCodec|raw$).

View File

@ -122,8 +122,8 @@ func TestListWatchesCanWatch(t *testing.T) {
// Node
{
location: buildLocation(
testapi.Default.ResourcePathWithPrefix("watch", "nodes", metav1.NamespaceAll, ""),
buildQueryValues(url.Values{})),
testapi.Default.ResourcePath("nodes", metav1.NamespaceAll, ""),
buildQueryValues(url.Values{"watch": []string{"true"}})),
rv: "",
resource: "nodes",
namespace: metav1.NamespaceAll,
@ -131,8 +131,8 @@ func TestListWatchesCanWatch(t *testing.T) {
},
{
location: buildLocation(
testapi.Default.ResourcePathWithPrefix("watch", "nodes", metav1.NamespaceAll, ""),
buildQueryValues(url.Values{"resourceVersion": []string{"42"}})),
testapi.Default.ResourcePath("nodes", metav1.NamespaceAll, ""),
buildQueryValues(url.Values{"resourceVersion": []string{"42"}, "watch": []string{"true"}})),
rv: "42",
resource: "nodes",
namespace: metav1.NamespaceAll,
@ -141,8 +141,8 @@ func TestListWatchesCanWatch(t *testing.T) {
// pod with "assigned" field selector.
{
location: buildLocation(
testapi.Default.ResourcePathWithPrefix("watch", "pods", metav1.NamespaceAll, ""),
buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}, "resourceVersion": []string{"0"}})),
testapi.Default.ResourcePath("pods", metav1.NamespaceAll, ""),
buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}, "resourceVersion": []string{"0"}, "watch": []string{"true"}})),
rv: "0",
resource: "pods",
namespace: metav1.NamespaceAll,
@ -151,8 +151,8 @@ func TestListWatchesCanWatch(t *testing.T) {
// pod with namespace foo and assigned field selector
{
location: buildLocation(
testapi.Default.ResourcePathWithPrefix("watch", "pods", "foo", ""),
buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}, "resourceVersion": []string{"0"}})),
testapi.Default.ResourcePath("pods", "foo", ""),
buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}, "resourceVersion": []string{"0"}, "watch": []string{"true"}})),
rv: "0",
resource: "pods",
namespace: "foo",

View File

@ -354,7 +354,7 @@ func TestGCListWatcher(t *testing.T) {
if e, a := 2, len(testHandler.actions); e != a {
t.Errorf("expect %d requests, got %d", e, a)
}
if e, a := "resourceVersion=1", testHandler.actions[0].query; e != a {
if e, a := "resourceVersion=1&watch=true", testHandler.actions[0].query; e != a {
t.Errorf("expect %s, got %s", e, a)
}
if e, a := "resourceVersion=1", testHandler.actions[1].query; e != a {

View File

@ -720,9 +720,11 @@ func TestWatchSelector(t *testing.T) {
}
switch req.URL.Path {
case "/namespaces/test/pods":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil
case "/watch/namespaces/test/pods":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil
if req.URL.Query().Get("watch") == "true" {
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil
} else {
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil
}
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
@ -760,8 +762,12 @@ func TestWatchResource(t *testing.T) {
switch req.URL.Path {
case "/namespaces/test/pods/foo":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods[1])}, nil
case "/watch/namespaces/test/pods/foo":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil
case "/namespaces/test/pods":
if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" {
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil
}
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
@ -798,8 +804,12 @@ func TestWatchResourceIdentifiedByFile(t *testing.T) {
switch req.URL.Path {
case "/namespaces/test/replicationcontrollers/cassandra":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods[1])}, nil
case "/watch/namespaces/test/replicationcontrollers/cassandra":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil
case "/namespaces/test/replicationcontrollers":
if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=cassandra" {
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil
}
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
@ -837,8 +847,12 @@ func TestWatchOnlyResource(t *testing.T) {
switch req.URL.Path {
case "/namespaces/test/pods/foo":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods[1])}, nil
case "/watch/namespaces/test/pods/foo":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil
case "/namespaces/test/pods":
if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" {
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil
}
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
@ -880,9 +894,11 @@ func TestWatchOnlyList(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path {
case "/namespaces/test/pods":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil
case "/watch/namespaces/test/pods":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil
if req.URL.Query().Get("watch") == "true" {
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil
} else {
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil
}
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil

View File

@ -31,6 +31,7 @@ go_library(
"//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apimachinery/pkg/api/meta",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/fields",
"//vendor:k8s.io/apimachinery/pkg/labels",
"//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",

View File

@ -1069,7 +1069,7 @@ func TestListObjectWithDifferentVersions(t *testing.T) {
func TestWatch(t *testing.T) {
_, svc := testData()
w, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{
"/watch/namespaces/test/services/redis-master?resourceVersion=12": watchBody(watch.Event{
"/namespaces/test/services?fieldSelector=metadata.name%3Dredis-master&resourceVersion=12&watch=true": watchBody(watch.Event{
Type: watch.Added,
Object: &svc.Items[0],
}),

View File

@ -20,6 +20,7 @@ import (
"strconv"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
@ -75,21 +76,21 @@ func (m *Helper) List(namespace, apiVersion string, selector labels.Selector, ex
func (m *Helper) Watch(namespace, resourceVersion, apiVersion string, labelSelector labels.Selector) (watch.Interface, error) {
return m.RESTClient.Get().
Prefix("watch").
NamespaceIfScoped(namespace, m.NamespaceScoped).
Resource(m.Resource).
Param("resourceVersion", resourceVersion).
Param("watch", "true").
LabelsSelectorParam(labelSelector).
Watch()
}
func (m *Helper) WatchSingle(namespace, name, resourceVersion string) (watch.Interface, error) {
return m.RESTClient.Get().
Prefix("watch").
NamespaceIfScoped(namespace, m.NamespaceScoped).
Resource(m.Resource).
Name(name).
Param("resourceVersion", resourceVersion).
Param("watch", "true").
FieldsSelectorParam(fields.OneTermEqualSelector("metadata.name", name)).
Watch()
}

View File

@ -737,6 +737,7 @@ func TestNotFound(t *testing.T) {
"groupless namespaced PUT with extra segment": {"PUT", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
"groupless namespaced watch missing storage": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/", http.StatusNotFound},
"groupless namespaced watch with bad method": {"POST", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
"groupless namespaced watch param with bad method": {"POST", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar?watch=true", http.StatusMethodNotAllowed},
// Positive checks to make sure everything is wired correctly
"GET root": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots", http.StatusOK},
@ -768,6 +769,7 @@ func TestNotFound(t *testing.T) {
"namespaced PUT with extra segment": {"PUT", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
"namespaced watch missing storage": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/", http.StatusNotFound},
"namespaced watch with bad method": {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
"namespaced watch param with bad method": {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar?watch=true", http.StatusMethodNotAllowed},
}
handler := handle(map[string]rest.Storage{
"simples": &SimpleRESTStorage{},

View File

@ -197,8 +197,8 @@ func (rc *ResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error
if parameterEncoder == nil {
parameterEncoder = defaultParameterEncoder
}
opts.Watch = true
return rc.cl.Get().
Prefix("watch").
NamespaceIfScoped(rc.ns, rc.resource.Namespaced).
Resource(rc.resource.Name).
VersionedParams(&opts, parameterEncoder).

View File

@ -425,10 +425,12 @@ func TestWatch(t *testing.T) {
namespace string
events []watch.Event
path string
query string
}{
{
name: "normal_watch",
path: "/api/gtest/vtest/watch/rtest",
name: "normal_watch",
path: "/api/gtest/vtest/rtest",
query: "watch=true",
events: []watch.Event{
{Type: watch.Added, Object: getObject("vTest", "rTest", "normal_watch")},
{Type: watch.Modified, Object: getObject("vTest", "rTest", "normal_watch")},
@ -438,7 +440,8 @@ func TestWatch(t *testing.T) {
{
name: "namespaced_watch",
namespace: "nstest",
path: "/api/gtest/vtest/watch/namespaces/nstest/rtest",
path: "/api/gtest/vtest/namespaces/nstest/rtest",
query: "watch=true",
events: []watch.Event{
{Type: watch.Added, Object: getObject("vTest", "rTest", "namespaced_watch")},
{Type: watch.Modified, Object: getObject("vTest", "rTest", "namespaced_watch")},
@ -457,6 +460,9 @@ func TestWatch(t *testing.T) {
if r.URL.Path != tc.path {
t.Errorf("Watch(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
if r.URL.RawQuery != tc.query {
t.Errorf("Watch(%q) got query %s. wanted %s", tc.name, r.URL.RawQuery, tc.query)
}
enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, dynamicCodec{}), dynamicCodec{})
for _, e := range tc.events {

View File

@ -67,8 +67,8 @@ func NewListWatchFromClient(c Getter, resource string, namespace string, fieldSe
Get()
}
watchFunc := func(options metav1.ListOptions) (watch.Interface, error) {
options.Watch = true
return c.Get().
Prefix("watch").
Namespace(namespace).
Resource(resource).
VersionedParams(&options, metav1.ParameterCodec).

View File

@ -29,6 +29,7 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@ -491,11 +492,11 @@ func TestSingleWatch(t *testing.T) {
}
w, err := client.Core().RESTClient().Get().
Prefix("watch").
Namespace(ns.Name).
Resource("events").
Name("event-9").
Param("resourceVersion", rv1).
Param("watch", "true").
FieldsSelectorParam(fields.OneTermEqualSelector("metadata.name", "event-9")).
Watch()
if err != nil {