test: improved master coverage.

pull/6/head
Steve Milner 2015-09-03 13:35:04 -04:00
parent 90ba96d486
commit 66dff577f4
2 changed files with 402 additions and 87 deletions

View File

@ -1024,6 +1024,7 @@ func (m *Master) setupSecureProxy(user, privateKeyfile, publicKeyfile string) {
} }
func (m *Master) generateSSHKey(user, privateKeyfile, publicKeyfile string) error { func (m *Master) generateSSHKey(user, privateKeyfile, publicKeyfile string) error {
// TODO: user is not used. Consider removing it as an input to the function.
private, public, err := util.GenerateKey(2048) private, public, err := util.GenerateKey(2048)
if err != nil { if err != nil {
return err return err

View File

@ -19,25 +19,41 @@ package master
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"errors"
"fmt"
"io/ioutil" "io/ioutil"
"net"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os"
"path/filepath"
"reflect" "reflect"
"testing" "testing"
"time"
"github.com/emicklei/go-restful"
"github.com/stretchr/testify/assert"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/latest"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/apiserver"
client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/expapi" "k8s.io/kubernetes/pkg/expapi"
explatest "k8s.io/kubernetes/pkg/expapi/latest" explatest "k8s.io/kubernetes/pkg/expapi/latest"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/endpoint"
"k8s.io/kubernetes/pkg/registry/namespace"
"k8s.io/kubernetes/pkg/registry/registrytest" "k8s.io/kubernetes/pkg/registry/registrytest"
etcdstorage "k8s.io/kubernetes/pkg/storage/etcd" etcdstorage "k8s.io/kubernetes/pkg/storage/etcd"
"k8s.io/kubernetes/pkg/tools" "k8s.io/kubernetes/pkg/tools"
"k8s.io/kubernetes/pkg/tools/etcdtest" "k8s.io/kubernetes/pkg/tools/etcdtest"
"k8s.io/kubernetes/pkg/util"
"github.com/emicklei/go-restful"
) )
func TestGetServersToValidate(t *testing.T) { // setUp is a convience function for setting up for (most) tests.
func setUp(t *testing.T) (Master, Config, *assert.Assertions) {
master := Master{} master := Master{}
config := Config{} config := Config{}
fakeClient := tools.NewFakeEtcdClient(t) fakeClient := tools.NewFakeEtcdClient(t)
@ -47,11 +63,64 @@ func TestGetServersToValidate(t *testing.T) {
master.nodeRegistry = registrytest.NewNodeRegistry([]string{"node1", "node2"}, api.NodeResources{}) master.nodeRegistry = registrytest.NewNodeRegistry([]string{"node1", "node2"}, api.NodeResources{})
return master, config, assert.New(t)
}
// TestNew verifies that the New function returns a Master
// using the configuration properly.
func TestNew(t *testing.T) {
_, config, assert := setUp(t)
config.KubeletClient = client.FakeKubeletClient{}
master := New(&config)
// Verify many of the variables match their config counterparts
assert.Equal(master.enableCoreControllers, config.EnableCoreControllers)
assert.Equal(master.enableLogsSupport, config.EnableLogsSupport)
assert.Equal(master.enableUISupport, config.EnableUISupport)
assert.Equal(master.enableSwaggerSupport, config.EnableSwaggerSupport)
assert.Equal(master.enableSwaggerSupport, config.EnableSwaggerSupport)
assert.Equal(master.enableProfiling, config.EnableProfiling)
assert.Equal(master.apiPrefix, config.APIPrefix)
assert.Equal(master.expAPIPrefix, config.ExpAPIPrefix)
assert.Equal(master.corsAllowedOriginList, config.CorsAllowedOriginList)
assert.Equal(master.authenticator, config.Authenticator)
assert.Equal(master.authorizer, config.Authorizer)
assert.Equal(master.admissionControl, config.AdmissionControl)
assert.Equal(master.v1, !config.DisableV1)
assert.Equal(master.exp, config.EnableExp)
assert.Equal(master.requestContextMapper, config.RequestContextMapper)
assert.Equal(master.cacheTimeout, config.CacheTimeout)
assert.Equal(master.masterCount, config.MasterCount)
assert.Equal(master.externalHost, config.ExternalHost)
assert.Equal(master.clusterIP, config.PublicAddress)
assert.Equal(master.publicReadWritePort, config.ReadWritePort)
assert.Equal(master.serviceReadWriteIP, config.ServiceReadWriteIP)
assert.Equal(master.installSSHKey, config.InstallSSHKey)
}
// TestNewEtcdStorage verifies that the usage of NewEtcdStorage reacts properly when
// the correct data is input
func TestNewEtcdStorage(t *testing.T) {
assert := assert.New(t)
fakeClient := tools.NewFakeEtcdClient(t)
// Pass case
_, err := NewEtcdStorage(fakeClient, latest.InterfacesFor, latest.Version, etcdtest.PathPrefix())
assert.NoError(err, "Unable to create etcdstorage: %s", err)
// Fail case
errorFunc := func(apiVersion string) (*meta.VersionInterfaces, error) { return nil, errors.New("ERROR") }
_, err = NewEtcdStorage(fakeClient, errorFunc, latest.Version, etcdtest.PathPrefix())
assert.Error(err, "NewEtcdStorage should have failed")
}
// TestGetServersToValidate verifies the unexported getServersToValidate function
func TestGetServersToValidate(t *testing.T) {
master, config, assert := setUp(t)
servers := master.getServersToValidate(&config) servers := master.getServersToValidate(&config)
if len(servers) != 5 { assert.Equal(5, len(servers), "unexpected server list: %#v", servers)
t.Errorf("unexpected server list: %#v", servers)
}
for _, server := range []string{"scheduler", "controller-manager", "etcd-0", "etcd-1", "etcd-2"} { for _, server := range []string{"scheduler", "controller-manager", "etcd-0", "etcd-1", "etcd-2"} {
if _, ok := servers[server]; !ok { if _, ok := servers[server]; !ok {
t.Errorf("server list missing: %s", server) t.Errorf("server list missing: %s", server)
@ -59,7 +128,10 @@ func TestGetServersToValidate(t *testing.T) {
} }
} }
// TestFindExternalAddress verifies both pass and fail cases for the unexported
// findExternalAddress function
func TestFindExternalAddress(t *testing.T) { func TestFindExternalAddress(t *testing.T) {
assert := assert.New(t)
expectedIP := "172.0.0.1" expectedIP := "172.0.0.1"
nodes := []*api.Node{new(api.Node), new(api.Node), new(api.Node)} nodes := []*api.Node{new(api.Node), new(api.Node), new(api.Node)}
@ -67,20 +139,287 @@ func TestFindExternalAddress(t *testing.T) {
nodes[1].Status.Addresses = []api.NodeAddress{{"LegacyHostIP", expectedIP}} nodes[1].Status.Addresses = []api.NodeAddress{{"LegacyHostIP", expectedIP}}
nodes[2].Status.Addresses = []api.NodeAddress{{"ExternalIP", expectedIP}, {"LegacyHostIP", "172.0.0.2"}} nodes[2].Status.Addresses = []api.NodeAddress{{"ExternalIP", expectedIP}, {"LegacyHostIP", "172.0.0.2"}}
// Pass Case
for _, node := range nodes { for _, node := range nodes {
ip, err := findExternalAddress(node) ip, err := findExternalAddress(node)
if err != nil { assert.NoError(err, "error getting node external address")
t.Errorf("error getting node external address: %s", err) assert.Equal(expectedIP, ip, "expected ip to be %s, but was %s", expectedIP, ip)
} }
if ip != expectedIP {
t.Errorf("expected ip to be %s, but was %s", expectedIP, ip) // Fail case
_, err := findExternalAddress(new(api.Node))
assert.Error(err, "expected findExternalAddress to fail on a node with missing ip information")
}
// TestApi_v1 verifies that the unexported api_v1 function does indeed
// utilize the correct Version and Codec.
func TestApi_v1(t *testing.T) {
master, _, assert := setUp(t)
version := master.api_v1()
assert.Equal("v1", version.Version, "Version was not v1: %s", version.Version)
assert.Equal(v1.Codec, version.Codec, "version.Codec was not for v1: %s", version.Codec)
for k, v := range master.storage {
assert.Contains(version.Storage, v, "Value %s not found (key: %s)", k, v)
} }
} }
_, err := findExternalAddress(new(api.Node)) // TestNewBootstrapController verifies master fields are properly copied into controller
if err == nil { func TestNewBootstrapController(t *testing.T) {
t.Errorf("expected findExternalAddress to fail on a node with missing ip information") // Tests a subset of inputs to ensure they are set properly in the controller
master, _, assert := setUp(t)
portRange := util.PortRange{Base: 10, Size: 10}
master.namespaceRegistry = namespace.NewRegistry(nil)
master.serviceRegistry = registrytest.NewServiceRegistry()
master.endpointRegistry = endpoint.NewRegistry(nil)
master.serviceNodePortRange = portRange
master.masterCount = 1
master.serviceReadWritePort = 1000
master.publicReadWritePort = 1010
controller := master.NewBootstrapController()
assert.Equal(controller.NamespaceRegistry, master.namespaceRegistry)
assert.Equal(controller.EndpointRegistry, master.endpointRegistry)
assert.Equal(controller.ServiceRegistry, master.serviceRegistry)
assert.Equal(controller.ServiceNodePortRange, portRange)
assert.Equal(controller.MasterCount, master.masterCount)
assert.Equal(controller.ServicePort, master.serviceReadWritePort)
assert.Equal(controller.PublicServicePort, master.publicReadWritePort)
} }
// TestNewHandlerContainer verifies that NewHandlerContainer uses the
// mux provided
func TestNewHandlerContainer(t *testing.T) {
assert := assert.New(t)
mux := http.NewServeMux()
container := NewHandlerContainer(mux)
assert.Equal(mux, container.ServeMux, "ServerMux's do not match")
}
// TestHandleWithAuth verifies HandleWithAuth adds the path
// to the muxHelper.RegisteredPaths.
func TestHandleWithAuth(t *testing.T) {
master, _, assert := setUp(t)
mh := apiserver.MuxHelper{Mux: http.NewServeMux()}
master.muxHelper = &mh
handler := func(r http.ResponseWriter, w *http.Request) { w.Write(nil) }
master.HandleWithAuth("/test", http.HandlerFunc(handler))
assert.Contains(master.muxHelper.RegisteredPaths, "/test", "Path not found in muxHelper")
}
// TestHandleFuncWithAuth verifies HandleFuncWithAuth adds the path
// to the muxHelper.RegisteredPaths.
func TestHandleFuncWithAuth(t *testing.T) {
master, _, assert := setUp(t)
mh := apiserver.MuxHelper{Mux: http.NewServeMux()}
master.muxHelper = &mh
handler := func(r http.ResponseWriter, w *http.Request) { w.Write(nil) }
master.HandleFuncWithAuth("/test", handler)
assert.Contains(master.muxHelper.RegisteredPaths, "/test", "Path not found in muxHelper")
}
// TestInstallSwaggerAPI verifies that the swagger api is added
// at the proper endpoint.
func TestInstallSwaggerAPI(t *testing.T) {
master, _, assert := setUp(t)
mux := http.NewServeMux()
master.handlerContainer = NewHandlerContainer(mux)
// Ensure swagger isn't installed without the call
ws := master.handlerContainer.RegisteredWebServices()
if !assert.Equal(len(ws), 0) {
for x := range ws {
assert.NotEqual("/swaggerapi", ws[x].RootPath(), "SwaggerAPI was installed without a call to InstallSwaggerAPI()")
}
}
// Install swagger and test
master.InstallSwaggerAPI()
ws = master.handlerContainer.RegisteredWebServices()
if assert.NotEqual(0, len(ws), "SwaggerAPI not installed.") {
assert.Equal("/swaggerapi/", ws[0].RootPath(), "SwaggerAPI did not install to the proper path. %s != /swaggerapi", ws[0].RootPath())
}
// Empty externalHost verification
mux = http.NewServeMux()
master.handlerContainer = NewHandlerContainer(mux)
master.externalHost = ""
master.clusterIP = net.IPv4(10, 10, 10, 10)
master.publicReadWritePort = 1010
master.InstallSwaggerAPI()
if assert.NotEqual(0, len(ws), "SwaggerAPI not installed.") {
assert.Equal("/swaggerapi/", ws[0].RootPath(), "SwaggerAPI did not install to the proper path. %s != /swaggerapi", ws[0].RootPath())
}
}
// TestDefaultAPIGroupVersion verifies that the unexported defaultAPIGroupVersion
// creates the expected APIGroupVersion based off of master.
func TestDefaultAPIGroupVersion(t *testing.T) {
master, _, assert := setUp(t)
master.dialer = func(network, addr string) (net.Conn, error) { return nil, nil }
apiGroup := master.defaultAPIGroupVersion()
assert.Equal(apiGroup.Root, master.apiPrefix)
assert.Equal(apiGroup.Admit, master.admissionControl)
assert.Equal(apiGroup.Context, master.requestContextMapper)
assert.Equal(apiGroup.MinRequestTimeout, master.minRequestTimeout)
// These functions should be different instances of the same function
groupDialerFunc := fmt.Sprintf("%+v", apiGroup.ProxyDialerFn)
masterDialerFunc := fmt.Sprintf("%+v", master.dialer)
assert.Equal(groupDialerFunc, masterDialerFunc)
}
// TestExpapi verifies that the unexported exapi creates
// the an experimental api APIGroupVersion.
func TestExpapi(t *testing.T) {
master, config, assert := setUp(t)
expAPIGroup := master.expapi(&config)
assert.Equal(expAPIGroup.Root, master.expAPIPrefix)
assert.Equal(expAPIGroup.Mapper, explatest.RESTMapper)
assert.Equal(expAPIGroup.Codec, explatest.Codec)
assert.Equal(expAPIGroup.Linker, explatest.SelfLinker)
assert.Equal(expAPIGroup.Version, explatest.Version)
}
// TestSecondsSinceSync verifies that proper results are returned
// when checking the time between syncs
func TestSecondsSinceSync(t *testing.T) {
master, _, assert := setUp(t)
master.lastSync = time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix()
// Nano Second. No difference.
master.clock = &util.FakeClock{Time: time.Date(2015, time.January, 1, 1, 1, 1, 2, time.UTC)}
assert.Equal(int64(0), master.secondsSinceSync())
// Second
master.clock = &util.FakeClock{Time: time.Date(2015, time.January, 1, 1, 1, 2, 1, time.UTC)}
assert.Equal(int64(1), master.secondsSinceSync())
// Minute
master.clock = &util.FakeClock{Time: time.Date(2015, time.January, 1, 1, 2, 1, 1, time.UTC)}
assert.Equal(int64(60), master.secondsSinceSync())
// Hour
master.clock = &util.FakeClock{Time: time.Date(2015, time.January, 1, 2, 1, 1, 1, time.UTC)}
assert.Equal(int64(3600), master.secondsSinceSync())
// Day
master.clock = &util.FakeClock{Time: time.Date(2015, time.January, 2, 1, 1, 1, 1, time.UTC)}
assert.Equal(int64(86400), master.secondsSinceSync())
// Month
master.clock = &util.FakeClock{Time: time.Date(2015, time.February, 1, 1, 1, 1, 1, time.UTC)}
assert.Equal(int64(2678400), master.secondsSinceSync())
// Future Month. Should be -Month.
master.lastSync = time.Date(2015, time.February, 1, 1, 1, 1, 1, time.UTC).Unix()
master.clock = &util.FakeClock{Time: time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC)}
assert.Equal(int64(-2678400), master.secondsSinceSync())
}
// TestGetNodeAddresses verifies that proper results are returned
// when requesting node addresses.
func TestGetNodeAddresses(t *testing.T) {
master, _, assert := setUp(t)
// Fail case (no addresses associated with nodes)
nodes, _ := master.nodeRegistry.ListNodes(api.NewDefaultContext(), labels.Everything(), fields.Everything())
addrs, err := master.getNodeAddresses()
assert.Error(err, "getNodeAddresses should have caused an error as there are no addresses.")
assert.Equal([]string(nil), addrs)
// Pass case with External type IP
nodes, _ = master.nodeRegistry.ListNodes(api.NewDefaultContext(), labels.Everything(), fields.Everything())
for index := range nodes.Items {
nodes.Items[index].Status.Addresses = []api.NodeAddress{{Type: api.NodeExternalIP, Address: "127.0.0.1"}}
}
addrs, err = master.getNodeAddresses()
assert.NoError(err, "getNodeAddresses should not have returned an error.")
assert.Equal([]string{"127.0.0.1", "127.0.0.1"}, addrs)
// Pass case with LegacyHost type IP
nodes, _ = master.nodeRegistry.ListNodes(api.NewDefaultContext(), labels.Everything(), fields.Everything())
for index := range nodes.Items {
nodes.Items[index].Status.Addresses = []api.NodeAddress{{Type: api.NodeLegacyHostIP, Address: "127.0.0.2"}}
}
addrs, err = master.getNodeAddresses()
assert.NoError(err, "getNodeAddresses failback should not have returned an error.")
assert.Equal([]string{"127.0.0.2", "127.0.0.2"}, addrs)
}
// TestRefreshTunnels verifies that the function errors when no addresses
// are associated with nodes
func TestRefreshTunnels(t *testing.T) {
master, _, assert := setUp(t)
// Fail case (no addresses associated with nodes)
assert.Error(master.refreshTunnels("test", "/tmp/undefined"))
// TODO: pass case without needing actual connections?
}
// TestIsTunnelSyncHealthy verifies that the 600 second lag test
// is honored.
func TestIsTunnelSyncHealthy(t *testing.T) {
master, _, assert := setUp(t)
// Pass case: 540 second lag
master.lastSync = time.Date(2015, time.January, 1, 1, 1, 1, 1, time.UTC).Unix()
master.clock = &util.FakeClock{Time: time.Date(2015, time.January, 1, 1, 9, 1, 1, time.UTC)}
err := master.IsTunnelSyncHealthy(nil)
assert.NoError(err, "IsTunnelSyncHealthy() should not have returned an error.")
// Fail case: 720 second lag
master.clock = &util.FakeClock{Time: time.Date(2015, time.January, 1, 1, 12, 1, 1, time.UTC)}
err = master.IsTunnelSyncHealthy(nil)
assert.Error(err, "IsTunnelSyncHealthy() should have returned an error.")
}
// generateTempFile creates a temporary file path
func generateTempFilePath(prefix string) string {
tmpPath, _ := filepath.Abs(fmt.Sprintf("%s/%s-%d", os.TempDir(), prefix, time.Now().Unix()))
return tmpPath
}
// TestGenerateSSHKey verifies that SSH key generation does indeed
// generate keys even with keys already exist.
func TestGenerateSSHKey(t *testing.T) {
master, _, assert := setUp(t)
privateKey := generateTempFilePath("private")
publicKey := generateTempFilePath("public")
// Make sure we have no test keys laying around
os.Remove(privateKey)
os.Remove(publicKey)
// Pass case: Sunny day case
err := master.generateSSHKey("unused", privateKey, publicKey)
assert.NoError(err, "generateSSHKey should not have retuend an error: %s", err)
// Pass case: PrivateKey exists test case
os.Remove(publicKey)
err = master.generateSSHKey("unused", privateKey, publicKey)
assert.NoError(err, "generateSSHKey should not have retuend an error: %s", err)
// Pass case: PublicKey exists test case
os.Remove(privateKey)
err = master.generateSSHKey("unused", privateKey, publicKey)
assert.NoError(err, "generateSSHKey should not have retuend an error: %s", err)
// Make sure we have no test keys laying around
os.Remove(privateKey)
os.Remove(publicKey)
// TODO: testing error cases where the file can not be removed?
} }
var versionsToTest = []string{"v1", "v3"} var versionsToTest = []string{"v1", "v3"}
@ -100,8 +439,9 @@ type FooList struct {
items []Foo `json:"items"` items []Foo `json:"items"`
} }
func initThirdParty(t *testing.T, version string) (*tools.FakeEtcdClient, *httptest.Server) { func initThirdParty(t *testing.T, version string) (*tools.FakeEtcdClient, *httptest.Server, *assert.Assertions) {
master := &Master{} master, _, assert := setUp(t)
api := &expapi.ThirdPartyResource{ api := &expapi.ThirdPartyResource{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: "foo.company.com", Name: "foo.company.com",
@ -119,13 +459,12 @@ func initThirdParty(t *testing.T, version string) (*tools.FakeEtcdClient, *httpt
fakeClient.Machines = []string{"http://machine1:4001", "http://machine2", "http://machine3:4003"} fakeClient.Machines = []string{"http://machine1:4001", "http://machine2", "http://machine3:4003"}
master.thirdPartyStorage = etcdstorage.NewEtcdStorage(fakeClient, explatest.Codec, etcdtest.PathPrefix()) master.thirdPartyStorage = etcdstorage.NewEtcdStorage(fakeClient, explatest.Codec, etcdtest.PathPrefix())
if err := master.InstallThirdPartyAPI(api); err != nil { if !assert.NoError(master.InstallThirdPartyAPI(api)) {
t.Errorf("unexpected error: %v", err)
t.FailNow() t.FailNow()
} }
server := httptest.NewServer(master.handlerContainer.ServeMux) server := httptest.NewServer(master.handlerContainer.ServeMux)
return fakeClient, server return fakeClient, server, assert
} }
func TestInstallThirdPartyAPIList(t *testing.T) { func TestInstallThirdPartyAPIList(t *testing.T) {
@ -135,31 +474,27 @@ func TestInstallThirdPartyAPIList(t *testing.T) {
} }
func testInstallThirdPartyAPIListVersion(t *testing.T, version string) { func testInstallThirdPartyAPIListVersion(t *testing.T, version string) {
fakeClient, server := initThirdParty(t, version) fakeClient, server, assert := initThirdParty(t, version)
defer server.Close() defer server.Close()
fakeClient.ExpectNotFoundGet(etcdtest.PathPrefix() + "/ThirdPartyResourceData/company.com/foos/default") fakeClient.ExpectNotFoundGet(etcdtest.PathPrefix() + "/ThirdPartyResourceData/company.com/foos/default")
resp, err := http.Get(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos") resp, err := http.Get(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos")
if err != nil { if !assert.NoError(err) {
t.Errorf("unexpected error: %v", err)
return return
} }
defer resp.Body.Close() defer resp.Body.Close()
if resp.StatusCode != http.StatusOK { assert.Equal(http.StatusOK, resp.StatusCode)
t.Errorf("unexpected status: %v", resp)
}
data, err := ioutil.ReadAll(resp.Body) data, err := ioutil.ReadAll(resp.Body)
if err != nil { assert.NoError(err)
t.Errorf("unexpected error: %v", err)
}
list := FooList{} list := FooList{}
if err := json.Unmarshal(data, &list); err != nil { err = json.Unmarshal(data, &list)
t.Errorf("unexpected error: %v", err) assert.NoError(err)
}
} }
func encodeToThirdParty(name string, obj interface{}) ([]byte, error) { func encodeToThirdParty(name string, obj interface{}) ([]byte, error) {
@ -204,7 +539,7 @@ func TestInstallThirdPartyAPIGet(t *testing.T) {
} }
func testInstallThirdPartyAPIGetVersion(t *testing.T, version string) { func testInstallThirdPartyAPIGetVersion(t *testing.T, version string) {
fakeClient, server := initThirdParty(t, version) fakeClient, server, assert := initThirdParty(t, version)
defer server.Close() defer server.Close()
expectedObj := Foo{ expectedObj := Foo{
@ -218,28 +553,26 @@ func testInstallThirdPartyAPIGetVersion(t *testing.T, version string) {
SomeField: "test field", SomeField: "test field",
OtherField: 10, OtherField: 10,
} }
if err := storeToEtcd(fakeClient, "/ThirdPartyResourceData/company.com/foos/default/test", "test", expectedObj); err != nil { if !assert.NoError(storeToEtcd(fakeClient, "/ThirdPartyResourceData/company.com/foos/default/test", "test", expectedObj)) {
t.Errorf("unexpected error: %v", err)
t.FailNow() t.FailNow()
return return
} }
resp, err := http.Get(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos/test") resp, err := http.Get(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos/test")
if err != nil { if !assert.NoError(err) {
t.Errorf("unexpected error: %v", err)
return return
} }
if resp.StatusCode != http.StatusOK { assert.Equal(http.StatusOK, resp.StatusCode)
t.Errorf("unexpected status: %v", resp)
}
item := Foo{} item := Foo{}
if err := decodeResponse(resp, &item); err != nil { assert.NoError(decodeResponse(resp, &item))
t.Errorf("unexpected error: %v", err) if !assert.False(reflect.DeepEqual(item, expectedObj)) {
t.Errorf("expected objects to not be equal:\n%v\nsaw:\n%v\n", expectedObj, item)
} }
// Fill in data that the apiserver injects // Fill in data that the apiserver injects
expectedObj.SelfLink = item.SelfLink expectedObj.SelfLink = item.SelfLink
if !reflect.DeepEqual(item, expectedObj) { if !assert.True(reflect.DeepEqual(item, expectedObj)) {
t.Errorf("expected:\n%#v\nsaw:\n%#v\n", expectedObj, item) t.Errorf("expected:\n%#v\nsaw:\n%#v\n", expectedObj, item)
} }
} }
@ -251,7 +584,7 @@ func TestInstallThirdPartyAPIPost(t *testing.T) {
} }
func testInstallThirdPartyAPIPostForVersion(t *testing.T, version string) { func testInstallThirdPartyAPIPostForVersion(t *testing.T, version string) {
fakeClient, server := initThirdParty(t, version) fakeClient, server, assert := initThirdParty(t, version)
defer server.Close() defer server.Close()
inputObj := Foo{ inputObj := Foo{
@ -266,25 +599,19 @@ func testInstallThirdPartyAPIPostForVersion(t *testing.T, version string) {
OtherField: 10, OtherField: 10,
} }
data, err := json.Marshal(inputObj) data, err := json.Marshal(inputObj)
if err != nil { if !assert.NoError(err) {
t.Errorf("unexpected error: %v")
return return
} }
resp, err := http.Post(server.URL+"/thirdparty/company.com/"+version+"/namespaces/default/foos", "application/json", bytes.NewBuffer(data)) resp, err := http.Post(server.URL+"/thirdparty/company.com/"+version+"/namespaces/default/foos", "application/json", bytes.NewBuffer(data))
if err != nil { if !assert.NoError(err) {
t.Errorf("unexpected error: %v", err)
return return
} }
if resp.StatusCode != http.StatusCreated { assert.Equal(http.StatusCreated, resp.StatusCode)
t.Errorf("unexpected status: %v", resp)
}
item := Foo{} item := Foo{}
if err := decodeResponse(resp, &item); err != nil { assert.NoError(decodeResponse(resp, &item))
t.Errorf("unexpected error: %v", err)
}
// fill in fields set by the apiserver // fill in fields set by the apiserver
expectedObj := inputObj expectedObj := inputObj
@ -292,29 +619,26 @@ func testInstallThirdPartyAPIPostForVersion(t *testing.T, version string) {
expectedObj.Namespace = item.Namespace expectedObj.Namespace = item.Namespace
expectedObj.UID = item.UID expectedObj.UID = item.UID
expectedObj.CreationTimestamp = item.CreationTimestamp expectedObj.CreationTimestamp = item.CreationTimestamp
if !reflect.DeepEqual(item, expectedObj) { if !assert.True(reflect.DeepEqual(item, expectedObj)) {
t.Errorf("expected:\n%v\nsaw:\n%v\n", expectedObj, item) t.Errorf("expected:\n%v\nsaw:\n%v\n", expectedObj, item)
} }
etcdResp, err := fakeClient.Get(etcdtest.PathPrefix()+"/ThirdPartyResourceData/company.com/foos/default/test", false, false) etcdResp, err := fakeClient.Get(etcdtest.PathPrefix()+"/ThirdPartyResourceData/company.com/foos/default/test", false, false)
if err != nil { if !assert.NoError(err) {
t.Errorf("unexpected error: %v", err)
t.FailNow() t.FailNow()
} }
obj, err := explatest.Codec.Decode([]byte(etcdResp.Node.Value)) obj, err := explatest.Codec.Decode([]byte(etcdResp.Node.Value))
if err != nil { assert.NoError(err)
t.Errorf("unexpected error: %v", err)
}
thirdPartyObj, ok := obj.(*expapi.ThirdPartyResourceData) thirdPartyObj, ok := obj.(*expapi.ThirdPartyResourceData)
if !ok { if !assert.True(ok) {
t.Errorf("unexpected object: %v", obj) t.Errorf("unexpected object: %v", obj)
} }
item = Foo{} item = Foo{}
if err := json.Unmarshal(thirdPartyObj.Data, &item); err != nil { assert.NoError(json.Unmarshal(thirdPartyObj.Data, &item))
t.Errorf("unexpected error: %v", err)
}
if !reflect.DeepEqual(item, inputObj) { if !assert.True(reflect.DeepEqual(item, inputObj)) {
t.Errorf("expected:\n%v\nsaw:\n%v\n", inputObj, item) t.Errorf("expected:\n%v\nsaw:\n%v\n", inputObj, item)
} }
} }
@ -326,7 +650,7 @@ func TestInstallThirdPartyAPIDelete(t *testing.T) {
} }
func testInstallThirdPartyAPIDeleteVersion(t *testing.T, version string) { func testInstallThirdPartyAPIDeleteVersion(t *testing.T, version string) {
fakeClient, server := initThirdParty(t, version) fakeClient, server, assert := initThirdParty(t, version)
defer server.Close() defer server.Close()
expectedObj := Foo{ expectedObj := Foo{
@ -340,55 +664,45 @@ func testInstallThirdPartyAPIDeleteVersion(t *testing.T, version string) {
SomeField: "test field", SomeField: "test field",
OtherField: 10, OtherField: 10,
} }
if err := storeToEtcd(fakeClient, "/ThirdPartyResourceData/company.com/foos/default/test", "test", expectedObj); err != nil { if !assert.NoError(storeToEtcd(fakeClient, "/ThirdPartyResourceData/company.com/foos/default/test", "test", expectedObj)) {
t.Errorf("unexpected error: %v", err)
t.FailNow() t.FailNow()
return return
} }
resp, err := http.Get(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos/test") resp, err := http.Get(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos/test")
if err != nil { if !assert.NoError(err) {
t.Errorf("unexpected error: %v", err)
return return
} }
if resp.StatusCode != http.StatusOK { assert.Equal(http.StatusOK, resp.StatusCode)
t.Errorf("unexpected status: %v", resp)
}
item := Foo{} item := Foo{}
if err := decodeResponse(resp, &item); err != nil { assert.NoError(decodeResponse(resp, &item))
t.Errorf("unexpected error: %v", err)
}
// Fill in fields set by the apiserver // Fill in fields set by the apiserver
expectedObj.SelfLink = item.SelfLink expectedObj.SelfLink = item.SelfLink
expectedObj.Namespace = item.Namespace expectedObj.Namespace = item.Namespace
if !reflect.DeepEqual(item, expectedObj) { if !assert.True(reflect.DeepEqual(item, expectedObj)) {
t.Errorf("expected:\n%v\nsaw:\n%v\n", expectedObj, item) t.Errorf("expected:\n%v\nsaw:\n%v\n", expectedObj, item)
} }
resp, err = httpDelete(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos/test") resp, err = httpDelete(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos/test")
if err != nil { if !assert.NoError(err) {
t.Errorf("unexpected error: %v", err)
return return
} }
if resp.StatusCode != http.StatusOK { assert.Equal(http.StatusOK, resp.StatusCode)
t.Errorf("unexpected status: %v", resp)
}
resp, err = http.Get(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos/test") resp, err = http.Get(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos/test")
if err != nil { if !assert.NoError(err) {
t.Errorf("unexpected error: %v", err)
return return
} }
if resp.StatusCode != http.StatusNotFound { assert.Equal(http.StatusNotFound, resp.StatusCode)
t.Errorf("unexpected status: %v", resp)
}
expectDeletedKeys := []string{etcdtest.PathPrefix() + "/ThirdPartyResourceData/company.com/foos/default/test"} expectDeletedKeys := []string{etcdtest.PathPrefix() + "/ThirdPartyResourceData/company.com/foos/default/test"}
if !reflect.DeepEqual(fakeClient.DeletedKeys, expectDeletedKeys) {
if !assert.True(reflect.DeepEqual(fakeClient.DeletedKeys, expectDeletedKeys)) {
t.Errorf("unexpected deleted keys: %v", fakeClient.DeletedKeys) t.Errorf("unexpected deleted keys: %v", fakeClient.DeletedKeys)
} }
} }