boris 1.0.0.beta.1 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +11 -0
- data/README.md +114 -32
- data/Rakefile +19 -0
- data/lib/boris.rb +0 -13
- data/lib/boris/connectors.rb +25 -7
- data/lib/boris/connectors/snmp.rb +24 -4
- data/lib/boris/connectors/ssh.rb +32 -6
- data/lib/boris/connectors/wmi.rb +109 -54
- data/lib/boris/errors.rb +1 -1
- data/lib/boris/helpers/array.rb +62 -62
- data/lib/boris/helpers/constants.rb +22 -19
- data/lib/boris/helpers/hash.rb +7 -7
- data/lib/boris/helpers/network.rb +68 -0
- data/lib/boris/helpers/scrubber.rb +53 -51
- data/lib/boris/helpers/string.rb +148 -26
- data/lib/boris/lumberjack.rb +74 -47
- data/lib/boris/options.rb +28 -16
- data/lib/boris/profiler.rb +19 -0
- data/lib/boris/profilers/linux/redhat.rb +74 -0
- data/lib/boris/{profiles → profilers}/linux_core.rb +13 -4
- data/lib/boris/{profiles → profilers}/unix/solaris.rb +25 -15
- data/lib/boris/{profiles → profilers}/unix_core.rb +90 -85
- data/lib/boris/profilers/windows/windows2003.rb +11 -0
- data/lib/boris/profilers/windows/windows2008.rb +26 -0
- data/lib/boris/profilers/windows/windows2012.rb +11 -0
- data/lib/boris/{profiles → profilers}/windows_core.rb +36 -14
- data/lib/boris/structure.rb +173 -167
- data/lib/boris/target.rb +110 -168
- data/lib/boris/version.rb +3 -0
- metadata +32 -115
- data/boris.gemspec +0 -28
- data/doc/Array.html +0 -437
- data/doc/Boris.html +0 -230
- data/doc/Boris/ConnectionAlreadyActive.html +0 -123
- data/doc/Boris/ConnectionFailed.html +0 -127
- data/doc/Boris/Connector.html +0 -794
- data/doc/Boris/InvalidCredentials.html +0 -131
- data/doc/Boris/InvalidOption.html +0 -123
- data/doc/Boris/InvalidTargetName.html +0 -123
- data/doc/Boris/Lumberjack.html +0 -466
- data/doc/Boris/MissingCredentials.html +0 -123
- data/doc/Boris/NoActiveConnection.html +0 -123
- data/doc/Boris/NoProfileDetected.html +0 -123
- data/doc/Boris/Options.html +0 -783
- data/doc/Boris/Profiles.html +0 -117
- data/doc/Boris/Profiles/Linux.html +0 -1151
- data/doc/Boris/Profiles/RedHat.html +0 -875
- data/doc/Boris/Profiles/Solaris.html +0 -1230
- data/doc/Boris/Profiles/Structure.html +0 -2050
- data/doc/Boris/Profiles/UNIX.html +0 -893
- data/doc/Boris/Profiles/Windows.html +0 -1846
- data/doc/Boris/Profiles/Windows/Windows2003.html +0 -304
- data/doc/Boris/Profiles/Windows/Windows2008.html +0 -379
- data/doc/Boris/Profiles/Windows/Windows2012.html +0 -304
- data/doc/Boris/SNMPConnector.html +0 -512
- data/doc/Boris/SSHConnector.html +0 -633
- data/doc/Boris/Target.html +0 -2002
- data/doc/Boris/WMIConnector.html +0 -1134
- data/doc/BorisLogger.html +0 -217
- data/doc/Hash.html +0 -195
- data/doc/String.html +0 -1246
- data/doc/_index.html +0 -420
- data/doc/class_list.html +0 -53
- data/doc/css/common.css +0 -1
- data/doc/css/full_list.css +0 -57
- data/doc/css/style.css +0 -328
- data/doc/file.README.html +0 -183
- data/doc/file_list.html +0 -55
- data/doc/frames.html +0 -28
- data/doc/index.html +0 -183
- data/doc/js/app.js +0 -214
- data/doc/js/full_list.js +0 -173
- data/doc/js/jquery.js +0 -4
- data/doc/method_list.html +0 -1468
- data/doc/top-level-namespace.html +0 -126
- data/lib/boris/profiles/linux/redhat.rb +0 -77
- data/lib/boris/profiles/windows/windows2003.rb +0 -15
- data/lib/boris/profiles/windows/windows2008.rb +0 -23
- data/lib/boris/profiles/windows/windows2012.rb +0 -15
- data/test/connector_tests/test_snmp.rb +0 -35
- data/test/connector_tests/test_ssh.rb +0 -51
- data/test/connector_tests/test_wmi.rb +0 -129
- data/test/helper_tests/test_array.rb +0 -25
- data/test/helper_tests/test_hash.rb +0 -10
- data/test/helper_tests/test_string.rb +0 -136
- data/test/profile_tests/test_core_skeleton +0 -107
- data/test/profile_tests/test_linux_core.rb +0 -331
- data/test/profile_tests/test_redhat.rb +0 -134
- data/test/profile_tests/test_solaris.rb +0 -523
- data/test/profile_tests/test_unix_core.rb +0 -117
- data/test/profile_tests/test_windows.rb +0 -536
- data/test/setup_tests.rb +0 -14
- data/test/test_all.rb +0 -8
- data/test/test_options.rb +0 -44
- data/test/test_structure.rb +0 -136
- data/test/test_target.rb +0 -146
data/CHANGELOG.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# 1.0.1
|
2
|
+
* Renamed Profiles to Profilers
|
3
|
+
* Moved networking helper methods to newly created Network module
|
4
|
+
* Separated Structure and Profilers
|
5
|
+
* Profilers are now separate classes for easier subclassing
|
6
|
+
* Simplified logging
|
7
|
+
|
8
|
+
# 1.0.0.beta1
|
9
|
+
* Initial public release
|
10
|
+
|
11
|
+
# 1.0.0* was yanked
|
data/README.md
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
# Boris
|
2
|
-
##
|
2
|
+
## Networked-device scanning library written in Ruby
|
3
3
|
|
4
4
|
* Code: http://github.com/alkalinecoffee/boris
|
5
|
-
*
|
5
|
+
* Developer's blog: http://www.sharkwavemedia.com
|
6
|
+
* Documentation: http://rdoc.info/github/alkalinecoffee/boris/frames
|
6
7
|
* Issues: https://github.com/alkalinecoffee/boris/issues
|
7
8
|
|
8
9
|
## Introduction
|
9
10
|
Boris is a library that facilitates the communication between you and various networked devices over SNMP, SSH and WMI, pulling a large amount of configuration items including installed software, network settings, serial numbers, user accounts, disk utilization, and more.
|
10
11
|
|
11
|
-
Out of the box, Boris has server support for
|
12
|
+
Out of the box, Boris has server support for Red Hat, Solaris,and Windows (with other platforms available with future plugins), with a focus on returning precisely formatted data, no matter which platforms your organization may have deployed. Through the use of profilers, Boris can easily be extended by the developer to include other platforms. Highly suitable for small and large environments alike looking to pull configuration data from various platforms.
|
12
13
|
|
13
14
|
## Features
|
14
|
-
*
|
15
|
+
* Currently, pulls information from Red Hat Linux, Solaris, and Windows servers (support for OS X, F5 BIG-IP, and Cisco IOS devices in the works)
|
15
16
|
* Utilizes SNMP, SSH, and WMI communication technologies
|
16
17
|
* Expandable to include other networked devices, such as switches, load balancers, and other operating systems
|
17
18
|
|
@@ -24,43 +25,109 @@ Let's pull some information from a RedHat Enterprise Linux server on our network
|
|
24
25
|
```ruby
|
25
26
|
require 'boris'
|
26
27
|
|
27
|
-
|
28
|
+
# Boris has different levels of logging. We can optionally set our logging level, which will apply
|
29
|
+
# to all Targets created during this session. If not set, the log level defaults to :fatal.
|
30
|
+
Boris.log_level = :debug
|
31
|
+
|
32
|
+
hostname = 'redhatserver01.mydomain.com'
|
28
33
|
|
29
34
|
# let's use a helper to suggest how we should connect to it (which is useful if we're not sure what
|
30
35
|
# kind of device this is)
|
31
|
-
puts
|
36
|
+
puts Boris::Network.suggested_connection_method(hostname)
|
32
37
|
|
33
38
|
# you can also add the logic to make the decision yourself by checking if certain TCP ports are responsive
|
34
|
-
puts
|
39
|
+
puts Boris::Network.tcp_port_responding?(hostname, 22)
|
40
|
+
|
41
|
+
# create our target
|
42
|
+
target = Boris::Target.new(hostname)
|
35
43
|
|
36
44
|
# add credentials to try against this target
|
37
|
-
target.options.add_credential(:user=>'
|
45
|
+
target.options.add_credential(:user=>'myusername', :password=>'mypassword', :connection_types=>[:ssh])
|
46
|
+
|
47
|
+
# if this is a host using SSH, we can also pass in Net::SSH options (such as a private key for authentication).
|
48
|
+
# SSH options passed to Boris will automatically be pushed to Net:SSH.
|
49
|
+
target.options[:ssh_options] = {:keys=>['/path/to/my/private/key']}
|
38
50
|
|
39
51
|
# attempt to connect to this target using the credentials we supplied above
|
40
52
|
target.connect
|
41
53
|
|
42
54
|
if target.connected?
|
43
|
-
# detect which
|
44
|
-
# detect a suitable
|
45
|
-
target.
|
55
|
+
# we can try to detect which profiler to load up (is this target running windows? solaris? or
|
56
|
+
# what?). if we can't detect a suitable profiler, this will throw an error.
|
57
|
+
target.detect_profiler
|
58
|
+
|
59
|
+
puts target.profiler.class
|
60
|
+
|
61
|
+
# we can call individual methods to grab specific information we may be interested in
|
62
|
+
target.get(:hardware)
|
63
|
+
|
64
|
+
# or maybe get some network interface info
|
65
|
+
puts target.get(:network_interfaces)
|
66
|
+
|
67
|
+
# retrieved items can be referenced two ways:
|
68
|
+
puts target[:network_interfaces].inspect
|
69
|
+
puts target.profiler.network_interfaces.inspect
|
70
|
+
|
71
|
+
# we can also call #retrieve_all to grab everything we can from this target (file systems, hardware,
|
72
|
+
# installed applications, etc.)
|
73
|
+
target.retrieve_all
|
74
|
+
|
75
|
+
# if there is more information we want to collect but is not collected by default, we can specify
|
76
|
+
# our own commands to run against the target via two methods: #get_values returns an Array (each
|
77
|
+
# line is an element of the array), or #get_value, which returns a String (the first line returned
|
78
|
+
# from the command)
|
79
|
+
puts target.connector.values_at('cat /etc/redhat-release')
|
80
|
+
puts target.connector.value_at('uname -a')
|
81
|
+
|
82
|
+
# NOTE: if this were a Windows server, you would send WMI queries instead of shell commands, ie:
|
83
|
+
#
|
84
|
+
# target.connector.values_at('SELECT * FROM Win32_ComputerSystem')
|
85
|
+
#
|
86
|
+
|
87
|
+
# finally, we can package up all of the data into json format for portability (the true argument
|
88
|
+
# tells the #to_json method to output the json with tabbed formatting)
|
89
|
+
puts target.to_json(:pretty_print)
|
90
|
+
|
91
|
+
target.disconnect
|
92
|
+
end
|
93
|
+
```
|
46
94
|
|
47
|
-
|
95
|
+
## Extending Boris
|
96
|
+
You can also run your own commands to grab information off of systems. For example, on a Linux device, to run your own script that is already on the target and retrieve its output:
|
48
97
|
|
49
|
-
|
50
|
-
|
51
|
-
|
98
|
+
```ruby
|
99
|
+
# use the target's connector to grab multiple values. #values_at will return an array with each line
|
100
|
+
# returned as an item in the returned array.
|
101
|
+
multiple_lines_of_data = target.connector.values_at('/path/to/some/script')
|
52
102
|
|
53
|
-
|
103
|
+
# to grab only the first line from a script or file, you can use #value_at:
|
104
|
+
single_line_of_data = target.connector.value_at('/path/to/some/script')
|
105
|
+
```
|
54
106
|
|
55
|
-
|
56
|
-
puts target.to_json
|
57
|
-
end
|
107
|
+
Running commands in this fashion utilizes the #exec function from Net::SSH.
|
58
108
|
|
59
|
-
|
109
|
+
For a Windows host, which uses WMI vice SSH, you can send WMI queries or registry keys to the connector to get information:
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
# this will pull rows from a class in the standard root\CIMV2 namespace, returning an array of hashes
|
113
|
+
multiple_rows_of_data = target.connector.values_at('SELECT * FROM Win32_NetworkAdapter')
|
114
|
+
|
115
|
+
# this will pull rows from a class in the lower-level root\WMI namespace (note the second argument we're passing to #values_at):
|
116
|
+
multiple_rows_of_data = target.connector.values_at('SELECT * FROM MSNdis_EnumerateAdapter', :root_wmi)
|
117
|
+
|
118
|
+
# you can also poll for registry keys under HKEY_LOCAL_MACHINE by providing a base key path, which returns an array of keys:
|
119
|
+
registry_keys = target.connector.registry_subkeys_at('SOFTWARE\Microsoft\Windows')
|
120
|
+
|
121
|
+
# and then grab values found at some key via #registry_values_at, which returns value/data elements in a Hash:
|
122
|
+
registry_values = target.connector.registry_values_at('SOFTWARE\Microsoft\Windows\CurrentVersion')
|
60
123
|
```
|
61
124
|
|
125
|
+
**Coming soon--a write-up for SNMP devices**
|
126
|
+
|
127
|
+
Boris also comes with the ability to add your own complete modules for using the framework by writing your own data collection algorithms. This will also be written up in the near future.
|
128
|
+
|
62
129
|
## Data
|
63
|
-
Through a number of queries and algorithms, Boris
|
130
|
+
Through a number of queries and algorithms, Boris efficiently polls devices on the network for information including, but not limited to, network configuration, hardware capabilities, installed software and services, applied hotfixes/patches, and more.
|
64
131
|
|
65
132
|
**Available methods for use on most platforms include:**
|
66
133
|
|
@@ -75,20 +142,35 @@ Through a number of queries and algorithms, Boris effeciently polls devices on t
|
|
75
142
|
* **network interfaces** - ethernet and fibre channel interfaces, including IPs, MAC addresses, connection status
|
76
143
|
* **operating system** - name, version, kernel, date installed
|
77
144
|
|
78
|
-
See {Boris::
|
145
|
+
See {http://www.rubydoc.info/github/alkalinecoffee/boris/Boris/Profilers/Structure Boris::Profilers::Structure} for more details on the data structure.
|
79
146
|
|
80
147
|
Because the commands that might work correctly on one type of platform most likely won't work on another, Boris handles this by the use of...
|
81
148
|
|
82
|
-
##
|
83
|
-
|
149
|
+
## Profilers
|
150
|
+
Profilers contain the instructions that allow us to run commands against our target and then parse and make sense of the data. Boris comes with the capability to communicate with targets over SNMP, SSH, or WMI. Each profiler is written to use one of these methods of communication (internally called 'connectors'), which serve as a vehicle for running commands against a server. Boris comes with a few profilers built-in for some popular platforms, but can be easily extended to include other devices.
|
151
|
+
|
152
|
+
**Available profilers:**
|
153
|
+
|
154
|
+
* **Linux Core**
|
155
|
+
* Red Hat Linux
|
156
|
+
* **UNIX Core**
|
157
|
+
* Oracle Solaris
|
158
|
+
* **Windows Core**
|
159
|
+
* Windows 2003 Server
|
160
|
+
* Windows 2008 Server
|
161
|
+
* Windows 2012 Server
|
162
|
+
|
163
|
+
## User Account Requirements
|
164
|
+
While Boris does its best to gather data from devices without any special privileges, sometimes it just can't be helped. One example of this is the RedHat profiler, which requires `sudo` access for the `dmidecode` command, as there isn't a well known, reliable way to grab this info without `dmidecode`. If Boris attempts to run a command that requires special access and is denied, it will throw a message to the logger and move on.
|
165
|
+
|
166
|
+
**Here is a list of known scan account requirements for each platform:**
|
84
167
|
|
85
|
-
|
86
|
-
*
|
87
|
-
*
|
88
|
-
*
|
89
|
-
*
|
90
|
-
*
|
91
|
-
* Shoulda (for tests only)
|
168
|
+
* **Linux (any flavor)**
|
169
|
+
* User must have `sudo` for `dmidecode`
|
170
|
+
* **Solaris**
|
171
|
+
* User must have `sudo` for `fcinfo`
|
172
|
+
* **Windows**
|
173
|
+
* User must be a member of local Administrator group (looking into what other groups provide required access)
|
92
174
|
|
93
|
-
##
|
175
|
+
## License
|
94
176
|
This software is provided under the MIT license. See the LICENSE.md file.
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
4
|
+
|
5
|
+
require 'boris/version'
|
6
|
+
|
7
|
+
task :build do
|
8
|
+
system 'gem build boris.gemspec'
|
9
|
+
end
|
10
|
+
|
11
|
+
task :install => :build do
|
12
|
+
system "gem install boris-#{Boris::VERSION}.gem"
|
13
|
+
end
|
14
|
+
|
15
|
+
task :release => :build do
|
16
|
+
system "git tag -a v#{Boris::VERSION} -m 'Pushed #{Boris::VERSION}'"
|
17
|
+
system 'git push --tags'
|
18
|
+
system "gem push boris-#{Boris::VERSION}.gem"
|
19
|
+
end
|
data/lib/boris.rb
CHANGED
@@ -14,17 +14,4 @@ require 'thread'
|
|
14
14
|
require 'win32ole' if PLATFORM == :win32
|
15
15
|
|
16
16
|
require 'boris/lumberjack'
|
17
|
-
|
18
|
-
require 'boris/errors'
|
19
|
-
require 'boris/options'
|
20
17
|
require 'boris/target'
|
21
|
-
|
22
|
-
require 'boris/helpers/array'
|
23
|
-
require 'boris/helpers/constants'
|
24
|
-
require 'boris/helpers/hash'
|
25
|
-
require 'boris/helpers/scrubber'
|
26
|
-
require 'boris/helpers/string'
|
27
|
-
|
28
|
-
module Boris
|
29
|
-
|
30
|
-
end
|
data/lib/boris/connectors.rb
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
module Boris
|
2
|
+
# The Connector class is the parent of the main Connector types that Boris
|
3
|
+
# utilizes (WMI, SNMP, and SSH). It's primary purpose is to create the general
|
4
|
+
# structure of a connector and offer some debugging messages for different
|
5
|
+
# actions. Typically, Connector objects would not be created by user code.
|
6
|
+
# Instead, your own connectors would be a subclass of Connector with calls
|
7
|
+
# to super as appropriate.
|
2
8
|
class Connector
|
3
9
|
include Lumberjack
|
4
10
|
|
@@ -7,31 +13,43 @@ module Boris
|
|
7
13
|
attr_reader :options
|
8
14
|
attr_reader :reconnectable
|
9
15
|
|
10
|
-
def initialize(host, cred
|
11
|
-
|
12
|
-
|
16
|
+
def initialize(host, cred={})
|
17
|
+
@logger = Boris.logger
|
18
|
+
|
13
19
|
@host = host
|
14
20
|
@user = cred[:user]
|
15
21
|
@password = cred[:password]
|
16
22
|
@connected = false
|
17
23
|
@reconnectable = true
|
18
|
-
|
19
|
-
@logger = logger
|
24
|
+
debug 'creating connection object'
|
20
25
|
end
|
21
26
|
|
27
|
+
# Convience method for retrieveing the connection status for this Connector.
|
28
|
+
#
|
29
|
+
# connector.connected? #=> true
|
30
|
+
#
|
31
|
+
# @return [Boolean] true if connected
|
22
32
|
def connected?
|
23
33
|
@connected
|
24
34
|
end
|
25
35
|
|
36
|
+
# Disconnect from the host.
|
26
37
|
def disconnect
|
27
|
-
|
38
|
+
info 'closing connection to host'
|
28
39
|
@connected = false
|
29
40
|
end
|
30
41
|
|
42
|
+
# Establish our connection.
|
31
43
|
def establish_connection
|
32
44
|
debug 'attempting connection'
|
33
45
|
end
|
34
46
|
|
47
|
+
# Only to be called from a child class, as this method only performs some simple
|
48
|
+
# checks for errors and provides debugging messages. Not intended to be directly
|
49
|
+
# called from user code.
|
50
|
+
#
|
51
|
+
# @param [String] request the command we wish to execute over this connection
|
52
|
+
# @param [Integer] limit the maximum number of results we wish to return
|
35
53
|
def values_at(request, limit)
|
36
54
|
if !limit.kind_of?(Integer)
|
37
55
|
raise ArgumentError, "non-integer limit specified (#{limit.inspect})"
|
@@ -41,7 +59,7 @@ module Boris
|
|
41
59
|
|
42
60
|
amount = limit == 1 ? 'single value' : 'multiple values'
|
43
61
|
|
44
|
-
debug "issuing request for #{amount} (#{request
|
62
|
+
debug "issuing request for #{amount} (#{request})"
|
45
63
|
end
|
46
64
|
end
|
47
65
|
end
|
@@ -2,20 +2,32 @@ require 'boris/connectors'
|
|
2
2
|
|
3
3
|
module Boris
|
4
4
|
class SNMPConnector < Connector
|
5
|
-
|
6
|
-
|
5
|
+
|
6
|
+
# Create an instance of SNMPConnector by passing in a mandatory hostname or IP address,
|
7
|
+
# credential to try, and optional Hash of {Boris::Options options}. Under the hood, this
|
8
|
+
# class uses the SNMP library.
|
9
|
+
#
|
10
|
+
# @param [String] host hostname or IP address
|
11
|
+
# @param [Hash] cred credential we wish to use
|
12
|
+
# @param [Hash] options an optional list of options. See {Boris::Options} for a list of all
|
13
|
+
# possible options. The relevant option set here would be :snmp_options.
|
14
|
+
def initialize(host, cred, options={})
|
15
|
+
super(host, cred)
|
7
16
|
@snmp_options = options[:snmp_options].merge(:host=>@host, :version=>:SNMPv1, :community=>@user)
|
8
17
|
|
9
18
|
#snmp connections are always reconnectable
|
10
19
|
@reconnectable = true
|
11
20
|
end
|
12
21
|
|
22
|
+
# Disconnect from the host.
|
13
23
|
def disconnect
|
14
24
|
super
|
15
25
|
@transport = nil
|
16
26
|
debug 'connections closed'
|
17
27
|
end
|
18
28
|
|
29
|
+
# Establish our connection.
|
30
|
+
# @return [SNMPConnector] instance of SNMPConnector
|
19
31
|
def establish_connection
|
20
32
|
super
|
21
33
|
|
@@ -30,13 +42,21 @@ module Boris
|
|
30
42
|
warn "connection failed (#{error.message})"
|
31
43
|
end
|
32
44
|
|
33
|
-
|
45
|
+
self
|
34
46
|
end
|
35
47
|
|
48
|
+
# Return a single value from our request.
|
49
|
+
# @param [String] request the command we wish to execute over this connection
|
50
|
+
# @return [String] the first row/line returned by the host
|
36
51
|
def value_at(request)
|
37
52
|
values_at(request, 1)[0]
|
38
53
|
end
|
39
54
|
|
55
|
+
# Return multiple values from our request, up to the limit specified (or no
|
56
|
+
# limit if no limit parameter is specified.
|
57
|
+
# @param [String] request the command we wish to execute over this connection
|
58
|
+
# @param [Integer] limit the optional maximum number of results we wish to return
|
59
|
+
# @return [Array] an array of rows returned by the query
|
40
60
|
def values_at(request, limit=nil)
|
41
61
|
super(request, limit)
|
42
62
|
|
@@ -46,7 +66,7 @@ module Boris
|
|
46
66
|
row.each {|item| return_data << {:name=>item.name.to_s, :value=>item.value}}
|
47
67
|
end
|
48
68
|
|
49
|
-
|
69
|
+
debug "#{return_data.size} row(s) returned"
|
50
70
|
|
51
71
|
limit = return_data.size if limit.nil?
|
52
72
|
|
data/lib/boris/connectors/ssh.rb
CHANGED
@@ -2,22 +2,36 @@ require 'boris/connectors'
|
|
2
2
|
|
3
3
|
module Boris
|
4
4
|
class SSHConnector < Connector
|
5
|
-
|
5
|
+
|
6
|
+
# Create an instance of SSHConnector by passing in a mandatory hostname or IP address,
|
7
|
+
# credential to try, and optional Hash of {Boris::Options options}. Under the hood, this
|
8
|
+
# class uses the Net/SSH library.
|
9
|
+
#
|
10
|
+
# @param [String] host hostname or IP address
|
11
|
+
# @param [Hash] cred credential we wish to use
|
12
|
+
# @param [Hash] options an optional list of options. See {Boris::Options} for a list of all
|
13
|
+
# possible options. The relevant option set here would be :ssh_options.
|
14
|
+
def initialize(host, cred, options={})
|
6
15
|
@ssh_options = options[:ssh_options]
|
7
16
|
@ssh_options[:password] = @password if @password
|
8
17
|
|
9
|
-
|
10
|
-
|
18
|
+
if @ssh_options
|
19
|
+
invalid_ssh_options = @ssh_options.keys - Net::SSH::VALID_OPTIONS
|
20
|
+
raise ArgumentError, "invalid ssh option(s): #{invalid_ssh_options.join(', ')}" if invalid_ssh_options.any?
|
21
|
+
end
|
11
22
|
|
12
|
-
super(host, cred
|
23
|
+
super(host, cred)
|
13
24
|
end
|
14
25
|
|
26
|
+
# Disconnect from the host.
|
15
27
|
def disconnect
|
16
28
|
super
|
17
29
|
@transport = nil
|
18
30
|
debug 'connections closed'
|
19
31
|
end
|
20
32
|
|
33
|
+
# Establish our connection.
|
34
|
+
# @return [SSHConnector] instance of SSHConnector
|
21
35
|
def establish_connection
|
22
36
|
super
|
23
37
|
|
@@ -42,13 +56,25 @@ module Boris
|
|
42
56
|
info 'connection does not seem to be available (so we will not retry)'
|
43
57
|
end unless @transport
|
44
58
|
|
45
|
-
|
59
|
+
self
|
46
60
|
end
|
47
61
|
|
62
|
+
# Return a single value from our request.
|
63
|
+
# @param [String] request the command we wish to execute over this connection
|
64
|
+
# @param [Boolean] request_pty if true, we should request psuedo-terminal (PTY).
|
65
|
+
# This is necessary if we are calling a command that uses elevated privileges (sudo).
|
66
|
+
# @return [String] the first row/line returned by the host
|
48
67
|
def value_at(request, request_pty=false)
|
49
68
|
values_at(request, request_pty, 1)[0]
|
50
69
|
end
|
51
70
|
|
71
|
+
# Return multiple values from our request, up to the limit specified (or no
|
72
|
+
# limit if no limit parameter is specified.
|
73
|
+
# @param [String] request the command we wish to execute over this connection
|
74
|
+
# @param [Boolean] request_pty if true, we should request psuedo-terminal (PTY).
|
75
|
+
# This is necessary if we are calling a command that uses elevated privileges (sudo).
|
76
|
+
# @param [Integer] limit the optional maximum number of results we wish to return
|
77
|
+
# @return [Array] an array of rows returned by the command
|
52
78
|
def values_at(request, request_pty=false, limit=nil)
|
53
79
|
super(request, limit)
|
54
80
|
|
@@ -100,7 +126,7 @@ module Boris
|
|
100
126
|
|
101
127
|
return_data = return_data.join.split(/\n/)
|
102
128
|
|
103
|
-
|
129
|
+
debug "#{return_data.size} row(s) returned"
|
104
130
|
|
105
131
|
limit = return_data.size if limit.nil?
|
106
132
|
|