nissh 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3101450e4df71a8c85bfe1291a2afc908548fbb2
4
+ data.tar.gz: 09667cd03ed47386c30ddfe64880c285de8a7fec
5
+ SHA512:
6
+ metadata.gz: 9aaf6594647384a86aa6e6640d3d84d6c0b29642d764eb8b0fcf09756065251469eac7b0b08b36d4e0eccf0ad7718feb8340e233d2fa9b3895adea16c0b0ea4c
7
+ data.tar.gz: 3441ccf451bf16810a3f46d29ca991d01ee8d154b480087b21d9bfe1d0aa9a0f7c44e96ee8dad2b489f4e85ec79fa2747eb783abcba1a04ccba18b6e5d023dcd
data/lib/nissh.rb ADDED
@@ -0,0 +1 @@
1
+ require 'nissh/session'
@@ -0,0 +1,24 @@
1
+ module Nissh
2
+ class Response
3
+
4
+ attr_accessor :stdout, :stderr, :exit_code, :exit_signal, :command
5
+
6
+ def initialize
7
+ reset_output!
8
+ end
9
+
10
+ def success?
11
+ exit_code == 0
12
+ end
13
+
14
+ def output
15
+ "#{stdout}\n#{stderr}"
16
+ end
17
+
18
+ def reset_output!
19
+ @stdout = ""
20
+ @stderr = ""
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,114 @@
1
+ require 'net/ssh'
2
+ require 'nissh/response'
3
+
4
+ module Nissh
5
+ class Session
6
+
7
+ class CommandExecutionFailed < StandardError; end
8
+
9
+ class << self
10
+ attr_accessor :logger
11
+ end
12
+
13
+ attr_reader :session
14
+ attr_accessor :sudo_password
15
+
16
+ def initialize(*args)
17
+ if args.first.is_a?(Net::SSH::Connection::Session)
18
+ @session = args.first
19
+ else
20
+ @session = Net::SSH.start(*args)
21
+ end
22
+ end
23
+
24
+ def execute!(commands, options = {})
25
+ unless commands.is_a?(Array)
26
+ commands = [commands]
27
+ end
28
+
29
+ if options[:sudo]
30
+ commands = commands.map do |command|
31
+ "sudo --stdin #{command}"
32
+ end
33
+ end
34
+
35
+ command = commands.join(' && ')
36
+ log :info, "\e[44;37m=> #{command}\e[0m"
37
+
38
+ response = Nissh::Response.new
39
+ response.command = command
40
+ channel = @session.open_channel do |channel|
41
+ channel.exec(command) do |_, success|
42
+ raise CommandExecutionFailed, "Command \"#{command}\" was unable to execute" unless success
43
+ channel.on_data do |_,data|
44
+ response.stdout += data
45
+ log :debug, data.gsub(/[\r]/, ''), :tab => 4
46
+ end
47
+
48
+ channel.on_extended_data do |_,_,data|
49
+ response.stderr += data.gsub(/\r/, '')
50
+ log :warn, data, :tab => 4
51
+ if data =~ /^\[sudo\] password for/
52
+ password = options[:sudo].is_a?(String) ? options[:sudo] : self.sudo_password
53
+ channel.send_data "#{password}\n"
54
+ end
55
+ end
56
+
57
+ channel.on_request("exit-status") do |_,data|
58
+ response.exit_code = data.read_long
59
+ log :info, "\e[43;37m=> Exit status: #{response.exit_code}\e[0m"
60
+ end
61
+
62
+ channel.on_request("exit-signal") do |_, data|
63
+ response.exit_signal = data.read_long
64
+ end
65
+ end
66
+ end
67
+ channel.wait
68
+ response
69
+ end
70
+
71
+ def execute_with_timeout!(command, timeout = 30)
72
+ Timeout.timeout(timeout) do
73
+ execute!(command)
74
+ end
75
+ rescue Timeout::Error => e
76
+ response = Nissh::Response.new
77
+ response.exit_code -255
78
+ response.stderr = "Command did not finish executing within the allowed #{timeout} seconds."
79
+ response.command = command
80
+ response
81
+ end
82
+
83
+ def execute_with_success!(command, success_code = 0)
84
+ result = execute!(command)
85
+ if result.success?
86
+ result
87
+ else
88
+ false
89
+ end
90
+ end
91
+
92
+ def execute_with_exception!(command, success_code = 0)
93
+ result = execute!(command)
94
+ if result.exit_code == success_code
95
+ result
96
+ else
97
+ raise CommandExecutionFailed, result.output
98
+ end
99
+ end
100
+
101
+ private
102
+
103
+ def log(type, text, options = {})
104
+ if self.class.logger
105
+ prefix = "\e[45;37m[#{@session.transport.host}]\e[0m"
106
+ tabs = " " * (options[:tab] || 0)
107
+ text.split(/\n/).each do |line|
108
+ self.class.logger.send(type, prefix + tabs + line)
109
+ end
110
+ end
111
+ end
112
+
113
+ end
114
+ end
@@ -0,0 +1,3 @@
1
+ module Nissh
2
+ VERSION = '1.0.0'
3
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nissh
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Adam Cooke
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-08-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: net-ssh
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '2'
27
+ description: A wrapper for net/ssh to make running commands more fun
28
+ email:
29
+ - me@adamcooke.io
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - lib/nissh.rb
35
+ - lib/nissh/response.rb
36
+ - lib/nissh/session.rb
37
+ - lib/nissh/version.rb
38
+ homepage: https://github.com/adamcooke/nissh
39
+ licenses:
40
+ - MIT
41
+ metadata: {}
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubyforge_project:
58
+ rubygems_version: 2.4.5
59
+ signing_key:
60
+ specification_version: 4
61
+ summary: A wrapper for net/ssh to make running commands more fun
62
+ test_files: []
63
+ has_rdoc: