diff --git a/deploy-agent b/deploy-agent new file mode 100755 index 0000000..034e162 Binary files /dev/null and b/deploy-agent differ diff --git a/deploy.go b/deploy.go index 898ab3f..9f7aea4 100644 --- a/deploy.go +++ b/deploy.go @@ -8,29 +8,28 @@ import ( "log" "github.com/tsuru/tsuru/exec" - "github.com/tsuru/tsuru/fs" ) -func build(c Client, appName string, cmd []string, filesystem fs.Fs, executor exec.Executor) { +func build(c Client, appName string, cmd []string, fs Filesystem, executor exec.Executor) { log.SetFlags(0) envs, err := c.getAppEnvs(appName) if err != nil { log.Fatal(err) } - err = execScript(cmd, envs, nil, filesystem, executor) + err = execScript(cmd, envs, nil, fs, executor) if err != nil { log.Fatal(err) } } -func deploy(c Client, appName string, filesystem fs.Fs, executor exec.Executor) { +func deploy(c Client, appName string, fs Filesystem, executor exec.Executor) { log.SetFlags(0) var yamlData TsuruYaml envs, err := c.registerUnit(appName, yamlData) if err != nil { log.Fatal(err) } - diff, firstDeploy, err := readDiffDeploy(filesystem) + diff, firstDeploy, err := readDiffDeploy(fs) if err != nil { log.Fatal(err) } @@ -40,15 +39,15 @@ func deploy(c Client, appName string, filesystem fs.Fs, executor exec.Executor) log.Fatal(err) } } - yamlData, err = loadTsuruYaml(filesystem) + yamlData, err = loadTsuruYaml(fs) if err != nil { log.Fatal(err) } - err = buildHooks(yamlData, envs, filesystem, executor) + err = buildHooks(yamlData, envs, fs, executor) if err != nil { log.Fatal(err) } - err = loadProcesses(&yamlData, filesystem) + err = loadProcesses(&yamlData, fs) if err != nil { log.Fatal(err) } diff --git a/filesystem.go b/filesystem.go new file mode 100644 index 0000000..1a076e3 --- /dev/null +++ b/filesystem.go @@ -0,0 +1,38 @@ +package main + +import ( + "io/ioutil" + "os" + + "github.com/tsuru/tsuru/fs" +) + +type Filesystem interface { + ReadFile(name string) ([]byte, error) + CheckFile(name string) (bool, error) + RemoveFile(name string) error +} + +// localFS is a wrapper around fs.Fs that implements Filesystem +type localFS struct{ fs.Fs } + +func (f *localFS) ReadFile(name string) ([]byte, error) { + file, err := f.Fs.Open(name) + if err != nil { + return nil, err + } + defer file.Close() + return ioutil.ReadAll(file) +} + +func (f *localFS) CheckFile(name string) (bool, error) { + _, err := f.Fs.Stat(name) + if os.IsNotExist(err) { + return false, nil + } + return err == nil, err +} + +func (f *localFS) RemoveFile(name string) error { + return f.Fs.Remove(name) +} diff --git a/main.go b/main.go index ee4a3ad..9ab453a 100644 --- a/main.go +++ b/main.go @@ -8,22 +8,24 @@ import ( "flag" "fmt" "os" + + "github.com/tsuru/tsuru/exec" ) const version = "0.2.8" -var printVersion bool - -func init() { +func main() { + var ( + printVersion bool + ) flag.BoolVar(&printVersion, "version", false, "Print version and exit") flag.Parse() -} -func main() { if printVersion { fmt.Printf("deploy-agent version %s\n", version) return } + c := Client{ URL: os.Args[1], Token: os.Args[2], @@ -33,15 +35,15 @@ func main() { switch command[len(command)-1] { case "build": - build(c, appName, command[:len(command)-1], &fs.OsFs{}, &exec.OsExecutor{}) + build(c, appName, command[:len(command)-1], &localFS{}, &exec.OsExecutor{}) case "deploy-only": - deploy(c, appName, &fs.OsFs{}, &exec.OsExecutor{}) + deploy(c, appName, &localFS{}, &exec.OsExecutor{}) case "deploy": // backward compatibility with tsuru < 1.4.0 command = command[:len(command)-1] fallthrough default: - build(c, appName, command, &fs.OsFs{}, &exec.OsExecutor{}) - deploy(c, appName, &fs.OsFs{}, &exec.OsExecutor{}) + build(c, appName, command, &localFS{}, &exec.OsExecutor{}) + deploy(c, appName, &localFS{}, &exec.OsExecutor{}) } } diff --git a/suite_test.go b/suite_test.go index 445f8de..3f57ef7 100644 --- a/suite_test.go +++ b/suite_test.go @@ -15,15 +15,19 @@ import ( func Test(t *testing.T) { check.TestingT(t) } type S struct { - fs *fstest.RecordingFs + fs *localFS exec *exectest.FakeExecutor } var _ = check.Suite(&S{}) func (s *S) SetUpTest(c *check.C) { - s.fs = &fstest.RecordingFs{} + s.fs = &localFS{Fs: &fstest.RecordingFs{}} s.exec = &exectest.FakeExecutor{} err := s.fs.Mkdir(defaultWorkingDir, 0777) c.Assert(err, check.IsNil) } + +func (s *S) testFS() *fstest.RecordingFs { + return s.fs.Fs.(*fstest.RecordingFs) +} diff --git a/tasks.go b/tasks.go index af27e16..23a8849 100644 --- a/tasks.go +++ b/tasks.go @@ -16,7 +16,6 @@ import ( "github.com/tsuru/deploy-agent/internal/user" "github.com/tsuru/tsuru/app/bind" "github.com/tsuru/tsuru/exec" - "github.com/tsuru/tsuru/fs" "gopkg.in/yaml.v2" ) @@ -26,7 +25,7 @@ var ( appEnvsFile = "/tmp/app_envs" ) -func execScript(cmds []string, envs []bind.EnvVar, w io.Writer, filesystem fs.Fs, executor exec.Executor) error { +func execScript(cmds []string, envs []bind.EnvVar, w io.Writer, fs Filesystem, executor exec.Executor) error { if w == nil { w = ioutil.Discard } @@ -35,12 +34,12 @@ func execScript(cmds []string, envs []bind.EnvVar, w io.Writer, filesystem fs.Fs return err } workingDir := defaultWorkingDir - if _, err := filesystem.Stat(defaultWorkingDir); err != nil { - if os.IsNotExist(err) { - workingDir = "/" - } else { - return err - } + exists, err := fs.CheckFile(defaultWorkingDir) + if err != nil { + return err + } + if exists == false { + workingDir = "/" } formatedEnvs := []string{} for _, env := range envs { @@ -80,19 +79,14 @@ type Hook struct { func (t *TsuruYaml) isEmpty() bool { return len(t.Hooks.BuildHooks) == 0 && t.Processes == nil } -func loadTsuruYaml(filesystem fs.Fs) (TsuruYaml, error) { +func loadTsuruYaml(fs Filesystem) (TsuruYaml, error) { var tsuruYamlData TsuruYaml for _, yamlFile := range tsuruYamlFiles { filePath := fmt.Sprintf("%s/%s", defaultWorkingDir, yamlFile) - f, err := filesystem.Open(filePath) + tsuruYaml, err := fs.ReadFile(filePath) if err != nil { continue } - defer f.Close() - tsuruYaml, err := ioutil.ReadAll(f) - if err != nil { - return TsuruYaml{}, err - } err = yaml.Unmarshal(tsuruYaml, &tsuruYamlData) if err != nil { return TsuruYaml{}, err @@ -102,19 +96,14 @@ func loadTsuruYaml(filesystem fs.Fs) (TsuruYaml, error) { return tsuruYamlData, nil } -func buildHooks(yamlData TsuruYaml, envs []bind.EnvVar, filesystem fs.Fs, executor exec.Executor) error { +func buildHooks(yamlData TsuruYaml, envs []bind.EnvVar, fs Filesystem, executor exec.Executor) error { cmds := append([]string{}, yamlData.Hooks.BuildHooks...) fmt.Fprintln(os.Stdout, "---- Running build hooks ----") - return execScript(cmds, envs, os.Stdout, filesystem, executor) + return execScript(cmds, envs, os.Stdout, fs, executor) } -func readProcfile(path string, filesystem fs.Fs) (string, error) { - f, err := filesystem.Open(fmt.Sprintf("%v/Procfile", path)) - if err != nil { - return "", err - } - defer f.Close() - procfile, err := ioutil.ReadAll(f) +func readProcfile(path string, fs Filesystem) (string, error) { + procfile, err := fs.ReadFile(fmt.Sprintf("%v/Procfile", path)) if err != nil { return "", err } @@ -123,8 +112,8 @@ func readProcfile(path string, filesystem fs.Fs) (string, error) { var procfileRegex = regexp.MustCompile(`^([\w-]+):\s*(\S.+)$`) -func loadProcesses(t *TsuruYaml, filesystem fs.Fs) error { - procfile, err := readProcfile(defaultWorkingDir, filesystem) +func loadProcesses(t *TsuruYaml, fs Filesystem) error { + procfile, err := readProcfile(defaultWorkingDir, fs) if err != nil { return err } @@ -142,17 +131,12 @@ func loadProcesses(t *TsuruYaml, filesystem fs.Fs) error { return nil } -func readDiffDeploy(filesystem fs.Fs) (string, bool, error) { +func readDiffDeploy(fs Filesystem) (string, bool, error) { filePath := fmt.Sprintf("%s/%s", defaultWorkingDir, "diff") - f, err := filesystem.Open(filePath) - defer f.Close() - defer filesystem.Remove(filePath) - if err != nil { - return "", true, nil - } - deployDiff, err := ioutil.ReadAll(f) + deployDiff, err := fs.ReadFile(filePath) if err != nil { return "", true, err } + defer fs.RemoveFile(filePath) return string(deployDiff), false, nil } diff --git a/tasks_test.go b/tasks_test.go index 1033a80..ea1d494 100644 --- a/tasks_test.go +++ b/tasks_test.go @@ -90,10 +90,10 @@ healthcheck: match: .*OK allowed_failures: 0` tsuruYmlPath := fmt.Sprintf("%s/%s", defaultWorkingDir, "tsuru.yml") - s.fs.FileContent = tsuruYmlData + s.testFS().FileContent = tsuruYmlData _, err := s.fs.Create(tsuruYmlPath) c.Assert(err, check.IsNil) - c.Assert(s.fs.HasAction(fmt.Sprintf("create %s", tsuruYmlPath)), check.Equals, true) + c.Assert(s.testFS().HasAction(fmt.Sprintf("create %s", tsuruYmlPath)), check.Equals, true) expected := TsuruYaml{ Hooks: Hook{ BuildHooks: []string{"test", "another_test"}, @@ -138,10 +138,10 @@ func (s *S) TestHooks(c *check.C) { func (s *S) TestLoadProcesses(c *check.C) { procfile := "web: python app.py" procfilePath := fmt.Sprintf("%s/%s", defaultWorkingDir, "Procfile") - s.fs.FileContent = procfile + s.testFS().FileContent = procfile _, err := s.fs.Create(procfilePath) c.Assert(err, check.IsNil) - c.Assert(s.fs.HasAction(fmt.Sprintf("create %s", procfilePath)), check.Equals, true) + c.Assert(s.testFS().HasAction(fmt.Sprintf("create %s", procfilePath)), check.Equals, true) expected := TsuruYaml{ Processes: map[string]string{ "web": "python app.py", @@ -160,10 +160,10 @@ another-worker: run-task # disabled-worker: run-task ` procfilePath := fmt.Sprintf("%s/%s", defaultWorkingDir, "Procfile") - s.fs.FileContent = procfile + s.testFS().FileContent = procfile _, err := s.fs.Create(procfilePath) c.Assert(err, check.IsNil) - c.Assert(s.fs.HasAction(fmt.Sprintf("create %s", procfilePath)), check.Equals, true) + c.Assert(s.testFS().HasAction(fmt.Sprintf("create %s", procfilePath)), check.Equals, true) expected := TsuruYaml{ Processes: map[string]string{ "web": "python app.py", @@ -180,10 +180,10 @@ func (s *S) TestDontLoadWrongProcfile(c *check.C) { procfile := `web: @python test.py` procfilePath := fmt.Sprintf("%s/%s", defaultWorkingDir, "Procfile") - s.fs.FileContent = procfile + s.testFS().FileContent = procfile _, err := s.fs.Create(procfilePath) c.Assert(err, check.IsNil) - c.Assert(s.fs.HasAction(fmt.Sprintf("create %s", procfilePath)), check.Equals, true) + c.Assert(s.testFS().HasAction(fmt.Sprintf("create %s", procfilePath)), check.Equals, true) t := TsuruYaml{} err = loadProcesses(&t, s.fs) c.Assert(err, check.NotNil) @@ -208,10 +208,10 @@ func (s *S) TestDiffDeploy(c *check.C) { } ` diffPath := fmt.Sprintf("%s/%s", defaultWorkingDir, "diff") - s.fs.FileContent = diff + s.testFS().FileContent = diff _, err := s.fs.Create(diffPath) c.Assert(err, check.IsNil) - c.Assert(s.fs.HasAction(fmt.Sprintf("create %s", diffPath)), check.Equals, true) + c.Assert(s.testFS().HasAction(fmt.Sprintf("create %s", diffPath)), check.Equals, true) result, first, err := readDiffDeploy(s.fs) c.Assert(err, check.IsNil) c.Assert(result, check.DeepEquals, diff)