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:
|
Use the SSH plugin to execute commands on a remote server. The below pipeline configuration demonstrates simple usage:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
pipeline:
|
- name: ssh commands
|
||||||
ssh:
|
image: appleboy/drone-ssh
|
||||||
image: appleboy/drone-ssh
|
settings:
|
||||||
settings:
|
host: foo.com
|
||||||
host: foo.com
|
username: root
|
||||||
username: root
|
password: 1234
|
||||||
password: 1234
|
port: 22
|
||||||
port: 22
|
script:
|
||||||
script:
|
- echo hello
|
||||||
- echo hello
|
- echo world
|
||||||
- echo world
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Example configuration in your `.drone.yml` file for multiple hosts:
|
Example configuration in your `.drone.yml` file for multiple hosts:
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
pipeline:
|
- name: ssh commands
|
||||||
ssh:
|
|
||||||
image: appleboy/drone-ssh
|
image: appleboy/drone-ssh
|
||||||
settings:
|
settings:
|
||||||
host:
|
host:
|
||||||
@@ -38,22 +36,21 @@ pipeline:
|
|||||||
password: 1234
|
password: 1234
|
||||||
port: 22
|
port: 22
|
||||||
script:
|
script:
|
||||||
- echo hello
|
- echo hello
|
||||||
- echo world
|
- echo world
|
||||||
```
|
```
|
||||||
|
|
||||||
Example configuration for command timeout, default value is 60 seconds:
|
Example configuration for command timeout, default value is 60 seconds:
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
pipeline:
|
- name: ssh commands
|
||||||
ssh:
|
|
||||||
image: appleboy/drone-ssh
|
image: appleboy/drone-ssh
|
||||||
settings:
|
settings:
|
||||||
host: foo.com
|
host: foo.com
|
||||||
username: root
|
username: root
|
||||||
password: 1234
|
password: 1234
|
||||||
port: 22
|
port: 22
|
||||||
+ command_timeout: 2m
|
+ command_timeout: 2m
|
||||||
script:
|
script:
|
||||||
- echo hello
|
- echo hello
|
||||||
- echo world
|
- echo world
|
||||||
@@ -62,8 +59,7 @@ pipeline:
|
|||||||
Example configuration for execute commands on a remote server using `SSHProxyCommand`:
|
Example configuration for execute commands on a remote server using `SSHProxyCommand`:
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
pipeline:
|
- name: ssh commands
|
||||||
ssh:
|
|
||||||
image: appleboy/drone-ssh
|
image: appleboy/drone-ssh
|
||||||
settings:
|
settings:
|
||||||
host: foo.com
|
host: foo.com
|
||||||
@@ -82,8 +78,7 @@ pipeline:
|
|||||||
Example configuration using password from secrets:
|
Example configuration using password from secrets:
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
pipeline:
|
- name: ssh commands
|
||||||
ssh:
|
|
||||||
image: appleboy/drone-ssh
|
image: appleboy/drone-ssh
|
||||||
settings:
|
settings:
|
||||||
host: foo.com
|
host: foo.com
|
||||||
@@ -99,8 +94,7 @@ pipeline:
|
|||||||
Example configuration using ssh key from secrets:
|
Example configuration using ssh key from secrets:
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
pipeline:
|
- name: ssh commands
|
||||||
ssh:
|
|
||||||
image: appleboy/drone-ssh
|
image: appleboy/drone-ssh
|
||||||
settings:
|
settings:
|
||||||
host: foo.com
|
host: foo.com
|
||||||
@@ -116,8 +110,7 @@ pipeline:
|
|||||||
Example configuration for exporting custom secrets:
|
Example configuration for exporting custom secrets:
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
pipeline:
|
- name: ssh commands
|
||||||
ssh:
|
|
||||||
image: appleboy/drone-ssh
|
image: appleboy/drone-ssh
|
||||||
settings:
|
settings:
|
||||||
host: foo.com
|
host: foo.com
|
||||||
@@ -130,6 +123,22 @@ pipeline:
|
|||||||
- export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
|
- 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
|
## Secret Reference
|
||||||
|
|
||||||
ssh_username
|
ssh_username
|
||||||
@@ -176,11 +185,14 @@ envs
|
|||||||
script
|
script
|
||||||
: execute commands on a remote server
|
: execute commands on a remote server
|
||||||
|
|
||||||
|
script_stop
|
||||||
|
: stop script after first failure
|
||||||
|
|
||||||
timeout
|
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
|
||||||
: 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_host
|
||||||
: proxy hostname or IP
|
: proxy hostname or IP
|
||||||
|
|||||||
@@ -80,12 +80,17 @@ func main() {
|
|||||||
Name: "command.timeout,T",
|
Name: "command.timeout,T",
|
||||||
Usage: "command timeout",
|
Usage: "command timeout",
|
||||||
EnvVar: "PLUGIN_COMMAND_TIMEOUT,SSH_COMMAND_TIMEOUT,COMMAND_TIMEOUT,INPUT_COMMAND_TIMEOUT",
|
EnvVar: "PLUGIN_COMMAND_TIMEOUT,SSH_COMMAND_TIMEOUT,COMMAND_TIMEOUT,INPUT_COMMAND_TIMEOUT",
|
||||||
Value: 60 * time.Second,
|
Value: 10 * time.Minute,
|
||||||
},
|
},
|
||||||
cli.StringSliceFlag{
|
cli.StringSliceFlag{
|
||||||
Name: "script,s",
|
Name: "script,s",
|
||||||
Usage: "execute commands",
|
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{
|
cli.BoolFlag{
|
||||||
Name: "script.stop",
|
Name: "script.stop",
|
||||||
@@ -180,6 +185,10 @@ REPOSITORY:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func run(c *cli.Context) error {
|
func run(c *cli.Context) error {
|
||||||
|
scripts := c.StringSlice("script")
|
||||||
|
if s := c.String("script.string"); s != "" {
|
||||||
|
scripts = append(scripts, s)
|
||||||
|
}
|
||||||
plugin := Plugin{
|
plugin := Plugin{
|
||||||
Config: Config{
|
Config: Config{
|
||||||
Key: c.String("ssh-key"),
|
Key: c.String("ssh-key"),
|
||||||
@@ -190,7 +199,7 @@ func run(c *cli.Context) error {
|
|||||||
Port: c.Int("port"),
|
Port: c.Int("port"),
|
||||||
Timeout: c.Duration("timeout"),
|
Timeout: c.Duration("timeout"),
|
||||||
CommandTimeout: c.Duration("command.timeout"),
|
CommandTimeout: c.Duration("command.timeout"),
|
||||||
Script: c.StringSlice("script"),
|
Script: scripts,
|
||||||
ScriptStop: c.Bool("script.stop"),
|
ScriptStop: c.Bool("script.stop"),
|
||||||
Envs: c.StringSlice("envs"),
|
Envs: c.StringSlice("envs"),
|
||||||
Debug: c.Bool("debug"),
|
Debug: c.Bool("debug"),
|
||||||
|
|||||||
@@ -174,27 +174,34 @@ func (p Plugin) Exec() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("==========================================")
|
fmt.Println("==============================================")
|
||||||
fmt.Println("Successfully executed commands to all host.")
|
fmt.Println("✅ Successfully executed commands to all host.")
|
||||||
fmt.Println("==========================================")
|
fmt.Println("==============================================")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Plugin) scriptCommands() []string {
|
func (p Plugin) scriptCommands() []string {
|
||||||
numCommands := len(p.Config.Script)
|
scripts := []string{}
|
||||||
if p.Config.ScriptStop {
|
|
||||||
numCommands *= 2
|
|
||||||
}
|
|
||||||
|
|
||||||
commands := make([]string, numCommands)
|
|
||||||
|
|
||||||
for _, cmd := range p.Config.Script {
|
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 {
|
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, "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
|
return commands
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -527,3 +529,66 @@ func TestEnvOutput(t *testing.T) {
|
|||||||
func unindent(text string) string {
|
func unindent(text string) string {
|
||||||
return strings.TrimSpace(strings.Replace(text, "\t", "", -1))
|
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