feat(pkg/tasks): load and run tasks

This commit is contained in:
Michelle Noorali 2018-04-12 18:51:14 -04:00
Родитель 626da5f9e9
Коммит d7beeb1156
4 изменённых файлов: 197 добавлений и 0 удалений

130
pkg/tasks/tasks.go Normal file
Просмотреть файл

@ -0,0 +1,130 @@
package tasks
import (
"errors"
"fmt"
"os"
"os/exec"
"strings"
"github.com/BurntSushi/toml"
)
var (
ErrNoTaskFile = errors.New(".draft-tasks.toml not found")
)
const (
PreUp = "PreUp"
PostDeploy = "PostDeploy"
PostDelete = "PostDelete"
)
type Tasks struct {
PreUp map[string]string `toml:"pre-up"`
PostDeploy map[string]string `toml:"post-deploy"`
PostDelete map[string]string `toml:"cleanup"`
}
type Result struct {
Kind string
Command []string
Pass bool
Message string
}
// Load takes a path to file where tasks are defined and loads them in tasks
func Load(path string) (*Tasks, error) {
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
return nil, ErrNoTaskFile
}
return nil, err
}
t := Tasks{}
if _, err := toml.DecodeFile(path, &t); err != nil {
return nil, err
}
return &t, nil
}
func (t *Tasks) Run(kind, podName string) ([]Result, error) {
results := []Result{}
switch kind {
case PreUp:
for _, task := range t.PreUp {
result := executeTask(task, kind)
results = append(results, result)
}
case PostDeploy:
for _, task := range t.PostDeploy {
cmd := preparePostDeployTask(evaluateArgs(task), podName)
result := runTask(cmd, kind)
results = append(results, result)
}
case PostDelete:
for _, task := range t.PostDelete {
result := executeTask(task, kind)
results = append(results, result)
}
default:
return results, fmt.Errorf("Task kind: %s not supported", kind)
}
return results, nil
}
func executeTask(task, kind string) Result {
args := evaluateArgs(task)
cmd := prepareTask(args)
return runTask(cmd, kind)
}
func runTask(cmd *exec.Cmd, kind string) Result {
result := Result{Kind: kind, Pass: false}
result.Command = append([]string{cmd.Path}, cmd.Args[0:]...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
result.Pass = false
result.Message = err.Error()
return result
}
result.Pass = true
return result
}
func prepareTask(args []string) *exec.Cmd {
var cmd *exec.Cmd
if len(args) < 2 {
cmd = exec.Command(args[0])
} else {
cmd = exec.Command(args[0], args[1:]...)
}
return cmd
}
func preparePostDeployTask(args []string, podName string) *exec.Cmd {
args = append([]string{"exec", podName, "--"}, args[0:]...)
return exec.Command("kubectl", args[0:]...)
}
func evaluateArgs(task string) []string {
args := strings.Split(task, " ")
argsCopy := args
count := 0
for _, part := range argsCopy {
if strings.HasPrefix(part, "$") {
evaluatedPart := os.Getenv(strings.TrimPrefix(part, "$"))
args[count] = evaluatedPart
}
count = count + 1
}
return args
}

57
pkg/tasks/tasks_test.go Normal file
Просмотреть файл

@ -0,0 +1,57 @@
package tasks
import (
"testing"
)
func TestLoad(t *testing.T) {
tasksFile, err := Load("testdata/tasks.toml")
if err != nil {
t.Fatal(err)
}
if len(tasksFile.PreUp) != 1 {
t.Errorf("Expected 1 pre-up task, got %v", len(tasksFile.PreUp))
}
if len(tasksFile.PostDeploy) != 1 {
t.Errorf("Expected 1 post-deploy task, got %v", len(tasksFile.PostDeploy))
}
if len(tasksFile.PostDelete) != 1 {
t.Errorf("Expected 1 post-delete task, got %v", len(tasksFile.PostDeploy))
}
}
func TestLoadError(t *testing.T) {
_, err := Load("testdata/nonexistent.yaml")
if err == nil {
t.Error(err)
}
_, err = Load("testdata/malformedTasks.yaml")
if err == nil {
}
}
func TestRun(t *testing.T) {
taskFile, err := Load("testdata/tasks.toml")
if err != nil {
t.Fatal(err)
}
results, err := taskFile.Run(PreUp, "")
if err != nil {
t.Fatal(err)
}
if len(results) != 1 {
t.Errorf("Expected one pre-up command to be run, got %v", len(results))
}
results, _ = taskFile.Run(PostDeploy, "testpod")
if len(results) != 1 {
t.Errorf("Expected one post deploy command to be run, got %v", len(results))
}
results, _ = taskFile.Run(PostDelete, "")
if len(results) != 1 {
t.Errorf("Expected one post-delete command to be run, got %v", len(results))
}
}

2
pkg/tasks/testdata/malformedTasks.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
lorem ipsum abra kadabra
-- a lot of nothing

8
pkg/tasks/testdata/tasks.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,8 @@
[pre-up]
prep = "echo hello"
[post-deploy]
"setting up your app" = "echo setup"
[cleanup]
"cleaning up stuff" = "echo cleaning up"