drone-ssh/plugin.go

109 lines
2.1 KiB
Go
Raw Normal View History

2016-07-11 19:47:15 +02:00
package main
import (
2017-01-23 10:07:49 +08:00
"log"
2016-07-11 19:47:15 +02:00
"net"
"os"
"strconv"
"strings"
"time"
2017-01-23 10:07:49 +08:00
"fmt"
2016-07-11 19:47:15 +02:00
"golang.org/x/crypto/ssh"
)
2017-01-23 14:24:27 +08:00
const (
missingHostOrUser = "Error: missing server host or user"
missingPasswordOrKey = "Error: can't connect without a private SSH key or password"
)
2016-07-11 19:47:15 +02:00
type (
2017-01-23 10:03:54 +08:00
// Config for the plugin.
2016-07-11 19:47:15 +02:00
Config struct {
Key string
User string
Password string
Host []string
Port int
Sleep int
Timeout time.Duration
Script []string
2016-07-11 19:47:15 +02:00
}
2017-01-23 10:03:54 +08:00
// Plugin structure
2016-07-11 19:47:15 +02:00
Plugin struct {
Config Config
}
)
2017-01-23 10:03:54 +08:00
// Exec executes the plugin.
2016-07-11 19:47:15 +02:00
func (p Plugin) Exec() error {
2017-01-23 14:24:27 +08:00
if len(p.Config.Host) == 0 && p.Config.User == "" {
return fmt.Errorf(missingHostOrUser)
}
if p.Config.Key == "" && p.Config.Password == "" {
2017-01-23 14:24:27 +08:00
return fmt.Errorf(missingPasswordOrKey)
2016-07-11 19:47:15 +02:00
}
for i, host := range p.Config.Host {
addr := net.JoinHostPort(
host,
strconv.Itoa(p.Config.Port),
)
// auths holds the detected ssh auth methods
auths := []ssh.AuthMethod{}
2016-07-11 19:47:15 +02:00
if p.Config.Key != "" {
signer, err := ssh.ParsePrivateKey([]byte(p.Config.Key))
if err != nil {
2017-01-23 10:07:49 +08:00
return fmt.Errorf("Error: Failed to parse private key. %s", err)
}
auths = append(auths, ssh.PublicKeys(signer))
}
// figure out what auths are requested, what is supported
if p.Config.Password != "" {
auths = append(auths, ssh.Password(p.Config.Password))
2016-07-11 19:47:15 +02:00
}
config := &ssh.ClientConfig{
2016-07-12 13:31:38 +02:00
Timeout: p.Config.Timeout,
User: p.Config.User,
Auth: auths,
2016-07-11 19:47:15 +02:00
}
2017-01-23 10:03:54 +08:00
log.Printf("+ ssh %s@%s -p %d\n", p.Config.User, addr, p.Config.Port)
2016-07-11 19:47:15 +02:00
client, err := ssh.Dial("tcp", addr, config)
if err != nil {
2017-01-23 10:07:49 +08:00
return fmt.Errorf("Error: Failed to dial to server. %s", err)
2016-07-11 19:47:15 +02:00
}
session, err := client.NewSession()
if err != nil {
2017-01-23 10:07:49 +08:00
return fmt.Errorf("Error: Failed to start a SSH session. %s", err)
2016-07-11 19:47:15 +02:00
}
defer session.Close()
session.Stdout = os.Stdout
session.Stderr = os.Stderr
if err := session.Run(strings.Join(p.Config.Script, "\n")); err != nil {
2016-07-11 19:47:15 +02:00
return err
}
if p.Config.Sleep != 0 && i != len(p.Config.Host)-1 {
2017-01-23 10:03:54 +08:00
log.Printf("+ sleep %d\n", p.Config.Sleep)
2016-07-11 19:47:15 +02:00
time.Sleep(time.Duration(p.Config.Sleep) * time.Second)
}
}
return nil
}