Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
khash committed Oct 24, 2019
2 parents 23f7a59 + 65c9a87 commit fdcaab5
Show file tree
Hide file tree
Showing 15 changed files with 167 additions and 6 deletions.
51 changes: 50 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ steps:

This workflow will run `kubectl apply -f manifest.yml` first. If it returns with exist status 0 (it ran successfully), will then run `kubectl wait --for=condition=complete job/myjob` until it returns with exist status 0 and considers the step successful.

Trackman can continue running if a step fails if the step has a `continue_on_failure: true`.
Trackman can continue running if a step fails if the step has a `continue_on_fail: true`.

### Timeouts

Expand Down Expand Up @@ -141,8 +141,45 @@ steps:
message: "Oh nose!"
```

## Workflow Attributes

The following attributes can be set for the workflow:
| Attribute | Description | Default |
|---|---|---|
| version | Workflow format version | `1` |
| version | Any metadata for the workflow | None |
| steps | List of all workflow steps (See below) | [] |

## Step Attributes

The following attributes can be set for each step:

| Attribute | Description | Default |
|---|---|---|
| metadata | Any metadata for the step | None |
| name | Given name for the step | `''` |
| command | Command to run, including arguments | `''` |
| continue_on_fail | Continue to the next step even after failure | `false` |
| timeout | Timeout after which the step will be stopped. A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". | Never |
| workdir | Work directory for the step | None |
| probe | Health probe definition. See above | None |
| depends_on | List of the steps this one depends on (should run after all of them have successfully finished) | [] |
| preflights | List of pre-flight checks (see above) | None |
| ask_to_proceed | Stops the execution of the workflow and asks the user for a confirmation to continue | `false` |
| show_command | Shows the command and arguments for this step before running it | `false` |

## Trackman CLI

### Global Options

The CLI supports the following global options:

| Option | Description | Default |
|---|---|---|
| config | Config file | $HOME/.trackman.yaml |
| log-level | Log level | info |
| no-update | Don't update trackman CLI automatically | false |

### Run

Runs the given workflow. Use `--help` for more details.
Expand All @@ -151,6 +188,18 @@ Runs the given workflow. Use `--help` for more details.
$ trackman run -f file.yml
```

### Params

Run command supports the following options

| Option | Description | Default |
|---|---|---|
| file, f | Workflow file | None |
| timeout | Timeout after which the step will be stopped. A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". | 10 seconds |
| concurrency | Number of concurrent steps to run | Number of CPUs - 1 |
| yes, y | Answer Yes to all `ask_to_proceed` questions | false |


### Update

Manually checks for updates. It can also switch the current release channel.
Expand Down
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ var (
func init() {
UpdateDone = &sync.WaitGroup{}
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.trackman.yaml)")
rootCmd.PersistentFlags().String("log-level", "info", "log level. Use debug to see process output")
rootCmd.PersistentFlags().Bool("no-update", false, "turn off auto update")

Expand Down
2 changes: 2 additions & 0 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ func init() {
runCmd.Flags().StringVarP(&workflowFile, "file", "f", "", "workflow file to run")
runCmd.Flags().DurationP("timeout", "", 10*time.Second, "global timeout unless overwritten by a step")
runCmd.Flags().IntP("concurrency", "", runtime.NumCPU()-1, "maximum number of concurrent steps to run")
runCmd.Flags().BoolP("yes", "y", false, "Answer Yes to all confirmation questions")

_ = viper.BindPFlag("timeout", runCmd.Flags().Lookup("timeout"))
_ = viper.BindPFlag("concurrency", runCmd.Flags().Lookup("concurrency"))
_ = viper.BindPFlag("confirm.yes", runCmd.Flags().Lookup("yes"))

rootCmd.AddCommand(runCmd)
}
Expand Down
13 changes: 13 additions & 0 deletions samples/kubernetes/job.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
4 changes: 4 additions & 0 deletions samples/kubernetes/workflow-1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
version: 1
steps:
- name: run
command: kubectl apply -f job.yml
8 changes: 8 additions & 0 deletions samples/kubernetes/workflow-2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: 1
steps:
- name: run
command: kubectl apply -f job.yml
timeout: 1m
probe:
command: kubectl wait --for=condition=complete job/pi
timeout: 1m
11 changes: 11 additions & 0 deletions samples/kubernetes/workflow-3.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: 1
steps:
- name: run
command: kubectl apply -f job.yml
probe:
command: kubectl wait --for=condition=complete job/pi
timeout: 1m
- name: cleanup
command: kubectl delete job pi
depends_on:
- run
13 changes: 13 additions & 0 deletions samples/kubernetes/workflow-4.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: 1
steps:
- name: run
command: kubectl apply -f job.yml
probe:
command: kubectl wait --for=condition=complete job/pi
timeout: 1m
preflights:
- command: kubectl version
- name: cleanup
command: kubectl delete job pi
depends_on:
- run
12 changes: 12 additions & 0 deletions samples/timeout.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: 1
steps:
- name: hello
command: echo "Hello, World!"
depends_on:
- timeout
- name: timeout
ask_to_proceed: true
show_command: true
command: sleep 20
timeout: 10s
continue_on_fail: true
31 changes: 31 additions & 0 deletions utils/interactive.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package utils

import (
"bufio"
"fmt"
"log"
"os"
"strings"
)

func confirm(s string, tries int) bool {
r := bufio.NewReader(os.Stdin)

for ; tries > 0; tries-- {
fmt.Printf("%s [y/N]: ", s)

res, err := r.ReadString('\n')
if err != nil {
log.Fatal(err)
}

// Empty input (i.e. "\n")
if len(res) < 2 {
continue
}

return strings.ToLower(strings.TrimSpace(res))[0] == 'y'
}

return false
}
6 changes: 3 additions & 3 deletions utils/spinner.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ import (
"syscall"
"time"

"github.com/kballard/go-shellquote"

"github.com/google/uuid"
"github.com/kballard/go-shellquote"
"github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -165,6 +164,7 @@ func (s *Spinner) Run(ctx context.Context) error {
errChannel := NewLogWriter(ctx, logrus.ErrorLevel)

logger.WithField(FldStep, s.Name).Tracef("Running %s with %s", s.cmd, s.args)

cmd := exec.CommandContext(cmdCtx, s.cmd, s.args...)
cmd.Stderr = errChannel
cmd.Stdout = outChannel
Expand All @@ -183,7 +183,7 @@ func (s *Spinner) Run(ctx context.Context) error {
if cmdCtx.Err() == context.DeadlineExceeded {
s.push(ctx, NewEvent(s, EventRunTimeout, nil))

return fmt.Errorf("step %s timed out after %s", s.step.Name, s.timeout)
return fmt.Errorf("Timed out after %s", s.timeout)
}

if exitErr, ok := err.(*exec.ExitError); ok {
Expand Down
2 changes: 2 additions & 0 deletions utils/step.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ type Step struct {
Probe *Probe `yaml:"probe" json:"probe"`
DependsOn []string `yaml:"depends_on" json:"depends_on"`
Preflights []Preflight `yaml:"preflights" json:"preflights"`
AskToProceed bool `yaml:"ask_to_proceed" json:"ask_to_proceed"`
ShowCommand bool `yaml:"show_command" json:"show_command"`

options *StepOptions
workflow *Workflow
Expand Down
14 changes: 13 additions & 1 deletion utils/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"time"

"github.com/hashicorp/go-multierror"

"github.com/sirupsen/logrus"
"github.com/spf13/viper"
"golang.org/x/sync/semaphore"
"gopkg.in/yaml.v2"
)
Expand Down Expand Up @@ -166,6 +166,18 @@ func (w *Workflow) Run(ctx context.Context) (runErrors error, stepErrors error)

w.logger.WithField(FldStep, toRun.Name).Trace("Preparing to run")

if toRun.ShowCommand {
w.logger.WithField(FldStep, toRun.Name).Info(toRun.Command)
}

if toRun.AskToProceed && !viper.GetBool("confirm.yes") {
// we need an interactive permission for this
if !confirm(fmt.Sprintf("Run %s?", toRun.Name), 1) {
w.logger.WithField(FldStep, toRun.Name).Info("Stopping execution")
w.stop(ctx)
}
}

err := toRun.Run(ctx)
if err != nil {
stepErrors = multierror.Append(err, stepErrors)
Expand Down
2 changes: 2 additions & 0 deletions vendor/github.com/sirupsen/logrus/go.mod

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions vendor/github.com/spf13/viper/go.mod

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit fdcaab5

Please sign in to comment.