Merge pull request #5233 from brendandburns/labels

Make label and field selector query strings versionable.
This commit is contained in:
Brian Grant
2015-03-16 16:01:37 -07:00
22 changed files with 92 additions and 74 deletions

View File

@@ -17,6 +17,7 @@ limitations under the License.
package cache
import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@@ -38,12 +39,12 @@ type ListWatch struct {
}
// NewListWatchFromClient creates a new ListWatch from the specified client, resource, namespace and field selector.
func NewListWatchFromClient(client *client.Client, resource string, namespace string, fieldSelector labels.Selector) *ListWatch {
func NewListWatchFromClient(c *client.Client, resource string, namespace string, fieldSelector labels.Selector) *ListWatch {
listFunc := func() (runtime.Object, error) {
return client.Get().Namespace(namespace).Resource(resource).SelectorParam("fields", fieldSelector).Do().Get()
return c.Get().Namespace(namespace).Resource(resource).SelectorParam(api.FieldSelectorQueryParam(c.APIVersion()), fieldSelector).Do().Get()
}
watchFunc := func(resourceVersion string) (watch.Interface, error) {
return client.Get().Prefix("watch").Namespace(namespace).Resource(resource).SelectorParam("fields", fieldSelector).Param("resourceVersion", resourceVersion).Watch()
return c.Get().Prefix("watch").Namespace(namespace).Resource(resource).SelectorParam(api.FieldSelectorQueryParam(c.APIVersion()), fieldSelector).Param("resourceVersion", resourceVersion).Watch()
}
return &ListWatch{ListFunc: listFunc, WatchFunc: watchFunc}
}

View File

@@ -149,8 +149,3 @@ func IsTimeout(err error) bool {
}
return false
}
// preV1Beta3 returns true if the provided API version is an API introduced before v1beta3.
func preV1Beta3(version string) bool {
return version == "v1beta1" || version == "v1beta2"
}

View File

@@ -60,7 +60,12 @@ func (c *endpoints) Create(endpoints *api.Endpoints) (*api.Endpoints, error) {
// 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) {
result = &api.EndpointsList{}
err = c.r.Get().Namespace(c.ns).Resource("endpoints").SelectorParam("labels", selector).Do().Into(result)
err = c.r.Get().
Namespace(c.ns).
Resource("endpoints").
SelectorParam(api.LabelSelectorQueryParam(c.r.APIVersion()), selector).
Do().
Into(result)
return
}
@@ -82,8 +87,8 @@ func (c *endpoints) Watch(label, field labels.Selector, resourceVersion string)
Namespace(c.ns).
Resource("endpoints").
Param("resourceVersion", resourceVersion).
SelectorParam("labels", label).
SelectorParam("fields", field).
SelectorParam(api.LabelSelectorQueryParam(c.r.APIVersion()), label).
SelectorParam(api.FieldSelectorQueryParam(c.r.APIVersion()), field).
Watch()
}

View File

@@ -101,8 +101,8 @@ func (e *events) List(label, field labels.Selector) (*api.EventList, error) {
err := e.client.Get().
NamespaceIfScoped(e.namespace, len(e.namespace) > 0).
Resource("events").
SelectorParam("labels", label).
SelectorParam("fields", field).
SelectorParam(api.LabelSelectorQueryParam(e.client.APIVersion()), label).
SelectorParam(api.FieldSelectorQueryParam(e.client.APIVersion()), field).
Do().
Into(result)
return result, err
@@ -131,8 +131,8 @@ func (e *events) Watch(label, field labels.Selector, resourceVersion string) (wa
NamespaceIfScoped(e.namespace, len(e.namespace) > 0).
Resource("events").
Param("resourceVersion", resourceVersion).
SelectorParam("labels", label).
SelectorParam("fields", field).
SelectorParam(api.LabelSelectorQueryParam(e.client.APIVersion()), label).
SelectorParam(api.FieldSelectorQueryParam(e.client.APIVersion()), field).
Watch()
}

View File

@@ -21,6 +21,7 @@ import (
"net/url"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/version"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
@@ -120,19 +121,19 @@ type FakeRESTClient struct {
}
func (c *FakeRESTClient) Get() *Request {
return NewRequest(c, "GET", &url.URL{Host: "localhost"}, c.Codec, c.Legacy, c.Legacy)
return NewRequest(c, "GET", &url.URL{Host: "localhost"}, testapi.Version(), c.Codec, c.Legacy, c.Legacy)
}
func (c *FakeRESTClient) Put() *Request {
return NewRequest(c, "PUT", &url.URL{Host: "localhost"}, c.Codec, c.Legacy, c.Legacy)
return NewRequest(c, "PUT", &url.URL{Host: "localhost"}, testapi.Version(), c.Codec, c.Legacy, c.Legacy)
}
func (c *FakeRESTClient) Post() *Request {
return NewRequest(c, "POST", &url.URL{Host: "localhost"}, c.Codec, c.Legacy, c.Legacy)
return NewRequest(c, "POST", &url.URL{Host: "localhost"}, testapi.Version(), c.Codec, c.Legacy, c.Legacy)
}
func (c *FakeRESTClient) Delete() *Request {
return NewRequest(c, "DELETE", &url.URL{Host: "localhost"}, c.Codec, c.Legacy, c.Legacy)
return NewRequest(c, "DELETE", &url.URL{Host: "localhost"}, testapi.Version(), c.Codec, c.Legacy, c.Legacy)
}
func (c *FakeRESTClient) Do(req *http.Request) (*http.Response, error) {

View File

@@ -57,7 +57,7 @@ func newLimitRanges(c *Client, namespace string) *limitRanges {
// List takes a selector, and returns the list of limitRanges that match that selector.
func (c *limitRanges) List(selector labels.Selector) (result *api.LimitRangeList, err error) {
result = &api.LimitRangeList{}
err = c.r.Get().Namespace(c.ns).Resource("limitRanges").SelectorParam("labels", selector).Do().Into(result)
err = c.r.Get().Namespace(c.ns).Resource("limitRanges").SelectorParam(api.LabelSelectorQueryParam(c.r.APIVersion()), selector).Do().Into(result)
return
}
@@ -102,7 +102,7 @@ func (c *limitRanges) Watch(label, field labels.Selector, resourceVersion string
Namespace(c.ns).
Resource("limitRanges").
Param("resourceVersion", resourceVersion).
SelectorParam("labels", label).
SelectorParam("fields", field).
SelectorParam(api.LabelSelectorQueryParam(c.r.APIVersion()), label).
SelectorParam(api.FieldSelectorQueryParam(c.r.APIVersion()), field).
Watch()
}

View File

@@ -48,7 +48,7 @@ func newNodes(c *Client) *nodes {
// resourceName returns node's URL resource name based on resource version.
func (c *nodes) resourceName() string {
if preV1Beta3(c.r.APIVersion()) {
if api.PreV1Beta3(c.r.APIVersion()) {
return "minions"
}
return "nodes"

View File

@@ -58,7 +58,7 @@ func (c *namespaces) Create(namespace *api.Namespace) (*api.Namespace, error) {
// List lists all the namespaces in the cluster.
func (c *namespaces) List(selector labels.Selector) (*api.NamespaceList, error) {
result := &api.NamespaceList{}
err := c.r.Get().Resource("namespaces").SelectorParam("labels", selector).Do().Into(result)
err := c.r.Get().Resource("namespaces").SelectorParam(api.LabelSelectorQueryParam(c.r.APIVersion()), selector).Do().Into(result)
return result, err
}
@@ -95,7 +95,7 @@ func (c *namespaces) Watch(label, field labels.Selector, resourceVersion string)
Prefix("watch").
Resource("namespaces").
Param("resourceVersion", resourceVersion).
SelectorParam("labels", label).
SelectorParam("fields", field).
SelectorParam(api.LabelSelectorQueryParam(c.r.APIVersion()), label).
SelectorParam(api.FieldSelectorQueryParam(c.r.APIVersion()), field).
Watch()
}

View File

@@ -58,7 +58,7 @@ func newPods(c *Client, namespace string) *pods {
// List 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) {
result = &api.PodList{}
err = c.r.Get().Namespace(c.ns).Resource("pods").SelectorParam("labels", selector).Do().Into(result)
err = c.r.Get().Namespace(c.ns).Resource("pods").SelectorParam(api.LabelSelectorQueryParam(c.r.APIVersion()), selector).Do().Into(result)
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.
func (c *replicationControllers) List(selector labels.Selector) (result *api.ReplicationControllerList, err error) {
result = &api.ReplicationControllerList{}
err = c.r.Get().Namespace(c.ns).Resource("replicationControllers").SelectorParam("labels", selector).Do().Into(result)
err = c.r.Get().Namespace(c.ns).Resource("replicationControllers").SelectorParam(api.LabelSelectorQueryParam(c.r.APIVersion()), selector).Do().Into(result)
return
}
@@ -99,7 +99,7 @@ func (c *replicationControllers) Watch(label, field labels.Selector, resourceVer
Namespace(c.ns).
Resource("replicationControllers").
Param("resourceVersion", resourceVersion).
SelectorParam("labels", label).
SelectorParam("fields", field).
SelectorParam(api.LabelSelectorQueryParam(c.r.APIVersion()), label).
SelectorParam(api.FieldSelectorQueryParam(c.r.APIVersion()), field).
Watch()
}

View File

@@ -110,6 +110,8 @@ type Request struct {
selector labels.Selector
timeout time.Duration
apiVersion string
// output
err error
body io.Reader
@@ -120,7 +122,7 @@ type Request struct {
}
// NewRequest creates a new request helper object for accessing runtime.Objects on a server.
func NewRequest(client HTTPClient, verb string, baseURL *url.URL,
func NewRequest(client HTTPClient, verb string, baseURL *url.URL, apiVersion string,
codec runtime.Codec, namespaceInQuery bool, preserveResourceCase bool) *Request {
return &Request{
client: client,

View File

@@ -50,12 +50,11 @@ func TestRequestWithErrorWontChange(t *testing.T) {
original := Request{err: errors.New("test")}
r := original
changed := r.Param("foo", "bar").
SelectorParam("labels", labels.Set{"a": "b"}.AsSelector()).
SelectorParam(api.LabelSelectorQueryParam(testapi.Version()), labels.Set{"a": "b"}.AsSelector()).
UintParam("uint", 1).
AbsPath("/abs").
Prefix("test").
Suffix("testing").
ParseSelectorParam("foo", "a=b").
Namespace("new").
Resource("foos").
Name("bars").
@@ -154,13 +153,6 @@ func TestRequestSetTwiceError(t *testing.T) {
}
}
func TestRequestParseSelectorParam(t *testing.T) {
r := (&Request{}).ParseSelectorParam("foo", "a=")
if r.err == nil || r.params != nil {
t.Errorf("should have set err and left params nil: %#v", r)
}
}
func TestRequestParam(t *testing.T) {
r := (&Request{}).Param("foo", "a")
if !api.Semantic.DeepDerivative(r.params, url.Values{"foo": []string{"a"}}) {
@@ -242,7 +234,7 @@ func TestTransformResponse(t *testing.T) {
{Response: &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewReader(invalid))}, Data: invalid},
}
for i, test := range testCases {
r := NewRequest(nil, "", uri, testapi.Codec(), true, true)
r := NewRequest(nil, "", uri, testapi.Version(), testapi.Codec(), true, true)
if test.Response.Body == nil {
test.Response.Body = ioutil.NopCloser(bytes.NewReader([]byte{}))
}
@@ -540,7 +532,7 @@ func TestRequestUpgrade(t *testing.T) {
Err: true,
},
{
Request: NewRequest(nil, "", uri, testapi.Codec(), true, true),
Request: NewRequest(nil, "", uri, testapi.Version(), testapi.Codec(), true, true),
Config: &Config{
Username: "u",
Password: "p",
@@ -549,7 +541,7 @@ func TestRequestUpgrade(t *testing.T) {
Err: false,
},
{
Request: NewRequest(nil, "", uri, testapi.Codec(), true, true),
Request: NewRequest(nil, "", uri, testapi.Version(), testapi.Codec(), true, true),
Config: &Config{
BearerToken: "b",
},
@@ -638,7 +630,6 @@ func TestDoRequestNewWay(t *testing.T) {
obj, err := c.Verb("POST").
Prefix("foo", "bar").
Suffix("baz").
ParseSelectorParam("labels", "name=foo").
Timeout(time.Second).
Body([]byte(reqBody)).
Do().Get()
@@ -651,7 +642,7 @@ func TestDoRequestNewWay(t *testing.T) {
} else if !api.Semantic.DeepDerivative(expectedObj, obj) {
t.Errorf("Expected: %#v, got %#v", expectedObj, obj)
}
fakeHandler.ValidateRequest(t, "/api/v1beta2/foo/bar/baz?labels=name%3Dfoo&timeout=1s", "POST", &reqBody)
fakeHandler.ValidateRequest(t, "/api/v1beta2/foo/bar/baz?timeout=1s", "POST", &reqBody)
if fakeHandler.RequestReceived.Header["Authorization"] == nil {
t.Errorf("Request is missing authorization header: %#v", *fakeHandler.RequestReceived)
}
@@ -673,7 +664,7 @@ func TestDoRequestNewWayReader(t *testing.T) {
Resource("bar").
Name("baz").
Prefix("foo").
SelectorParam("labels", labels.Set{"name": "foo"}.AsSelector()).
SelectorParam(api.LabelSelectorQueryParam(c.APIVersion()), labels.Set{"name": "foo"}.AsSelector()).
Timeout(time.Second).
Body(bytes.NewBuffer(reqBodyExpected)).
Do().Get()
@@ -709,7 +700,7 @@ func TestDoRequestNewWayObj(t *testing.T) {
Suffix("baz").
Name("bar").
Resource("foo").
SelectorParam("labels", labels.Set{"name": "foo"}.AsSelector()).
SelectorParam(api.LabelSelectorQueryParam(c.APIVersion()), labels.Set{"name": "foo"}.AsSelector()).
Timeout(time.Second).
Body(reqObj).
Do().Get()
@@ -758,7 +749,6 @@ func TestDoRequestNewWayFile(t *testing.T) {
wasCreated := true
obj, err := c.Verb("POST").
Prefix("foo/bar", "baz").
ParseSelectorParam("labels", "name=foo").
Timeout(time.Second).
Body(file.Name()).
Do().WasCreated(&wasCreated).Get()
@@ -775,7 +765,7 @@ func TestDoRequestNewWayFile(t *testing.T) {
t.Errorf("expected object was not created")
}
tmpStr := string(reqBodyExpected)
fakeHandler.ValidateRequest(t, "/api/v1beta1/foo/bar/baz?labels=name%3Dfoo&timeout=1s", "POST", &tmpStr)
fakeHandler.ValidateRequest(t, "/api/v1beta1/foo/bar/baz?timeout=1s", "POST", &tmpStr)
if fakeHandler.RequestReceived.Header["Authorization"] == nil {
t.Errorf("Request is missing authorization header: %#v", *fakeHandler.RequestReceived)
}
@@ -800,7 +790,6 @@ func TestWasCreated(t *testing.T) {
wasCreated := false
obj, err := c.Verb("PUT").
Prefix("foo/bar", "baz").
ParseSelectorParam("labels", "name=foo").
Timeout(time.Second).
Body(reqBodyExpected).
Do().WasCreated(&wasCreated).Get()
@@ -818,7 +807,7 @@ func TestWasCreated(t *testing.T) {
}
tmpStr := string(reqBodyExpected)
fakeHandler.ValidateRequest(t, "/api/v1beta1/foo/bar/baz?labels=name%3Dfoo&timeout=1s", "PUT", &tmpStr)
fakeHandler.ValidateRequest(t, "/api/v1beta1/foo/bar/baz?timeout=1s", "PUT", &tmpStr)
if fakeHandler.RequestReceived.Header["Authorization"] == nil {
t.Errorf("Request is missing authorization header: %#v", *fakeHandler.RequestReceived)
}

View File

@@ -58,7 +58,7 @@ func newResourceQuotas(c *Client, namespace string) *resourceQuotas {
// List takes a selector, and returns the list of resourceQuotas that match that selector.
func (c *resourceQuotas) List(selector labels.Selector) (result *api.ResourceQuotaList, err error) {
result = &api.ResourceQuotaList{}
err = c.r.Get().Namespace(c.ns).Resource("resourceQuotas").SelectorParam("labels", selector).Do().Into(result)
err = c.r.Get().Namespace(c.ns).Resource("resourceQuotas").SelectorParam(api.LabelSelectorQueryParam(c.r.APIVersion()), selector).Do().Into(result)
return
}
@@ -114,7 +114,7 @@ func (c *resourceQuotas) Watch(label, field labels.Selector, resourceVersion str
Namespace(c.ns).
Resource("resourceQuotas").
Param("resourceVersion", resourceVersion).
SelectorParam("labels", label).
SelectorParam("fields", field).
SelectorParam(api.LabelSelectorQueryParam(c.r.APIVersion()), label).
SelectorParam(api.FieldSelectorQueryParam(c.r.APIVersion()), field).
Watch()
}

View File

@@ -92,7 +92,7 @@ func (c *RESTClient) Verb(verb string) *Request {
// if c.Client != nil {
// timeout = c.Client.Timeout
// }
return NewRequest(c.Client, verb, c.baseURL, c.Codec, c.LegacyBehavior, c.LegacyBehavior).Timeout(c.Timeout)
return NewRequest(c.Client, verb, c.baseURL, c.apiVersion, c.Codec, c.LegacyBehavior, c.LegacyBehavior).Timeout(c.Timeout)
}
// Post begins a POST request. Short for c.Verb("POST").

View File

@@ -75,8 +75,8 @@ func (s *secrets) List(label, field labels.Selector) (*api.SecretList, error) {
err := s.client.Get().
Namespace(s.namespace).
Resource("secrets").
SelectorParam("labels", label).
SelectorParam("fields", field).
SelectorParam(api.LabelSelectorQueryParam(s.client.APIVersion()), label).
SelectorParam(api.FieldSelectorQueryParam(s.client.APIVersion()), field).
Do().
Into(result)
@@ -107,8 +107,8 @@ func (s *secrets) Watch(label, field labels.Selector, resourceVersion string) (w
Namespace(s.namespace).
Resource("secrets").
Param("resourceVersion", resourceVersion).
SelectorParam("labels", label).
SelectorParam("fields", field).
SelectorParam(api.LabelSelectorQueryParam(s.client.APIVersion()), label).
SelectorParam(api.FieldSelectorQueryParam(s.client.APIVersion()), field).
Watch()
}

View File

@@ -54,7 +54,12 @@ func newServices(c *Client, namespace string) *services {
// 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) {
result = &api.ServiceList{}
err = c.r.Get().Namespace(c.ns).Resource("services").SelectorParam("labels", selector).Do().Into(result)
err = c.r.Get().
Namespace(c.ns).
Resource("services").
SelectorParam(api.LabelSelectorQueryParam(c.r.APIVersion()), selector).
Do().
Into(result)
return
}
@@ -99,7 +104,7 @@ func (c *services) Watch(label, field labels.Selector, resourceVersion string) (
Namespace(c.ns).
Resource("services").
Param("resourceVersion", resourceVersion).
SelectorParam("labels", label).
SelectorParam("fields", field).
SelectorParam(api.LabelSelectorQueryParam(c.r.APIVersion()), label).
SelectorParam(api.FieldSelectorQueryParam(c.r.APIVersion()), field).
Watch()
}