diff --git a/pkg/master/master.go b/pkg/master/master.go index e334495483..1ea3cc423a 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -1024,6 +1024,7 @@ func (m *Master) setupSecureProxy(user, privateKeyfile, publicKeyfile string) { } 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) if err != nil { return err diff --git a/pkg/master/master_test.go b/pkg/master/master_test.go index 898d92385a..7f30a96618 100644 --- a/pkg/master/master_test.go +++ b/pkg/master/master_test.go @@ -19,25 +19,41 @@ package master import ( "bytes" "encoding/json" + "errors" + "fmt" "io/ioutil" + "net" "net/http" "net/http/httptest" + "os" + "path/filepath" "reflect" "testing" + "time" + "github.com/emicklei/go-restful" + "github.com/stretchr/testify/assert" "k8s.io/kubernetes/pkg/api" "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" 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" etcdstorage "k8s.io/kubernetes/pkg/storage/etcd" "k8s.io/kubernetes/pkg/tools" "k8s.io/kubernetes/pkg/tools/etcdtest" - - "github.com/emicklei/go-restful" + "k8s.io/kubernetes/pkg/util" ) -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{} config := Config{} fakeClient := tools.NewFakeEtcdClient(t) @@ -47,11 +63,64 @@ func TestGetServersToValidate(t *testing.T) { 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) - if len(servers) != 5 { - t.Errorf("unexpected server list: %#v", servers) - } + assert.Equal(5, len(servers), "unexpected server list: %#v", servers) + for _, server := range []string{"scheduler", "controller-manager", "etcd-0", "etcd-1", "etcd-2"} { if _, ok := servers[server]; !ok { 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) { + assert := assert.New(t) expectedIP := "172.0.0.1" 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[2].Status.Addresses = []api.NodeAddress{{"ExternalIP", expectedIP}, {"LegacyHostIP", "172.0.0.2"}} + // Pass Case for _, node := range nodes { ip, err := findExternalAddress(node) - if err != nil { - t.Errorf("error getting node external address: %s", err) - } - if ip != expectedIP { - t.Errorf("expected ip to be %s, but was %s", expectedIP, ip) + assert.NoError(err, "error getting node external address") + assert.Equal(expectedIP, ip, "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) + } +} + +// TestNewBootstrapController verifies master fields are properly copied into controller +func TestNewBootstrapController(t *testing.T) { + // 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()") } } - _, err := findExternalAddress(new(api.Node)) - if err == nil { - t.Errorf("expected findExternalAddress to fail on a node with missing ip information") + // 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"} @@ -100,8 +439,9 @@ type FooList struct { items []Foo `json:"items"` } -func initThirdParty(t *testing.T, version string) (*tools.FakeEtcdClient, *httptest.Server) { - master := &Master{} +func initThirdParty(t *testing.T, version string) (*tools.FakeEtcdClient, *httptest.Server, *assert.Assertions) { + master, _, assert := setUp(t) + api := &expapi.ThirdPartyResource{ ObjectMeta: api.ObjectMeta{ 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"} master.thirdPartyStorage = etcdstorage.NewEtcdStorage(fakeClient, explatest.Codec, etcdtest.PathPrefix()) - if err := master.InstallThirdPartyAPI(api); err != nil { - t.Errorf("unexpected error: %v", err) + if !assert.NoError(master.InstallThirdPartyAPI(api)) { t.FailNow() } server := httptest.NewServer(master.handlerContainer.ServeMux) - return fakeClient, server + return fakeClient, server, assert } func TestInstallThirdPartyAPIList(t *testing.T) { @@ -135,31 +474,27 @@ func TestInstallThirdPartyAPIList(t *testing.T) { } func testInstallThirdPartyAPIListVersion(t *testing.T, version string) { - fakeClient, server := initThirdParty(t, version) + fakeClient, server, assert := initThirdParty(t, version) defer server.Close() fakeClient.ExpectNotFoundGet(etcdtest.PathPrefix() + "/ThirdPartyResourceData/company.com/foos/default") resp, err := http.Get(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos") - if err != nil { - t.Errorf("unexpected error: %v", err) + if !assert.NoError(err) { return } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Errorf("unexpected status: %v", resp) - } + assert.Equal(http.StatusOK, resp.StatusCode) data, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Errorf("unexpected error: %v", err) - } + assert.NoError(err) list := FooList{} - if err := json.Unmarshal(data, &list); err != nil { - t.Errorf("unexpected error: %v", err) - } + err = json.Unmarshal(data, &list) + assert.NoError(err) + } func encodeToThirdParty(name string, obj interface{}) ([]byte, error) { @@ -204,7 +539,7 @@ func TestInstallThirdPartyAPIGet(t *testing.T) { } func testInstallThirdPartyAPIGetVersion(t *testing.T, version string) { - fakeClient, server := initThirdParty(t, version) + fakeClient, server, assert := initThirdParty(t, version) defer server.Close() expectedObj := Foo{ @@ -218,28 +553,26 @@ func testInstallThirdPartyAPIGetVersion(t *testing.T, version string) { SomeField: "test field", OtherField: 10, } - if err := storeToEtcd(fakeClient, "/ThirdPartyResourceData/company.com/foos/default/test", "test", expectedObj); err != nil { - t.Errorf("unexpected error: %v", err) + if !assert.NoError(storeToEtcd(fakeClient, "/ThirdPartyResourceData/company.com/foos/default/test", "test", expectedObj)) { t.FailNow() return } resp, err := http.Get(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos/test") - if err != nil { - t.Errorf("unexpected error: %v", err) + if !assert.NoError(err) { return } - if resp.StatusCode != http.StatusOK { - t.Errorf("unexpected status: %v", resp) - } + assert.Equal(http.StatusOK, resp.StatusCode) + item := Foo{} - if err := decodeResponse(resp, &item); err != nil { - t.Errorf("unexpected error: %v", err) + assert.NoError(decodeResponse(resp, &item)) + 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 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) } } @@ -251,7 +584,7 @@ func TestInstallThirdPartyAPIPost(t *testing.T) { } func testInstallThirdPartyAPIPostForVersion(t *testing.T, version string) { - fakeClient, server := initThirdParty(t, version) + fakeClient, server, assert := initThirdParty(t, version) defer server.Close() inputObj := Foo{ @@ -266,25 +599,19 @@ func testInstallThirdPartyAPIPostForVersion(t *testing.T, version string) { OtherField: 10, } data, err := json.Marshal(inputObj) - if err != nil { - t.Errorf("unexpected error: %v") + if !assert.NoError(err) { return } resp, err := http.Post(server.URL+"/thirdparty/company.com/"+version+"/namespaces/default/foos", "application/json", bytes.NewBuffer(data)) - if err != nil { - t.Errorf("unexpected error: %v", err) + if !assert.NoError(err) { return } - if resp.StatusCode != http.StatusCreated { - t.Errorf("unexpected status: %v", resp) - } + assert.Equal(http.StatusCreated, resp.StatusCode) item := Foo{} - if err := decodeResponse(resp, &item); err != nil { - t.Errorf("unexpected error: %v", err) - } + assert.NoError(decodeResponse(resp, &item)) // fill in fields set by the apiserver expectedObj := inputObj @@ -292,29 +619,26 @@ func testInstallThirdPartyAPIPostForVersion(t *testing.T, version string) { expectedObj.Namespace = item.Namespace expectedObj.UID = item.UID 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) } etcdResp, err := fakeClient.Get(etcdtest.PathPrefix()+"/ThirdPartyResourceData/company.com/foos/default/test", false, false) - if err != nil { - t.Errorf("unexpected error: %v", err) + if !assert.NoError(err) { t.FailNow() } + obj, err := explatest.Codec.Decode([]byte(etcdResp.Node.Value)) - if err != nil { - t.Errorf("unexpected error: %v", err) - } + assert.NoError(err) + thirdPartyObj, ok := obj.(*expapi.ThirdPartyResourceData) - if !ok { + if !assert.True(ok) { t.Errorf("unexpected object: %v", obj) } item = Foo{} - if err := json.Unmarshal(thirdPartyObj.Data, &item); err != nil { - t.Errorf("unexpected error: %v", err) - } + assert.NoError(json.Unmarshal(thirdPartyObj.Data, &item)) - if !reflect.DeepEqual(item, inputObj) { + if !assert.True(reflect.DeepEqual(item, inputObj)) { 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) { - fakeClient, server := initThirdParty(t, version) + fakeClient, server, assert := initThirdParty(t, version) defer server.Close() expectedObj := Foo{ @@ -340,55 +664,45 @@ func testInstallThirdPartyAPIDeleteVersion(t *testing.T, version string) { SomeField: "test field", OtherField: 10, } - if err := storeToEtcd(fakeClient, "/ThirdPartyResourceData/company.com/foos/default/test", "test", expectedObj); err != nil { - t.Errorf("unexpected error: %v", err) + if !assert.NoError(storeToEtcd(fakeClient, "/ThirdPartyResourceData/company.com/foos/default/test", "test", expectedObj)) { t.FailNow() return } resp, err := http.Get(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos/test") - if err != nil { - t.Errorf("unexpected error: %v", err) + if !assert.NoError(err) { return } - if resp.StatusCode != http.StatusOK { - t.Errorf("unexpected status: %v", resp) - } + assert.Equal(http.StatusOK, resp.StatusCode) item := Foo{} - if err := decodeResponse(resp, &item); err != nil { - t.Errorf("unexpected error: %v", err) - } + assert.NoError(decodeResponse(resp, &item)) // Fill in fields set by the apiserver expectedObj.SelfLink = item.SelfLink 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) } resp, err = httpDelete(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos/test") - if err != nil { - t.Errorf("unexpected error: %v", err) + if !assert.NoError(err) { return } - if resp.StatusCode != http.StatusOK { - t.Errorf("unexpected status: %v", resp) - } + assert.Equal(http.StatusOK, resp.StatusCode) resp, err = http.Get(server.URL + "/thirdparty/company.com/" + version + "/namespaces/default/foos/test") - if err != nil { - t.Errorf("unexpected error: %v", err) + if !assert.NoError(err) { return } - if resp.StatusCode != http.StatusNotFound { - t.Errorf("unexpected status: %v", resp) - } + assert.Equal(http.StatusNotFound, resp.StatusCode) + 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) } }