Class: Cyclid::API::Plugins::Ssh

Inherits:
Transport show all
Defined in:
app/cyclid/plugins/transport/ssh.rb

Overview

SSH based transport

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Transport

#export_env, human_name

Methods inherited from Base

author, config?, config_schema, default_config, get_config, homepage, human_name, license, register_plugin, set_config, update_config, version

Constructor Details

#initialize(args = {}) ⇒ Ssh

Returns a new instance of Ssh.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'app/cyclid/plugins/transport/ssh.rb', line 30

def initialize(args = {})
  args.symbolize_keys!

  # Hostname, username & a log target are required
  return false unless args.include? :host and \
                      args.include? :user and \
                      args.include? :log

  password = args[:password] if args.include? :password
  keys = [args[:key]] if args.include? :key

  @log = args[:log]

  # Create an SSH channel
  Cyclid.logger.debug 'waiting for SSH...'

  start = Time.now
  loop do
    begin
      @session = Net::SSH.start(args[:host],
                                args[:user],
                                password: password,
                                keys: keys,
                                timeout: 5)
      break unless @session.nil?
    rescue Net::SSH::Exception
      Cyclid.logger.debug 'SSH authentication failed'
    rescue StandardError => ex
      Cyclid.logger.debug "SSH connection failed: #{ex}"
    end

    sleep 5

    raise 'timed out waiting for SSH' \
      if (Time.now - start) >= 30
  end
end

Instance Attribute Details

#exit_codeObject (readonly)

Returns the value of attribute exit_code.



28
29
30
# File 'app/cyclid/plugins/transport/ssh.rb', line 28

def exit_code
  @exit_code
end

#exit_signalObject (readonly)

Returns the value of attribute exit_signal.



28
29
30
# File 'app/cyclid/plugins/transport/ssh.rb', line 28

def exit_signal
  @exit_signal
end

Class Method Details

.metadataObject

Plugin metadata



132
133
134
135
136
137
# File 'app/cyclid/plugins/transport/ssh.rb', line 132

def self.
  super.merge!(version: Cyclid::Api::VERSION,
               license: 'Apache-2.0',
               author: 'Liqwyd Ltd.',
               homepage: 'http://docs.cyclid.io')
end

Instance Method Details

#closeObject

Close the SSH connection



127
128
129
# File 'app/cyclid/plugins/transport/ssh.rb', line 127

def close
  @session.close
end

#download(io, path) ⇒ Object

Copy a data from remote file to a local IO object



121
122
123
124
# File 'app/cyclid/plugins/transport/ssh.rb', line 121

def download(io, path)
  channel = @session.scp.download path, io
  channel.wait
end

#exec(cmd, args = {}) ⇒ Object

Execute a command via. SSH



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'app/cyclid/plugins/transport/ssh.rb', line 69

def exec(cmd, args = {})
  sudo = args[:sudo] || false
  path = args[:path]

  command = build_command(cmd, sudo, path, @env)
  Cyclid.logger.debug "command=#{command}"

  @session.open_channel do |channel|
    channel.on_open_failed do |_ch, _code, desc|
      # XXX raise
      abort "failed to open channel: #{desc}"
    end

    # STDOUT
    channel.on_data do |_ch, data|
      # Send to Log Buffer
      @log.write data
    end

    # STDERR
    channel.on_extended_data do |_ch, _type, data|
      # Send to Log Buffer
      @log.write data
    end

    # Capture return value from commands
    channel.on_request 'exit-status' do |_ch, data|
      @exit_code = data.read_long
    end

    # Capture a command exiting with a signal
    channel.on_request 'exit-signal' do |_ch, data|
      @exit_signal = data.read_long
    end

    channel.exec command do |_ch, _success|
    end
  end

  # Run the SSH even loop; this blocks until the command has completed
  @session.loop

  @exit_code.zero? && @exit_signal.nil? ? true : false
end

#upload(io, path) ⇒ Object

Copy data from a local IO object to a remote file via. SCP



115
116
117
118
# File 'app/cyclid/plugins/transport/ssh.rb', line 115

def upload(io, path)
  channel = @session.scp.upload io, path
  channel.wait
end