From 1027e0dc32e9bc47d352de9d60ff792bba0d7cf7 Mon Sep 17 00:00:00 2001 From: Umputun Date: Wed, 3 May 2023 15:25:21 -0500 Subject: [PATCH] support of mcopy command type --- README.md | 1 + app/config/command.go | 1 + app/runner/runner.go | 16 +++++++++++++++- app/runner/runner_test.go | 6 +++--- app/runner/testdata/conf.yml | 5 +++++ 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a615dc9e..9249503e 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,7 @@ Spot supports the following command types: - `script`: can be any valid shell script. The script will be executed on the remote host(s) using SSH, inside a shell. - `copy`: copies a file from the local machine to the remote host(s). Example: `copy: {"src": "testdata/conf.yml", "dst": "/tmp/conf.yml", "mkdir": true}`. If `mkdir` is set to `true` the command will create the destination directory if it doesn't exist, same as `mkdir -p` in bash. +- `mcopy`: copies multiple files from the local machine to the remote host(s). Example: `mcopy: [{"src": "testdata/1.yml", "dst": "/tmp/1.yml", "mkdir": true}, {"src": "testdata/1.txt", "dst": "/tmp/1.txt"}]`. This is just a shortcut for multiple `copy` commands. - `sync`: syncs directory from the local machine to the remote host(s). Optionally supports deleting files on the remote host(s) that don't exist locally. Example: `sync: {"src": "testdata", "dst": "/tmp/things", "delete": true}` - `delete`: deletes a file or directory on the remote host(s), optionally can remove recursively. Example: `delete: {"path": "/tmp/things", "recur": true}` - `wait`: waits for the specified command to finish on the remote host(s) with 0 error code. This command is useful when you need to wait for a service to start before executing the next command. Allows to specify the timeout as well as check interval. Example: `wait: {"cmd": "curl -s --fail localhost:8080", "timeout": "30s", "interval": "1s"}` diff --git a/app/config/command.go b/app/config/command.go index 5b65c686..97f087ba 100644 --- a/app/config/command.go +++ b/app/config/command.go @@ -14,6 +14,7 @@ import ( type Cmd struct { Name string `yaml:"name" toml:"name"` Copy CopyInternal `yaml:"copy" toml:"copy"` + MCopy []CopyInternal `yaml:"mcopy" toml:"mcopy"` Sync SyncInternal `yaml:"sync" toml:"sync"` Delete DeleteInternal `yaml:"delete" toml:"delete"` Wait WaitInternal `yaml:"wait" toml:"wait"` diff --git a/app/runner/runner.go b/app/runner/runner.go index c86d4138..f4662ccc 100644 --- a/app/runner/runner.go +++ b/app/runner/runner.go @@ -197,7 +197,7 @@ func (p *Process) execCommand(ctx context.Context, ep execCmdParams) (details st return details, fmt.Errorf("can't run script on %s: %w", ep.hostAddr, err) } case ep.cmd.Copy.Source != "" && ep.cmd.Copy.Dest != "": - log.Printf("[DEBUG] copy file on %s", ep.hostAddr) + log.Printf("[DEBUG] copy file to %s", ep.hostAddr) src := p.applyTemplates(ep.cmd.Copy.Source, templateData{hostAddr: ep.hostAddr, hostName: ep.hostName, task: ep.tsk, command: ep.cmd.Name}) dst := p.applyTemplates(ep.cmd.Copy.Dest, @@ -206,6 +206,20 @@ func (p *Process) execCommand(ctx context.Context, ep execCmdParams) (details st if err := ep.exec.Upload(ctx, src, dst, ep.cmd.Copy.Mkdir); err != nil { return details, fmt.Errorf("can't copy file on %s: %w", ep.hostAddr, err) } + case len(ep.cmd.MCopy) > 0: + log.Printf("[DEBUG] copy multiple files to %s", ep.hostAddr) + msgs := []string{} + for _, c := range ep.cmd.MCopy { + src := p.applyTemplates(c.Source, + templateData{hostAddr: ep.hostAddr, hostName: ep.hostName, task: ep.tsk, command: ep.cmd.Name}) + dst := p.applyTemplates(c.Dest, + templateData{hostAddr: ep.hostAddr, hostName: ep.hostName, task: ep.tsk, command: ep.cmd.Name}) + msgs = append(msgs, fmt.Sprintf("%s -> %s", src, dst)) + if err := ep.exec.Upload(ctx, src, dst, c.Mkdir); err != nil { + return details, fmt.Errorf("can't copy file on %s: %w", ep.hostAddr, err) + } + } + details = fmt.Sprintf(" {copy: %s}", strings.Join(msgs, ", ")) case ep.cmd.Sync.Source != "" && ep.cmd.Sync.Dest != "": log.Printf("[DEBUG] sync files on %s", ep.hostAddr) src := p.applyTemplates(ep.cmd.Sync.Source, diff --git a/app/runner/runner_test.go b/app/runner/runner_test.go index 895d3f73..3435854e 100644 --- a/app/runner/runner_test.go +++ b/app/runner/runner_test.go @@ -37,7 +37,7 @@ func TestProcess_Run(t *testing.T) { } res, err := p.Run(ctx, "task1", hostAndPort) require.NoError(t, err) - assert.Equal(t, 6, res.Commands) + assert.Equal(t, 7, res.Commands) assert.Equal(t, 1, res.Hosts) } @@ -82,7 +82,7 @@ func TestProcess_RunDry(t *testing.T) { } res, err := p.Run(ctx, "task1", hostAndPort) require.NoError(t, err) - assert.Equal(t, 6, res.Commands) + assert.Equal(t, 7, res.Commands) assert.Equal(t, 1, res.Hosts) } @@ -151,7 +151,7 @@ func TestProcess_RunSkip(t *testing.T) { } res, err := p.Run(ctx, "task1", hostAndPort) require.NoError(t, err) - assert.Equal(t, 4, res.Commands) + assert.Equal(t, 5, res.Commands) assert.Equal(t, 1, res.Hosts) } diff --git a/app/runner/testdata/conf.yml b/app/runner/testdata/conf.yml index 52a74909..77d636b0 100644 --- a/app/runner/testdata/conf.yml +++ b/app/runner/testdata/conf.yml @@ -17,6 +17,11 @@ tasks: - name: copy configuration copy: {"src": "testdata/conf.yml", "dst": "/tmp/conf.yml", "mkdir": true} + - name: copy multiple files + mcopy: + - {src: "testdata/conf2.yml", dst: "/tmp/conf2.yml"} + - {src: "testdata/conf-local.yml", dst: "/tmp/conf3.yml"} + - name: sync things sync: {"src": "testdata", "dst": "/tmp/things"}