Allow server and client to take api version as argument

* Defaults to v1beta1
* apiserver takes -storage_version which controls etcd storage version
  and the version of the client used to connect to other apiservers
* Changed signature of client.New to add version parameter
* All controller code and component code prefers the oldest (most common)
  server version
This commit is contained in:
Clayton Coleman
2014-09-11 19:01:29 -04:00
parent ca5355908f
commit 5483333e29
22 changed files with 309 additions and 164 deletions

View File

@@ -16,5 +16,6 @@ limitations under the License.
// Package latest defines the default output serializations that code should
// use and imports the required schemas. It also ensures all previously known
// and supported API versions are available for conversion.
// and supported API versions are available for conversion. Consumers may
// import this package in lieu of importing individual versions.
package latest

View File

@@ -17,13 +17,26 @@ limitations under the License.
package latest
import (
"fmt"
"strings"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)
// Version is the string that represents the current external default version
var Version = "v1beta1"
// Version is the string that represents the current external default version.
const Version = "v1beta1"
// OldestVersion is the string that represents the oldest server version supported,
// for client code that wants to hardcode the lowest common denominator.
const OldestVersion = "v1beta1"
// Versions is the list of versions that are recognized in code. The order provided
// may be assumed to be least feature rich to most feature rich, and clients may
// choose to prefer the latter items in the list over the former items when presented
// with a set of versions to choose.
var Versions = []string{"v1beta1", "v1beta2"}
// Codec is the default codec for serializing output that should use
// the latest supported version. Use this Codec when writing to
@@ -35,3 +48,17 @@ var Codec = v1beta1.Codec
// of versioning.
// TODO: when versioning changes, make this part of each API definition.
var ResourceVersioner = runtime.NewJSONBaseResourceVersioner()
// InterfacesFor returns the default Codec and ResourceVersioner for a given version
// string, or an error if the version is not known.
func InterfacesFor(version string) (codec runtime.Codec, versioner runtime.ResourceVersioner, err error) {
switch version {
case "v1beta1":
codec, versioner = v1beta1.Codec, ResourceVersioner
case "v1beta2":
codec, versioner = v1beta2.Codec, ResourceVersioner
default:
err = fmt.Errorf("unsupported storage version: %s (valid: %s)", version, strings.Join(Versions, ", "))
}
return
}

View File

@@ -144,3 +144,14 @@ func TestCodec(t *testing.T) {
t.Errorf("unexpected unmarshalled object %#v", other)
}
}
func TestInterfacesFor(t *testing.T) {
if _, _, err := InterfacesFor(""); err == nil {
t.Fatalf("unexpected non-error: %v", err)
}
for i, version := range append([]string{Version, OldestVersion}, Versions...) {
if codec, versioner, err := InterfacesFor(version); err != nil || codec == nil || versioner == nil {
t.Fatalf("%d: unexpected result: %v", i, err)
}
}
}

View File

@@ -23,6 +23,7 @@ import (
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
@@ -96,19 +97,30 @@ type Client struct {
// New creates a Kubernetes client. This client works with pods, replication controllers
// and services. It allows operations such as list, get, update and delete on these objects.
// host must be a host string, a host:port combo, or an http or https URL. Passing a prefix
// to a URL will prepend the server path. Returns an error if host cannot be converted to a
// valid URL.
func New(host string, auth *AuthInfo) (*Client, error) {
restClient, err := NewRESTClient(host, auth, "/api/v1beta1/", latest.Codec)
// to a URL will prepend the server path. The API version to use may be specified or left
// empty to use the client preferred version. Returns an error if host cannot be converted to
// a valid URL.
func New(host, version string, auth *AuthInfo) (*Client, error) {
if version == "" {
// Clients default to the preferred code API version
// TODO: implement version negotation (highest version supported by server)
version = latest.Version
}
serverCodec, _, err := latest.InterfacesFor(version)
if err != nil {
return nil, err
return nil, fmt.Errorf("API version '%s' is not recognized (valid values: %s)", version, strings.Join(latest.Versions, ", "))
}
prefix := fmt.Sprintf("/api/%s/", version)
restClient, err := NewRESTClient(host, auth, prefix, serverCodec)
if err != nil {
return nil, fmt.Errorf("API URL '%s' is not valid: %v", host, err)
}
return &Client{restClient}, nil
}
// NewOrDie creates a Kubernetes client and panics if the provided host is invalid.
func NewOrDie(host string, auth *AuthInfo) *Client {
client, err := New(host, auth)
func NewOrDie(host, version string, auth *AuthInfo) *Client {
client, err := New(host, version, auth)
if err != nil {
panic(err)
}

View File

@@ -27,6 +27,8 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
@@ -36,6 +38,38 @@ import (
// TODO: Move this to a common place, it's needed in multiple tests.
const apiPath = "/api/v1beta1"
func TestChecksCodec(t *testing.T) {
testCases := map[string]struct {
Err bool
Prefix string
Codec runtime.Codec
}{
"v1beta1": {false, "/api/v1beta1/", v1beta1.Codec},
"": {false, "/api/v1beta1/", v1beta1.Codec},
"v1beta2": {false, "/api/v1beta2/", v1beta2.Codec},
"v1beta3": {true, "", nil},
}
for version, expected := range testCases {
client, err := New("127.0.0.1", version, nil)
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
case err != nil:
continue
}
if e, a := expected.Prefix, client.prefix; e != a {
t.Errorf("expected %#v, got %#v", e, a)
}
if e, a := expected.Codec, client.Codec; e != a {
t.Errorf("expected %#v, got %#v", e, a)
}
}
}
func TestValidatesHostParameter(t *testing.T) {
testCases := map[string]struct {
Host string
@@ -49,7 +83,7 @@ func TestValidatesHostParameter(t *testing.T) {
"host/server": {"", "", true},
}
for k, expected := range testCases {
c, err := NewRESTClient(k, nil, "/api/v1beta1/", latest.Codec)
c, err := NewRESTClient(k, nil, "/api/v1beta1/", v1beta1.Codec)
switch {
case err == nil && expected.Err:
t.Errorf("expected error but was nil")
@@ -355,7 +389,7 @@ func (c *testClient) Setup() *testClient {
}
c.server = httptest.NewServer(c.handler)
if c.Client == nil {
c.Client = NewOrDie("localhost", nil)
c.Client = NewOrDie("localhost", "v1beta1", nil)
}
c.Client.host = c.server.URL
c.Client.prefix = "/api/v1beta1/"
@@ -512,7 +546,7 @@ func TestDoRequest(t *testing.T) {
testClients := []testClient{
{Request: testRequest{Method: "GET", Path: "good"}, Response: Response{StatusCode: 200}},
{Request: testRequest{Method: "GET", Path: "bad%ZZ"}, Error: true},
{Client: NewOrDie("localhost", &AuthInfo{"foo", "bar"}), Request: testRequest{Method: "GET", Path: "auth", Header: "Authorization"}, Response: Response{StatusCode: 200}},
{Client: NewOrDie("localhost", "v1beta1", &AuthInfo{"foo", "bar"}), Request: testRequest{Method: "GET", Path: "auth", Header: "Authorization"}, Response: Response{StatusCode: 200}},
{Client: &Client{&RESTClient{httpClient: http.DefaultClient}}, Request: testRequest{Method: "GET", Path: "nocertificate"}, Error: true},
{Request: testRequest{Method: "GET", Path: "error"}, Response: Response{StatusCode: 500}, Error: true},
{Request: testRequest{Method: "POST", Path: "faildecode"}, Response: Response{StatusCode: 200, RawBody: &invalid}},
@@ -543,7 +577,7 @@ func TestDoRequestAccepted(t *testing.T) {
testServer := httptest.NewServer(&fakeHandler)
request, _ := http.NewRequest("GET", testServer.URL+"/foo/bar", nil)
auth := AuthInfo{User: "user", Password: "pass"}
c, err := New(testServer.URL, &auth)
c, err := New(testServer.URL, "", &auth)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
@@ -580,7 +614,7 @@ func TestDoRequestAcceptedSuccess(t *testing.T) {
testServer := httptest.NewServer(&fakeHandler)
request, _ := http.NewRequest("GET", testServer.URL+"/foo/bar", nil)
auth := AuthInfo{User: "user", Password: "pass"}
c, err := New(testServer.URL, &auth)
c, err := New(testServer.URL, "", &auth)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
@@ -617,7 +651,7 @@ func TestGetServerVersion(t *testing.T) {
w.WriteHeader(http.StatusOK)
w.Write(output)
}))
client := NewOrDie(server.URL, nil)
client := NewOrDie(server.URL, "", nil)
got, err := client.ServerVersion()
if err != nil {

View File

@@ -29,7 +29,8 @@ import (
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
@@ -39,7 +40,7 @@ import (
func TestDoRequestNewWay(t *testing.T) {
reqBody := "request body"
expectedObj := &api.Service{Port: 12345}
expectedBody, _ := latest.Codec.Encode(expectedObj)
expectedBody, _ := v1beta2.Codec.Encode(expectedObj)
fakeHandler := util.FakeHandler{
StatusCode: 200,
ResponseBody: string(expectedBody),
@@ -47,7 +48,7 @@ func TestDoRequestNewWay(t *testing.T) {
}
testServer := httptest.NewServer(&fakeHandler)
auth := AuthInfo{User: "user", Password: "pass"}
c := NewOrDie(testServer.URL, &auth)
c := NewOrDie(testServer.URL, "v1beta2", &auth)
obj, err := c.Verb("POST").
Path("foo/bar").
Path("baz").
@@ -64,7 +65,7 @@ func TestDoRequestNewWay(t *testing.T) {
} else if !reflect.DeepEqual(obj, expectedObj) {
t.Errorf("Expected: %#v, got %#v", expectedObj, obj)
}
fakeHandler.ValidateRequest(t, "/api/v1beta1/foo/bar/baz?labels=name%3Dfoo", "POST", &reqBody)
fakeHandler.ValidateRequest(t, "/api/v1beta2/foo/bar/baz?labels=name%3Dfoo", "POST", &reqBody)
if fakeHandler.RequestReceived.Header["Authorization"] == nil {
t.Errorf("Request is missing authorization header: %#v", *fakeHandler.RequestReceived)
}
@@ -72,9 +73,9 @@ func TestDoRequestNewWay(t *testing.T) {
func TestDoRequestNewWayReader(t *testing.T) {
reqObj := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
reqBodyExpected, _ := latest.Codec.Encode(reqObj)
reqBodyExpected, _ := v1beta1.Codec.Encode(reqObj)
expectedObj := &api.Service{Port: 12345}
expectedBody, _ := latest.Codec.Encode(expectedObj)
expectedBody, _ := v1beta1.Codec.Encode(expectedObj)
fakeHandler := util.FakeHandler{
StatusCode: 200,
ResponseBody: string(expectedBody),
@@ -82,7 +83,7 @@ func TestDoRequestNewWayReader(t *testing.T) {
}
testServer := httptest.NewServer(&fakeHandler)
auth := AuthInfo{User: "user", Password: "pass"}
c := NewOrDie(testServer.URL, &auth)
c := NewOrDie(testServer.URL, "v1beta1", &auth)
obj, err := c.Verb("POST").
Path("foo/bar").
Path("baz").
@@ -109,9 +110,9 @@ func TestDoRequestNewWayReader(t *testing.T) {
func TestDoRequestNewWayObj(t *testing.T) {
reqObj := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
reqBodyExpected, _ := latest.Codec.Encode(reqObj)
reqBodyExpected, _ := v1beta2.Codec.Encode(reqObj)
expectedObj := &api.Service{Port: 12345}
expectedBody, _ := latest.Codec.Encode(expectedObj)
expectedBody, _ := v1beta2.Codec.Encode(expectedObj)
fakeHandler := util.FakeHandler{
StatusCode: 200,
ResponseBody: string(expectedBody),
@@ -119,7 +120,7 @@ func TestDoRequestNewWayObj(t *testing.T) {
}
testServer := httptest.NewServer(&fakeHandler)
auth := AuthInfo{User: "user", Password: "pass"}
c := NewOrDie(testServer.URL, &auth)
c := NewOrDie(testServer.URL, "v1beta2", &auth)
obj, err := c.Verb("POST").
Path("foo/bar").
Path("baz").
@@ -137,7 +138,7 @@ func TestDoRequestNewWayObj(t *testing.T) {
t.Errorf("Expected: %#v, got %#v", expectedObj, obj)
}
tmpStr := string(reqBodyExpected)
fakeHandler.ValidateRequest(t, "/api/v1beta1/foo/bar/baz?labels=name%3Dfoo", "POST", &tmpStr)
fakeHandler.ValidateRequest(t, "/api/v1beta2/foo/bar/baz?labels=name%3Dfoo", "POST", &tmpStr)
if fakeHandler.RequestReceived.Header["Authorization"] == nil {
t.Errorf("Request is missing authorization header: %#v", *fakeHandler.RequestReceived)
}
@@ -145,7 +146,7 @@ func TestDoRequestNewWayObj(t *testing.T) {
func TestDoRequestNewWayFile(t *testing.T) {
reqObj := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
reqBodyExpected, err := latest.Codec.Encode(reqObj)
reqBodyExpected, err := v1beta1.Codec.Encode(reqObj)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
@@ -161,7 +162,7 @@ func TestDoRequestNewWayFile(t *testing.T) {
}
expectedObj := &api.Service{Port: 12345}
expectedBody, _ := latest.Codec.Encode(expectedObj)
expectedBody, _ := v1beta1.Codec.Encode(expectedObj)
fakeHandler := util.FakeHandler{
StatusCode: 200,
ResponseBody: string(expectedBody),
@@ -169,7 +170,7 @@ func TestDoRequestNewWayFile(t *testing.T) {
}
testServer := httptest.NewServer(&fakeHandler)
auth := AuthInfo{User: "user", Password: "pass"}
c := NewOrDie(testServer.URL, &auth)
c := NewOrDie(testServer.URL, "v1beta1", &auth)
obj, err := c.Verb("POST").
Path("foo/bar").
Path("baz").
@@ -194,7 +195,7 @@ func TestDoRequestNewWayFile(t *testing.T) {
}
func TestVerbs(t *testing.T) {
c := NewOrDie("localhost", nil)
c := NewOrDie("localhost", "", nil)
if r := c.Post(); r.verb != "POST" {
t.Errorf("Post verb is wrong")
}
@@ -211,7 +212,7 @@ func TestVerbs(t *testing.T) {
func TestAbsPath(t *testing.T) {
expectedPath := "/bar/foo"
c := NewOrDie("localhost", nil)
c := NewOrDie("localhost", "", nil)
r := c.Post().Path("/foo").AbsPath(expectedPath)
if r.path != expectedPath {
t.Errorf("unexpected path: %s, expected %s", r.path, expectedPath)
@@ -219,7 +220,7 @@ func TestAbsPath(t *testing.T) {
}
func TestSync(t *testing.T) {
c := NewOrDie("localhost", nil)
c := NewOrDie("localhost", "", nil)
r := c.Get()
if r.sync {
t.Errorf("sync has wrong default")
@@ -246,7 +247,7 @@ func TestUintParam(t *testing.T) {
}
for _, item := range table {
c := NewOrDie("localhost", nil)
c := NewOrDie("localhost", "", nil)
r := c.Get().AbsPath("").UintParam(item.name, item.testVal)
if e, a := item.expectStr, r.finalURL(); e != a {
t.Errorf("expected %v, got %v", e, a)
@@ -265,7 +266,7 @@ func TestUnacceptableParamNames(t *testing.T) {
}
for _, item := range table {
c := NewOrDie("localhost", nil)
c := NewOrDie("localhost", "", nil)
r := c.Get().setParam(item.name, item.testVal)
if e, a := item.expectSuccess, r.err == nil; e != a {
t.Errorf("expected %v, got %v (%v)", e, a, r.err)
@@ -274,7 +275,7 @@ func TestUnacceptableParamNames(t *testing.T) {
}
func TestSetPollPeriod(t *testing.T) {
c := NewOrDie("localhost", nil)
c := NewOrDie("localhost", "", nil)
r := c.Get()
if r.pollPeriod == 0 {
t.Errorf("polling should be on by default")
@@ -296,7 +297,7 @@ func TestPolling(t *testing.T) {
callNumber := 0
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
data, err := latest.Codec.Encode(objects[callNumber])
data, err := v1beta1.Codec.Encode(objects[callNumber])
if err != nil {
t.Errorf("Unexpected encode error")
}
@@ -305,7 +306,7 @@ func TestPolling(t *testing.T) {
}))
auth := AuthInfo{User: "user", Password: "pass"}
c := NewOrDie(testServer.URL, &auth)
c := NewOrDie(testServer.URL, "v1beta1", &auth)
trials := []func(){
func() {
@@ -402,7 +403,7 @@ func TestWatch(t *testing.T) {
encoder := json.NewEncoder(w)
for _, item := range table {
data, err := api.NewJSONWatchEvent(latest.Codec, watch.Event{item.t, item.obj})
data, err := api.NewJSONWatchEvent(v1beta1.Codec, watch.Event{item.t, item.obj})
if err != nil {
panic(err)
}
@@ -413,7 +414,7 @@ func TestWatch(t *testing.T) {
}
}))
s, err := New(testServer.URL, &auth)
s, err := New(testServer.URL, "v1beta1", &auth)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

View File

@@ -117,7 +117,7 @@ func TestSyncReplicationControllerDoesNothing(t *testing.T) {
ResponseBody: string(body),
}
testServer := httptest.NewTLSServer(&fakeHandler)
client := client.NewOrDie(testServer.URL, nil)
client := client.NewOrDie(testServer.URL, "v1beta1", nil)
fakePodControl := FakePodControl{}
@@ -137,7 +137,7 @@ func TestSyncReplicationControllerDeletes(t *testing.T) {
ResponseBody: string(body),
}
testServer := httptest.NewTLSServer(&fakeHandler)
client := client.NewOrDie(testServer.URL, nil)
client := client.NewOrDie(testServer.URL, "v1beta1", nil)
fakePodControl := FakePodControl{}
@@ -157,7 +157,7 @@ func TestSyncReplicationControllerCreates(t *testing.T) {
ResponseBody: string(body),
}
testServer := httptest.NewTLSServer(&fakeHandler)
client := client.NewOrDie(testServer.URL, nil)
client := client.NewOrDie(testServer.URL, "v1beta1", nil)
fakePodControl := FakePodControl{}
@@ -177,7 +177,7 @@ func TestCreateReplica(t *testing.T) {
ResponseBody: string(body),
}
testServer := httptest.NewTLSServer(&fakeHandler)
client := client.NewOrDie(testServer.URL, nil)
client := client.NewOrDie(testServer.URL, "v1beta1", nil)
podControl := RealPodControl{
kubeClient: client,
@@ -227,7 +227,7 @@ func TestCreateReplica(t *testing.T) {
}
}
func TestSyncronize(t *testing.T) {
func TestSynchonize(t *testing.T) {
controllerSpec1 := api.ReplicationController{
JSONBase: api.JSONBase{APIVersion: "v1beta1"},
DesiredState: api.ReplicationControllerState{
@@ -310,7 +310,7 @@ func TestSyncronize(t *testing.T) {
t.Errorf("Unexpected request for %v", req.RequestURI)
})
testServer := httptest.NewServer(mux)
client := client.NewOrDie(testServer.URL, nil)
client := client.NewOrDie(testServer.URL, "v1beta1", nil)
manager := NewReplicationManager(client)
fakePodControl := FakePodControl{}
manager.podControl = &fakePodControl

View File

@@ -38,18 +38,18 @@ func NewParser(objectMap map[string]runtime.Object) *Parser {
// ToWireFormat takes input 'data' as either json or yaml, checks that it parses as the
// appropriate object type, and returns json for sending to the API or an error.
func (p *Parser) ToWireFormat(data []byte, storage string, c runtime.Codec) ([]byte, error) {
func (p *Parser) ToWireFormat(data []byte, storage string, decode runtime.Codec, encode runtime.Codec) ([]byte, error) {
prototypeType, found := p.storageToType[storage]
if !found {
return nil, fmt.Errorf("unknown storage type: %v", storage)
}
obj := reflect.New(prototypeType).Interface().(runtime.Object)
err := c.DecodeInto(data, obj)
err := decode.DecodeInto(data, obj)
if err != nil {
return nil, err
}
return c.Encode(obj)
return encode.Encode(obj)
}
func (p *Parser) SupportedWireStorage() []string {

View File

@@ -22,28 +22,28 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"gopkg.in/v1/yaml"
)
func TestParseBadStorage(t *testing.T) {
p := NewParser(map[string]runtime.Object{})
_, err := p.ToWireFormat([]byte("{}"), "badstorage", latest.Codec)
_, err := p.ToWireFormat([]byte("{}"), "badstorage", latest.Codec, latest.Codec)
if err == nil {
t.Errorf("Expected error, received none")
}
}
func DoParseTest(t *testing.T, storage string, obj runtime.Object, p *Parser) {
jsonData, _ := latest.Codec.Encode(obj)
func DoParseTest(t *testing.T, storage string, obj runtime.Object, codec runtime.Codec, p *Parser) {
jsonData, _ := codec.Encode(obj)
var tmp map[string]interface{}
json.Unmarshal(jsonData, &tmp)
yamlData, _ := yaml.Marshal(tmp)
t.Logf("Intermediate yaml:\n%v\n", string(yamlData))
t.Logf("Intermediate json:\n%v\n", string(jsonData))
jsonGot, jsonErr := p.ToWireFormat(jsonData, storage, latest.Codec)
yamlGot, yamlErr := p.ToWireFormat(yamlData, storage, latest.Codec)
jsonGot, jsonErr := p.ToWireFormat(jsonData, storage, latest.Codec, codec)
yamlGot, yamlErr := p.ToWireFormat(yamlData, storage, latest.Codec, codec)
if jsonErr != nil {
t.Errorf("json err: %#v", jsonErr)
@@ -81,7 +81,7 @@ func TestParsePod(t *testing.T) {
},
},
},
}, testParser)
}, v1beta1.Codec, testParser)
}
func TestParseService(t *testing.T) {
@@ -94,7 +94,7 @@ func TestParseService(t *testing.T) {
Selector: map[string]string{
"area": "staging",
},
}, testParser)
}, v1beta1.Codec, testParser)
}
func TestParseController(t *testing.T) {
@@ -116,7 +116,7 @@ func TestParseController(t *testing.T) {
},
},
},
}, testParser)
}, v1beta1.Codec, testParser)
}
type TestParseType struct {
@@ -136,5 +136,5 @@ func TestParseCustomType(t *testing.T) {
DoParseTest(t, "custom", &TestParseType{
JSONBase: api.JSONBase{APIVersion: "", ID: "my custom object", Kind: "TestParseType"},
Data: "test data",
}, parser)
}, v1beta1.Codec, parser)
}

View File

@@ -20,6 +20,7 @@ import (
"net/http"
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
@@ -34,6 +35,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/service"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
servicecontroller "github.com/GoogleCloudPlatform/kubernetes/pkg/service"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
goetcd "github.com/coreos/go-etcd/etcd"
@@ -44,7 +46,7 @@ import (
type Config struct {
Client *client.Client
Cloud cloudprovider.Interface
EtcdServers []string
EtcdHelper tools.EtcdHelper
HealthCheckMinions bool
Minions []string
MinionCacheTTL time.Duration
@@ -64,16 +66,29 @@ type Master struct {
client *client.Client
}
// New returns a new instance of Master connected to the given etcdServer.
// NewEtcdHelper returns an EtcdHelper for the provided arguments or an error if the version
// is incorrect.
func NewEtcdHelper(etcdServers []string, version string) (helper tools.EtcdHelper, err error) {
client := goetcd.NewClient(etcdServers)
if version == "" {
version = latest.Version
}
codec, versioner, err := latest.InterfacesFor(version)
if err != nil {
return helper, err
}
return tools.EtcdHelper{client, codec, versioner}, nil
}
// New returns a new instance of Master connected to the given etcd server.
func New(c *Config) *Master {
etcdClient := goetcd.NewClient(c.EtcdServers)
minionRegistry := makeMinionRegistry(c)
m := &Master{
podRegistry: etcd.NewRegistry(etcdClient),
controllerRegistry: etcd.NewRegistry(etcdClient),
serviceRegistry: etcd.NewRegistry(etcdClient),
endpointRegistry: etcd.NewRegistry(etcdClient),
bindingRegistry: etcd.NewRegistry(etcdClient),
podRegistry: etcd.NewRegistry(c.EtcdHelper),
controllerRegistry: etcd.NewRegistry(c.EtcdHelper),
serviceRegistry: etcd.NewRegistry(c.EtcdHelper),
endpointRegistry: etcd.NewRegistry(c.EtcdHelper),
bindingRegistry: etcd.NewRegistry(c.EtcdHelper),
minionRegistry: minionRegistry,
client: c.Client,
}

View File

@@ -21,7 +21,6 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
etcderr "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/constraint"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@@ -42,13 +41,9 @@ type Registry struct {
}
// NewRegistry creates an etcd registry.
func NewRegistry(client tools.EtcdClient) *Registry {
func NewRegistry(helper tools.EtcdHelper) *Registry {
registry := &Registry{
EtcdHelper: tools.EtcdHelper{
client,
latest.Codec,
latest.ResourceVersioner,
},
EtcdHelper: helper,
}
registry.manifestFactory = &BasicManifestFactory{
serviceRegistry: registry,

View File

@@ -32,7 +32,7 @@ import (
)
func NewTestEtcdRegistry(client tools.EtcdClient) *Registry {
registry := NewRegistry(client)
registry := NewRegistry(tools.EtcdHelper{client, latest.Codec, latest.ResourceVersioner})
registry.manifestFactory = &BasicManifestFactory{
serviceRegistry: &registrytest.ServiceRegistry{},
}

View File

@@ -150,7 +150,7 @@ func TestSyncEndpointsEmpty(t *testing.T) {
testServer := makeTestServer(t,
serverResponse{http.StatusOK, newPodList(0)},
serverResponse{http.StatusOK, api.ServiceList{}})
client := client.NewOrDie(testServer.URL, nil)
client := client.NewOrDie(testServer.URL, "v1beta1", nil)
serviceRegistry := registrytest.ServiceRegistry{}
endpoints := NewEndpointController(&serviceRegistry, client)
if err := endpoints.SyncServiceEndpoints(); err != nil {
@@ -162,7 +162,7 @@ func TestSyncEndpointsError(t *testing.T) {
testServer := makeTestServer(t,
serverResponse{http.StatusOK, newPodList(0)},
serverResponse{http.StatusInternalServerError, api.ServiceList{}})
client := client.NewOrDie(testServer.URL, nil)
client := client.NewOrDie(testServer.URL, "v1beta1", nil)
serviceRegistry := registrytest.ServiceRegistry{
Err: fmt.Errorf("test error"),
}
@@ -185,7 +185,7 @@ func TestSyncEndpointsItems(t *testing.T) {
testServer := makeTestServer(t,
serverResponse{http.StatusOK, newPodList(1)},
serverResponse{http.StatusOK, serviceList})
client := client.NewOrDie(testServer.URL, nil)
client := client.NewOrDie(testServer.URL, "v1beta1", nil)
serviceRegistry := registrytest.ServiceRegistry{}
endpoints := NewEndpointController(&serviceRegistry, client)
if err := endpoints.SyncServiceEndpoints(); err != nil {
@@ -210,7 +210,7 @@ func TestSyncEndpointsPodError(t *testing.T) {
testServer := makeTestServer(t,
serverResponse{http.StatusInternalServerError, api.PodList{}},
serverResponse{http.StatusOK, serviceList})
client := client.NewOrDie(testServer.URL, nil)
client := client.NewOrDie(testServer.URL, "v1beta1", nil)
serviceRegistry := registrytest.ServiceRegistry{
List: api.ServiceList{
Items: []api.Service{