assemblr 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +84 -0
- data/Rakefile +8 -0
- data/assemblr.gemspec +37 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/assemblr.rb +275 -0
- data/lib/assemblr/logging.rb +48 -0
- data/lib/assemblr/utilities.rb +39 -0
- data/lib/assemblr/version.rb +5 -0
- metadata +141 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a56be997b4579f72b563f67e40f81a2aaaec974dc2568a345528e9171b0813c1
|
4
|
+
data.tar.gz: 2d08815cb4b1c2d2245c75a9337a7586dfa2ef7e646ed726d8ed6527c90166c6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7571588a2718e3ed241d328b5d25d9fd9efb75054bee707c27d65b549e3dd944e909dc715d93958a0eeb18386cffead01d92306a800a3957d6b4dae5aeac9fa9
|
7
|
+
data.tar.gz: cb10006737feca4ee02d42af22b6d06e9fc4fea7ae258d374f27e3363c37bcc03abf3877280cf29812d52ff9ae2fc2d4f5f5677752468dbca6d5f29b82f03a70
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2020 Ryan Burmeister-Morrison
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# Assemblr
|
2
|
+
|
3
|
+
A small DSL for the construction of quick automation tasks.
|
4
|
+
|
5
|
+
**NOTE:** This version is just a prototype. It will be completely re-written.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'assemblr'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle install
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install assemblr
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
This is an example of a simple assemblr script:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
# frozen_string_literal: true
|
29
|
+
|
30
|
+
require 'assemblr'
|
31
|
+
|
32
|
+
# Configuration options. The values listed below are the defaults for assemblr.
|
33
|
+
set :default_user, 'root' # set the default user nodes are assigned to
|
34
|
+
set :default_group, 'default' # set the default group nodes are assigned to
|
35
|
+
set :log, true # turn on or off built-in logging.
|
36
|
+
set :quit_on_error, true # quit if anything goes wrong.
|
37
|
+
|
38
|
+
group :dev_servers do
|
39
|
+
# Define nodes. All nodes defined in this block will be added to the
|
40
|
+
# specified group (:dev_servers). After the block ends, the default user and
|
41
|
+
# group will be restored for any other top-level node definitions.
|
42
|
+
node '10.0.0.173'
|
43
|
+
node '10.0.0.332'
|
44
|
+
node '10.0.1.22'
|
45
|
+
end
|
46
|
+
|
47
|
+
node '10.0.0.33' # assigned to group :default and user 'root' as per the
|
48
|
+
# defaults
|
49
|
+
|
50
|
+
group :dev_servers do
|
51
|
+
upload 'Gemfile', '/tmp/Gemmm' # upload a file to all nodes in a group
|
52
|
+
upload 'lib', '/tmp',
|
53
|
+
recursive: true # upload a directory to all nodes in a group
|
54
|
+
|
55
|
+
remote_exec 'echo "Hello, world!"'
|
56
|
+
end
|
57
|
+
|
58
|
+
upload_to '10.0.2.43', 'root', 'message.txt', '/home/user/message.txt'
|
59
|
+
result = remote_exec_on 'ruby', inject: ['puts "Hello, world!"', 'exit']
|
60
|
+
|
61
|
+
puts result
|
62
|
+
```
|
63
|
+
|
64
|
+
## Development
|
65
|
+
|
66
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can
|
67
|
+
also run `bin/console` for an interactive prompt that will allow you to
|
68
|
+
experiment.
|
69
|
+
|
70
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
71
|
+
release a new version, update the version number in `version.rb`, and then run
|
72
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
73
|
+
git commits and tags, and push the `.gem` file to
|
74
|
+
[rubygems.org](https://rubygems.org).
|
75
|
+
|
76
|
+
## Contributing
|
77
|
+
|
78
|
+
Bug reports and pull requests are welcome on GitHub at
|
79
|
+
https://github.com/rburmorrison/assemblr.
|
80
|
+
|
81
|
+
## License
|
82
|
+
|
83
|
+
The gem is available as open source under the terms of the [MIT
|
84
|
+
License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/assemblr.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/assemblr/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'assemblr'
|
7
|
+
spec.version = Assemblr::VERSION
|
8
|
+
spec.authors = ['Ryan Burmeister-Morrison']
|
9
|
+
spec.email = ['rburmeistermorrison@gmail.com']
|
10
|
+
|
11
|
+
spec.summary = 'A small DSL for the construction of quick automation tasks.'
|
12
|
+
spec.homepage = 'https://github.com/rburmorrison/assemblr'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
|
15
|
+
|
16
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
17
|
+
spec.metadata['source_code_uri'] = 'https://github.com/rburmorrison/assemblr'
|
18
|
+
|
19
|
+
# Specify which files should be added to the gem when it is released. The `git
|
20
|
+
# ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
22
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
23
|
+
f.match(%r{^(test|spec|features)/})
|
24
|
+
end
|
25
|
+
end
|
26
|
+
spec.bindir = 'exe'
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ['lib']
|
29
|
+
|
30
|
+
spec.add_development_dependency 'rake', '~> 12.0'
|
31
|
+
spec.add_development_dependency 'rubocop', '~> 0.80'
|
32
|
+
|
33
|
+
spec.add_runtime_dependency 'net-ping', '~> 2.0'
|
34
|
+
spec.add_runtime_dependency 'net-scp', '~> 2.0'
|
35
|
+
spec.add_runtime_dependency 'net-ssh', '~> 5.2'
|
36
|
+
spec.add_runtime_dependency 'tty-logger', '~> 0.3'
|
37
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'assemblr'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/assemblr.rb
ADDED
@@ -0,0 +1,275 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'assemblr/version'
|
4
|
+
require 'assemblr/logging'
|
5
|
+
require 'assemblr/utilities'
|
6
|
+
|
7
|
+
require 'open3'
|
8
|
+
require 'net/ssh'
|
9
|
+
require 'net/scp'
|
10
|
+
|
11
|
+
module Assemblr
|
12
|
+
$VERBOSE = nil # turn off warnings from external libraries
|
13
|
+
|
14
|
+
# Local variables are prefixed with an 'm' for 'Module' as to not clash with
|
15
|
+
# method names.
|
16
|
+
m_nodes = []
|
17
|
+
m_current_group = 'default'
|
18
|
+
m_current_user = 'root'
|
19
|
+
|
20
|
+
##
|
21
|
+
# Set a configuration option.
|
22
|
+
#
|
23
|
+
# Available options are:
|
24
|
+
#
|
25
|
+
# - *default_user* - the default user to assign nodes to
|
26
|
+
# - *default_group* - the default group to assign nodes to
|
27
|
+
# - *log* - turn on or off logging
|
28
|
+
# - *quit_on_error* - quit if any error occur
|
29
|
+
#
|
30
|
+
# @return [void]
|
31
|
+
define_method :set do |key, value|
|
32
|
+
options = %i[log quit_on_error default_user default_group]
|
33
|
+
unless options.include?(key)
|
34
|
+
raise ArgumentError, "#{key} is not a valid option"
|
35
|
+
end
|
36
|
+
|
37
|
+
key = :current_user if key == :default_user
|
38
|
+
key = :current_group if key == :default_group
|
39
|
+
|
40
|
+
info %(config: set "#{key}" to "#{value}")
|
41
|
+
eval "m_#{key} = value", binding, __FILE__, __LINE__
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# @!method local_exec(cmd, inject: [])
|
46
|
+
# Execute a command locally.
|
47
|
+
#
|
48
|
+
# @param cmd [String] the command to run locally
|
49
|
+
# @param inject [Array<String>] strings to inject into stdin
|
50
|
+
#
|
51
|
+
# @return [Array(String, Process::Status)]
|
52
|
+
define_method :local_exec do |cmd, inject: []|
|
53
|
+
log_string = "running `#{cmd}` locally"
|
54
|
+
log_string += " with these inputs: #{inject}" unless inject.empty?
|
55
|
+
info log_string
|
56
|
+
|
57
|
+
result = ''
|
58
|
+
status = nil
|
59
|
+
Open3.popen2e(cmd) do |i, o, wait|
|
60
|
+
inject.each do |line|
|
61
|
+
line = line.strip
|
62
|
+
i.write line + "\n"
|
63
|
+
end
|
64
|
+
i.close
|
65
|
+
result = o.read
|
66
|
+
status = wait.value
|
67
|
+
end
|
68
|
+
|
69
|
+
if status.exitstatus != 0
|
70
|
+
code = status.exitstatus
|
71
|
+
error "local command `#{cmd}` exited with a status of #{code}"
|
72
|
+
else
|
73
|
+
success "local command `#{cmd}` executed successfully"
|
74
|
+
end
|
75
|
+
|
76
|
+
return result, status
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Execute a command on a remote machine using SSH. It returns the combined
|
81
|
+
# stdout and stderr data.
|
82
|
+
#
|
83
|
+
# @param ip [String] the ip of the node to run the command on
|
84
|
+
# @param user [String] the user to log in as
|
85
|
+
# @param cmd [String] the command to execute remotely
|
86
|
+
# @param inject [Array<String>] strings to inject into stdin
|
87
|
+
#
|
88
|
+
# @return [String]
|
89
|
+
# @return [Array<String>]
|
90
|
+
def remote_exec_on(ip, user, cmd, inject: [])
|
91
|
+
info "attempting to execute `#{cmd}` on #{user}@#{ip}"
|
92
|
+
|
93
|
+
result = ''
|
94
|
+
Net::SSH.start(ip, user) do |ssh|
|
95
|
+
ch = ssh.open_channel do |ch|
|
96
|
+
ch.exec(cmd) do |ch, success|
|
97
|
+
error "unable to execute `#{cmd}` on #{user}@#{ip}" unless success
|
98
|
+
|
99
|
+
# Collect stdout data.
|
100
|
+
ch.on_data do |_, data|
|
101
|
+
result += data if data.is_a?(String)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Collect stderr data.
|
105
|
+
ch.on_extended_data do |_, _, data|
|
106
|
+
result += data if data.is_a?(String)
|
107
|
+
end
|
108
|
+
|
109
|
+
inject.each do |line|
|
110
|
+
ch.send_data(line + "\n")
|
111
|
+
end
|
112
|
+
|
113
|
+
ch.on_request 'exit-status' do |_, data|
|
114
|
+
code = data.read_long
|
115
|
+
if code.zero?
|
116
|
+
success "`#{cmd}` executed successfully on #{user}@#{ip}"
|
117
|
+
else
|
118
|
+
error "`#{cmd}` returned status code #{code} on #{user}@#{ip}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
ch.wait
|
125
|
+
end
|
126
|
+
result
|
127
|
+
end
|
128
|
+
|
129
|
+
##
|
130
|
+
# Upload a file to a node.
|
131
|
+
#
|
132
|
+
# @param ip [String] the node to upload to
|
133
|
+
# @param user [String] the user to authenticate as
|
134
|
+
# @param src [String] the file to upload
|
135
|
+
# @param dest [String] the location to upload to
|
136
|
+
# @param recursive [Bool] recursively upload files in a directory
|
137
|
+
# @param timeout [Integer] how many seconds to wait before throwing an error
|
138
|
+
#
|
139
|
+
# @return [void]
|
140
|
+
def upload_to(ip, user, src, dest, recursive: false, timeout: 5)
|
141
|
+
info %(attempting to upload "#{src}" to #{user}@#{ip}:#{dest})
|
142
|
+
Timeout.timeout timeout do
|
143
|
+
Net::SCP.upload!(ip, user, src, dest, recursive: recursive)
|
144
|
+
end
|
145
|
+
rescue StandardError
|
146
|
+
error %(failed to upload "#{src}" to #{user}@#{ip}:#{dest})
|
147
|
+
rescue Timeout::Error
|
148
|
+
error %(failed to upload "#{src}" to #{user}@#{ip}:#{dest} within #{timeout} seconds)
|
149
|
+
else
|
150
|
+
success %(uploaded "#{src}" to #{user}@#{ip}:#{dest})
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# @!method current_nodes()
|
155
|
+
# Get all nodes in the current group.
|
156
|
+
#
|
157
|
+
# @return [void]
|
158
|
+
define_method :current_nodes do
|
159
|
+
return nodes if m_current_group == 'all'
|
160
|
+
|
161
|
+
nodes.select { |n| n[:group] == m_current_group }
|
162
|
+
end
|
163
|
+
|
164
|
+
##
|
165
|
+
# Execute a command on all machines within the current group.
|
166
|
+
#
|
167
|
+
# @param cmd [String] the command to execute
|
168
|
+
# @param inject [Array<String>] strings to inject into stdin
|
169
|
+
#
|
170
|
+
# @return [String] the combined output of the command
|
171
|
+
def remote_exec(cmd, inject: [])
|
172
|
+
results = []
|
173
|
+
current_nodes.each do |n|
|
174
|
+
result = remote_exec_on(n[:ip], n[:user], cmd, inject: inject)
|
175
|
+
results << result
|
176
|
+
end
|
177
|
+
results
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# Upload a file or directory to all machines within the current group.
|
182
|
+
#
|
183
|
+
# @param src [String] the file to upload
|
184
|
+
# @param dest [String] the location to upload the file to
|
185
|
+
# @param recursive [Bool] recursively upload files in a directory
|
186
|
+
# @param timeout [Integer] how many seconds to wait before throwing an error
|
187
|
+
#
|
188
|
+
# @return [void]
|
189
|
+
def upload(src, dest, recursive: false, timeout: 5)
|
190
|
+
current_nodes.each do |n|
|
191
|
+
upload_to(n[:ip], n[:user], src, dest, recursive: recursive)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
##
|
196
|
+
# @!method group(group, &block)
|
197
|
+
# Temporarily change current_group to refer to the specified group while
|
198
|
+
# within the passed block.
|
199
|
+
#
|
200
|
+
# @param group [Symbol] the group to temporarily switch to
|
201
|
+
#
|
202
|
+
# @return [void]
|
203
|
+
define_method :group do |group, &block|
|
204
|
+
info %(entered group block with group "#{group}")
|
205
|
+
|
206
|
+
# Temporarily switch to the target group.
|
207
|
+
old_current_group = m_current_group
|
208
|
+
m_current_group = group.to_s
|
209
|
+
|
210
|
+
block.call
|
211
|
+
|
212
|
+
m_current_group = old_current_group
|
213
|
+
|
214
|
+
info %(exited group block with group "#{group}")
|
215
|
+
end
|
216
|
+
|
217
|
+
##
|
218
|
+
# @!method current_group
|
219
|
+
# Get the current default group.
|
220
|
+
#
|
221
|
+
# @return [String]
|
222
|
+
|
223
|
+
##
|
224
|
+
# @!method current_user
|
225
|
+
# Get the current default user.
|
226
|
+
#
|
227
|
+
# @return [String]
|
228
|
+
%w[group user].each do |item|
|
229
|
+
define_method "current_#{item}" do
|
230
|
+
eval "m_current_#{item}"
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
##
|
235
|
+
# @!method node(ip, group: current_group, user: current_user)
|
236
|
+
# Add a node to the list of nodes.
|
237
|
+
#
|
238
|
+
# @param ip [String] the ip address of the node
|
239
|
+
# @param group [Symbol] the group to assign the node to
|
240
|
+
# @param user [String] the user to associate with the node
|
241
|
+
#
|
242
|
+
# @return [Hash{ip=>String, group=>String, user=>String}] the added node
|
243
|
+
define_method :node do |ip, group: m_current_group, user: m_current_user|
|
244
|
+
group = group.to_s
|
245
|
+
if group == 'all'
|
246
|
+
error = ArgumentError.new('nodes can not be assigned to the "all" group')
|
247
|
+
raise error
|
248
|
+
end
|
249
|
+
|
250
|
+
l_node = { ip: ip, group: group, user: user }
|
251
|
+
m_nodes << l_node
|
252
|
+
info "added node: #{l_node}"
|
253
|
+
|
254
|
+
l_node
|
255
|
+
end
|
256
|
+
|
257
|
+
##
|
258
|
+
# @!method nodes()
|
259
|
+
# Get all registered nodes.
|
260
|
+
#
|
261
|
+
# @return [Array<Hash{ip=>String, group=>String, user=>String}>]
|
262
|
+
define_method :nodes do
|
263
|
+
m_nodes
|
264
|
+
end
|
265
|
+
|
266
|
+
define_method :nodes_reachable? do
|
267
|
+
reachable = true
|
268
|
+
m_nodes.each do |node|
|
269
|
+
reachable &&= reachable?(node[:ip])
|
270
|
+
end
|
271
|
+
reachable
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
extend Assemblr
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tty-logger'
|
4
|
+
|
5
|
+
module Assemblr
|
6
|
+
Logger = TTY::Logger.new do |config|
|
7
|
+
config.metadata = %i[time date]
|
8
|
+
end
|
9
|
+
|
10
|
+
m_log = true
|
11
|
+
m_quit_on_error = true
|
12
|
+
|
13
|
+
##
|
14
|
+
# @!method info(message)
|
15
|
+
# Logs an info message.
|
16
|
+
#
|
17
|
+
# @return [void]
|
18
|
+
|
19
|
+
##
|
20
|
+
# @!method success(message)
|
21
|
+
# Logs a success message.
|
22
|
+
#
|
23
|
+
# @return [void]
|
24
|
+
|
25
|
+
##
|
26
|
+
# @!method warn(message)
|
27
|
+
# Logs a warning message.
|
28
|
+
#
|
29
|
+
# @return [void]
|
30
|
+
%i[info success warn].each do |level|
|
31
|
+
define_method level do |*args, &block|
|
32
|
+
return unless m_log
|
33
|
+
|
34
|
+
Logger.send(level, *args, &block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# @!method error(message)
|
40
|
+
# Logs a error message. If configured, this will end the task with error code
|
41
|
+
# 1.
|
42
|
+
#
|
43
|
+
# @return [void]
|
44
|
+
define_method :error do |*args, &block|
|
45
|
+
Logger.send(:error, *args, &block) if m_log
|
46
|
+
exit 1 if m_quit_on_error
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
require 'net/ping'
|
5
|
+
|
6
|
+
##
|
7
|
+
# A collection of utility functions for assemblr.
|
8
|
+
module Assemblr
|
9
|
+
##
|
10
|
+
# Retrieve the first ip address that is not '127.0.0.1' on the local machine.
|
11
|
+
#
|
12
|
+
# @param pattern [Regexp] a pattern to test the ips against
|
13
|
+
def get_local_ip(pattern = //)
|
14
|
+
Socket.ip_address_list.each do |ip|
|
15
|
+
address = ip.ip_address
|
16
|
+
next if address == '127.0.0.1'
|
17
|
+
return address if address.match?(pattern)
|
18
|
+
end
|
19
|
+
''
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Check if a remote machine can be contacted.
|
24
|
+
#
|
25
|
+
# @return [Bool]
|
26
|
+
def reachable?(ip)
|
27
|
+
external = Net::Ping::External.new(ip)
|
28
|
+
|
29
|
+
info %(attempting to contact host "#{ip}"...)
|
30
|
+
reachable = external.ping || external.ping6
|
31
|
+
if reachable
|
32
|
+
success %(host "#{ip}" is reachable)
|
33
|
+
else
|
34
|
+
error %(unable to contact host "#{ip}")
|
35
|
+
end
|
36
|
+
|
37
|
+
reachable
|
38
|
+
end
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: assemblr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Burmeister-Morrison
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-03-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '12.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '12.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rubocop
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.80'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.80'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: net-ping
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: net-scp
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: net-ssh
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '5.2'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '5.2'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: tty-logger
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.3'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.3'
|
97
|
+
description:
|
98
|
+
email:
|
99
|
+
- rburmeistermorrison@gmail.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- Gemfile
|
106
|
+
- LICENSE.txt
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- assemblr.gemspec
|
110
|
+
- bin/console
|
111
|
+
- bin/setup
|
112
|
+
- lib/assemblr.rb
|
113
|
+
- lib/assemblr/logging.rb
|
114
|
+
- lib/assemblr/utilities.rb
|
115
|
+
- lib/assemblr/version.rb
|
116
|
+
homepage: https://github.com/rburmorrison/assemblr
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
metadata:
|
120
|
+
homepage_uri: https://github.com/rburmorrison/assemblr
|
121
|
+
source_code_uri: https://github.com/rburmorrison/assemblr
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 2.3.0
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
requirements: []
|
137
|
+
rubygems_version: 3.1.2
|
138
|
+
signing_key:
|
139
|
+
specification_version: 4
|
140
|
+
summary: A small DSL for the construction of quick automation tasks.
|
141
|
+
test_files: []
|