Skip to content

Commit

Permalink
add playbook-level ssh_shell
Browse files Browse the repository at this point in the history
  • Loading branch information
umputun committed Jul 25, 2023
1 parent ad3500c commit 6ebd598
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 5 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ Spot supports the following command-line options:
```yaml
user: umputun # default ssh user. Can be overridden by -u flag or by inventory or host definition
ssh_key: keys/id_rsa # ssh key
ssh_shell: /bin/bash # shell to use for remote ssh execution, default is /bin/sh
inventory: /etc/spot/inventory.yml # default inventory file. Can be overridden by --inventory flag

# list of targets, i.e. hosts, inventory files or inventory URLs
Expand Down Expand Up @@ -236,6 +237,7 @@ In some cases the rich syntax of the full playbook is not needed and can felt ov
```yaml
user: umputun # default ssh user. Can be overridden by -u flag or by inventory or host definition
ssh_key: keys/id_rsa # ssh key
ssh_shell: /bin/bash # shell to use for remote ssh execution, default is /bin/sh
inventory: /etc/spot/inventory.yml # default inventory file. Can be overridden by --inventory flag

targets: ["devbox1", "devbox2", "h1.example.com:2222", "h2.example.com"] # list of host names from inventory and direct host ips
Expand Down
17 changes: 13 additions & 4 deletions pkg/config/playbook.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
type PlayBook struct {
User string `yaml:"user" toml:"user"` // ssh user
SSHKey string `yaml:"ssh_key" toml:"ssh_key"` // ssh key
SSHShell string `yaml:"ssh_shell" toml:"ssh_shell"` // ssh shell to use
Inventory string `yaml:"inventory" toml:"inventory"` // inventory file or url
Targets map[string]Target `yaml:"targets" toml:"targets"` // list of targets/environments
Tasks []Task `yaml:"tasks" toml:"tasks"` // list of tasks
Expand Down Expand Up @@ -153,9 +154,7 @@ func New(fname string, overrides *Overrides, secProvider SecretsProvider) (res *
log.Printf("[INFO] playbook loaded with %d tasks", len(res.Tasks))
for i, tsk := range res.Tasks {
for j, c := range tsk.Commands {
if overrides != nil && overrides.SSHShell != "" {
res.Tasks[i].Commands[j].SSHShell = overrides.SSHShell // set ssh shell for all commands in task
}
res.Tasks[i].Commands[j].SSHShell = res.shell() // set secrets for all commands in task
log.Printf("[DEBUG] load command %q (task: %s)", c.Name, tsk.Name)
}
}
Expand Down Expand Up @@ -301,7 +300,7 @@ func (p *PlayBook) Task(name string) (*Task, error) {
if name == "ad-hoc" && p.overrides.AdHocCommand != "" {
// special case for ad-hoc command, make a fake task with a single command from overrides.AdHocCommand
return &Task{Name: "ad-hoc", Commands: []Cmd{
{Name: "ad-hoc", Script: p.overrides.AdHocCommand, SSHShell: p.overrides.SSHShell}}}, nil
{Name: "ad-hoc", Script: p.overrides.AdHocCommand, SSHShell: p.shell()}}}, nil
}
for _, t := range tsk {
if strings.EqualFold(t.Name, name) {
Expand Down Expand Up @@ -590,3 +589,13 @@ func (p *PlayBook) loadSecrets() error {
}
return nil
}

func (p *PlayBook) shell() string {
if p.overrides != nil && p.overrides.SSHShell != "" {
return p.overrides.SSHShell
}
if p.SSHShell != "" {
return p.SSHShell
}
return "/bin/sh"
}
38 changes: 38 additions & 0 deletions pkg/config/playbook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func TestPlaybook_New(t *testing.T) {
t.Logf("%+v", c)
assert.Equal(t, 1, len(c.Tasks), "single task")
assert.Equal(t, "umputun", c.User, "user")
assert.Equal(t, "/bin/sh", c.Tasks[0].Commands[0].SSHShell, "ssh shel")

This comment has been minimized.

Copy link
@knutov

knutov Jul 26, 2023

Contributor

typo here - shel


tsk := c.Tasks[0]
assert.Equal(t, 5, len(tsk.Commands), "5 commands")
Expand Down Expand Up @@ -188,6 +189,31 @@ func TestPlaybook_New(t *testing.T) {
_, err := New("testdata/playbook-with-all-group.yml", nil, nil)
require.ErrorContains(t, err, "config testdata/playbook-with-all-group.yml is invalid: target \"all\" is reserved for all hosts")
})

t.Run("playbook with custom ssh shell set", func(t *testing.T) {
c, err := New("testdata/with-ssh-shell.yml", nil, nil)
require.NoError(t, err)
t.Logf("%+v", c)
assert.Equal(t, 1, len(c.Tasks), "single task")
assert.Equal(t, "umputun", c.User, "user")
assert.Equal(t, "/bin/bash", c.Tasks[0].Commands[0].SSHShell, "ssh shel")

This comment has been minimized.

Copy link
@knutov

knutov Jul 26, 2023

Contributor

same typo


tsk := c.Tasks[0]
assert.Equal(t, 5, len(tsk.Commands), "5 commands")
assert.Equal(t, "deploy-remark42", tsk.Name, "task name")
})
t.Run("playbook with custom ssh shell override", func(t *testing.T) {
c, err := New("testdata/with-ssh-shell.yml", &Overrides{SSHShell: "/bin/zsh"}, nil)
require.NoError(t, err)
t.Logf("%+v", c)
assert.Equal(t, 1, len(c.Tasks), "single task")
assert.Equal(t, "umputun", c.User, "user")
assert.Equal(t, "/bin/zsh", c.Tasks[0].Commands[0].SSHShell, "ssh shel")

tsk := c.Tasks[0]
assert.Equal(t, 5, len(tsk.Commands), "5 commands")
assert.Equal(t, "deploy-remark42", tsk.Name, "task name")
})
}

func TestPlayBook_Task(t *testing.T) {
Expand Down Expand Up @@ -216,6 +242,18 @@ func TestPlayBook_Task(t *testing.T) {
assert.Equal(t, 1, len(tsk.Commands))
assert.Equal(t, "ad-hoc", tsk.Name)
assert.Equal(t, "echo 123", tsk.Commands[0].Script)
assert.Equal(t, "/bin/sh", tsk.Commands[0].SSHShell)
})

t.Run("adhoc with custom shell", func(t *testing.T) {
c, err := New("", &Overrides{AdHocCommand: "echo 123", User: "umputun", SSHShell: "/bin/zsh"}, nil)
require.NoError(t, err)
tsk, err := c.Task("ad-hoc")
require.NoError(t, err)
assert.Equal(t, 1, len(tsk.Commands))
assert.Equal(t, "ad-hoc", tsk.Name)
assert.Equal(t, "echo 123", tsk.Commands[0].Script)
assert.Equal(t, "/bin/zsh", tsk.Commands[0].SSHShell)
})
}

Expand Down
42 changes: 42 additions & 0 deletions pkg/config/testdata/with-ssh-shell.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
user: umputun
ssh_shell: /bin/bash

targets:
remark42:
hosts: [{name: "h1", host: "h1.example.com"}, {host: "h2.example.com"}]


tasks:
- name: deploy-remark42
commands:
- name: wait
script: sleep 5

- name: copy configuration
copy: {"src": "/local/remark42.yml", "dst": "/srv/remark42.yml", "mkdir": true}

- name: some local command
options: {local: true}
script: |
ls -la /srv
du -hcs /srv
- name: git
before: "echo before git"
after: "echo after git"
onerror: "echo onerror git"
script: |
git clone https://example.com/remark42.git /srv || true # clone if doesn't exists, but don't fail if exists
cd /srv
git pull
- name: docker
options: {no_auto: true}
script: |
docker pull umputun/remark42:latest
docker stop remark42 || true
docker rm remark42 || true
docker run -d --name remark42 -p 8080:8080 umputun/remark42:latest
env:
FOO: bar
BAR: qux
4 changes: 3 additions & 1 deletion spot.1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH "SPOT" 1 20230723T193408 spot manual
.TH "SPOT" 1 20230723T201928 spot manual
.\" Automatically generated by Pandoc 3.1.6
.\"
.\" Define V font for inline verbatim, using C font in formats
Expand Down Expand Up @@ -261,6 +261,7 @@ hosts and groups of hosts on which a task can be executed.
\f[C]
user: umputun # default ssh user. Can be overridden by -u flag or by inventory or host definition
ssh_key: keys/id_rsa # ssh key
ssh_shell: /bin/bash # shell to use for remote ssh execution, default is /bin/sh
inventory: /etc/spot/inventory.yml # default inventory file. Can be overridden by --inventory flag

# list of targets, i.e. hosts, inventory files or inventory URLs
Expand Down Expand Up @@ -334,6 +335,7 @@ is easier to read and write, but also more limited in its capabilities.
\f[C]
user: umputun # default ssh user. Can be overridden by -u flag or by inventory or host definition
ssh_key: keys/id_rsa # ssh key
ssh_shell: /bin/bash # shell to use for remote ssh execution, default is /bin/sh
inventory: /etc/spot/inventory.yml # default inventory file. Can be overridden by --inventory flag

targets: [\[dq]devbox1\[dq], \[dq]devbox2\[dq], \[dq]h1.example.com:2222\[dq], \[dq]h2.example.com\[dq]] # list of host names from inventory and direct host ips
Expand Down

0 comments on commit 6ebd598

Please sign in to comment.