Back to godoc.org
github.com/yahoo/vssh

Package vssh

v0.0.0 (1a184d5)
Latest Go to latest
Published: Jul 30, 2020 | License: Apache-2.0 | Module: github.com/yahoo/vssh

Overview

Package vssh is a Go library to handle tens of thousands SSH connections and execute the command with higher-level API for building network device / server automation.

run(ctx, command, timeout)
runWithLabel(ctx, command, timeout, "OS == Ubuntu && POP == LAX")

By calling the run method vssh sends the given command to all available clients or based on your query it runs the command on the specific clients and the results of the ran command can be received in two options, streaming or final result.In streaming you can get line by line from command’s stdout / stderr in real time or in case of non-real time you can get the whole of the lines together.

Example (Cloud)

This example demonstrates integration vSSH with AWS EC2

Code:

vs := vssh.New().Start()
config, _ := vssh.GetConfigPEM("ubuntu", "aws.pem")

awsConfig := &aws.Config{
	Region:      aws.String("us-west-1"),
	Credentials: credentials.NewStaticCredentials("YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", ""),
}
sess, err := session.NewSession(awsConfig)
if err != nil {
	fmt.Println("error creating new session:", err.Error())
	log.Fatal(err)
}
ec2svc := ec2.New(sess)
params := &ec2.DescribeInstancesInput{

	Filters: []*ec2.Filter{
		{
			Name:   aws.String("instance-state-name"),
			Values: []*string{aws.String("running")},
		},
	},
}
resp, err := ec2svc.DescribeInstances(params)
if err != nil {
	fmt.Println("there was an error listing instances in", err.Error())
	log.Fatal(err.Error())
}

for idx := range resp.Reservations {
	for _, inst := range resp.Reservations[idx].Instances {
		labels := make(map[string]string)
		for _, tag := range inst.Tags {
			labels[*tag.Key] = *tag.Value
		}
		addr := net.JoinHostPort(*inst.PublicIpAddress, "22")
		vs.AddClient(addr, config, vssh.SetLabels(labels))
	}
}

vs.Wait()

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

cmd := "uname -a"
timeout, _ := time.ParseDuration("5s")
respChan := vs.Run(ctx, cmd, timeout)

for resp := range respChan {

	if err := resp.Err(); err != nil {
		log.Println(err)
		continue
	}

	outTxt, errTxt, err := resp.GetText(vs)

	if err != nil {
		log.Println(err)
	}

	fmt.Println(outTxt)

	fmt.Println(errTxt)

	fmt.Println(resp.ExitStatus())
}

Index

Examples

Package Files

func GetConfigPEM

func GetConfigPEM(user, keyFile string) (*ssh.ClientConfig, error)

GetConfigPEM returns SSH configuration that uses the given private key. the keyfile should be unencrypted PEM-encoded private key file.

func GetConfigUserPass

func GetConfigUserPass(user, password string) *ssh.ClientConfig

GetConfigUserPass returns SSH configuration that uses the given username and password.

func SetClientsShardNumber

func SetClientsShardNumber(n int)

SetClientsShardNumber sets the clients shard number.

vSSH uses map data structure to keep the clients data in the memory. Sharding helps to have better performance on write/read with mutex. This setting can be tuned if needed.

type ClientOption

type ClientOption func(c *clientAttr)

ClientOption represents client optional parameters.

func DisableRequestPty

func DisableRequestPty() ClientOption

DisableRequestPty disables the pty.

func RequestPty

func RequestPty(term string, h, w uint, modes ssh.TerminalModes) ClientOption

RequestPty sets the pty parameters.

func SetLabels

func SetLabels(labels map[string]string) ClientOption

SetLabels sets labels for a client.

func SetMaxSessions

func SetMaxSessions(n int) ClientOption

SetMaxSessions sets maximum sessions for given client.

type MaxSessionsError

type MaxSessionsError struct {
	// contains filtered or unexported fields
}

MaxSessionsError represents max sessions error.

type Response

type Response struct {
	// contains filtered or unexported fields
}

Response represents the response for given session.

Example

This example demonstrates the use of GetText() for two hosts.

Code:

vs := vssh.New().Start()

config := vssh.GetConfigUserPass("vssh", "vssh")

for _, addr := range []string{"54.193.17.197:22", "192.168.2.19:22"} {
	vs.AddClient(addr, config, vssh.SetMaxSessions(4))
}

vs.Wait()

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

cmd := "ping -c 4 192.168.55.10"
timeout, _ := time.ParseDuration("6s")
respChan := vs.Run(ctx, cmd, timeout)

for resp := range respChan {

	if err := resp.Err(); err != nil {
		log.Println(err)
		continue
	}

	outTxt, errTxt, err := resp.GetText(vs)

	if err != nil {
		log.Println(err)
	}

	fmt.Println(outTxt)

	fmt.Println(errTxt)

	fmt.Println(resp.ExitStatus())
}

func (*Response) Err

func (r *Response) Err() error

Err returns response error.

func (*Response) ExitStatus

func (r *Response) ExitStatus() int

ExitStatus returns the exit status of the remote command.

func (*Response) GetStream

func (r *Response) GetStream() *Stream

GetStream constructs a new stream from a response.

func (*Response) GetText

func (r *Response) GetText(v *VSSH) (string, string, error)

GetText gets the final result of the given response.

func (*Response) ID

func (r *Response) ID() string

ID returns response identification.

type RunOption

type RunOption func(q *query)

RunOption represents run optional parameters.

func SetLimitReaderStderr

func SetLimitReaderStderr(n int64) RunOption

SetLimitReaderStderr sets limit for stderr reader.

func SetLimitReaderStdout

func SetLimitReaderStdout(n int64) RunOption

SetLimitReaderStdout sets limit for stdout reader.

respChan := vs.Run(ctx, cmd, timeout, vssh.SetLimitReaderStdout(1024))
Example

This example demonstrates how to set limit the amount of returned data

Code:

vs := vssh.New().Start()

config, _ := vssh.GetConfigPEM("ubuntu", "aws.pem")

vs.AddClient("54.215.209.152:22", config, vssh.SetMaxSessions(2))

vs.Wait()

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

timeout, _ := time.ParseDuration("6s")

respChan := vs.Run(ctx, "dmesg", timeout, vssh.SetLimitReaderStdout(1024))

resp := <-respChan

if err := resp.Err(); err != nil {
	log.Fatal(err)
}

outTxt, errTxt, err := resp.GetText(vs)

if err != nil {
	log.Println(err)
}

fmt.Println(outTxt)
fmt.Println(errTxt)

type Stream

type Stream struct {
	// contains filtered or unexported fields
}

Stream represents data stream for given response. It provides convenient interfaces to get the returned data real-time.

Example

This example demonstrates the use of stream

Code:

vs := vssh.New().Start()
config, _ := vssh.GetConfigPEM("ubuntu", "aws.pem")
vs.AddClient("54.193.17.197:22", config, vssh.SetMaxSessions(4))
vs.Wait()

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

cmd := "uname -a"
timeout, _ := time.ParseDuration("5s")
respChan := vs.Run(ctx, cmd, timeout)

resp := <-respChan
if err := resp.Err(); err != nil {
	log.Fatal(err)
}

stream := resp.GetStream()
defer stream.Close()

for stream.ScanStdout() {
	txt := stream.TextStdout()
	fmt.Println(txt)
}

if err := stream.Err(); err != nil {
	log.Fatal(err)
}

func (*Stream) BytesStderr

func (s *Stream) BytesStderr() []byte

BytesStderr returns the most recent data scanned by ScanStderr as bytes.

func (*Stream) BytesStdout

func (s *Stream) BytesStdout() []byte

BytesStdout returns the most recent data scanned by ScanStdout as bytes.

func (*Stream) Close

func (s *Stream) Close() error

Close cleans up the stream's response.

func (*Stream) Err

func (s *Stream) Err() error

Err returns stream response error.

func (*Stream) Input

func (s *Stream) Input(in io.Reader)

Input writes the given reader to remote command's standard input when the command starts.

func (*Stream) ScanStderr

func (s *Stream) ScanStderr() bool

ScanStderr provides a convenient interface for reading stderr which it connected to remote host. It reads a line and buffers it. The TextStdout() or BytesStdout() methods return the buffer in string or bytes.

func (*Stream) ScanStdout

func (s *Stream) ScanStdout() bool

ScanStdout provides a convenient interface for reading stdout which it connected to remote host. It reads a line and buffers it. The TextStdout() or BytesStdout() methods return the buffer in string or bytes.

func (*Stream) Signal

func (s *Stream) Signal(sig ssh.Signal)

Signal sends the given signal to remote process.

func (*Stream) TextStderr

func (s *Stream) TextStderr() string

TextStderr returns the most recent data scanned by ScanStderr as string.

func (*Stream) TextStdout

func (s *Stream) TextStdout() string

TextStdout returns the most recent data scanned by ScanStdout as string.

type TimeoutError

type TimeoutError struct {
	// contains filtered or unexported fields
}

TimeoutError represents timeout error.

type VSSH

type VSSH struct {
	// contains filtered or unexported fields
}

VSSH represents VSSH instance.

func New

func New() *VSSH

New constructs a new VSSH instance.

func (*VSSH) AddClient

func (v *VSSH) AddClient(addr string, config *ssh.ClientConfig, opts ...ClientOption) error

AddClient adds a new SSH client to VSSH.

func (*VSSH) CurrentProc

func (v *VSSH) CurrentProc() uint64

CurrentProc returns number of running processes / workers.

func (*VSSH) DecreaseProc

func (v *VSSH) DecreaseProc(n ...int)

DecreaseProc destroys the idle processes / workers.

func (*VSSH) ForceReConn

func (v *VSSH) ForceReConn(addr string) error

ForceReConn reconnects the client immediately.

func (*VSSH) IncreaseProc

func (v *VSSH) IncreaseProc(n ...int)

IncreaseProc adds more processes / workers.

func (*VSSH) OnDemand

func (v *VSSH) OnDemand() *VSSH

OnDemand changes VSSH connection behavior. By default VSSH connects to all of the clients before any run request and it maintains the authenticated SSH connection to all clients. We can call this "persistent SSH connection" but with OnDemand it tries to connect to clients once the run requested and it closes the appropriate connection once the response data returned.

func (*VSSH) Run

func (v *VSSH) Run(ctx context.Context, cmd string, timeout time.Duration, opts ...RunOption) chan *Response

Run sends a new run query with given context, command and timeout.

timeout allows you to set a limit on the length of time the command will run for. You can cancel the running command by context.WithCancel.

func (*VSSH) RunWithLabel

func (v *VSSH) RunWithLabel(ctx context.Context, cmd, queryStmt string, timeout time.Duration, opts ...RunOption) (chan *Response, error)

RunWithLabel runs the command on the specific clients which they matched with given query statement.

	labels := map[string]string {
 	"POP" : "LAX",
 	"OS" : "JUNOS",
	}
	// sets labels to a client
	vs.AddClient(addr, config, vssh.SetLabels(labels))
	// run the command with label
	vs.RunWithLabel(ctx, cmd, timeout, "POP == LAX || POP == DCA) && OS == JUNOS")

func (*VSSH) SetInitNumProc

func (v *VSSH) SetInitNumProc(n int)

SetInitNumProc sets the initial number of processes / workers.

You need to set this number right after creating vssh.

vs := vssh.New()
vs.SetInitNumProc(200)
vs.Start()

There are two other methods in case you need to change the settings in the middle of your code.

IncreaseProc(n int)
DecreaseProc(n int)

func (*VSSH) SetLogger

func (v *VSSH) SetLogger(l *log.Logger)

SetLogger sets external logger.

func (*VSSH) Start

func (v *VSSH) Start() *VSSH

Start starts vSSH, including action queue and re-connect procedures. You can construct and start the vssh like below:

vs := vssh.New().Start()

func (*VSSH) StartWithContext

func (v *VSSH) StartWithContext(ctx context.Context) *VSSH

StartWithContext is same as Run but it accepts external context.

func (*VSSH) Wait

func (v *VSSH) Wait(p ...int) (float64, error)

Wait stands by until percentage of the clients have been processed. An optional percentage can be passed as an argument - otherwise the default value of 100% is used.

Documentation was rendered with GOOS=linux and GOARCH=amd64.

Jump to identifier

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to identifier