зеркало из https://github.com/Azure/draft-classic.git
feat(pkg/tasks): load and run tasks
This commit is contained in:
Родитель
626da5f9e9
Коммит
d7beeb1156
|
@ -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
|
||||||
|
}
|
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
lorem ipsum abra kadabra
|
||||||
|
-- a lot of nothing
|
|
@ -0,0 +1,8 @@
|
||||||
|
[pre-up]
|
||||||
|
prep = "echo hello"
|
||||||
|
|
||||||
|
[post-deploy]
|
||||||
|
"setting up your app" = "echo setup"
|
||||||
|
|
||||||
|
[cleanup]
|
||||||
|
"cleaning up stuff" = "echo cleaning up"
|
Загрузка…
Ссылка в новой задаче