README

vSSH

Go library to handle tens of thousands SSH connections and execute the command(s) with higher-level API for building network device / server automation. Documentation and examples are available via godoc.

Test Status Go Report Card Coverage Status GoDoc PkgGoDev

Alt text

Features

  • Connect to multiple remote machines concurrently
  • Persistent SSH connection
  • DSL query based on the labels
  • Manage number of sessions per SSH connection
  • Limit amount of stdout and stderr data in bytes
  • Higher-level API for building automation
Sample query with label
labels := map[string]string {
  "POP" : "LAX",
  "OS" : "JUNOS",
}
// sets labels to a client
vs.AddClient(addr, config, vssh.SetLabels(labels))
// query with label
vs.RunWithLabel(ctx, cmd, timeout, "(POP == LAX || POP == DCA) && OS == JUNOS")
Basic example
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, _ := resp.GetText(vs)
  fmt.Println(outTxt, errTxt, resp.ExitStatus())
}
Stream example
vs := vssh.New().Start()
config, _ := vssh.GetConfigPEM("vssh", "mypem.pem")
vs.AddClient("54.193.17.197:22", 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)

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)
}

Supported platform

  • Linux
  • Windows
  • Darwin
  • BSD
  • Solaris

License

Code is licensed under the Apache License, Version 2.0 (the "License"). Content is licensed under the CC BY 4.0 license. Terms available at https://creativecommons.org/licenses/by/4.0/.

Contribute

Welcomes any kind of contribution, please follow the next steps:

  • Fork the project on github.com.
  • Create a new branch.
  • Commit changes to the new branch.
  • Send a pull request.

Documentation

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

      Output:
      
      
      Example (Stream)
      Output:
      
      

      Index

      Examples

      Constants

      This section is empty.

      Variables

      This section is empty.

      Functions

      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.

            Types

            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.

                            Output:
                            
                            

                            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

                                              Output:
                                              
                                              

                                              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

                                                  Output:
                                                  
                                                  

                                                  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.