From 6948db175714c25ee2f2dc8825d6f0d2011b7b46 Mon Sep 17 00:00:00 2001 From: bigeagle Date: Thu, 21 Apr 2016 23:35:49 +0800 Subject: [PATCH] feature(worker): cmd_provider, first part, no test, fix me --- worker/cmd_provider.go | 114 ++++++++++++++++++++++++++++++++++++++++ worker/provider_test.go | 1 + 2 files changed, 115 insertions(+) create mode 100644 worker/cmd_provider.go diff --git a/worker/cmd_provider.go b/worker/cmd_provider.go new file mode 100644 index 0000000..36cc700 --- /dev/null +++ b/worker/cmd_provider.go @@ -0,0 +1,114 @@ +package worker + +import ( + "os" + "os/exec" + "strings" + + "github.com/anmitsu/go-shlex" + "github.com/codeskyblue/go-sh" +) + +type cmdConfig struct { + name string + upstreamURL, command string + workingDir, logDir, logFile string + interval int + env map[string]string +} + +type cmdProvider struct { + baseProvider + cmdConfig + cmd []string + session *sh.Session +} + +func newCmdProvider(c cmdConfig) (*cmdProvider, error) { + // TODO: check config options + provider := &cmdProvider{ + baseProvider: baseProvider{ + name: c.name, + ctx: NewContext(), + interval: c.interval, + }, + cmdConfig: c, + } + + provider.ctx.Set(_WorkingDirKey, c.workingDir) + provider.ctx.Set(_LogDirKey, c.logDir) + provider.ctx.Set(_LogFileKey, c.logFile) + + cmd, err := shlex.Split(c.command, true) + if err != nil { + return nil, err + } + provider.cmd = cmd + + return provider, nil +} + +// Copied from go-sh +func newEnviron(env map[string]string, inherit bool) []string { //map[string]string { + environ := make([]string, 0, len(env)) + if inherit { + for _, line := range os.Environ() { + // if os environment and env collapses, + // omit the os one + k := strings.Split(line, "=")[0] + if _, ok := env[k]; ok { + continue + } + environ = append(environ, line) + } + } + for k, v := range env { + environ = append(environ, k+"="+v) + } + return environ +} + +// TODO: implement this +func (p *cmdProvider) Run() error { + var cmd *exec.Cmd + if len(p.cmd) == 1 { + cmd = exec.Command(p.cmd[0]) + } else if len(p.cmd) > 1 { + c := p.cmd[0] + args := p.cmd[1:] + cmd = exec.Command(c, args...) + } else if len(p.cmd) == 0 { + panic("Command length should be at least 1!") + } + cmd.Dir = p.WorkingDir() + + env := map[string]string{ + "TUNASYNC_MIRROR_NAME": p.Name(), + "TUNASYNC_WORKING_DIR": p.WorkingDir(), + "TUNASYNC_UPSTREAM_URL": p.upstreamURL, + "TUNASYNC_LOG_FILE": p.LogFile(), + } + for k, v := range p.env { + env[k] = v + } + cmd.Env = newEnviron(env, true) + + logFile, err := os.OpenFile(p.LogFile(), os.O_WRONLY, 0644) + if err != nil { + return err + } + cmd.Stdout = logFile + cmd.Stderr = logFile + + return cmd.Start() +} + +// TODO: implement this +func (p *cmdProvider) Terminate() { + +} + +// TODO: implement this +func (p *cmdProvider) Hooks() { + +} diff --git a/worker/provider_test.go b/worker/provider_test.go index 7374da8..ce09316 100644 --- a/worker/provider_test.go +++ b/worker/provider_test.go @@ -26,6 +26,7 @@ func TestRsyncProvider(t *testing.T) { So(provider.WorkingDir(), ShouldEqual, c.workingDir) So(provider.LogDir(), ShouldEqual, c.logDir) So(provider.LogFile(), ShouldEqual, c.logFile) + So(provider.Interval(), ShouldEqual, c.interval) Convey("When entering a context (auto exit)", func() { func() {