mirror of
https://github.com/appleboy/drone-ssh.git
synced 2026-06-16 14:49:25 +08:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d0b62974a | |||
| 9b57f85e47 | |||
| 648e3c1321 | |||
| 9ef0a47bc0 | |||
| 530cb1df6e | |||
| 414ebba911 | |||
| ff6e63366c | |||
| 553894abe6 |
@@ -11,24 +11,22 @@ image: appleboy/drone-ssh
|
||||
Use the SSH plugin to execute commands on a remote server. The below pipeline configuration demonstrates simple usage:
|
||||
|
||||
```yaml
|
||||
pipeline:
|
||||
ssh:
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host: foo.com
|
||||
username: root
|
||||
password: 1234
|
||||
port: 22
|
||||
script:
|
||||
- echo hello
|
||||
- echo world
|
||||
- name: ssh commands
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host: foo.com
|
||||
username: root
|
||||
password: 1234
|
||||
port: 22
|
||||
script:
|
||||
- echo hello
|
||||
- echo world
|
||||
```
|
||||
|
||||
Example configuration in your `.drone.yml` file for multiple hosts:
|
||||
|
||||
```diff
|
||||
pipeline:
|
||||
ssh:
|
||||
- name: ssh commands
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host:
|
||||
@@ -38,22 +36,21 @@ pipeline:
|
||||
password: 1234
|
||||
port: 22
|
||||
script:
|
||||
- echo hello
|
||||
- echo world
|
||||
- echo hello
|
||||
- echo world
|
||||
```
|
||||
|
||||
Example configuration for command timeout, default value is 60 seconds:
|
||||
|
||||
```diff
|
||||
pipeline:
|
||||
ssh:
|
||||
- name: ssh commands
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host: foo.com
|
||||
username: root
|
||||
password: 1234
|
||||
port: 22
|
||||
+ command_timeout: 2m
|
||||
+ command_timeout: 2m
|
||||
script:
|
||||
- echo hello
|
||||
- echo world
|
||||
@@ -62,8 +59,7 @@ pipeline:
|
||||
Example configuration for execute commands on a remote server using `SSHProxyCommand`:
|
||||
|
||||
```diff
|
||||
pipeline:
|
||||
ssh:
|
||||
- name: ssh commands
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host: foo.com
|
||||
@@ -82,8 +78,7 @@ pipeline:
|
||||
Example configuration using password from secrets:
|
||||
|
||||
```diff
|
||||
pipeline:
|
||||
ssh:
|
||||
- name: ssh commands
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host: foo.com
|
||||
@@ -99,8 +94,7 @@ pipeline:
|
||||
Example configuration using ssh key from secrets:
|
||||
|
||||
```diff
|
||||
pipeline:
|
||||
ssh:
|
||||
- name: ssh commands
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host: foo.com
|
||||
@@ -116,8 +110,7 @@ pipeline:
|
||||
Example configuration for exporting custom secrets:
|
||||
|
||||
```diff
|
||||
pipeline:
|
||||
ssh:
|
||||
- name: ssh commands
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host: foo.com
|
||||
@@ -130,6 +123,22 @@ pipeline:
|
||||
- export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
|
||||
```
|
||||
|
||||
Example configuration for stoping script after first failure:
|
||||
|
||||
```diff
|
||||
- name: ssh commands
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host: foo.com
|
||||
username: root
|
||||
password: 1234
|
||||
port: 22
|
||||
+ script_stop: true
|
||||
script:
|
||||
- mkdir abc/def/efg
|
||||
- echo "you can't see the steps."
|
||||
```
|
||||
|
||||
## Secret Reference
|
||||
|
||||
ssh_username
|
||||
@@ -176,11 +185,14 @@ envs
|
||||
script
|
||||
: execute commands on a remote server
|
||||
|
||||
script_stop
|
||||
: stop script after first failure
|
||||
|
||||
timeout
|
||||
: Timeout is the maximum amount of time for the TCP connection to establish.
|
||||
: Timeout is the maximum amount of time for the ssh connection to establish, default is 30 seconds.
|
||||
|
||||
command_timeout
|
||||
: Command timeout is the maximum amount of time for the execute commands, default is 60 secs.
|
||||
: Command timeout is the maximum amount of time for the execute commands, default is 10 minutes.
|
||||
|
||||
proxy_host
|
||||
: proxy hostname or IP
|
||||
|
||||
@@ -80,12 +80,17 @@ func main() {
|
||||
Name: "command.timeout,T",
|
||||
Usage: "command timeout",
|
||||
EnvVar: "PLUGIN_COMMAND_TIMEOUT,SSH_COMMAND_TIMEOUT,COMMAND_TIMEOUT,INPUT_COMMAND_TIMEOUT",
|
||||
Value: 60 * time.Second,
|
||||
Value: 10 * time.Minute,
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "script,s",
|
||||
Usage: "execute commands",
|
||||
EnvVar: "PLUGIN_SCRIPT,SSH_SCRIPT,SCRIPT,INPUT_SCRIPT",
|
||||
EnvVar: "PLUGIN_SCRIPT,SSH_SCRIPT,SCRIPT",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "script.string",
|
||||
Usage: "execute single commands for github action",
|
||||
EnvVar: "INPUT_SCRIPT",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "script.stop",
|
||||
@@ -180,6 +185,10 @@ REPOSITORY:
|
||||
}
|
||||
|
||||
func run(c *cli.Context) error {
|
||||
scripts := c.StringSlice("script")
|
||||
if s := c.String("script.string"); s != "" {
|
||||
scripts = append(scripts, s)
|
||||
}
|
||||
plugin := Plugin{
|
||||
Config: Config{
|
||||
Key: c.String("ssh-key"),
|
||||
@@ -190,7 +199,7 @@ func run(c *cli.Context) error {
|
||||
Port: c.Int("port"),
|
||||
Timeout: c.Duration("timeout"),
|
||||
CommandTimeout: c.Duration("command.timeout"),
|
||||
Script: c.StringSlice("script"),
|
||||
Script: scripts,
|
||||
ScriptStop: c.Bool("script.stop"),
|
||||
Envs: c.StringSlice("envs"),
|
||||
Debug: c.Bool("debug"),
|
||||
|
||||
@@ -174,27 +174,34 @@ func (p Plugin) Exec() error {
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("==========================================")
|
||||
fmt.Println("Successfully executed commands to all host.")
|
||||
fmt.Println("==========================================")
|
||||
fmt.Println("==============================================")
|
||||
fmt.Println("✅ Successfully executed commands to all host.")
|
||||
fmt.Println("==============================================")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p Plugin) scriptCommands() []string {
|
||||
numCommands := len(p.Config.Script)
|
||||
if p.Config.ScriptStop {
|
||||
numCommands *= 2
|
||||
}
|
||||
|
||||
commands := make([]string, numCommands)
|
||||
scripts := []string{}
|
||||
|
||||
for _, cmd := range p.Config.Script {
|
||||
if p.Config.ScriptStop {
|
||||
scripts = append(scripts, strings.Split(cmd, "\n")...)
|
||||
} else {
|
||||
scripts = append(scripts, cmd)
|
||||
}
|
||||
}
|
||||
|
||||
commands := make([]string, 0)
|
||||
|
||||
for _, cmd := range scripts {
|
||||
if strings.TrimSpace(cmd) == "" {
|
||||
continue
|
||||
}
|
||||
commands = append(commands, cmd)
|
||||
if p.Config.ScriptStop {
|
||||
commands = append(commands, "DRONE_SSH_PREV_COMMAND_EXIT_CODE=$? ; if [ $DRONE_SSH_PREV_COMMAND_EXIT_CODE -ne 0 ]; then exit $DRONE_SSH_PREV_COMMAND_EXIT_CODE; fi;")
|
||||
}
|
||||
|
||||
commands = append(commands, cmd)
|
||||
}
|
||||
|
||||
return commands
|
||||
|
||||
@@ -2,7 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -527,3 +529,66 @@ func TestEnvOutput(t *testing.T) {
|
||||
func unindent(text string) string {
|
||||
return strings.TrimSpace(strings.Replace(text, "\t", "", -1))
|
||||
}
|
||||
|
||||
func TestPlugin_scriptCommands(t *testing.T) {
|
||||
type fields struct {
|
||||
Config Config
|
||||
Writer io.Writer
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "normal testing",
|
||||
fields: fields{
|
||||
Config: Config{
|
||||
Script: []string{"mkdir a", "mkdir b"},
|
||||
},
|
||||
},
|
||||
want: []string{"mkdir a", "mkdir b"},
|
||||
},
|
||||
{
|
||||
name: "script stop",
|
||||
fields: fields{
|
||||
Config: Config{
|
||||
Script: []string{"mkdir a", "mkdir b"},
|
||||
ScriptStop: true,
|
||||
},
|
||||
},
|
||||
want: []string{"mkdir a", "DRONE_SSH_PREV_COMMAND_EXIT_CODE=$? ; if [ $DRONE_SSH_PREV_COMMAND_EXIT_CODE -ne 0 ]; then exit $DRONE_SSH_PREV_COMMAND_EXIT_CODE; fi;", "mkdir b", "DRONE_SSH_PREV_COMMAND_EXIT_CODE=$? ; if [ $DRONE_SSH_PREV_COMMAND_EXIT_CODE -ne 0 ]; then exit $DRONE_SSH_PREV_COMMAND_EXIT_CODE; fi;"},
|
||||
},
|
||||
{
|
||||
name: "normal testing 2",
|
||||
fields: fields{
|
||||
Config: Config{
|
||||
Script: []string{"mkdir a\nmkdir c", "mkdir b"},
|
||||
ScriptStop: true,
|
||||
},
|
||||
},
|
||||
want: []string{"mkdir a", "DRONE_SSH_PREV_COMMAND_EXIT_CODE=$? ; if [ $DRONE_SSH_PREV_COMMAND_EXIT_CODE -ne 0 ]; then exit $DRONE_SSH_PREV_COMMAND_EXIT_CODE; fi;", "mkdir c", "DRONE_SSH_PREV_COMMAND_EXIT_CODE=$? ; if [ $DRONE_SSH_PREV_COMMAND_EXIT_CODE -ne 0 ]; then exit $DRONE_SSH_PREV_COMMAND_EXIT_CODE; fi;", "mkdir b", "DRONE_SSH_PREV_COMMAND_EXIT_CODE=$? ; if [ $DRONE_SSH_PREV_COMMAND_EXIT_CODE -ne 0 ]; then exit $DRONE_SSH_PREV_COMMAND_EXIT_CODE; fi;"},
|
||||
},
|
||||
{
|
||||
name: "trim space",
|
||||
fields: fields{
|
||||
Config: Config{
|
||||
Script: []string{"mkdir a", "mkdir b", "\t", " "},
|
||||
ScriptStop: false,
|
||||
},
|
||||
},
|
||||
want: []string{"mkdir a", "mkdir b"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p := Plugin{
|
||||
Config: tt.fields.Config,
|
||||
Writer: tt.fields.Writer,
|
||||
}
|
||||
if got := p.scriptCommands(); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Plugin.scriptCommands() = %#v, want %#v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user