diff --git a/main.go b/main.go index 2da8c6b..9b21025 100644 --- a/main.go +++ b/main.go @@ -3,15 +3,17 @@ package main import ( "bytes" "io" - "io/ioutil" + "net" "os" "fmt" "errors" "time" "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/agent" "github.com/pkg/sftp" + "github.com/scaleway/scaleway-sdk-go/scw" "github.com/scaleway/scaleway-sdk-go/api/instance/v1" ) @@ -256,7 +258,42 @@ func (dt *destroyer) onInstance(zone, machine, image, name string) error { type runner struct { action } -func (r *runner) onInstance(zone, machine, image, name string) error { +func (r *runner) connect(zone, name string) (*ssh.Client, error) { + // Connect to the remote + z, err := scw.ParseZone(zone) + if err != nil { + return nil, err + } + + targetServer, err := r.getInstanceByName(z, name) + if err != nil { + return nil, err + } + + if targetServer.PublicIP == nil { + return nil, errors.New("run failed: this instance has no public ip.") + } + ip := targetServer.PublicIP.Address + + socket := os.Getenv("SSH_AUTH_SOCK") + conn, err := net.Dial("unix", socket) + if err != nil { + return nil, err + } + + agentClient := agent.NewClient(conn) + config := &ssh.ClientConfig{ + User: "root", + Auth: []ssh.AuthMethod{ + ssh.PublicKeysCallback(agentClient.Signers), + }, + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + } + + return ssh.Dial("tcp", ip.String()+":22", config) +} + +func (r *runner) send(sshClient *ssh.Client) error { // Source script if len(os.Args) < 3 { return errors.New("Missing script to run on the command line") @@ -268,47 +305,6 @@ func (r *runner) onInstance(zone, machine, image, name string) error { } defer src.Close() - // Connect to the remote - z, err := scw.ParseZone(zone) - if err != nil { - return err - } - - targetServer, err := r.getInstanceByName(z, name) - if err != nil { - return err - } - - if targetServer.PublicIP == nil { - return errors.New("run failed: this instance has no public ip.") - } - ip := targetServer.PublicIP.Address - - var hostKey ssh.PublicKey - key, err := ioutil.ReadFile(os.Getenv("HOME") + "/.ssh/id_rsa") - if err != nil { - return err - } - - signer, err := ssh.ParsePrivateKey(key) - if err != nil { - return err - } - - config := &ssh.ClientConfig{ - User: "root", - Auth: []ssh.AuthMethod{ - ssh.PublicKeys(signer), - }, - HostKeyCallback: ssh.FixedHostKey(hostKey), - } - - sshClient, err := ssh.Dial("tcp", ip.String()+":22", config) - if err != nil { - return err - } - defer sshClient.Close() - // Send our script to the destination sftpClient, err := sftp.NewClient(sshClient) if err != nil { @@ -328,10 +324,10 @@ func (r *runner) onInstance(zone, machine, image, name string) error { } _, err = io.Copy(dst, src) - if err != nil { - return err - } + return err +} +func (r *runner) exec(sshClient *ssh.Client) error { // Run the script session, err := sshClient.NewSession() if err != nil { @@ -345,7 +341,7 @@ func (r *runner) onInstance(zone, machine, image, name string) error { err = session.Run("/tmp/nuage") if os.Getenv("VERBOSE") != "" { - fmt.Fprintf(os.Stdout, "logs for %v\n", name) + fmt.Fprintf(os.Stdout, "logs\n") io.Copy(os.Stdout, &sshStdout) io.Copy(os.Stderr, &sshStderr) } @@ -356,6 +352,27 @@ func (r *runner) onInstance(zone, machine, image, name string) error { return nil } +func (r *runner) onInstance(zone, machine, image, name string) error { + sshClient, err := r.connect(zone, name) + if err != nil { + return err + } + defer sshClient.Close() + + err = r.send(sshClient) + if err != nil { + return err + } + + err = r.exec(sshClient) + if err != nil { + return err + } + + fmt.Fprintf(os.Stdout, "✅ Successfully ran the script on %v (zone %v)\n", name, zone) + return nil +} + /** * Commands