Skip to content

Commit

Permalink
add variable support.
Browse files Browse the repository at this point in the history
  • Loading branch information
tj committed Apr 12, 2015
1 parent bac2f6c commit b5ce7c1
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 1 deletion.
21 changes: 21 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,27 @@ events:
command: robo events gy2d 25
```

### Variables

Robo supports variables via the [text/template](https://golang.org/pkg/text/template/) package. All you have to do is define a map of `variables` and use `{{` `}}` to refer to them.

Here's an example:

```yml
stage:
summary: Run commands against stage.
command: ssh {{.hosts.stage}} -t robo
prod:
summary: Run commands against prod.
command: ssh {{.hosts.prod}} -t robo
variables:
hosts:
prod: bastion-prod
stage: bastion-stage
```

### Templates

Task `list` and `help` output may be re-configured, for example if you
Expand Down
41 changes: 41 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package config

import "github.com/tj/robo/task"
import "gopkg.in/yaml.v2"
import "text/template"
import "io/ioutil"
import "bytes"

// Config.
type Config struct {
Tasks map[string]*task.Task `yaml:",inline"`
Variables map[string]interface{}
Templates struct {
List string
Help string
Expand All @@ -27,14 +30,52 @@ func New(file string) (*Config, error) {
func NewString(s string) (*Config, error) {
c := new(Config)

// unmarshal
err := yaml.Unmarshal([]byte(s), &c)
if err != nil {
return nil, err
}

// assign .Name
for name, task := range c.Tasks {
task.Name = name
}

// interpolation
for _, task := range c.Tasks {
err := interpolate(c.Variables, &task.Command, &task.Summary, &task.Script, &task.Exec)
if err != nil {
return nil, err
}
}

return c, nil
}

// Apply interpolation against the given strings.
func interpolate(v interface{}, s ...*string) error {
for _, p := range s {
ret, err := eval(*p, v)
if err != nil {
return err
}
*p = ret
}
return nil
}

// Evaluate template against `v`.
func eval(s string, v interface{}) (string, error) {
t, err := template.New("task").Parse(s)
if err != nil {
return "", err
}

var b bytes.Buffer
err = t.Execute(&b, v)
if err != nil {
return "", err
}

return string(b.Bytes()), nil
}
18 changes: 17 additions & 1 deletion config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,30 @@ bar:
summary: Command bar.
command: echo "bar"
stage:
summary: Run commands against stage.
command: ssh {{.hosts.stage}} -t robo
prod:
summary: Run commands against prod.
command: ssh {{.hosts.prod}} -t robo
templates:
list: testing
variables:
hosts:
prod: bastion-prod
stage: bastion-stage
`

func TestNewString(t *testing.T) {
c, err := config.NewString(s)
assert.Equal(t, nil, err)
assert.Equal(t, 2, len(c.Tasks))
assert.Equal(t, 4, len(c.Tasks))

assert.Equal(t, `ssh bastion-stage -t robo`, c.Tasks["stage"].Command)
assert.Equal(t, `ssh bastion-prod -t robo`, c.Tasks["prod"].Command)

assert.Equal(t, `foo`, c.Tasks["foo"].Name)
assert.Equal(t, `Command foo.`, c.Tasks["foo"].Summary)
Expand Down

0 comments on commit b5ce7c1

Please sign in to comment.