assemblr 0.1.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 +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: []
|