diff --git a/README.md b/README.md index 28d5e17..042616f 100755 --- a/README.md +++ b/README.md @@ -81,6 +81,8 @@ The `assets/summon.config.yaml` is an (optional) configuration file to customize * default output-dir * executables +> Breaking in v0.11.0: Handles now take an array of params + ```yaml version: 1 outputdir: .summoned @@ -94,18 +96,18 @@ exec: bash -c: # ^ invoker # (script can be inlined with | yaml operator) - hello: echo hello + hello: [echo, hello] # ^ optional params that will be passed to invoker # these can contain templates (in v0.10.0) # ^ handle to script (must be unique). This is what you use # to invoke the script: `summon run hello`. gobin -run: # go gettable executables - gobin: github.com/myitcv/gobin@v0.0.8 - gohack: github.com/rogppepe/gohack + gobin: [github.com/myitcv/gobin@v0.0.8] + gohack: [github.com/rogppepe/gohack] python -c: - hello-python: print("hello from python!") + hello-python: [print("hello from python!")] ``` You can invoke executables like so: @@ -230,7 +232,7 @@ in the config file: ... exec: docker run -v {{ env "PWD" }}:/mounted-app alpine ls: - list: /mounted-app + list: [/mounted-app] ``` Calling `summon run list` would render the [{{ env "PWD" }}](https://masterminds.github.io/sprig/os.html) part to the current directory, resulting in this call: @@ -245,7 +247,7 @@ invocable (new in v.0.10.0). You would use the `summon` template function bundle ```yaml exec: bash -c: - hello: '{{ summon "hello.sh" }}' + hello: ['{{ summon "hello.sh" }}'] ``` Assuming you have a `hello.sh` file in the assets repo, this would result in sommoning the file in a temp dir and calling the invoker: diff --git a/cmd/testdata/summon.config.yaml b/cmd/testdata/summon.config.yaml index 53206bb..2fe99e6 100644 --- a/cmd/testdata/summon.config.yaml +++ b/cmd/testdata/summon.config.yaml @@ -5,10 +5,12 @@ aliases: outputdir: "overridden_dir" exec: bash: - echo: echo hello {{ .Name -}} - hello-bash: hello.sh + echo: + - echo + - hello {{ .Name -}} + hello-bash: [hello.sh] gobin -run: - gobin: github.com/myitcv/gobin@v0.0.8 - gohack: github.com/rogpeppe/gohack + gobin: [github.com/myitcv/gobin@v0.0.8] + gohack: [github.com/rogpeppe/gohack] python -c: - hello: print("hello from python!") + hello: [print("hello from python!")] diff --git a/go.mod b/go.mod index 0dbe5d1..62e6fde 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/davidovich/summon require ( github.com/DiSiqueira/GoTree v1.0.1-0.20190529205929-3e23dcd4532b github.com/Masterminds/sprig/v3 v3.1.0 - github.com/alessio/shellescape v1.2.2 // indirect github.com/gobuffalo/packr/v2 v2.5.1 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/lithammer/dedent v1.1.0 @@ -12,7 +11,6 @@ require ( github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.5.1 golang.org/x/sys v0.0.0-20200819091447-39769834ee22 // indirect - gopkg.in/alessio/shellescape.v1 v1.0.0-20170105083845-52074bc9df61 gopkg.in/yaml.v2 v2.2.2 ) diff --git a/go.sum b/go.sum index 6c002c2..bbed862 100644 --- a/go.sum +++ b/go.sum @@ -11,8 +11,6 @@ github.com/Masterminds/sprig/v3 v3.1.0/go.mod h1:ONGMf7UfYGAbMXCZmQLy8x3lCDIPrEZ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alessio/shellescape v1.2.2 h1:8LnL+ncxhWT2TR00dfJRT25JWWrhkMZXneHVWnetDZg= -github.com/alessio/shellescape v1.2.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -204,8 +202,6 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/alessio/shellescape.v1 v1.0.0-20170105083845-52074bc9df61 h1:8ajkpB4hXVftY5ko905id+dOnmorcS2CHNxxHLLDcFM= -gopkg.in/alessio/shellescape.v1 v1.0.0-20170105083845-52074bc9df61/go.mod h1:IfMagxm39Ys4ybJrDb7W3Ob8RwxftP0Yy+or/NVz1O8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/config/config.go b/pkg/config/config.go index 94c3c3b..4307eed 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -17,8 +17,8 @@ var OutputDir = DefaultOutputDir // Alias gives a shortcut to a name in data. type Alias map[string]string -// Executable describes a Name and invocable target. -type Executable map[string]string +// Executable describes a handle name and invocable target. +type Executable map[string][]string // Config is the summon config type Config struct { diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index ea7b47b..f5ed117 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -14,30 +14,34 @@ func TestConfigWriter(t *testing.T) { c := Config{ Version: 1, Executables: map[string]Executable{ - "go": Executable{ - "gobin": "github.com/myitcv/gobin", - "gohack": "github.com/rogppepe/gohack", + "go": { + "gobin": []string{"github.com/myitcv/gobin"}, + "gohack": []string{"github.com/rogppepe/gohack"}, }, - "bash": Executable{"hello-bash": "hello.sh"}, - "python -c": Executable{"hello": "print(\"hello from python!\")"}, + "bash": {"hello-bash": []string{"hello.sh"}}, + "python -c": {"hello": []string{"print(\"hello from python!\")"}}, }, } config, _ := yaml.Marshal(&c) - assert.Equal(t, dedent.Dedent(` - version: 1 - aliases: {} - outputdir: "" - exec: - bash: - hello-bash: hello.sh - go: - gobin: github.com/myitcv/gobin - gohack: github.com/rogppepe/gohack - python -c: - hello: print("hello from python!") - `), "\n"+string(config)) + assert.Equal(t, ` +version: 1 +aliases: {} +outputdir: "" +exec: + bash: + hello-bash: + - hello.sh + go: + gobin: + - github.com/myitcv/gobin + gohack: + - github.com/rogppepe/gohack + python -c: + hello: + - print("hello from python!") +`, "\n"+string(config)) } func TestConfigReader(t *testing.T) { @@ -45,12 +49,12 @@ func TestConfigReader(t *testing.T) { version: 1 exec: python -c: - hello: print("hello") + hello: [print("hello")] `) c := Config{} err := c.Unmarshal([]byte(config)) require.Nil(t, err) - assert.Equal(t, "print(\"hello\")", c.Executables["python -c"]["hello"]) + assert.Equal(t, "print(\"hello\")", c.Executables["python -c"]["hello"][0]) } diff --git a/pkg/summon/run.go b/pkg/summon/run.go index 4c6c429..d3a85a3 100644 --- a/pkg/summon/run.go +++ b/pkg/summon/run.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/google/shlex" - "gopkg.in/alessio/shellescape.v1" "github.com/davidovich/summon/pkg/config" ) @@ -14,43 +13,43 @@ import ( type execUnit struct { invoker string invOpts string - target string + targets []string } // Run will run executable scripts described in the summon.config.yaml file // of the data repository module. func (d *Driver) Run(opts ...Option) error { - d.Configure(opts...) + err := d.Configure(opts...) + if err != nil { + return err + } eu, err := d.findExecutor() if err != nil { return err } - args := []string{eu.invOpts} - if eu.target != "" { - args = append(args, eu.target) + eu.invOpts, err = d.renderTemplate(eu.invOpts, d.opts.data) + if err != nil { + return err } - args = append(args, d.opts.args...) - // render arg templates - rargs := make([]string, 0, len(args)) - for _, a := range args { - if a == "" { - continue - } - rarg, err := d.renderTemplate(a, d.opts.data) + targets := make([]string, 0, len(eu.targets)) + for _, t := range eu.targets { + rt, err := d.renderTemplate(t, d.opts.data) if err != nil { return err } + targets = append(targets, rt) + } - allrargs, err := shlex.Split(rarg) - if err != nil { - return err - } - rargs = append(rargs, allrargs...) + rargs, err := shlex.Split(eu.invOpts) + if err != nil { + return err } + rargs = append(rargs, append(targets, d.opts.args...)...) + cmd := d.execCommand(eu.invoker, rargs...) if d.opts.debug || d.opts.dryrun { @@ -58,7 +57,7 @@ func (d *Driver) Run(opts ...Option) error { if d.opts.dryrun { msg = "Would execute" } - fmt.Fprintf(os.Stderr, "%s `%s`...\n", msg, cmd.Args) + fmt.Fprintf(os.Stderr, "%s `%s`...\n", msg, cmd) } if !d.opts.dryrun { @@ -68,6 +67,7 @@ func (d *Driver) Run(opts ...Option) error { return cmd.Run() } + return nil } @@ -95,9 +95,8 @@ func (d *Driver) findExecutor() (execUnit, error) { if len(exec) == 2 { eu.invOpts = strings.TrimSpace(exec[1]) } - if c != "" { - eu.target = shellescape.Quote(c) - } + + eu.targets = c break } diff --git a/pkg/summon/testdata/summon.config.yaml b/pkg/summon/testdata/summon.config.yaml index 09261e0..285526c 100644 --- a/pkg/summon/testdata/summon.config.yaml +++ b/pkg/summon/testdata/summon.config.yaml @@ -5,12 +5,12 @@ aliases: outputdir: "overridden_dir" exec: bash: - hello-bash: hello.sh - bash-self-ref: '{{ summon "hello.sh" }}' + hello-bash: [ hello.sh ] + bash-self-ref: ['{{ summon "hello.sh" }}'] docker {{ lower "INFO" }}: # template example docker: gobin -run: - gobin: github.com/myitcv/gobin@v0.0.8 - gohack: github.com/rogpeppe/gohack + gobin: [github.com/myitcv/gobin@v0.0.8] + gohack: [github.com/rogpeppe/gohack] python -c: - hello: print("hello from python!") + hello: ['print("hello from python!")']