Skip to content
This repository has been archived by the owner on Sep 26, 2021. It is now read-only.

Commit

Permalink
libmachine/ssh: added the Start and Wait functions to the Client inte…
Browse files Browse the repository at this point in the history
…rface

The Start function starts an SSH session and executes the given command. The
returned parameters are readers for the stdout and stderr. This way, developers
can further manipulate the output of the remote command. The Wait function is
command to that of the exec.Cmd type.

The readers returned by the Start function are io.ReadCloser instead of
io.Reader, as one might think. This is done this way to simplify the API so
the ExternalClient doesn't have to provide extra functions to close the
io.ReadCloser's as returned by the cmd.StdoutPipe and cmd.StderrPipe functions.

Finally, I've also changed the receivers of the functions related to the Native
and the External clients. This is done this way because we need to save the
open session or the command from each client in order to implement the Wait
function. Note that the Wait function is needed in order to properly close the
session that is hidden underneath the Native client.

Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
  • Loading branch information
mssola committed Jan 27, 2016
1 parent 38b6ae3 commit 0a2b5ab
Show file tree
Hide file tree
Showing 6 changed files with 253 additions and 75 deletions.
145 changes: 145 additions & 0 deletions libmachine/examples/main.go
@@ -0,0 +1,145 @@
package main

import (
"bufio"
"encoding/json"
"fmt"
"os"

"github.com/docker/machine/drivers/virtualbox"
"github.com/docker/machine/libmachine"
"github.com/docker/machine/libmachine/log"
)

func usage() {
fmt.Println("Usage: go run main.go <example>\n" +
"Available examples: create streaming.")
os.Exit(1)
}

// Sample Virtualbox create independent of Machine CLI.
func create() {
log.SetDebug(true)

client := libmachine.NewClient("/tmp/automatic", "/tmp/automatic/certs")
defer client.Close()

hostName := "myfunhost"

// Set some options on the provider...
driver := virtualbox.NewDriver(hostName, "/tmp/automatic")
driver.CPU = 2
driver.Memory = 2048

data, err := json.Marshal(driver)
if err != nil {
log.Error(err)
return
}

h, err := client.NewHost("virtualbox", data)
if err != nil {
log.Error(err)
return
}

h.HostOptions.EngineOptions.StorageDriver = "overlay"

if err := client.Create(h); err != nil {
log.Error(err)
return
}

out, err := h.RunSSHCommand("df -h")
if err != nil {
log.Error(err)
return
}

fmt.Printf("Results of your disk space query:\n%s\n", out)

fmt.Println("Powering down machine now...")
if err := h.Stop(); err != nil {
log.Error(err)
return
}
}

// Streaming the output of an SSH session in virtualbox.
func streaming() {
log.SetDebug(true)

client := libmachine.NewClient("/tmp/automatic", "/tmp/automatic/certs")
defer client.Close()

hostName := "myfunhost"

// Set some options on the provider...
driver := virtualbox.NewDriver(hostName, "/tmp/automatic")
data, err := json.Marshal(driver)
if err != nil {
log.Error(err)
return
}

h, err := client.NewHost("virtualbox", data)
if err != nil {
log.Error(err)
return
}

if err := client.Create(h); err != nil {
log.Error(err)
return
}

h.HostOptions.EngineOptions.StorageDriver = "overlay"

sshClient, err := h.CreateSSHClient()
if err != nil {
log.Error(err)
return
}

stdout, stderr, err := sshClient.Start("yes | head -n 10000")
if err != nil {
log.Error(err)
return
}
defer func() {
_ = stdout.Close()
_ = stderr.Close()
}()

scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Error(err)
}
if err := sshClient.Wait(); err != nil {
log.Error(err)
}

fmt.Println("Powering down machine now...")
if err := h.Stop(); err != nil {
log.Error(err)
return
}
}

func main() {
if len(os.Args) != 2 {
usage()
}

switch os.Args[1] {
case "create":
create()
case "streaming":
streaming()
default:
usage()
}
}
58 changes: 0 additions & 58 deletions libmachine/examples/vbox_create.go

This file was deleted.

4 changes: 2 additions & 2 deletions libmachine/host/host.go
Expand Up @@ -77,12 +77,12 @@ func (h *Host) CreateSSHClient() (ssh.Client, error) {
func (creator *StandardSSHClientCreator) CreateSSHClient(d drivers.Driver) (ssh.Client, error) {
addr, err := d.GetSSHHostname()
if err != nil {
return ssh.ExternalClient{}, err
return &ssh.ExternalClient{}, err
}

port, err := d.GetSSHPort()
if err != nil {
return ssh.ExternalClient{}, err
return &ssh.ExternalClient{}, err
}

auth := &ssh.Auth{}
Expand Down
4 changes: 2 additions & 2 deletions libmachine/provision/redhat_ssh_commander.go
Expand Up @@ -20,10 +20,10 @@ func (sshCmder RedHatSSHCommander) SSHCommand(args string) (string, error) {
// Note: CentOS 7.0 needs multiple "-tt" to force tty allocation when ssh has
// no local tty.
switch c := client.(type) {
case ssh.ExternalClient:
case *ssh.ExternalClient:
c.BaseArgs = append(c.BaseArgs, "-tt")
client = c
case ssh.NativeClient:
case *ssh.NativeClient:
return c.OutputWithPty(args)
}

Expand Down

0 comments on commit 0a2b5ab

Please sign in to comment.