mirror of
https://github.com/tuna/tunasync.git
synced 2025-06-15 05:52:43 +00:00
Merge pull request #80 from tuna/dev
Fix the "list" command of tunasynctl
This commit is contained in:
commit
285ffb2f2f
@ -140,8 +140,7 @@ func listWorkers(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func listJobs(c *cli.Context) error {
|
func listJobs(c *cli.Context) error {
|
||||||
// FIXME: there should be an API on manager server side that return MirrorStatus list to tunasynctl
|
var jobs []tunasync.WebMirrorStatus
|
||||||
var jobs []tunasync.MirrorStatus
|
|
||||||
if c.Bool("all") {
|
if c.Bool("all") {
|
||||||
_, err := tunasync.GetJSON(baseURL+listJobsPath, &jobs, client)
|
_, err := tunasync.GetJSON(baseURL+listJobsPath, &jobs, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -158,10 +157,10 @@ func listJobs(c *cli.Context) error {
|
|||||||
fmt.Sprintf("Usage Error: jobs command need at"+
|
fmt.Sprintf("Usage Error: jobs command need at"+
|
||||||
" least one arguments or \"--all\" flag."), 1)
|
" least one arguments or \"--all\" flag."), 1)
|
||||||
}
|
}
|
||||||
ans := make(chan []tunasync.MirrorStatus, len(args))
|
ans := make(chan []tunasync.WebMirrorStatus, len(args))
|
||||||
for _, workerID := range args {
|
for _, workerID := range args {
|
||||||
go func(workerID string) {
|
go func(workerID string) {
|
||||||
var workerJobs []tunasync.MirrorStatus
|
var workerJobs []tunasync.WebMirrorStatus
|
||||||
_, err := tunasync.GetJSON(fmt.Sprintf("%s/workers/%s/jobs",
|
_, err := tunasync.GetJSON(fmt.Sprintf("%s/workers/%s/jobs",
|
||||||
baseURL, workerID), &workerJobs, client)
|
baseURL, workerID), &workerJobs, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -13,6 +13,7 @@ type MirrorStatus struct {
|
|||||||
IsMaster bool `json:"is_master"`
|
IsMaster bool `json:"is_master"`
|
||||||
Status SyncStatus `json:"status"`
|
Status SyncStatus `json:"status"`
|
||||||
LastUpdate time.Time `json:"last_update"`
|
LastUpdate time.Time `json:"last_update"`
|
||||||
|
LastEnded time.Time `json:"last_ended"`
|
||||||
Upstream string `json:"upstream"`
|
Upstream string `json:"upstream"`
|
||||||
Size string `json:"size"`
|
Size string `json:"size"`
|
||||||
ErrorMsg string `json:"error_msg"`
|
ErrorMsg string `json:"error_msg"`
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
package manager
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
. "github.com/tuna/tunasync/internal"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type textTime struct {
|
type textTime struct {
|
||||||
@ -38,24 +36,28 @@ func (t *stampTime) UnmarshalJSON(b []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// webMirrorStatus is the mirror status to be shown in the web page
|
// WebMirrorStatus is the mirror status to be shown in the web page
|
||||||
type webMirrorStatus struct {
|
type WebMirrorStatus struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
IsMaster bool `json:"is_master"`
|
IsMaster bool `json:"is_master"`
|
||||||
Status SyncStatus `json:"status"`
|
Status SyncStatus `json:"status"`
|
||||||
LastUpdate textTime `json:"last_update"`
|
LastUpdate textTime `json:"last_update"`
|
||||||
LastUpdateTs stampTime `json:"last_update_ts"`
|
LastUpdateTs stampTime `json:"last_update_ts"`
|
||||||
|
LastEnded textTime `json:"last_ended"`
|
||||||
|
LastEndedTs stampTime `json:"last_ended_ts"`
|
||||||
Upstream string `json:"upstream"`
|
Upstream string `json:"upstream"`
|
||||||
Size string `json:"size"` // approximate size
|
Size string `json:"size"` // approximate size
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertMirrorStatus(m MirrorStatus) webMirrorStatus {
|
func BuildWebMirrorStatus(m MirrorStatus) WebMirrorStatus {
|
||||||
return webMirrorStatus{
|
return WebMirrorStatus{
|
||||||
Name: m.Name,
|
Name: m.Name,
|
||||||
IsMaster: m.IsMaster,
|
IsMaster: m.IsMaster,
|
||||||
Status: m.Status,
|
Status: m.Status,
|
||||||
LastUpdate: textTime{m.LastUpdate},
|
LastUpdate: textTime{m.LastUpdate},
|
||||||
LastUpdateTs: stampTime{m.LastUpdate},
|
LastUpdateTs: stampTime{m.LastUpdate},
|
||||||
|
LastEnded: textTime{m.LastEnded},
|
||||||
|
LastEndedTs: stampTime{m.LastEnded},
|
||||||
Upstream: m.Upstream,
|
Upstream: m.Upstream,
|
||||||
Size: m.Size,
|
Size: m.Size,
|
||||||
}
|
}
|
76
internal/status_web_test.go
Normal file
76
internal/status_web_test.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStatus(t *testing.T) {
|
||||||
|
Convey("status json ser-de should work", t, func() {
|
||||||
|
tz := "Asia/Tokyo"
|
||||||
|
loc, err := time.LoadLocation(tz)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
t := time.Date(2016, time.April, 16, 23, 8, 10, 0, loc)
|
||||||
|
m := WebMirrorStatus{
|
||||||
|
Name: "tunalinux",
|
||||||
|
Status: Success,
|
||||||
|
LastUpdate: textTime{t},
|
||||||
|
LastUpdateTs: stampTime{t},
|
||||||
|
LastEnded: textTime{t},
|
||||||
|
LastEndedTs: stampTime{t},
|
||||||
|
Size: "5GB",
|
||||||
|
Upstream: "rsync://mirrors.tuna.tsinghua.edu.cn/tunalinux/",
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(m)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
//fmt.Println(string(b))
|
||||||
|
var m2 WebMirrorStatus
|
||||||
|
err = json.Unmarshal(b, &m2)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
// fmt.Printf("%#v", m2)
|
||||||
|
So(m2.Name, ShouldEqual, m.Name)
|
||||||
|
So(m2.Status, ShouldEqual, m.Status)
|
||||||
|
So(m2.LastUpdate.Unix(), ShouldEqual, m.LastUpdate.Unix())
|
||||||
|
So(m2.LastUpdateTs.Unix(), ShouldEqual, m.LastUpdate.Unix())
|
||||||
|
So(m2.LastUpdate.UnixNano(), ShouldEqual, m.LastUpdate.UnixNano())
|
||||||
|
So(m2.LastUpdateTs.UnixNano(), ShouldEqual, m.LastUpdate.UnixNano())
|
||||||
|
So(m2.LastEnded.Unix(), ShouldEqual, m.LastEnded.Unix())
|
||||||
|
So(m2.LastEndedTs.Unix(), ShouldEqual, m.LastEnded.Unix())
|
||||||
|
So(m2.LastEnded.UnixNano(), ShouldEqual, m.LastEnded.UnixNano())
|
||||||
|
So(m2.LastEndedTs.UnixNano(), ShouldEqual, m.LastEnded.UnixNano())
|
||||||
|
So(m2.Size, ShouldEqual, m.Size)
|
||||||
|
So(m2.Upstream, ShouldEqual, m.Upstream)
|
||||||
|
})
|
||||||
|
Convey("BuildWebMirrorStatus should work", t, func() {
|
||||||
|
m := MirrorStatus{
|
||||||
|
Name: "arch-sync3",
|
||||||
|
Worker: "testWorker",
|
||||||
|
IsMaster: true,
|
||||||
|
Status: Failed,
|
||||||
|
LastUpdate: time.Now().Add(-time.Minute * 30),
|
||||||
|
LastEnded: time.Now(),
|
||||||
|
Upstream: "mirrors.tuna.tsinghua.edu.cn",
|
||||||
|
Size: "4GB",
|
||||||
|
}
|
||||||
|
|
||||||
|
var m2 WebMirrorStatus
|
||||||
|
m2 = BuildWebMirrorStatus(m)
|
||||||
|
// fmt.Printf("%#v", m2)
|
||||||
|
So(m2.Name, ShouldEqual, m.Name)
|
||||||
|
So(m2.Status, ShouldEqual, m.Status)
|
||||||
|
So(m2.LastUpdate.Unix(), ShouldEqual, m.LastUpdate.Unix())
|
||||||
|
So(m2.LastUpdateTs.Unix(), ShouldEqual, m.LastUpdate.Unix())
|
||||||
|
So(m2.LastUpdate.UnixNano(), ShouldEqual, m.LastUpdate.UnixNano())
|
||||||
|
So(m2.LastUpdateTs.UnixNano(), ShouldEqual, m.LastUpdate.UnixNano())
|
||||||
|
So(m2.LastEnded.Unix(), ShouldEqual, m.LastEnded.Unix())
|
||||||
|
So(m2.LastEndedTs.Unix(), ShouldEqual, m.LastEnded.Unix())
|
||||||
|
So(m2.LastEnded.UnixNano(), ShouldEqual, m.LastEnded.UnixNano())
|
||||||
|
So(m2.LastEndedTs.UnixNano(), ShouldEqual, m.LastEnded.UnixNano())
|
||||||
|
So(m2.Size, ShouldEqual, m.Size)
|
||||||
|
So(m2.Upstream, ShouldEqual, m.Upstream)
|
||||||
|
})
|
||||||
|
}
|
@ -65,6 +65,7 @@ func TestBoltAdapter(t *testing.T) {
|
|||||||
IsMaster: true,
|
IsMaster: true,
|
||||||
Status: Success,
|
Status: Success,
|
||||||
LastUpdate: time.Now(),
|
LastUpdate: time.Now(),
|
||||||
|
LastEnded: time.Now(),
|
||||||
Upstream: "mirrors.tuna.tsinghua.edu.cn",
|
Upstream: "mirrors.tuna.tsinghua.edu.cn",
|
||||||
Size: "3GB",
|
Size: "3GB",
|
||||||
},
|
},
|
||||||
@ -73,7 +74,8 @@ func TestBoltAdapter(t *testing.T) {
|
|||||||
Worker: testWorkerIDs[1],
|
Worker: testWorkerIDs[1],
|
||||||
IsMaster: true,
|
IsMaster: true,
|
||||||
Status: Disabled,
|
Status: Disabled,
|
||||||
LastUpdate: time.Now(),
|
LastUpdate: time.Now().Add(-time.Hour),
|
||||||
|
LastEnded: time.Now(),
|
||||||
Upstream: "mirrors.tuna.tsinghua.edu.cn",
|
Upstream: "mirrors.tuna.tsinghua.edu.cn",
|
||||||
Size: "4GB",
|
Size: "4GB",
|
||||||
},
|
},
|
||||||
@ -82,7 +84,8 @@ func TestBoltAdapter(t *testing.T) {
|
|||||||
Worker: testWorkerIDs[1],
|
Worker: testWorkerIDs[1],
|
||||||
IsMaster: true,
|
IsMaster: true,
|
||||||
Status: Success,
|
Status: Success,
|
||||||
LastUpdate: time.Now(),
|
LastUpdate: time.Now().Add(-time.Second),
|
||||||
|
LastEnded: time.Now(),
|
||||||
Upstream: "mirrors.tuna.tsinghua.edu.cn",
|
Upstream: "mirrors.tuna.tsinghua.edu.cn",
|
||||||
Size: "4GB",
|
Size: "4GB",
|
||||||
},
|
},
|
||||||
|
@ -135,11 +135,11 @@ func (s *Manager) listAllJobs(c *gin.Context) {
|
|||||||
s.returnErrJSON(c, http.StatusInternalServerError, err)
|
s.returnErrJSON(c, http.StatusInternalServerError, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
webMirStatusList := []webMirrorStatus{}
|
webMirStatusList := []WebMirrorStatus{}
|
||||||
for _, m := range mirrorStatusList {
|
for _, m := range mirrorStatusList {
|
||||||
webMirStatusList = append(
|
webMirStatusList = append(
|
||||||
webMirStatusList,
|
webMirStatusList,
|
||||||
convertMirrorStatus(m),
|
BuildWebMirrorStatus(m),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, webMirStatusList)
|
c.JSON(http.StatusOK, webMirStatusList)
|
||||||
@ -242,6 +242,11 @@ func (s *Manager) updateJobOfWorker(c *gin.Context) {
|
|||||||
} else {
|
} else {
|
||||||
status.LastUpdate = curStatus.LastUpdate
|
status.LastUpdate = curStatus.LastUpdate
|
||||||
}
|
}
|
||||||
|
if status.Status == Success || status.Status == Failed {
|
||||||
|
status.LastEnded = time.Now()
|
||||||
|
} else {
|
||||||
|
status.LastEnded = curStatus.LastEnded
|
||||||
|
}
|
||||||
|
|
||||||
// Only message with meaningful size updates the mirror size
|
// Only message with meaningful size updates the mirror size
|
||||||
if len(curStatus.Size) > 0 && curStatus.Size != "unknown" {
|
if len(curStatus.Size) > 0 && curStatus.Size != "unknown" {
|
||||||
|
@ -121,11 +121,12 @@ func TestHTTPServer(t *testing.T) {
|
|||||||
So(m.Size, ShouldEqual, status.Size)
|
So(m.Size, ShouldEqual, status.Size)
|
||||||
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
||||||
So(time.Now().Sub(m.LastUpdate), ShouldBeLessThan, 1*time.Second)
|
So(time.Now().Sub(m.LastUpdate), ShouldBeLessThan, 1*time.Second)
|
||||||
|
So(time.Now().Sub(m.LastEnded), ShouldBeLessThan, 1*time.Second)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("list all job status of all workers", func(ctx C) {
|
Convey("list all job status of all workers", func(ctx C) {
|
||||||
var ms []webMirrorStatus
|
var ms []WebMirrorStatus
|
||||||
resp, err := GetJSON(baseURL+"/jobs", &ms, nil)
|
resp, err := GetJSON(baseURL+"/jobs", &ms, nil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode, ShouldEqual, http.StatusOK)
|
So(resp.StatusCode, ShouldEqual, http.StatusOK)
|
||||||
@ -137,6 +138,7 @@ func TestHTTPServer(t *testing.T) {
|
|||||||
So(m.Size, ShouldEqual, status.Size)
|
So(m.Size, ShouldEqual, status.Size)
|
||||||
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
||||||
So(time.Now().Sub(m.LastUpdate.Time), ShouldBeLessThan, 1*time.Second)
|
So(time.Now().Sub(m.LastUpdate.Time), ShouldBeLessThan, 1*time.Second)
|
||||||
|
So(time.Now().Sub(m.LastEnded.Time), ShouldBeLessThan, 1*time.Second)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -166,6 +168,7 @@ func TestHTTPServer(t *testing.T) {
|
|||||||
So(m.Size, ShouldEqual, "5GB")
|
So(m.Size, ShouldEqual, "5GB")
|
||||||
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
||||||
So(time.Now().Sub(m.LastUpdate), ShouldBeLessThan, 1*time.Second)
|
So(time.Now().Sub(m.LastUpdate), ShouldBeLessThan, 1*time.Second)
|
||||||
|
So(time.Now().Sub(m.LastEnded), ShouldBeLessThan, 1*time.Second)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -180,6 +183,32 @@ func TestHTTPServer(t *testing.T) {
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode, ShouldEqual, http.StatusInternalServerError)
|
So(resp.StatusCode, ShouldEqual, http.StatusInternalServerError)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// what if status changed to failed
|
||||||
|
status.Status = Failed
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
resp, err = PostJSON(fmt.Sprintf("%s/workers/%s/jobs/%s", baseURL, status.Worker, status.Name), status, nil)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp.StatusCode, ShouldEqual, http.StatusOK)
|
||||||
|
|
||||||
|
Convey("What if syncing job failed", func(ctx C) {
|
||||||
|
var ms []MirrorStatus
|
||||||
|
resp, err := GetJSON(baseURL+"/workers/test_worker1/jobs", &ms, nil)
|
||||||
|
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp.StatusCode, ShouldEqual, http.StatusOK)
|
||||||
|
// err = json.NewDecoder(resp.Body).Decode(&mirrorStatusList)
|
||||||
|
m := ms[0]
|
||||||
|
So(m.Name, ShouldEqual, status.Name)
|
||||||
|
So(m.Worker, ShouldEqual, status.Worker)
|
||||||
|
So(m.Status, ShouldEqual, status.Status)
|
||||||
|
So(m.Upstream, ShouldEqual, status.Upstream)
|
||||||
|
So(m.Size, ShouldEqual, status.Size)
|
||||||
|
So(m.IsMaster, ShouldEqual, status.IsMaster)
|
||||||
|
So(time.Now().Sub(m.LastUpdate), ShouldBeGreaterThan, 3*time.Second)
|
||||||
|
So(time.Now().Sub(m.LastEnded), ShouldBeLessThan, 1*time.Second)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("update mirror status of an inexisted worker", func(ctx C) {
|
Convey("update mirror status of an inexisted worker", func(ctx C) {
|
||||||
@ -190,6 +219,7 @@ func TestHTTPServer(t *testing.T) {
|
|||||||
IsMaster: true,
|
IsMaster: true,
|
||||||
Status: Success,
|
Status: Success,
|
||||||
LastUpdate: time.Now(),
|
LastUpdate: time.Now(),
|
||||||
|
LastEnded: time.Now(),
|
||||||
Upstream: "mirrors.tuna.tsinghua.edu.cn",
|
Upstream: "mirrors.tuna.tsinghua.edu.cn",
|
||||||
Size: "4GB",
|
Size: "4GB",
|
||||||
}
|
}
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
package manager
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
tunasync "github.com/tuna/tunasync/internal"
|
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestStatus(t *testing.T) {
|
|
||||||
Convey("status json ser-de should work", t, func() {
|
|
||||||
tz := "Asia/Tokyo"
|
|
||||||
loc, err := time.LoadLocation(tz)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
t := time.Date(2016, time.April, 16, 23, 8, 10, 0, loc)
|
|
||||||
m := webMirrorStatus{
|
|
||||||
Name: "tunalinux",
|
|
||||||
Status: tunasync.Success,
|
|
||||||
LastUpdate: textTime{t},
|
|
||||||
LastUpdateTs: stampTime{t},
|
|
||||||
Size: "5GB",
|
|
||||||
Upstream: "rsync://mirrors.tuna.tsinghua.edu.cn/tunalinux/",
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := json.Marshal(m)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
//fmt.Println(string(b))
|
|
||||||
var m2 webMirrorStatus
|
|
||||||
err = json.Unmarshal(b, &m2)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
// fmt.Printf("%#v", m2)
|
|
||||||
So(m2.Name, ShouldEqual, m.Name)
|
|
||||||
So(m2.Status, ShouldEqual, m.Status)
|
|
||||||
So(m2.LastUpdate.Unix(), ShouldEqual, m.LastUpdate.Unix())
|
|
||||||
So(m2.LastUpdateTs.Unix(), ShouldEqual, m.LastUpdate.Unix())
|
|
||||||
So(m2.LastUpdate.UnixNano(), ShouldEqual, m.LastUpdate.UnixNano())
|
|
||||||
So(m2.LastUpdateTs.UnixNano(), ShouldEqual, m.LastUpdate.UnixNano())
|
|
||||||
So(m2.Size, ShouldEqual, m.Size)
|
|
||||||
So(m2.Upstream, ShouldEqual, m.Upstream)
|
|
||||||
})
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user