ztk 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,4 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in ztk.gemspec
4
3
  gemspec
data/WIKI.md CHANGED
@@ -8,7 +8,7 @@ Zachary's Tool Kit is a general purpose utility gem, featuring a collection of c
8
8
 
9
9
  Add this line to your application's Gemfile:
10
10
 
11
- gem 'ztk'
11
+ gem "ztk"
12
12
 
13
13
  And then execute:
14
14
 
@@ -20,13 +20,18 @@ Or install it yourself as:
20
20
 
21
21
  ## Usage
22
22
 
23
- ### ZTK::Parallel
23
+ ## Console
24
+
25
+ bundle install
26
+ bundle exec ztk
27
+
28
+ ## ZTK::Parallel
24
29
 
25
30
  Parallel Processing Class
26
31
 
27
32
  This class can be used to easily run iterative and linear processes in a parallel manner.
28
33
 
29
- Example Ruby Code:
34
+ ### ZTK::Parallel Example Ruby Code
30
35
 
31
36
  $logger = ZTK::Logger.new(STDOUT)
32
37
  a_callback = Proc.new do |pid|
@@ -48,7 +53,7 @@ Example Ruby Code:
48
53
  parallel.waitall
49
54
  parallel.results
50
55
 
51
- Example Code Pry Run:
56
+ ### ZTK::Parallel Example Code Pry Run
52
57
 
53
58
  [1] pry(main)> $logger = ZTK::Logger.new(STDOUT)
54
59
  => #<ZTK::Logger:0x0000000204d498
@@ -129,8 +134,7 @@ Default Config Values for ZTK::Parallel:
129
134
  :before_fork => nil,
130
135
  :after_fork => nil
131
136
 
132
-
133
- ### ZTK::Logger
137
+ ## ZTK::Logger
134
138
 
135
139
  Logging Class
136
140
 
@@ -146,6 +150,260 @@ Example:
146
150
  $logger.error { "This is a error message!" }
147
151
  $logger.fatal { "This is a fatal message!" }
148
152
 
153
+ Example Output:
154
+
155
+ 2012-09-01|21:34:45.216262|23603|FATAL|logger_spec.rb:122:block (5 levels) in <top (required)>|This is a test fatal message
156
+
157
+ ## ZTK::SSH
158
+
159
+ SSH Class
160
+
161
+ Simplified SSH class; it provides for remote execute of commands and returning of command output. Additionally it allows for uploading and downloading of files.
162
+
163
+ ### ZTK::SSH Example Ruby Code
164
+
165
+ $logger = ZTK::Logger.new(STDOUT)
166
+ ssh = ZTK::SSH.new
167
+ ssh.config do |config|
168
+ config.ssh.user = ENV["USER"]
169
+ config.ssh.host = "127.0.0.1"
170
+ end
171
+ puts ssh.exec("hostname -f")
172
+ local = File.expand_path(File.join("/tmp", "id_rsa.pub"))
173
+ remote = File.expand_path(File.join(ENV["HOME"], ".ssh", "id_rsa.pub"))
174
+ ssh.download(remote, local)
175
+
176
+ ### ZTK::SSH Example Code Pry Run
177
+
178
+ [1] pry(main)> $logger = ZTK::Logger.new(STDOUT)
179
+ => #<ZTK::Logger:0x000000025f2c18
180
+ @default_formatter=#<Logger::Formatter:0x000000025f2ab0 @datetime_format=nil>,
181
+ @formatter=nil,
182
+ @level=1,
183
+ @logdev=
184
+ #<Logger::LogDevice:0x000000025fcc18
185
+ @dev=#<IO:<STDOUT>>,
186
+ @filename=nil,
187
+ @mutex=
188
+ #<Logger::LogDevice::LogDeviceMutex:0x000000025fcbf0
189
+ @mon_count=0,
190
+ @mon_mutex=#<Mutex:0x000000025fc9e8>,
191
+ @mon_owner=nil>,
192
+ @shift_age=nil,
193
+ @shift_size=nil>,
194
+ @progname=nil>
195
+ [2] pry(main)> ssh = ZTK::SSH.new
196
+ => #<ZTK::SSH:0x00000002c317c8
197
+ @config=
198
+ #<OpenStruct stdout=#<IO:<STDOUT>>, stderr=#<IO:<STDERR>>, stdin=#<IO:<STDIN>>, logger=#<ZTK::Logger:0x000000025f2c18 @progname=nil, @level=1, @default_formatter=#<Logger::Formatter:0x000000025f2ab0 @datetime_format=nil>, @formatter=nil, @logdev=#<Logger::LogDevice:0x000000025fcc18 @shift_size=nil, @shift_age=nil, @filename=nil, @dev=#<IO:<STDOUT>>, @mutex=#<Logger::LogDevice::LogDeviceMutex:0x000000025fcbf0 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Mutex:0x000000025fc9e8>>>>, ssh=#<OpenStruct>>>
199
+ [3] pry(main)> ssh.config do |config|
200
+ [3] pry(main)* config.ssh.user = ENV["USER"]
201
+ [3] pry(main)* config.ssh.host = "127.0.0.1"
202
+ [3] pry(main)* end
203
+ => "127.0.0.1"
204
+ [4] pry(main)> puts ssh.exec("hostname -f")
205
+ 2012-09-01|04:49:47.723411|25709| INFO|ssh.rb:76:exec|command(hostname -f)
206
+ staging.jovelabs.net
207
+ staging.jovelabs.net
208
+ => nil
209
+ [5] pry(main)> local = File.expand_path(File.join("/tmp", "id_rsa.pub"))
210
+ => "/tmp/id_rsa.pub"
211
+ [6] pry(main)> remote = File.expand_path(File.join(ENV["HOME"], ".ssh", "id_rsa.pub"))
212
+ => "/home/zpatten/.ssh/id_rsa.pub"
213
+ [7] pry(main)> ssh.download(remote, local)
214
+ 2012-09-01|04:49:48.153389|25709| INFO|ssh.rb:133:download|parameters(/home/zpatten/.ssh/id_rsa.pub,/tmp/id_rsa.pub)
215
+ 2012-09-01|04:49:48.153536|25709| INFO|ssh.rb:137:block in download|download(/home/zpatten/.ssh/id_rsa.pub -> /tmp/id_rsa.pub)
216
+ 2012-09-01|04:49:48.156243|25709| INFO|ssh.rb:145:block in download|finish
217
+ => true
218
+
219
+ ### ZTK::SSH Config
220
+
221
+ To proxy through another host, for example SSH to 192.168.1.1 through 192.168.0.1:
222
+
223
+ ssh.config do |config|
224
+ config.ssh.user = ENV["USER"]
225
+ config.ssh.host = "192.168.1.1"
226
+ config.ssh.proxy_user = ENV["USER"]
227
+ config.ssh.proxy_host = "192.168.0.1"
228
+ end
229
+
230
+ Specify an identity file:
231
+
232
+ ssh.config do |config|
233
+ config.ssh.identify_file = File.expand_path(File.join(ENV["HOME"], ".ssh", "id_rsa"))
234
+ config.ssh.proxy_identify_file = File.expand_path(File.join(ENV["HOME"], ".ssh", "id_rsa"))
235
+ end
236
+
237
+ Specify a timeout:
238
+
239
+ ssh.config do |config|
240
+ config.ssh.timeout = 30
241
+ end
242
+
243
+ Specify a password:
244
+
245
+ ssh.config do |config|
246
+ config.ssh.password = "p@$$w0rd"
247
+ end
248
+
249
+ Check host keys, the default is false (off):
250
+
251
+ ssh.config do |config|
252
+ config.ssh.host_key_verify = true
253
+ end
254
+
255
+ ### ZTK::SSH Core Methods
256
+
257
+ #### Execute A Command
258
+
259
+ ssh.exec(command, options={})
260
+
261
+ Where `command` is a command (i.e. `String`) to execute on the remote host (i.e. "hostname -f"). You can optionally pass `:silence => true` into `options` to suppress session output from going to STDOUT and STDERR.
262
+
263
+ #### Upload A File
264
+
265
+ ssh.upload(local, remote)
266
+
267
+ Where `local` is the local file/path you wish to upload on the local host to the `remote` file/path on the remote host.
268
+
269
+ #### Download A File
270
+
271
+ ssh.download(remote, local)
272
+
273
+ Where `remote` is the remote file/path you wish to download on the remote host to the `local` file/path on the local host.
274
+
275
+ ## ZTK::Template
276
+
277
+ Erubis Templating
278
+
279
+ ### ZTK::Template Example Ruby Code
280
+
281
+ template_file = File.expand_path(File.join(File.dirname(__FILE__), "spec", "support", "test-template.txt.erb"))
282
+ IO.read(template_file)
283
+ context = { :test_variable => "Hello World" }
284
+ ZTK::Template.render(template_file, context)
285
+
286
+ ### ZTK::Template Example Code Pry Run
287
+
288
+ [1] pry(main)> template_file = File.expand_path(File.join(File.dirname(__FILE__), "spec", "support", "test-template.txt.erb"))
289
+ => "/home/zpatten/Dropbox/code/ztk/spec/support/test-template.txt.erb"
290
+ [2] pry(main)> IO.read(template_file)
291
+ => "<%= @test_variable %>\n"
292
+ [3] pry(main)> context = { :test_variable => "Hello World" }
293
+ => {:test_variable=>"Hello World"}
294
+ [4] pry(main)> ZTK::Template.render(template_file, context)
295
+ => "Hello World"
296
+
297
+ ## ZTK::TCPSocketCheck
298
+
299
+ Check TCP Sockets
300
+
301
+ This class has two basic modes of operation:
302
+
303
+ * Read Test
304
+
305
+ By default we will perform a read test against the host and port specified. In this mode we will attempt to connect to the host and port supplied and if we can read any amount of data, regardless of the content we view this as success.
306
+
307
+ * Write Test
308
+
309
+ If `data` is supplied via the configuration, this will change the mode of operation to a write test. Certain services, such as HTTP don't send any data unless you send something first. In this mode we will attempt to connect to the host and port supplied, once connected we will write the supplied `data` to the socket and then attempt to read from the socket. If we can read any amount of data, reagardless of the conent we view this as success.
310
+
311
+ ### ZTK::TCPSocketCheck Example Ruby Code
312
+
313
+ tcp_check = ZTK::TCPSocketCheck.new(:host => "github.com", :port => 22)
314
+ tcp_check.wait
315
+ tcp_check.ready?
316
+
317
+ ### ZTK::TCPSocketCheck Example Code Pry Run
318
+
319
+ [1] pry(main)> tcp_check = ZTK::TCPSocketCheck.new(:host => "github.com", :port => 22)
320
+ => #<ZTK::TCPSocketCheck:0x00000001890d18
321
+ @config=
322
+ #<OpenStruct stdout=#<IO:<STDOUT>>, stderr=#<IO:<STDERR>>, stdin=#<IO:<STDIN>>, logger=nil, host="github.com", port=22, data=nil, timeout=5>>
323
+ [2] pry(main)> tcp_check.wait
324
+ => nil
325
+ [3] pry(main)> tcp_check.ready?
326
+ => true
327
+
328
+ ### ZTK::TCPSocketCheck Config
329
+
330
+ Here is an example TCPSocketCheck configuration. The `timeout` and `wait` values shown are the defaults if omitted.
331
+
332
+ tcp_check = ZTK::TCPSocketCheck.new
333
+ tcp_check.config do |config|
334
+ config.host = "www.google.com"
335
+ config.port = 80
336
+ config.data = "GET"
337
+ config.timeout = 5
338
+ config.wait = 60
339
+ end
340
+
341
+ Specify the host and port (required):
342
+
343
+ tcp_check = ZTK::TCPSocketCheck.new
344
+ tcp_check.config do |config|
345
+ config.host = "www.google.com"
346
+ config.port = 80
347
+ end
348
+
349
+ Specify data to write (switches to a write mode test if this is supplied):
350
+
351
+ tcp_check = ZTK::TCPSocketCheck.new
352
+ tcp_check.config do |config|
353
+ config.host = "www.google.com"
354
+ config.port = 80
355
+ config.data = "GET"
356
+ end
357
+
358
+ Override the `timeout` and `wait` values:
359
+
360
+ tcp_check = ZTK::TCPSocketCheck.new
361
+ tcp_check.config do |config|
362
+ config.host = "www.google.com"
363
+ config.port = 80
364
+ config.data = "GET"
365
+ config.timeout = 3
366
+ config.wait = 5
367
+ end
368
+
369
+ ### ZTK::TCPSocketCheck Core Methods
370
+
371
+ #### Socket Ready?
372
+
373
+ We can use the `ready?` method to test if the socket is ready in a one off manner. This operations runtime is bound by the `timeout` configuration value.
374
+
375
+ tcp_check = ZTK::TCPSocketCheck.new
376
+ tcp_check.config do |config|
377
+ config.host = "www.google.com"
378
+ config.port = 80
379
+ config.data = "GET"
380
+ end
381
+ if tcp_check.ready? == true
382
+ puts "The Socket Is Ready!"
383
+ else
384
+ puts "Looks like no one is home!"
385
+ end
386
+
387
+ #### Socket Wait
388
+
389
+ We can use the `wait` method to block on the socket's `ready?` state. The method will return only if the socket becomes ready or a timeout occurs. This operations runtime is bound by the `wait` configuration value.
390
+
391
+ tcp_check = ZTK::TCPSocketCheck.new
392
+ tcp_check.config do |config|
393
+ config.host = "www.google.com"
394
+ config.port = 80
395
+ config.data = "GET"
396
+ end
397
+ if tcp_check.wait == true
398
+ puts "The Socket Is Ready!"
399
+ else
400
+ puts "We timed out or got no answer!"
401
+ end
402
+
403
+ ## ZTK::Command
404
+
405
+ A class to execute commands locally.
406
+
149
407
  # RESOURCES
150
408
 
151
409
  Source:
data/lib/ztk.rb CHANGED
@@ -23,7 +23,10 @@ require "ztk/version"
23
23
  module ZTK
24
24
  class Error < StandardError; end
25
25
 
26
+ autoload :Base, "ztk/base"
26
27
  autoload :Logger, "ztk/logger"
27
28
  autoload :Parallel, "ztk/parallel"
28
29
  autoload :SSH, "ztk/ssh"
30
+ autoload :TCPSocketCheck, "ztk/tcp_socket_check"
31
+ autoload :Template, "ztk/template"
29
32
  end
@@ -0,0 +1,72 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary@jovelabs.com>
4
+ # Copyright: Copyright (c) Jove Labs
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ require "ostruct"
22
+
23
+ ################################################################################
24
+
25
+ module ZTK
26
+
27
+ ################################################################################
28
+
29
+ class BaseError < Error; end
30
+
31
+ ################################################################################
32
+
33
+ class Base
34
+
35
+ ################################################################################
36
+
37
+ def initialize(config={})
38
+ defined?(Rails) and rails_logger = Rails.logger
39
+ @config = OpenStruct.new({
40
+ :stdout => $stdout,
41
+ :stderr => $stderr,
42
+ :stdin => $stdin,
43
+ :logger => (rails_logger || $logger)
44
+ }.merge(config))
45
+
46
+ @config.stdout.respond_to?(:sync=) and @config.stdout.sync = true
47
+ @config.stderr.respond_to?(:sync=) and @config.stderr.sync = true
48
+ @config.stdin.respond_to?(:sync=) and @config.stdin.sync = true
49
+ @config.logger.respond_to?(:sync=) and @config.logger.sync = true
50
+
51
+ @config.logger and @config.logger.debug{ "config(#{@config.inspect})" }
52
+ end
53
+
54
+ ################################################################################
55
+
56
+ def config(&block)
57
+ if block_given?
58
+ block.call(@config)
59
+ else
60
+ @config
61
+ end
62
+ end
63
+
64
+ ################################################################################
65
+
66
+ end
67
+
68
+ ################################################################################
69
+
70
+ end
71
+
72
+ ################################################################################
@@ -20,7 +20,12 @@
20
20
 
21
21
  require "logger"
22
22
 
23
+ ################################################################################
24
+
23
25
  module ZTK
26
+
27
+ ################################################################################
28
+
24
29
  class Logger < ::Logger
25
30
 
26
31
  ################################################################################
@@ -74,6 +79,9 @@ module ZTK
74
79
  ################################################################################
75
80
 
76
81
  end
82
+
83
+ ################################################################################
84
+
77
85
  end
78
86
 
79
87
  ################################################################################
@@ -17,55 +17,43 @@
17
17
  # limitat::IOns under the License.
18
18
  #
19
19
  ################################################################################
20
+
20
21
  require "base64"
21
- require "ostruct"
22
+
23
+ ################################################################################
22
24
 
23
25
  module ZTK
24
- class Parallel
25
26
 
26
27
  ################################################################################
27
28
 
28
- attr_accessor :config, :results
29
+ class Parallel < ::ZTK::Base
30
+
31
+ ################################################################################
32
+
33
+ attr_accessor :results
29
34
 
30
35
  ################################################################################
31
36
 
32
37
  def initialize(config={})
33
- @config = OpenStruct.new({
34
- :stdout => $stdout,
35
- :stderr => $stderr,
36
- :stdin => $stdin,
37
- :logger => $logger,
38
- :max_forks => `grep -c processor /proc/cpuinfo`.chomp.to_i,
39
- :one_shot => false,
38
+ super({
39
+ :max_forks => %x( grep -c processor /proc/cpuinfo ).chomp.to_i,
40
40
  :before_fork => nil,
41
41
  :after_fork => nil
42
42
  }.merge(config))
43
- @config.stdout.sync = true if @config.stdout.respond_to?(:sync=)
44
- @config.stderr.sync = true if @config.stderr.respond_to?(:sync=)
45
- @config.stdin.sync = true if @config.stdin.respond_to?(:sync=)
46
- @config.logger.sync = true if @config.logger.respond_to?(:sync=)
47
43
 
48
44
  @forks = ::Array.new
49
45
  @results = ::Array.new
50
46
  ::GC.respond_to?(:copy_on_write_friendly=) and ::GC.copy_on_write_friendly = true
51
47
  end
52
48
 
53
- ################################################################################
54
-
55
- def config(&block)
56
- if block_given?
57
- yield(@config)
58
- else
59
- @config
60
- end
61
- end
62
-
63
49
  ################################################################################
64
50
 
65
51
  def process(*args)
66
- @config.logger.debug{ "FORKS #{@forks.inspect}" }
67
- pid = nil
68
- return pid if (@forks.count >= @config.max_forks)
52
+ @config.logger and @config.logger.debug{ "forks(#{@forks.inspect})" }
53
+
54
+ while (@forks.count >= @config.max_forks) do
55
+ wait
56
+ end
69
57
 
70
58
  child_reader, parent_writer = ::IO.pipe
71
59
  parent_reader, child_writer = ::IO.pipe
@@ -78,7 +66,7 @@ module ZTK
78
66
  parent_reader.close
79
67
 
80
68
  if !(data = yield).nil?
81
- @config.logger.debug{ "WRITE #{data.inspect}" }
69
+ @config.logger and @config.logger.debug{ "write(#{data.inspect})" }
82
70
  child_writer.write(::Base64.encode64(::Marshal.dump(data)))
83
71
  end
84
72
 
@@ -100,18 +88,19 @@ module ZTK
100
88
  ################################################################################
101
89
 
102
90
  def wait
103
- @config.logger.debug{ "FORKS #{@forks.inspect}" }
91
+ @config.logger and @config.logger.debug{ "forks(#{@forks.inspect})" }
104
92
  pid, status = (::Process.wait2(-1, ::Process::WNOHANG) rescue nil)
105
93
  if !pid.nil? && !status.nil? && !(fork = @forks.select{ |f| f[:pid] == pid }.first).nil?
106
94
  data = (::Marshal.load(::Base64.decode64(fork[:reader].read.to_s)) rescue nil)
107
- @config.logger.debug{ "READ #{data.inspect}" }
108
- @results.push(data) if (!data.nil? && !@config.one_shot)
95
+ @config.logger and @config.logger.debug{ "read(#{data.inspect})" }
96
+ !data.nil? and @results.push(data)
109
97
  fork[:reader].close
110
98
  fork[:writer].close
111
99
 
112
100
  @forks -= [fork]
113
101
  return [pid, status, data]
114
102
  end
103
+ sleep(1)
115
104
  nil
116
105
  end
117
106
 
@@ -128,12 +117,16 @@ module ZTK
128
117
  ################################################################################
129
118
 
130
119
  def count
120
+ @config.logger and @config.logger.debug{ "count(#{@forks.count})" }
131
121
  @forks.count
132
122
  end
133
123
 
134
124
  ################################################################################
135
125
 
136
126
  end
127
+
128
+ ################################################################################
129
+
137
130
  end
138
131
 
139
132
  ################################################################################
@@ -17,30 +17,30 @@
17
17
  # limitations under the License.
18
18
  #
19
19
  ################################################################################
20
+
20
21
  require "ostruct"
22
+ require "net/ssh"
23
+ require "net/ssh/proxy/command"
24
+ require "net/sftp"
25
+
26
+ ################################################################################
21
27
 
22
28
  module ZTK
29
+
30
+ ################################################################################
31
+
23
32
  class SSHError < Error; end
24
- class SSH
25
33
 
26
34
  ################################################################################
27
35
 
28
- attr_accessor :stdout, :stderr, :stdin, :config
36
+ class SSH < ::ZTK::Base
29
37
 
30
38
  ################################################################################
31
39
 
32
40
  def initialize(config={})
33
- @config = OpenStruct.new({
34
- :stdout => $stdout,
35
- :stderr => $stderr,
36
- :stdin => $stdin,
37
- :logger => $logger,
38
- :ssh => Hash.new(nil)
41
+ super({
42
+ :ssh => ::OpenStruct.new
39
43
  }.merge(config))
40
- @config.stdout.sync = true if @config.stdout.respond_to?(:sync=)
41
- @config.stderr.sync = true if @config.stderr.respond_to?(:sync=)
42
- @config.stdin.sync = true if @config.stdin.respond_to?(:sync=)
43
- @config.logger.sync = true if @config.logger.respond_to?(:sync=)
44
44
  end
45
45
 
46
46
  ################################################################################
@@ -54,18 +54,18 @@ module ZTK
54
54
  command << [ "-o", "StrictHostKeyChecking=no" ]
55
55
  command << [ "-o", "KeepAlive=yes" ]
56
56
  command << [ "-o", "ServerAliveInterval=60" ]
57
- command << [ "-i", @config.ssh[:identity_file] ] if @config.ssh[:identity_file]
58
- command << [ "-o", "ProxyCommand=\"#{proxy_command}\"" ] if @config.ssh[:proxy]
59
- command << "#{@config.ssh[:ssh_user]}@#{@config.ssh[:host]}"
57
+ command << [ "-i", @config.ssh.identity_file ] if @config.ssh.identity_file
58
+ command << [ "-o", "ProxyCommand=\"#{proxy_command}\"" ] if @config.ssh.proxy
59
+ command << "#{@config.ssh.user}@#{@config.ssh.host}"
60
60
  command = command.flatten.compact.join(" ")
61
61
  @config.logger and @config.logger.info { "command(#{command})" }
62
- Kernel.exec(command)
62
+ ::Kernel.exec(command)
63
63
  end
64
64
 
65
65
  ################################################################################
66
66
 
67
67
  def exec(command, options={})
68
- @ssh ||= Net::SSH.start(@config.ssh[:host], @config.ssh[:ssh_user], ssh_options)
68
+ @ssh ||= ::Net::SSH.start(@config.ssh.host, @config.ssh.user, ssh_options)
69
69
 
70
70
  options = { :silence => false }.merge(options)
71
71
  silence = options[:silence]
@@ -102,7 +102,7 @@ module ZTK
102
102
  ################################################################################
103
103
 
104
104
  def upload(local, remote)
105
- @sftp ||= Net::SFTP.start(@config.ssh[:host], @config.ssh[:ssh_user], ssh_options)
105
+ @sftp ||= ::Net::SFTP.start(@config.ssh.host, @config.ssh.user, ssh_options)
106
106
 
107
107
  @config.logger and @config.logger.debug { "config(#{@config.ssh.inspect})" }
108
108
  @config.logger and @config.logger.info { "parameters(#{local},#{remote})" }
@@ -120,12 +120,14 @@ module ZTK
120
120
  @config.logger and @config.logger.info { "finish" }
121
121
  end
122
122
  end
123
+
124
+ true
123
125
  end
124
126
 
125
127
  ################################################################################
126
128
 
127
129
  def download(remote, local)
128
- @sftp ||= Net::SFTP.start(@config.ssh[:host], @config.ssh[:ssh_user], ssh_options)
130
+ @sftp ||= ::Net::SFTP.start(@config.ssh.host, @config.ssh.user, ssh_options)
129
131
 
130
132
  @config.logger and @config.logger.debug { "config(#{@config.ssh.inspect})" }
131
133
  @config.logger and @config.logger.info { "parameters(#{remote},#{local})" }
@@ -143,6 +145,8 @@ module ZTK
143
145
  @config.logger and @config.logger.info { "finish" }
144
146
  end
145
147
  end
148
+
149
+ true
146
150
  end
147
151
 
148
152
 
@@ -153,7 +157,7 @@ module ZTK
153
157
  def proxy_command
154
158
  @config.logger and @config.logger.debug { "config(#{@config.ssh.inspect})" }
155
159
 
156
- if !@config.ssh[:identity_file]
160
+ if !@config.ssh.identity_file
157
161
  message = "You must specify an identity file in order to SSH proxy."
158
162
  @config.logger and @config.logger.fatal { message }
159
163
  raise SSHError, message
@@ -165,8 +169,8 @@ module ZTK
165
169
  command << [ "-o", "StrictHostKeyChecking=no" ]
166
170
  command << [ "-o", "KeepAlive=yes" ]
167
171
  command << [ "-o", "ServerAliveInterval=60" ]
168
- command << [ "-i", @config.ssh[:proxy_identity_file] ] if @config.ssh[:proxy_identity_file]
169
- command << "#{@config.ssh[:proxy_ssh_user]}@#{@config.ssh[:proxy_host]}"
172
+ command << [ "-i", @config.ssh.proxy_identity_file ] if @config.ssh.proxy_identity_file
173
+ command << "#{@config.ssh.proxy_user}@#{@config.ssh.proxy_host}"
170
174
  command << "nc %h %p"
171
175
  command = command.flatten.compact.join(" ")
172
176
  @config.logger and @config.logger.debug { "command(#{command})" }
@@ -178,11 +182,11 @@ module ZTK
178
182
  def ssh_options
179
183
  @config.logger and @config.logger.debug { "config(#{@config.ssh.inspect})" }
180
184
  options = {}
181
- options.merge!(:password => @config.ssh[:ssh_password]) if @config.ssh[:ssh_password]
182
- options.merge!(:keys => @config.ssh[:identity_file]) if @config.ssh[:identity_file]
183
- options.merge!(:timeout => @config.ssh[:timeout]) if @config.ssh[:timeout]
184
- options.merge!(:user_known_hosts_file => '/dev/null') if !@config.ssh[:host_key_verify]
185
- options.merge!(:proxy => Net::SSH::Proxy::Command.new(proxy_command)) if @config.ssh[:proxy]
185
+ options.merge!(:password => @config.ssh.password) if @config.ssh.password
186
+ options.merge!(:keys => @config.ssh.identity_file) if @config.ssh.identity_file
187
+ options.merge!(:timeout => @config.ssh.timeout) if @config.ssh.timeout
188
+ options.merge!(:user_known_hosts_file => '/dev/null') if !@config.ssh.host_key_verify
189
+ options.merge!(:proxy => ::Net::SSH::Proxy::Command.new(proxy_command)) if @config.ssh.proxy
186
190
  @config.logger and @config.logger.debug { "options(#{options.inspect})" }
187
191
  options
188
192
  end
@@ -190,6 +194,9 @@ module ZTK
190
194
  ################################################################################
191
195
 
192
196
  end
197
+
198
+ ################################################################################
199
+
193
200
  end
194
201
 
195
202
  ################################################################################
@@ -0,0 +1,103 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary@jovelabs.com>
4
+ # Copyright: Copyright (c) Jove Labs
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ require "socket"
22
+
23
+ ################################################################################
24
+
25
+ module ZTK
26
+
27
+ ################################################################################
28
+
29
+ class TCPSocketCheckError < Error; end
30
+
31
+ ################################################################################
32
+
33
+ class TCPSocketCheck < Base
34
+
35
+ ################################################################################
36
+
37
+ def initialize(config={})
38
+ super({
39
+ :host => nil,
40
+ :port => nil,
41
+ :data => nil,
42
+ :timeout => 5,
43
+ :wait => 60
44
+ }.merge(config))
45
+ end
46
+
47
+ ################################################################################
48
+
49
+ def ready?
50
+ if @config.host.nil?
51
+ message = "You must supply a host!"
52
+ @config.logger and @config.logger.fatal { message }
53
+ raise TCPSocketCheckError, message
54
+ end
55
+
56
+ if @config.port.nil?
57
+ message = "You must supply a port!"
58
+ @config.logger and @config.logger.fatal { message }
59
+ raise TCPSocketCheckError, message
60
+ end
61
+
62
+ socket = ::TCPSocket.new(@config.host, @config.port)
63
+
64
+ if @config.data.nil?
65
+ @config.logger and @config.logger.debug { "read(#{@config.host}:#{@config.port})" }
66
+ ((::IO.select([socket], nil, nil, @config.timeout) && socket.gets) ? true : false)
67
+ else
68
+ @config.logger and @config.logger.debug { "write(#{@config.host}:#{@config.port}, '#{@config.data}')" }
69
+ ((::IO.select(nil, [socket], nil, @config.timeout) && socket.write(@config.data)) ? true : false)
70
+ end
71
+
72
+ rescue Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e
73
+ @config.logger and @config.logger.debug { "#{@config.host}:#{@config.port} - #{e.message}" }
74
+ false
75
+ ensure
76
+ (socket && socket.close)
77
+ end
78
+
79
+ ################################################################################
80
+
81
+ def wait
82
+ @config.logger and @config.logger.debug{ "waiting for socket to become available; timeout after #{@config.wait} seconds" }
83
+ Timeout.timeout(@config.wait) do
84
+ until ready?
85
+ @config.logger and @config.logger.debug{ "sleeping 1 second" }
86
+ sleep(1)
87
+ end
88
+ end
89
+ true
90
+ rescue Timeout::Error => e
91
+ @config.logger and @config.logger.warn{ "socket(#{@config.host}:#{@config.port}) timeout!" }
92
+ false
93
+ end
94
+
95
+ ################################################################################
96
+
97
+ end
98
+
99
+ ################################################################################
100
+
101
+ end
102
+
103
+ ################################################################################
@@ -0,0 +1,71 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary@jovelabs.com>
4
+ # Copyright: Copyright (c) Jove Labs
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ require "erubis"
22
+
23
+ ################################################################################
24
+
25
+ module ZTK
26
+
27
+ ################################################################################
28
+
29
+ class TemplateError < Error; end
30
+
31
+ ################################################################################
32
+
33
+ class Template
34
+
35
+ ################################################################################
36
+
37
+ class << self
38
+
39
+ ################################################################################
40
+
41
+ def render(template, context=nil)
42
+ render_template(load_template(template), context)
43
+ end
44
+
45
+ ################################################################################
46
+ private
47
+ ################################################################################
48
+
49
+ def load_template(template)
50
+ ::IO.read(template).chomp
51
+ end
52
+
53
+ ################################################################################
54
+
55
+ def render_template(template, context={})
56
+ ::Erubis::Eruby.new(template).evaluate(context)
57
+ end
58
+
59
+ ################################################################################
60
+
61
+ end
62
+
63
+ ################################################################################
64
+
65
+ end
66
+
67
+ ################################################################################
68
+
69
+ end
70
+
71
+ ################################################################################
@@ -19,5 +19,5 @@
19
19
  ################################################################################
20
20
 
21
21
  module ZTK
22
- VERSION = "0.0.4" unless const_defined?(:VERSION)
22
+ VERSION = "0.0.5" unless const_defined?(:VERSION)
23
23
  end
@@ -0,0 +1 @@
1
+ <%= @test_variable %>
@@ -37,8 +37,12 @@ describe ZTK::Logger do
37
37
 
38
38
  subject { ZTK::Logger.new(@logfile) }
39
39
 
40
- it "should be of kind ZTK::Logger class" do
41
- subject.should be_an_instance_of ZTK::Logger
40
+ describe "class" do
41
+
42
+ it "should be an instance of ZTK::Logger" do
43
+ subject.should be_an_instance_of ZTK::Logger
44
+ end
45
+
42
46
  end
43
47
 
44
48
  describe "general logging functionality" do
@@ -22,13 +22,38 @@ require "spec_helper"
22
22
 
23
23
  describe ZTK::Parallel do
24
24
 
25
- before(:all) do
26
- end
27
-
28
25
  subject { ZTK::Parallel.new }
29
26
 
30
- it "should be of kind ZTK::Parallel class" do
31
- subject.should be_an_instance_of ZTK::Parallel
27
+ describe "class" do
28
+
29
+ it "should be an instance of ZTK::Parallel" do
30
+ subject.should be_an_instance_of ZTK::Parallel
31
+ end
32
+
33
+ describe "default config" do
34
+
35
+ it "should use $stdout as the default STDOUT" do
36
+ subject.config.stdout.should be_a_kind_of $stdout.class
37
+ subject.config.stdout.should == $stdout
38
+ end
39
+
40
+ it "should use $stderr as the default STDERR" do
41
+ subject.config.stderr.should be_a_kind_of $stderr.class
42
+ subject.config.stderr.should == $stderr
43
+ end
44
+
45
+ it "should use $stdin as the default STDIN" do
46
+ subject.config.stdin.should be_a_kind_of $stdin.class
47
+ subject.config.stdin.should == $stdin
48
+ end
49
+
50
+ it "should use $logger as the default logger" do
51
+ subject.config.logger.should be_a_kind_of ZTK::Logger
52
+ subject.config.logger.should == $logger
53
+ end
54
+
55
+ end
56
+
32
57
  end
33
58
 
34
59
  it "should spawn multiple processes to handle each iteration" do
@@ -41,12 +66,7 @@ describe ZTK::Parallel do
41
66
  puts subject.results.inspect
42
67
  subject.results.all?{ |r| r.should be_kind_of Integer }
43
68
  subject.results.all?{ |r| r.should > 0 }
44
- if ENV['CI'] && ENV['TRAVIS']
45
- # for some odd reason this is always -1 on travis-ci
46
- subject.results.uniq.count.should == 2
47
- else
48
- subject.results.uniq.count.should == 3
49
- end
69
+ subject.results.uniq.count.should == 3
50
70
  subject.results.include?(Process.pid).should be false
51
71
  end
52
72
 
@@ -0,0 +1,84 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary@jovelabs.com>
4
+ # Copyright: Copyright (c) Jove Labs
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ require "spec_helper"
22
+
23
+ describe ZTK::SSH do
24
+
25
+ subject { ZTK::SSH.new }
26
+
27
+ describe "class" do
28
+
29
+ it "should be an instance of ZTK::SSH" do
30
+ subject.should be_an_instance_of ZTK::SSH
31
+ end
32
+
33
+ describe "default config" do
34
+
35
+ it "should use $stdout as the default STDOUT" do
36
+ subject.config.stdout.should be_a_kind_of $stdout.class
37
+ subject.config.stdout.should == $stdout
38
+ end
39
+
40
+ it "should use $stderr as the default STDERR" do
41
+ subject.config.stderr.should be_a_kind_of $stderr.class
42
+ subject.config.stderr.should == $stderr
43
+ end
44
+
45
+ it "should use $stdin as the default STDIN" do
46
+ subject.config.stdin.should be_a_kind_of $stdin.class
47
+ subject.config.stdin.should == $stdin
48
+ end
49
+
50
+ it "should use $logger as the default logger" do
51
+ subject.config.logger.should be_a_kind_of ZTK::Logger
52
+ subject.config.logger.should == $logger
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+
59
+ # this stuff doesn't work as is under travis-ci
60
+ if !ENV['CI'] && !ENV['TRAVIS']
61
+
62
+ it "should be able to connect to 127.0.0.1 as the current user and execute a command (your key must be in ssh-agent)" do
63
+ subject.config do |config|
64
+ config.ssh.user = ENV["USER"]
65
+ config.ssh.host = "127.0.0.1"
66
+ end
67
+ hostname = %x( hostname -f ).chomp
68
+ subject.exec("hostname -f").chomp.should == hostname
69
+ end
70
+
71
+ it "should be able to proxy through 127.0.0.1, connecting to 127.0.0.1 as the current user and execute a command (your key must be in ssh-agent)" do
72
+ subject.config do |config|
73
+ config.ssh.user = ENV["USER"]
74
+ config.ssh.host = "127.0.0.1"
75
+ config.ssh.proxy_user = ENV["USER"]
76
+ config.ssh.proxy_host = "127.0.0.1"
77
+ end
78
+ hostname = %x( hostname -f ).chomp
79
+ subject.exec("hostname -f").chomp.should == hostname
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,115 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary@jovelabs.com>
4
+ # Copyright: Copyright (c) Jove Labs
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ require "spec_helper"
22
+
23
+ describe ZTK::TCPSocketCheck do
24
+
25
+ subject { ZTK::TCPSocketCheck }
26
+
27
+ describe "class" do
28
+
29
+ it "should be ZTK::TCPSocketCheck" do
30
+ subject.should be ZTK::TCPSocketCheck
31
+ end
32
+
33
+ describe "config" do
34
+
35
+ it "should throw an exception if the host is not specified" do
36
+ lambda{ subject.new(:port => 22).ready? }.should raise_error ZTK::TCPSocketCheckError, "You must supply a host!"
37
+ end
38
+
39
+ it "should throw an exception if the port is not specified" do
40
+ lambda{ subject.new(:host => "127.0.0.1").ready? }.should raise_error ZTK::TCPSocketCheckError, "You must supply a port!"
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
47
+ describe "behaviour" do
48
+
49
+ describe "ready?" do
50
+
51
+ describe "read check" do
52
+
53
+ it "should return true on a remote read check to github.com:22" do
54
+ tcp_check = subject.new(:host => "github.com", :port => 22)
55
+ tcp_check.ready?.should == true
56
+ end
57
+
58
+ it "should return false on a remote read check to 127.0.0.1:1" do
59
+ tcp_check = subject.new(:host => "127.0.0.1", :port => 1, :timeout => 3)
60
+ tcp_check.ready?.should == false
61
+ end
62
+
63
+ end
64
+
65
+ describe "write check" do
66
+
67
+ it "should return true on a remote write check to www.google.com:80" do
68
+ tcp_check = subject.new(:host => "www.google.com", :port => 80, :data => "GET")
69
+ tcp_check.ready?.should == true
70
+ end
71
+
72
+ it "should return false on a remote write check to 127.0.0.1:1" do
73
+ tcp_check = subject.new(:host => "127.0.0.1", :port => 1, :data => "GET", :timeout => 3)
74
+ tcp_check.ready?.should == false
75
+ end
76
+
77
+ end
78
+
79
+ end
80
+
81
+ describe "wait" do
82
+
83
+ describe "read check" do
84
+
85
+ it "should timeout and should return false on a read check to 127.0.0.1:1" do
86
+ tcp_check = subject.new(:host => "127.0.0.1", :port => 1, :wait => 3)
87
+ tcp_check.wait.should == false
88
+ end
89
+
90
+ it "should not timeout and should return true on a read check to github.com:22" do
91
+ tcp_check = subject.new(:host => "github.com", :port => 22, :wait => 3)
92
+ tcp_check.wait.should == true
93
+ end
94
+
95
+ end
96
+
97
+ describe "write check" do
98
+
99
+ it "should timeout and should return false on a write check to 127.0.0.1:1" do
100
+ tcp_check = subject.new(:host => "127.0.0.1", :port => 1, :data => "GET", :wait => 3)
101
+ tcp_check.wait.should == false
102
+ end
103
+
104
+ it "should not timeout and should return true on a write check to www.google.com:80" do
105
+ tcp_check = subject.new(:host => "www.google.com", :port => 80, :data => "GET", :wait => 3)
106
+ tcp_check.wait.should == true
107
+ end
108
+
109
+ end
110
+
111
+ end
112
+
113
+ end
114
+
115
+ end
@@ -0,0 +1,46 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary@jovelabs.com>
4
+ # Copyright: Copyright (c) Jove Labs
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ require "spec_helper"
22
+
23
+ describe ZTK::Template do
24
+
25
+ subject { ZTK::Template }
26
+
27
+ describe "class" do
28
+
29
+ it "should be ZTK::Template" do
30
+ subject.should be ZTK::Template
31
+ end
32
+
33
+ end
34
+
35
+ describe "behaviour" do
36
+
37
+ it "should render the template with the supplied context" do
38
+ template_file = File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "test-template.txt.erb"))
39
+ context = { :test_variable => "Hello World" }
40
+ output = subject.render(template_file, context)
41
+ output.should == "Hello World"
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -15,6 +15,7 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = ZTK::VERSION
17
17
 
18
+ gem.add_dependency("erubis")
18
19
  gem.add_dependency("net-ssh")
19
20
  gem.add_dependency("net-sftp")
20
21
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ztk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,6 +11,22 @@ bindir: bin
11
11
  cert_chain: []
12
12
  date: 2012-09-01 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: erubis
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: net-ssh
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -126,13 +142,20 @@ files:
126
142
  - WIKI.md
127
143
  - bin/ztk
128
144
  - lib/ztk.rb
145
+ - lib/ztk/base.rb
129
146
  - lib/ztk/logger.rb
130
147
  - lib/ztk/parallel.rb
131
148
  - lib/ztk/ssh.rb
149
+ - lib/ztk/tcp_socket_check.rb
150
+ - lib/ztk/template.rb
132
151
  - lib/ztk/version.rb
133
152
  - spec/spec_helper.rb
153
+ - spec/support/test-template.txt.erb
134
154
  - spec/ztk/logger_spec.rb
135
155
  - spec/ztk/parallel_spec.rb
156
+ - spec/ztk/ssh_spec.rb
157
+ - spec/ztk/tcp_socket_check_spec.rb
158
+ - spec/ztk/template_spec.rb
136
159
  - ztk.gemspec
137
160
  homepage: https://github.com/jovelabs/ztk
138
161
  licenses: []
@@ -148,7 +171,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
148
171
  version: '0'
149
172
  segments:
150
173
  - 0
151
- hash: -1407580608740853160
174
+ hash: -3563770214735056009
152
175
  required_rubygems_version: !ruby/object:Gem::Requirement
153
176
  none: false
154
177
  requirements:
@@ -157,7 +180,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
180
  version: '0'
158
181
  segments:
159
182
  - 0
160
- hash: -1407580608740853160
183
+ hash: -3563770214735056009
161
184
  requirements: []
162
185
  rubyforge_project:
163
186
  rubygems_version: 1.8.24
@@ -166,5 +189,9 @@ specification_version: 3
166
189
  summary: Contains various classes and utilities I find I regularly need.
167
190
  test_files:
168
191
  - spec/spec_helper.rb
192
+ - spec/support/test-template.txt.erb
169
193
  - spec/ztk/logger_spec.rb
170
194
  - spec/ztk/parallel_spec.rb
195
+ - spec/ztk/ssh_spec.rb
196
+ - spec/ztk/tcp_socket_check_spec.rb
197
+ - spec/ztk/template_spec.rb