瀏覽代碼

Merge pull request #35 from tuna/dev

Dev
bigeagle 9 年之前
父節點
當前提交
24bdfe5b33
共有 8 個文件被更改,包括 138 次插入5 次删除
  1. 1 4
      .gitignore
  2. 2 0
      .testandcover.bash
  3. 1 0
      .travis.yml
  4. 16 0
      Makefile
  5. 29 0
      cmd/tunasync/tunasync.go
  6. 67 0
      cmd/tunasynctl/tunasynctl.go
  7. 3 0
      internal/msg.go
  8. 19 1
      worker/worker.go

+ 1 - 4
.gitignore

@@ -1,4 +1 @@
-*.swp
-*~
-/*.cov
-node_modules
+/build

+ 2 - 0
.testandcover.bash

@@ -8,6 +8,8 @@ function die() {
 
 export GOPATH=`pwd`:$GOPATH
 
+make
+
 # Initialize profile.cov
 echo "mode: count" > profile.cov
 

+ 1 - 0
.travis.yml

@@ -4,6 +4,7 @@ go:
 
 before_install:
     - sudo apt-get install cgroup-bin
+    - go get github.com/smartystreets/goconvey
     - go get golang.org/x/tools/cmd/cover
     - go get -v github.com/mattn/goveralls
 

+ 16 - 0
Makefile

@@ -0,0 +1,16 @@
+LDFLAGS="-X main.buildstamp=`date -u '+%s'` -X main.githash=`git rev-parse HEAD`"
+
+all: get tunasync tunasynctl
+
+get: 
+	go get ./cmd/tunasync
+	go get ./cmd/tunasynctl
+
+build:
+	mkdir -p build
+
+tunasync: build
+	go build -o build/tunasync -ldflags ${LDFLAGS} github.com/tuna/tunasync/cmd/tunasync
+
+tunasynctl: build
+	go build -o build/tunasynctl -ldflags ${LDFLAGS} github.com/tuna/tunasync/cmd/tunasynctl

+ 29 - 0
cmd/tunasync/tunasync.go

@@ -1,8 +1,10 @@
 package main
 
 import (
+	"fmt"
 	"os"
 	"os/signal"
+	"strconv"
 	"syscall"
 	"time"
 
@@ -16,6 +18,11 @@ import (
 	"github.com/tuna/tunasync/worker"
 )
 
+var (
+	buildstamp = ""
+	githash    = "No githash provided"
+)
+
 var logger = logging.MustGetLogger("tunasync")
 
 func startManager(c *cli.Context) {
@@ -99,6 +106,28 @@ func startWorker(c *cli.Context) {
 }
 
 func main() {
+
+	cli.VersionPrinter = func(c *cli.Context) {
+		var builddate string
+		if buildstamp == "" {
+			builddate = "No build date provided"
+		} else {
+			ts, err := strconv.Atoi(buildstamp)
+			if err != nil {
+				builddate = "No build date provided"
+			} else {
+				t := time.Unix(int64(ts), 0)
+				builddate = t.String()
+			}
+		}
+		fmt.Printf(
+			"Version: %s\n"+
+				"Git Hash: %s\n"+
+				"Build Date: %s\n",
+			c.App.Version, githash, builddate,
+		)
+	}
+
 	app := cli.NewApp()
 	app.EnableBashCompletion = true
 	app.Version = "0.1"

+ 67 - 0
cmd/tunasynctl/tunasynctl.go

@@ -6,7 +6,9 @@ import (
 	"io/ioutil"
 	"net/http"
 	"os"
+	"strconv"
 	"strings"
+	"time"
 
 	"github.com/BurntSushi/toml"
 	"github.com/codegangsta/cli"
@@ -15,6 +17,11 @@ import (
 	tunasync "github.com/tuna/tunasync/internal"
 )
 
+var (
+	buildstamp = ""
+	githash    = "No githash provided"
+)
+
 const (
 	listJobsPath    = "/jobs"
 	listWorkersPath = "/workers"
@@ -225,7 +232,61 @@ func cmdJob(cmd tunasync.CmdVerb) cli.ActionFunc {
 	}
 }
 
+func cmdWorker(cmd tunasync.CmdVerb) cli.ActionFunc {
+	return func(c *cli.Context) error {
+		cmd := tunasync.ClientCmd{
+			Cmd:      cmd,
+			WorkerID: c.String("worker"),
+		}
+		resp, err := tunasync.PostJSON(baseURL+cmdPath, cmd, client)
+		if err != nil {
+			return cli.NewExitError(
+				fmt.Sprintf("Failed to correctly send command: %s",
+					err.Error()),
+				1)
+		}
+		defer resp.Body.Close()
+
+		if resp.StatusCode != http.StatusOK {
+			body, err := ioutil.ReadAll(resp.Body)
+			if err != nil {
+				return cli.NewExitError(
+					fmt.Sprintf("Failed to parse response: %s", err.Error()),
+					1)
+			}
+
+			return cli.NewExitError(fmt.Sprintf("Failed to correctly send"+
+				" command: HTTP status code is not 200: %s", body),
+				1)
+		}
+		logger.Info("Succesfully send command")
+
+		return nil
+	}
+}
+
 func main() {
+	cli.VersionPrinter = func(c *cli.Context) {
+		var builddate string
+		if buildstamp == "" {
+			builddate = "No build date provided"
+		} else {
+			ts, err := strconv.Atoi(buildstamp)
+			if err != nil {
+				builddate = "No build date provided"
+			} else {
+				t := time.Unix(int64(ts), 0)
+				builddate = t.String()
+			}
+		}
+		fmt.Printf(
+			"Version: %s\n"+
+				"Git Hash: %s\n"+
+				"Build Date: %s\n",
+			c.App.Version, githash, builddate,
+		)
+	}
+
 	app := cli.NewApp()
 	app.EnableBashCompletion = true
 	app.Version = "0.1"
@@ -304,6 +365,12 @@ func main() {
 			Flags:  append(commonFlags, cmdFlags...),
 			Action: initializeWrapper(cmdJob(tunasync.CmdRestart)),
 		},
+		{
+			Name:   "reload",
+			Usage:  "Tell worker to reload configurations",
+			Flags:  append(commonFlags, cmdFlags...),
+			Action: initializeWrapper(cmdWorker(tunasync.CmdReload)),
+		},
 		{
 			Name:   "ping",
 			Flags:  append(commonFlags, cmdFlags...),

+ 3 - 0
internal/msg.go

@@ -35,6 +35,7 @@ const (
 	CmdDisable         // disable the job (stops goroutine)
 	CmdRestart         // restart syncing
 	CmdPing            // ensure the goroutine is alive
+	CmdReload          // reload mirror config
 )
 
 func (c CmdVerb) String() string {
@@ -49,6 +50,8 @@ func (c CmdVerb) String() string {
 		return "restart"
 	case CmdPing:
 		return "ping"
+	case CmdReload:
+		return "reload"
 	}
 	return "unknown"
 }

+ 19 - 1
worker/worker.go

@@ -3,7 +3,9 @@ package worker
 import (
 	"fmt"
 	"net/http"
+	"os"
 	"sync"
+	"syscall"
 	"time"
 
 	"github.com/gin-gonic/gin"
@@ -185,16 +187,32 @@ func (w *Worker) makeHTTPServer() {
 			return
 		}
 
+		logger.Noticef("Received command: %v", cmd)
+
+		if cmd.MirrorID == "" {
+			// worker-level commands
+			switch cmd.Cmd {
+			case CmdReload:
+				// send myself a SIGHUP
+				pid := os.Getpid()
+				syscall.Kill(pid, syscall.SIGHUP)
+			default:
+				c.JSON(http.StatusNotAcceptable, gin.H{"msg": "Invalid Command"})
+				return
+			}
+		}
+
+		// job level comands
 		job, ok := w.jobs[cmd.MirrorID]
 		if !ok {
 			c.JSON(http.StatusNotFound, gin.H{"msg": fmt.Sprintf("Mirror ``%s'' not found", cmd.MirrorID)})
 			return
 		}
 
-		logger.Noticef("Received command: %v", cmd)
 		// No matter what command, the existing job
 		// schedule should be flushed
 		w.schedule.Remove(job.Name())
+
 		// if job disabled, start them first
 		switch cmd.Cmd {
 		case CmdStart, CmdRestart: