kube-proxy can read config from the apiserver

All clients that talk to a "master" as a host:port or URL
(scheme://host:port) parameter.  Add tests.
This commit is contained in:
Clayton Coleman
2014-08-15 17:14:22 -04:00
parent 083d81b6d7
commit 9006eadcfe
9 changed files with 393 additions and 17 deletions

View File

@@ -23,6 +23,7 @@ import (
"io"
"io/ioutil"
"net/http"
"net/url"
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
@@ -67,6 +68,9 @@ type ServiceInterface interface {
CreateService(api.Service) (api.Service, error)
UpdateService(api.Service) (api.Service, error)
DeleteService(string) error
WatchServices(label, field labels.Selector, resourceVersion uint64) (watch.Interface, error)
WatchEndpoints(label, field labels.Selector, resourceVersion uint64) (watch.Interface, error)
}
// VersionInterface has a method to retrieve the server version
@@ -183,7 +187,12 @@ func (c *RESTClient) doRequest(request *http.Request) ([]byte, error) {
// requestBody is the body of the request. Can be nil.
// target the interface to marshal the JSON response into. Can be nil.
func (c *RESTClient) rawRequest(method, path string, requestBody io.Reader, target interface{}) ([]byte, error) {
request, err := http.NewRequest(method, c.makeURL(path), requestBody)
reqUrl, err := c.makeURL(path)
if err != nil {
return nil, err
}
request, err := http.NewRequest(method, reqUrl, requestBody)
if err != nil {
return nil, err
}
@@ -201,8 +210,24 @@ func (c *RESTClient) rawRequest(method, path string, requestBody io.Reader, targ
return body, err
}
func (c *RESTClient) makeURL(path string) string {
return c.host + c.Prefix + path
func (c *RESTClient) makeURL(path string) (string, error) {
base := c.host
hostURL, err := url.Parse(base)
if err != nil {
return "", err
}
if hostURL.Scheme == "" {
hostURL, err = url.Parse("http://" + base)
if err != nil {
return "", err
}
if hostURL.Path != "" && hostURL.Path != "/" {
return "", fmt.Errorf("host must be a URL or a host:port pair: %s", base)
}
}
hostURL.Path += c.Prefix + path
return hostURL.String(), nil
}
// ListPods takes a selector, and returns the list of pods that match that selector
@@ -309,6 +334,28 @@ func (c *Client) DeleteService(name string) error {
return c.Delete().Path("services").Path(name).Do().Error()
}
// WatchService returns a watch.Interface that watches the requested services.
func (c *Client) WatchServices(label, field labels.Selector, resourceVersion uint64) (watch.Interface, error) {
return c.Get().
Path("watch").
Path("services").
UintParam("resourceVersion", resourceVersion).
SelectorParam("labels", label).
SelectorParam("fields", field).
Watch()
}
// WatchEndpoints returns a watch.Interface that watches the requested endpoints for a service.
func (c *Client) WatchEndpoints(label, field labels.Selector, resourceVersion uint64) (watch.Interface, error) {
return c.Get().
Path("watch").
Path("endpoints").
UintParam("resourceVersion", resourceVersion).
SelectorParam("labels", label).
SelectorParam("fields", field).
Watch()
}
// ServerVersion retrieves and parses the server's version.
func (c *Client) ServerVersion() (*version.Info, error) {
body, err := c.Get().AbsPath("/version").Do().Raw()

View File

@@ -37,6 +37,33 @@ func makeURL(suffix string) string {
return apiPath + suffix
}
func TestValidatesHostParameter(t *testing.T) {
testCases := map[string]struct {
Value string
Err bool
}{
"foo.bar.com": {"http://foo.bar.com/api/v1beta1/", false},
"http://host/server": {"http://host/server/api/v1beta1/", false},
"host/server": {"", true},
}
for k, expected := range testCases {
c := RESTClient{host: k, Prefix: "/api/v1beta1/"}
actual, err := c.makeURL("")
switch {
case err == nil && expected.Err:
t.Errorf("expected error but was nil")
continue
case err != nil && !expected.Err:
t.Errorf("unexpected error %v", err)
continue
}
if expected.Value != actual {
t.Errorf("%s: expected %s, got %s", k, expected.Value, actual)
continue
}
}
}
func TestListEmptyPods(t *testing.T) {
c := &testClient{
Request: testRequest{Method: "GET", Path: "/pods"},

View File

@@ -35,6 +35,7 @@ type Fake struct {
Actions []FakeAction
Pods api.PodList
Ctrl api.ReplicationController
Watch watch.Interface
}
func (c *Fake) ListPods(selector labels.Selector) (api.PodList, error) {
@@ -88,8 +89,8 @@ func (c *Fake) DeleteReplicationController(controller string) error {
}
func (c *Fake) WatchReplicationControllers(label, field labels.Selector, resourceVersion uint64) (watch.Interface, error) {
c.Actions = append(c.Actions, FakeAction{Action: "watch-controllers"})
return watch.NewFake(), nil
c.Actions = append(c.Actions, FakeAction{Action: "watch-controllers", Value: resourceVersion})
return c.Watch, nil
}
func (c *Fake) GetService(name string) (api.Service, error) {
@@ -112,6 +113,16 @@ func (c *Fake) DeleteService(service string) error {
return nil
}
func (c *Fake) WatchServices(label, field labels.Selector, resourceVersion uint64) (watch.Interface, error) {
c.Actions = append(c.Actions, FakeAction{Action: "watch-services", Value: resourceVersion})
return c.Watch, nil
}
func (c *Fake) WatchEndpoints(label, field labels.Selector, resourceVersion uint64) (watch.Interface, error) {
c.Actions = append(c.Actions, FakeAction{Action: "watch-endpoints", Value: resourceVersion})
return c.Watch, nil
}
func (c *Fake) ServerVersion() (*version.Info, error) {
c.Actions = append(c.Actions, FakeAction{Action: "get-version", Value: nil})
versionInfo := version.Get()