func TestLogError(t *testing.T) { var testbuffer bytes.Buffer defer tests.Patch(&stderr, &testbuffer).Restore() l := NewLogger("[testing]", LEVEL_DEBUG) l.LogError("Hello %v", "World") tests.Assert(t, strings.Contains(testbuffer.String(), "[testing] ERROR "), testbuffer.String()) tests.Assert(t, strings.Contains(testbuffer.String(), "Hello World"), testbuffer.String()) tests.Assert(t, strings.Contains(testbuffer.String(), "log_test.go"), testbuffer.String()) testbuffer.Reset() testbuffer.Reset() err := errors.New("BAD") l.Err(err) tests.Assert(t, strings.Contains(testbuffer.String(), "[testing] ERROR "), testbuffer.String()) tests.Assert(t, strings.Contains(testbuffer.String(), "BAD"), testbuffer.String()) tests.Assert(t, strings.Contains(testbuffer.String(), "log_test.go"), testbuffer.String()) testbuffer.Reset() l.SetLevel(LEVEL_CRITICAL) l.LogError("TEXT") tests.Assert(t, testbuffer.Len() == 0) }
func TestDeviceAddBadRequests(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() router := mux.NewRouter() app.SetRoutes(router) // Setup the server ts := httptest.NewServer(router) defer ts.Close() // ClusterCreate JSON Request request := []byte(`{ bad json }`) // Post bad JSON r, err := http.Post(ts.URL+"/devices", "application/json", bytes.NewBuffer(request)) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == 422) // Make a request with no devices request = []byte(`{ "node" : "123", "devices" : [] }`) // Post bad JSON r, err = http.Post(ts.URL+"/devices", "application/json", bytes.NewBuffer(request)) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusBadRequest) // Make a request with unknown node request = []byte(`{ "node" : "123", "devices" : [ { "name" : "/dev/fake", "weight" : 20 } ] }`) // Post bad JSON r, err = http.Post(ts.URL+"/devices", "application/json", bytes.NewBuffer(request)) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusNotFound) }
func TestNewNodeEntryNewInfoResponse(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() // Create a node req := &NodeAddRequest{ ClusterId: "123", Hostnames: HostAddresses{ Manage: []string{"manage"}, Storage: []string{"storage"}, }, Zone: 99, } n := NewNodeEntryFromRequest(req) // Save element in database err := app.db.Update(func(tx *bolt.Tx) error { return n.Save(tx) }) tests.Assert(t, err == nil) var info *NodeInfoResponse err = app.db.View(func(tx *bolt.Tx) error { node, err := NewNodeEntryFromId(tx, n.Info.Id) if err != nil { return err } info, err = node.NewInfoReponse(tx) if err != nil { return err } return nil }) tests.Assert(t, err == nil) tests.Assert(t, info.ClusterId == n.Info.ClusterId) tests.Assert(t, info.Id == n.Info.Id) tests.Assert(t, info.Zone == n.Info.Zone) tests.Assert(t, len(info.Hostnames.Manage) == 1) tests.Assert(t, len(info.Hostnames.Storage) == 1) tests.Assert(t, reflect.DeepEqual(info.Hostnames.Manage, n.Info.Hostnames.Manage)) tests.Assert(t, reflect.DeepEqual(info.Hostnames.Storage, n.Info.Hostnames.Storage)) }
func TestNewDeviceEntryNewInfoResponse(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() // Create a device req := &Device{ Name: "dev", Weight: 123, } nodeid := "abc" d := NewDeviceEntryFromRequest(req, nodeid) d.Info.Storage.Free = 10 d.Info.Storage.Total = 100 d.Info.Storage.Used = 1000 d.BrickAdd("abc") d.BrickAdd("def") // Save element in database err := app.db.Update(func(tx *bolt.Tx) error { return d.Save(tx) }) tests.Assert(t, err == nil) var info *DeviceInfoResponse err = app.db.View(func(tx *bolt.Tx) error { device, err := NewDeviceEntryFromId(tx, d.Info.Id) if err != nil { return err } info, err = device.NewInfoResponse(tx) if err != nil { return err } return nil }) tests.Assert(t, err == nil) tests.Assert(t, info.Id == d.Info.Id) tests.Assert(t, info.Name == d.Info.Name) tests.Assert(t, info.Weight == d.Info.Weight) tests.Assert(t, reflect.DeepEqual(info.Storage, d.Info.Storage)) tests.Assert(t, len(info.Bricks) == 0) }
func TestLogLevel(t *testing.T) { var testbuffer bytes.Buffer defer tests.Patch(&stdout, &testbuffer).Restore() l := NewLogger("[testing]", LEVEL_INFO) tests.Assert(t, LEVEL_INFO == l.level) tests.Assert(t, LEVEL_INFO == l.Level()) l.SetLevel(LEVEL_CRITICAL) tests.Assert(t, LEVEL_CRITICAL == l.level) tests.Assert(t, LEVEL_CRITICAL == l.Level()) }
func TestClusterCreate(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() router := mux.NewRouter() app.SetRoutes(router) // Setup the server ts := httptest.NewServer(router) defer ts.Close() // ClusterCreate JSON Request request := []byte(`{ }`) // Post nothing r, err := http.Post(ts.URL+"/clusters", "application/json", bytes.NewBuffer(request)) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusCreated) // Read JSON var msg ClusterInfoResponse err = utils.GetJsonFromResponse(r, &msg) tests.Assert(t, err == nil) // Test JSON tests.Assert(t, len(msg.Nodes) == 0) tests.Assert(t, len(msg.Volumes) == 0) // Check that the data on the database is recorded correctly var entry ClusterEntry err = app.db.View(func(tx *bolt.Tx) error { return entry.Unmarshal( tx.Bucket([]byte(BOLTDB_BUCKET_CLUSTER)). Get([]byte(msg.Id))) }) tests.Assert(t, err == nil) // Make sure they entries are euqal tests.Assert(t, entry.Info.Id == msg.Id) tests.Assert(t, len(entry.Info.Volumes) == 0) tests.Assert(t, len(entry.Info.Nodes) == 0) }
func TestDeviceDeleteErrors(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() router := mux.NewRouter() app.SetRoutes(router) // Setup the server ts := httptest.NewServer(router) defer ts.Close() // Create a device to save in the db device := NewDeviceEntry() device.Info.Id = "abc" device.Info.Name = "/dev/fake1" device.Info.Weight = 101 device.NodeId = "def" device.StorageSet(10000) device.StorageAllocate(1000) // Save device in the db err := app.db.Update(func(tx *bolt.Tx) error { return device.Save(tx) }) tests.Assert(t, err == nil) // Delete unknown id req, err := http.NewRequest("DELETE", ts.URL+"/devices/123", nil) tests.Assert(t, err == nil) r, err := http.DefaultClient.Do(req) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusNotFound) // Delete device without a node there.. that's probably a really // bad situation req, err = http.NewRequest("DELETE", ts.URL+"/devices/"+device.Info.Id, nil) tests.Assert(t, err == nil) r, err = http.DefaultClient.Do(req) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusInternalServerError) }
func TestDeviceInfo(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() router := mux.NewRouter() app.SetRoutes(router) // Setup the server ts := httptest.NewServer(router) defer ts.Close() // Create a device to save in the db device := NewDeviceEntry() device.Info.Id = "abc" device.Info.Name = "/dev/fake1" device.Info.Weight = 101 device.NodeId = "def" device.StorageSet(10000) device.StorageAllocate(1000) // Save device in the db err := app.db.Update(func(tx *bolt.Tx) error { return device.Save(tx) }) tests.Assert(t, err == nil) // Get device information r, err := http.Get(ts.URL + "/devices/" + device.Info.Id) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusOK) tests.Assert(t, r.Header.Get("Content-Type") == "application/json; charset=UTF-8") var info DeviceInfoResponse err = utils.GetJsonFromResponse(r, &info) tests.Assert(t, info.Id == device.Info.Id) tests.Assert(t, info.Name == device.Info.Name) tests.Assert(t, info.Weight == device.Info.Weight) tests.Assert(t, info.Storage.Free == device.Info.Storage.Free) tests.Assert(t, info.Storage.Used == device.Info.Storage.Used) tests.Assert(t, info.Storage.Total == device.Info.Storage.Total) }
func TestLogWarning(t *testing.T) { var testbuffer bytes.Buffer defer tests.Patch(&stdout, &testbuffer).Restore() l := NewLogger("[testing]", LEVEL_DEBUG) l.Warning("Hello %v", "World") tests.Assert(t, strings.Contains(testbuffer.String(), "[testing] WARNING "), testbuffer.String()) tests.Assert(t, strings.Contains(testbuffer.String(), "Hello World"), testbuffer.String()) testbuffer.Reset() l.SetLevel(LEVEL_ERROR) l.Warning("TEXT") tests.Assert(t, testbuffer.Len() == 0) }
func TestNodeInfo(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() router := mux.NewRouter() app.SetRoutes(router) // Setup the server ts := httptest.NewServer(router) defer ts.Close() // Create a node to save in the db node := NewNodeEntry() node.Info.Id = "abc" node.Info.ClusterId = "123" node.Info.Hostnames.Manage = sort.StringSlice{"manage.system"} node.Info.Hostnames.Storage = sort.StringSlice{"storage.system"} node.Info.Zone = 10 // Save node in the db err := app.db.Update(func(tx *bolt.Tx) error { return node.Save(tx) }) tests.Assert(t, err == nil) // Get unknown node id r, err := http.Get(ts.URL + "/nodes/" + node.Info.Id) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusOK) tests.Assert(t, r.Header.Get("Content-Type") == "application/json; charset=UTF-8") var info NodeInfoResponse err = utils.GetJsonFromResponse(r, &info) tests.Assert(t, info.Id == node.Info.Id) tests.Assert(t, info.Hostnames.Manage[0] == node.Info.Hostnames.Manage[0]) tests.Assert(t, len(info.Hostnames.Manage) == len(node.Info.Hostnames.Manage)) tests.Assert(t, info.Hostnames.Storage[0] == node.Info.Hostnames.Storage[0]) tests.Assert(t, len(info.Hostnames.Storage) == len(node.Info.Hostnames.Storage)) tests.Assert(t, info.Zone == node.Info.Zone) }
func TestNodeDeleteErrors(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() router := mux.NewRouter() app.SetRoutes(router) // Setup the server ts := httptest.NewServer(router) defer ts.Close() // Create a node to save in the db node := NewNodeEntry() node.Info.Id = "abc" node.Info.ClusterId = "123" node.Info.Hostnames.Manage = sort.StringSlice{"manage.system"} node.Info.Hostnames.Storage = sort.StringSlice{"storage.system"} node.Info.Zone = 10 // Save node in the db err := app.db.Update(func(tx *bolt.Tx) error { return node.Save(tx) }) tests.Assert(t, err == nil) // Delete unknown id req, err := http.NewRequest("DELETE", ts.URL+"/nodes/123", nil) tests.Assert(t, err == nil) r, err := http.DefaultClient.Do(req) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusNotFound) // Delete node without a cluster there.. that's probably a really // bad situation req, err = http.NewRequest("DELETE", ts.URL+"/nodes/"+node.Info.Id, nil) tests.Assert(t, err == nil) r, err = http.DefaultClient.Do(req) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusInternalServerError) }
func TestNewNodeEntryFromId(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() // Create a node req := &NodeAddRequest{ ClusterId: "123", Hostnames: HostAddresses{ Manage: []string{"manage"}, Storage: []string{"storage"}, }, Zone: 99, } n := NewNodeEntryFromRequest(req) n.DeviceAdd("abc") n.DeviceAdd("def") // Save element in database err := app.db.Update(func(tx *bolt.Tx) error { return n.Save(tx) }) tests.Assert(t, err == nil) var node *NodeEntry err = app.db.View(func(tx *bolt.Tx) error { var err error node, err = NewNodeEntryFromId(tx, n.Info.Id) if err != nil { return err } return nil }) tests.Assert(t, err == nil) tests.Assert(t, reflect.DeepEqual(node, n)) }
func TestNewClusterEntryNewInfoResponse(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() // Create a cluster c := NewClusterEntryFromRequest() c.NodeAdd("node_abc") c.NodeAdd("node_def") c.VolumeAdd("vol_abc") // Save element in database err := app.db.Update(func(tx *bolt.Tx) error { return c.Save(tx) }) tests.Assert(t, err == nil) var info *ClusterInfoResponse err = app.db.View(func(tx *bolt.Tx) error { cluster, err := NewClusterEntryFromId(tx, c.Info.Id) if err != nil { return err } info, err = cluster.NewClusterInfoResponse(tx) if err != nil { return err } return nil }) tests.Assert(t, err == nil) tests.Assert(t, info.Id == c.Info.Id) tests.Assert(t, reflect.DeepEqual(info.Nodes, c.Info.Nodes)) tests.Assert(t, reflect.DeepEqual(info.Volumes, c.Info.Volumes)) }
func TestNewNodeEntryFromIdNotFound(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() // Test for ID not found err := app.db.View(func(tx *bolt.Tx) error { _, err := NewNodeEntryFromId(tx, "123") return err }) tests.Assert(t, err == ErrNotFound) }
func TestNewClusterEntryFromId(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() // Create a cluster c := NewClusterEntryFromRequest() c.NodeAdd("node_abc") c.NodeAdd("node_def") c.VolumeAdd("vol_abc") // Save element in database err := app.db.Update(func(tx *bolt.Tx) error { return c.Save(tx) }) tests.Assert(t, err == nil) var cluster *ClusterEntry err = app.db.View(func(tx *bolt.Tx) error { var err error cluster, err = NewClusterEntryFromId(tx, c.Info.Id) if err != nil { return err } return nil }) tests.Assert(t, err == nil) tests.Assert(t, cluster.Info.Id == c.Info.Id) tests.Assert(t, len(c.Info.Nodes) == 2) tests.Assert(t, len(c.Info.Volumes) == 1) tests.Assert(t, utils.SortedStringHas(c.Info.Nodes, "node_abc")) tests.Assert(t, utils.SortedStringHas(c.Info.Nodes, "node_def")) tests.Assert(t, utils.SortedStringHas(c.Info.Volumes, "vol_abc")) }
func TestClusterInfoIdNotFound(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() router := mux.NewRouter() app.SetRoutes(router) // Setup the server ts := httptest.NewServer(router) defer ts.Close() // Now that we have some data in the database, we can // make a request for the clutser list r, err := http.Get(ts.URL + "/clusters/12345") tests.Assert(t, r.StatusCode == http.StatusNotFound) tests.Assert(t, err == nil) }
func TestNodeInfoIdNotFound(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() router := mux.NewRouter() app.SetRoutes(router) // Setup the server ts := httptest.NewServer(router) defer ts.Close() // Get unknown node id r, err := http.Get(ts.URL + "/nodes/123456789") tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusNotFound) }
func TestNodeAddBadRequests(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() router := mux.NewRouter() app.SetRoutes(router) // Setup the server ts := httptest.NewServer(router) defer ts.Close() // ClusterCreate JSON Request request := []byte(`{ bad json }`) // Post bad JSON r, err := http.Post(ts.URL+"/nodes", "application/json", bytes.NewBuffer(request)) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == 422) // Make a request without hostnames request = []byte(`{ "cluster" : "123", "hostname" : {} }`) // Post bad JSON r, err = http.Post(ts.URL+"/nodes", "application/json", bytes.NewBuffer(request)) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusBadRequest) // Make a request with only manage hostname request = []byte(`{ "cluster" : "123", "hostnames" : { "manage" : [ "manage.hostname.com" ] } }`) // Post bad JSON r, err = http.Post(ts.URL+"/nodes", "application/json", bytes.NewBuffer(request)) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusBadRequest) // Make a request with only storage hostname request = []byte(`{ "cluster" : "123", "hostnames" : { "storage" : [ "storage.hostname.com" ] } }`) // Post bad JSON r, err = http.Post(ts.URL+"/nodes", "application/json", bytes.NewBuffer(request)) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusBadRequest) // Make a request where the cluster id does not exist request = []byte(`{ "cluster" : "123", "hostnames" : { "storage" : [ "storage.hostname.com" ], "manage" : [ "manage.hostname.com" ] }, "zone" : 10 }`) // Check that it returns that the cluster id is not found r, err = http.Post(ts.URL+"/nodes", "application/json", bytes.NewBuffer(request)) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusNotFound) }
func TestDeviceAddDelete(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() router := mux.NewRouter() app.SetRoutes(router) // Setup the server ts := httptest.NewServer(router) defer ts.Close() // Add Cluster then a Node on the cluster // node cluster := NewClusterEntryFromRequest() nodereq := &NodeAddRequest{ ClusterId: cluster.Info.Id, Hostnames: HostAddresses{ Manage: []string{"manage"}, Storage: []string{"storage"}, }, Zone: 99, } node := NewNodeEntryFromRequest(nodereq) cluster.NodeAdd(node.Info.Id) // Save information in the db err := app.db.Update(func(tx *bolt.Tx) error { err := cluster.Save(tx) if err != nil { return err } err = node.Save(tx) if err != nil { return err } return nil }) tests.Assert(t, err == nil) // Create a request to add four devices request := []byte(`{ "node" : "` + node.Info.Id + `", "devices" : [ { "name" : "/dev/fake1", "weight" : 10 }, { "name" : "/dev/fake2", "weight" : 20 }, { "name" : "/dev/fake3", "weight" : 30 }, { "name" : "/dev/fake4", "weight" : 40 } ] }`) // Add device using POST r, err := http.Post(ts.URL+"/devices", "application/json", bytes.NewBuffer(request)) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusAccepted) location, err := r.Location() tests.Assert(t, err == nil) // Query queue until finished for { r, err = http.Get(location.String()) tests.Assert(t, err == nil) if r.Header.Get("X-Pending") == "true" { tests.Assert(t, r.StatusCode == http.StatusOK) time.Sleep(time.Millisecond * 10) continue } else { tests.Assert(t, r.StatusCode == http.StatusNoContent) break } } // Check db to make sure devices where added devicemap := make(map[string]*DeviceEntry) err = app.db.View(func(tx *bolt.Tx) error { node, err = NewNodeEntryFromId(tx, node.Info.Id) if err != nil { return err } for _, id := range node.Devices { device, err := NewDeviceEntryFromId(tx, id) if err != nil { return err } devicemap[device.Info.Name] = device } return nil }) tests.Assert(t, err == nil) val, ok := devicemap["/dev/fake1"] tests.Assert(t, ok) tests.Assert(t, val.Info.Name == "/dev/fake1") tests.Assert(t, val.Info.Weight == 10) tests.Assert(t, len(val.Bricks) == 0) val, ok = devicemap["/dev/fake2"] tests.Assert(t, ok) tests.Assert(t, val.Info.Name == "/dev/fake2") tests.Assert(t, val.Info.Weight == 20) tests.Assert(t, len(val.Bricks) == 0) val, ok = devicemap["/dev/fake3"] tests.Assert(t, ok) tests.Assert(t, val.Info.Name == "/dev/fake3") tests.Assert(t, val.Info.Weight == 30) tests.Assert(t, len(val.Bricks) == 0) val, ok = devicemap["/dev/fake4"] tests.Assert(t, ok) tests.Assert(t, val.Info.Name == "/dev/fake4") tests.Assert(t, val.Info.Weight == 40) tests.Assert(t, len(val.Bricks) == 0) // Add some bricks to check if delete conflicts works fakeid := devicemap["/dev/fake1"].Info.Id err = app.db.Update(func(tx *bolt.Tx) error { device, err := NewDeviceEntryFromId(tx, fakeid) if err != nil { return err } device.BrickAdd("123") device.BrickAdd("456") return device.Save(tx) }) tests.Assert(t, err == nil) // Now delete device and check for conflict req, err := http.NewRequest("DELETE", ts.URL+"/devices/"+fakeid, nil) tests.Assert(t, err == nil) r, err = http.DefaultClient.Do(req) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusConflict) // Check the db is still intact err = app.db.View(func(tx *bolt.Tx) error { device, err := NewDeviceEntryFromId(tx, fakeid) if err != nil { return err } node, err = NewNodeEntryFromId(tx, device.NodeId) if err != nil { return err } return nil }) tests.Assert(t, err == nil) tests.Assert(t, utils.SortedStringHas(node.Devices, fakeid)) // Node delete bricks from the device err = app.db.Update(func(tx *bolt.Tx) error { device, err := NewDeviceEntryFromId(tx, fakeid) if err != nil { return err } device.BrickDelete("123") device.BrickDelete("456") return device.Save(tx) }) tests.Assert(t, err == nil) // Delete device req, err = http.NewRequest("DELETE", ts.URL+"/devices/"+fakeid, nil) tests.Assert(t, err == nil) r, err = http.DefaultClient.Do(req) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusOK) // Check db err = app.db.View(func(tx *bolt.Tx) error { _, err := NewDeviceEntryFromId(tx, fakeid) return err }) tests.Assert(t, err == ErrNotFound) // Check node does not have the device err = app.db.View(func(tx *bolt.Tx) error { node, err = NewNodeEntryFromId(tx, node.Info.Id) return err }) tests.Assert(t, err == nil) tests.Assert(t, !utils.SortedStringHas(node.Devices, fakeid)) }
func TestNewDeviceEntrySaveDelete(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() // Create a device req := &Device{ Name: "dev", Weight: 123, } nodeid := "abc" d := NewDeviceEntryFromRequest(req, nodeid) d.Info.Storage.Free = 10 d.Info.Storage.Total = 100 d.Info.Storage.Used = 1000 d.BrickAdd("abc") d.BrickAdd("def") // Save element in database err := app.db.Update(func(tx *bolt.Tx) error { return d.Save(tx) }) tests.Assert(t, err == nil) var device *DeviceEntry err = app.db.View(func(tx *bolt.Tx) error { var err error device, err = NewDeviceEntryFromId(tx, d.Info.Id) if err != nil { return err } return nil }) tests.Assert(t, err == nil) tests.Assert(t, reflect.DeepEqual(device, d)) // Delete entry which has devices err = app.db.Update(func(tx *bolt.Tx) error { var err error device, err = NewDeviceEntryFromId(tx, d.Info.Id) if err != nil { return err } err = device.Delete(tx) if err != nil { return err } return nil }) tests.Assert(t, err == ErrConflict) // Delete devices in device device.BrickDelete("abc") device.BrickDelete("def") tests.Assert(t, len(device.Bricks) == 0) err = app.db.Update(func(tx *bolt.Tx) error { return device.Save(tx) }) tests.Assert(t, err == nil) // Now try to delete the device err = app.db.Update(func(tx *bolt.Tx) error { var err error device, err = NewDeviceEntryFromId(tx, d.Info.Id) if err != nil { return err } err = device.Delete(tx) if err != nil { return err } return nil }) tests.Assert(t, err == nil) // Check device has been deleted and is not in db err = app.db.View(func(tx *bolt.Tx) error { var err error device, err = NewDeviceEntryFromId(tx, d.Info.Id) if err != nil { return err } return nil }) tests.Assert(t, err == ErrNotFound) }
func TestNodeAddDelete(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() router := mux.NewRouter() app.SetRoutes(router) // Setup the server ts := httptest.NewServer(router) defer ts.Close() // ClusterCreate JSON Request request := []byte(`{ }`) // Post nothing r, err := http.Post(ts.URL+"/clusters", "application/json", bytes.NewBuffer(request)) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusCreated) tests.Assert(t, r.Header.Get("Content-Type") == "application/json; charset=UTF-8") // Read cluster information var clusterinfo ClusterInfoResponse err = utils.GetJsonFromResponse(r, &clusterinfo) tests.Assert(t, err == nil) // Create node on this cluster request = []byte(fmt.Sprintf(`{ "cluster" : "%v", "hostnames" : { "storage" : [ "storage.hostname.com" ], "manage" : [ "manage.hostname.com" ] }, "zone" : 1 }`, clusterinfo.Id)) // Post nothing r, err = http.Post(ts.URL+"/nodes", "application/json", bytes.NewBuffer(request)) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusAccepted) location, err := r.Location() tests.Assert(t, err == nil) // Query queue until finished var node NodeInfoResponse for { r, err = http.Get(location.String()) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusOK) if r.ContentLength <= 0 { time.Sleep(time.Millisecond * 10) continue } else { // Should have node information here tests.Assert(t, r.Header.Get("Content-Type") == "application/json; charset=UTF-8") err = utils.GetJsonFromResponse(r, &node) tests.Assert(t, err == nil) break } } tests.Assert(t, len(node.Id) > 0) tests.Assert(t, len(node.Hostnames.Manage) == 1) tests.Assert(t, len(node.Hostnames.Storage) == 1) tests.Assert(t, node.Hostnames.Manage[0] == "manage.hostname.com") tests.Assert(t, node.Hostnames.Storage[0] == "storage.hostname.com") tests.Assert(t, node.Zone == 1) tests.Assert(t, node.ClusterId == clusterinfo.Id) tests.Assert(t, len(node.DevicesInfo) == 0) // Check Cluster has node r, err = http.Get(ts.URL + "/clusters/" + clusterinfo.Id) tests.Assert(t, r.StatusCode == http.StatusOK) tests.Assert(t, err == nil) tests.Assert(t, r.Header.Get("Content-Type") == "application/json; charset=UTF-8") err = utils.GetJsonFromResponse(r, &clusterinfo) tests.Assert(t, len(clusterinfo.Nodes) == 1) tests.Assert(t, clusterinfo.Nodes[0] == node.Id) // Check the data is in the database correctly var entry *NodeEntry err = app.db.View(func(tx *bolt.Tx) error { entry, err = NewNodeEntryFromId(tx, node.Id) return err }) tests.Assert(t, err == nil) tests.Assert(t, entry != nil) tests.Assert(t, entry.Info.Id == node.Id) tests.Assert(t, len(entry.Info.Hostnames.Manage) == 1) tests.Assert(t, len(entry.Info.Hostnames.Storage) == 1) tests.Assert(t, entry.Info.Hostnames.Manage[0] == node.Hostnames.Manage[0]) tests.Assert(t, entry.Info.Hostnames.Storage[0] == node.Hostnames.Storage[0]) tests.Assert(t, len(entry.Devices) == 0) // Add some devices to check if delete conflict works err = app.db.Update(func(tx *bolt.Tx) error { entry, err = NewNodeEntryFromId(tx, node.Id) if err != nil { return err } entry.DeviceAdd("123") entry.DeviceAdd("456") return entry.Save(tx) }) tests.Assert(t, err == nil) // Now delete node and check for conflict req, err := http.NewRequest("DELETE", ts.URL+"/nodes/"+node.Id, nil) tests.Assert(t, err == nil) r, err = http.DefaultClient.Do(req) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusConflict) // Check that nothing has changed in the db var cluster *ClusterEntry err = app.db.View(func(tx *bolt.Tx) error { entry, err = NewNodeEntryFromId(tx, node.Id) if err != nil { return err } cluster, err = NewClusterEntryFromId(tx, entry.Info.ClusterId) if err != nil { return err } return nil }) tests.Assert(t, err == nil) tests.Assert(t, utils.SortedStringHas(cluster.Info.Nodes, node.Id)) // Node delete the drives err = app.db.Update(func(tx *bolt.Tx) error { entry, err = NewNodeEntryFromId(tx, node.Id) if err != nil { return err } entry.DeviceDelete("123") entry.DeviceDelete("456") return entry.Save(tx) }) tests.Assert(t, err == nil) // Now delete node req, err = http.NewRequest("DELETE", ts.URL+"/nodes/"+node.Id, nil) tests.Assert(t, err == nil) r, err = http.DefaultClient.Do(req) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusOK) // Check db to make sure key is removed err = app.db.View(func(tx *bolt.Tx) error { _, err = NewNodeEntryFromId(tx, node.Id) return err }) tests.Assert(t, err == ErrNotFound) // Check the cluster does not have this node id r, err = http.Get(ts.URL + "/clusters/" + clusterinfo.Id) tests.Assert(t, r.StatusCode == http.StatusOK) tests.Assert(t, err == nil) tests.Assert(t, r.Header.Get("Content-Type") == "application/json; charset=UTF-8") err = utils.GetJsonFromResponse(r, &clusterinfo) tests.Assert(t, len(clusterinfo.Nodes) == 0) }
func TestClusterList(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() router := mux.NewRouter() app.SetRoutes(router) // Setup the server ts := httptest.NewServer(router) defer ts.Close() // Save some objects in the database numclusters := 5 err := app.db.Update(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(BOLTDB_BUCKET_CLUSTER)) if b == nil { return errors.New("Unable to open bucket") } for i := 0; i < numclusters; i++ { var entry ClusterEntry entry.Info.Id = fmt.Sprintf("%v", 5000+i) buffer, err := entry.Marshal() if err != nil { return err } err = b.Put([]byte(entry.Info.Id), buffer) if err != nil { return err } } return nil }) tests.Assert(t, err == nil) // Now that we have some data in the database, we can // make a request for the clutser list r, err := http.Get(ts.URL + "/clusters") tests.Assert(t, r.StatusCode == http.StatusOK) tests.Assert(t, err == nil) tests.Assert(t, r.Header.Get("Content-Type") == "application/json; charset=UTF-8") // Read response var msg ClusterListResponse err = utils.GetJsonFromResponse(r, &msg) tests.Assert(t, err == nil) // Thanks to BoltDB they come back in order mockid := 5000 // This is the mock id value we set above for _, id := range msg.Clusters { tests.Assert(t, id == fmt.Sprintf("%v", mockid)) mockid++ } }
func TestNewClusterEntrySaveDelete(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() // Create a cluster c := NewClusterEntryFromRequest() c.NodeAdd("node_abc") c.NodeAdd("node_def") c.VolumeAdd("vol_abc") // Save element in database err := app.db.Update(func(tx *bolt.Tx) error { return c.Save(tx) }) tests.Assert(t, err == nil) var cluster *ClusterEntry err = app.db.View(func(tx *bolt.Tx) error { var err error cluster, err = NewClusterEntryFromId(tx, c.Info.Id) if err != nil { return err } return nil }) tests.Assert(t, err == nil) tests.Assert(t, cluster.Info.Id == c.Info.Id) tests.Assert(t, len(c.Info.Nodes) == 2) tests.Assert(t, len(c.Info.Volumes) == 1) tests.Assert(t, utils.SortedStringHas(c.Info.Nodes, "node_abc")) tests.Assert(t, utils.SortedStringHas(c.Info.Nodes, "node_def")) tests.Assert(t, utils.SortedStringHas(c.Info.Volumes, "vol_abc")) // Delete entry which has devices err = app.db.Update(func(tx *bolt.Tx) error { var err error cluster, err = NewClusterEntryFromId(tx, c.Info.Id) if err != nil { return err } err = cluster.Delete(tx) if err != nil { return err } return nil }) tests.Assert(t, err == ErrConflict) // Delete devices in cluster cluster.VolumeDelete("vol_abc") tests.Assert(t, len(cluster.Info.Volumes) == 0) tests.Assert(t, len(cluster.Info.Nodes) == 2) // Save cluster err = app.db.Update(func(tx *bolt.Tx) error { return cluster.Save(tx) }) tests.Assert(t, err == nil) // Try do delete a cluster which still has nodes err = app.db.Update(func(tx *bolt.Tx) error { var err error cluster, err = NewClusterEntryFromId(tx, c.Info.Id) if err != nil { return err } err = cluster.Delete(tx) if err != nil { return err } return nil }) tests.Assert(t, err == ErrConflict) // Delete cluster cluster.NodeDelete("node_abc") cluster.NodeDelete("node_def") tests.Assert(t, len(cluster.Info.Nodes) == 0) // Save cluster err = app.db.Update(func(tx *bolt.Tx) error { return cluster.Save(tx) }) tests.Assert(t, err == nil) // Now try to delete the cluster with no elements err = app.db.Update(func(tx *bolt.Tx) error { var err error cluster, err = NewClusterEntryFromId(tx, c.Info.Id) if err != nil { return err } err = cluster.Delete(tx) if err != nil { return err } return nil }) tests.Assert(t, err == nil) // Check cluster has been deleted and is not in db err = app.db.View(func(tx *bolt.Tx) error { var err error cluster, err = NewClusterEntryFromId(tx, c.Info.Id) if err != nil { return err } return nil }) tests.Assert(t, err == ErrNotFound) }
func TestClusterDelete(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() router := mux.NewRouter() app.SetRoutes(router) // Setup the server ts := httptest.NewServer(router) defer ts.Close() // Create an entry with volumes and nodes entries := make([]*ClusterEntry, 0) entry := NewClusterEntry() entry.Info.Id = "a1" for _, node := range []string{"a1", "a2", "a3"} { entry.NodeAdd(node) } for _, vol := range []string{"b1", "b2", "b3"} { entry.VolumeAdd(vol) } entries = append(entries, entry) // Create an entry with only volumes entry = NewClusterEntry() entry.Info.Id = "a2" for _, vol := range []string{"b1", "b2", "b3"} { entry.VolumeAdd(vol) } entries = append(entries, entry) // Create an entry with only nodes entry = NewClusterEntry() entry.Info.Id = "a3" for _, node := range []string{"a1", "a2", "a3"} { entry.NodeAdd(node) } entries = append(entries, entry) // Create an empty entry entry = NewClusterEntry() entry.Info.Id = "000" entries = append(entries, entry) // Save the info in the database err := app.db.Update(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(BOLTDB_BUCKET_CLUSTER)) if b == nil { return errors.New("Unable to open bucket") } for _, entry := range entries { buffer, err := entry.Marshal() if err != nil { return err } err = b.Put([]byte(entry.Info.Id), buffer) if err != nil { return err } } return nil }) tests.Assert(t, err == nil) // Check that we cannot delete a cluster with elements req, err := http.NewRequest("DELETE", ts.URL+"/clusters/"+"a1", nil) tests.Assert(t, err == nil) r, err := http.DefaultClient.Do(req) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusConflict) // Check that we cannot delete a cluster with volumes req, err = http.NewRequest("DELETE", ts.URL+"/clusters/"+"a2", nil) tests.Assert(t, err == nil) r, err = http.DefaultClient.Do(req) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusConflict) // Check that we cannot delete a cluster with nodes req, err = http.NewRequest("DELETE", ts.URL+"/clusters/"+"a3", nil) tests.Assert(t, err == nil) r, err = http.DefaultClient.Do(req) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusConflict) // Delete cluster with no elements req, err = http.NewRequest("DELETE", ts.URL+"/clusters/"+"000", nil) tests.Assert(t, err == nil) r, err = http.DefaultClient.Do(req) tests.Assert(t, err == nil) tests.Assert(t, r.StatusCode == http.StatusOK) // Check database still has a1,a2, and a3, but not '000' err = app.db.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(BOLTDB_BUCKET_CLUSTER)) if b == nil { return errors.New("Unable to open bucket") } // Check that the ids are still in the database for _, id := range []string{"a1", "a2", "a3"} { buffer := b.Get([]byte(id)) if buffer == nil { return errors.New(fmt.Sprintf("Id %v not found", id)) } } // Check that the id 000 is no longer in the database buffer := b.Get([]byte("000")) if buffer != nil { return errors.New(fmt.Sprintf("Id 000 still in database and was deleted")) } return nil }) tests.Assert(t, err == nil, err) }
func TestClusterInfo(t *testing.T) { tmpfile := tests.Tempfile() defer os.Remove(tmpfile) // Patch dbfilename so that it is restored at the end of the tests defer tests.Patch(&dbfilename, tmpfile).Restore() // Create the app app := NewApp() defer app.Close() router := mux.NewRouter() app.SetRoutes(router) // Setup the server ts := httptest.NewServer(router) defer ts.Close() // Create a new ClusterInfo entry := NewClusterEntry() entry.Info.Id = "123" for _, node := range []string{"a1", "a2", "a3"} { entry.NodeAdd(node) } for _, vol := range []string{"b1", "b2", "b3"} { entry.VolumeAdd(vol) } // Save the info in the database err := app.db.Update(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(BOLTDB_BUCKET_CLUSTER)) if b == nil { return errors.New("Unable to open bucket") } buffer, err := entry.Marshal() if err != nil { return err } err = b.Put([]byte(entry.Info.Id), buffer) if err != nil { return err } return nil }) tests.Assert(t, err == nil) // Now that we have some data in the database, we can // make a request for the clutser list r, err := http.Get(ts.URL + "/clusters/" + "123") tests.Assert(t, r.StatusCode == http.StatusOK) tests.Assert(t, err == nil) tests.Assert(t, r.Header.Get("Content-Type") == "application/json; charset=UTF-8") // Read response var msg ClusterInfoResponse err = utils.GetJsonFromResponse(r, &msg) tests.Assert(t, err == nil) // Check values are equal tests.Assert(t, entry.Info.Id == msg.Id) tests.Assert(t, entry.Info.Volumes[0] == msg.Volumes[0]) tests.Assert(t, entry.Info.Volumes[1] == msg.Volumes[1]) tests.Assert(t, entry.Info.Volumes[2] == msg.Volumes[2]) tests.Assert(t, entry.Info.Nodes[0] == msg.Nodes[0]) tests.Assert(t, entry.Info.Nodes[1] == msg.Nodes[1]) tests.Assert(t, entry.Info.Nodes[2] == msg.Nodes[2]) }