ztk 1.6.2 → 1.6.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,67 @@
1
+ module ZTK
2
+ class Report
3
+
4
+ # Report List Functionality
5
+ module List
6
+
7
+ # Displays data in a key-value list style.
8
+ #
9
+ # +-------------------------------------------------------------------+
10
+ # | PROVIDER: Cucumber::Chef::Provider::Vagrant |
11
+ # | ID: default |
12
+ # | STATE: aborted |
13
+ # | USERNAME: vagrant |
14
+ # | IP ADDRESS: 127.0.0.1 |
15
+ # | PORT: 2222 |
16
+ # | CHEF-SERVER API: http://127.0.0.1:4000 |
17
+ # | CHEF-SERVER WEBUI: http://127.0.0.1:4040 |
18
+ # | CHEF-SERVER DEFAULT USER: admin |
19
+ # | CHEF-SERVER DEFAULT PASSWORD: p@ssw0rd1 |
20
+ # +-------------------------------------------------------------------+
21
+ #
22
+ # @param [Array<Object>,Object] dataset A single object or an array of
23
+ # objects for which we want to generate a report
24
+ # @param [Array] headers An array of headers used for ordering the output.
25
+ # @return [OpenStruct]
26
+ def list(dataset, headers, &block)
27
+ !block_given? and log_and_raise(ReportError, "You must supply a block!")
28
+ headers.nil? and log_and_raise(ReportError, "Headers can not be nil!")
29
+ dataset.nil? and log_and_raise(ReportError, "Dataset can not be nil!")
30
+
31
+ rows = Array.new
32
+ max_lengths = OpenStruct.new
33
+ headers = headers.map(&:to_s).map(&:downcase).map(&:to_sym)
34
+
35
+ if dataset.is_a?(Array)
36
+ dataset.each do |data|
37
+ rows << block.call(data)
38
+ end
39
+ else
40
+ rows << block.call(dataset)
41
+ end
42
+ rows.compact!
43
+
44
+ if rows.count > 0
45
+ max_key_length = headers.collect{ |header| header.to_s.length }.max
46
+ max_value_length = rows.collect{ |row| headers.collect{ |header| row.send(:table)[header].to_s.length }.max }.max
47
+
48
+ width = (max_key_length + max_value_length + 2 + 2 + 2)
49
+
50
+ rows.each do |row|
51
+ config.ui.stdout.puts("+#{"-" * width}+")
52
+ headers.each do |header|
53
+ entry_line = format_entry(header, max_key_length, row.send(:table)[header], max_value_length)
54
+ config.ui.stdout.puts(entry_line)
55
+ end
56
+ end
57
+ config.ui.stdout.puts("+#{"-" * width}+")
58
+ OpenStruct.new(:rows => rows, :max_key_length => max_key_length, :max_value_length => max_value_length, :width => width)
59
+ else
60
+ OpenStruct.new(:rows => rows, :max_key_length => 0, :max_value_length => 0, :width => 0)
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,44 @@
1
+ module ZTK
2
+ class Report
3
+
4
+ # Report Private Functionality
5
+ module Private
6
+
7
+ def max_spreadsheet_lengths(headers, rows)
8
+ max_lengths = OpenStruct.new
9
+ headers.each do |header|
10
+ collection = [header, rows.collect{|r| r.send(:table)[header] } ].flatten
11
+ maximum = collection.map(&:to_s).map(&:length).max
12
+ max_lengths.send(:table)[header] = maximum
13
+ end
14
+
15
+ max_lengths
16
+ end
17
+
18
+ def calculate_spreadsheet_width(headers, max_lengths)
19
+ header_lengths = ((headers.count * 3) - 3)
20
+ max_length = max_lengths.send(:table).values.reduce(:+)
21
+ (2 + max_length + header_lengths + 2)
22
+ end
23
+
24
+ def format_header(headers, lengths)
25
+ line = headers.collect do |header|
26
+ "-" * lengths.send(:table)[header]
27
+ end
28
+
29
+ ["+-", line.join("-+-"), "-+"].join.strip
30
+ end
31
+
32
+ def format_row(*args)
33
+ spacer = " "
34
+ [spacer, args, spacer].flatten.join(" | ").strip
35
+ end
36
+
37
+ def format_entry(key, key_length, value, value_length)
38
+ "| %#{key_length}s: %-#{value_length}s |" % [key.to_s.upcase, value.to_s]
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,72 @@
1
+ module ZTK
2
+ class Report
3
+
4
+ # Report Spreadsheet Functionality
5
+ module Spreadsheet
6
+
7
+ # Displays data in a spreadsheet style.
8
+ #
9
+ # +-------------+-------+-------+--------+----------------+-------------------+--------------+---------+
10
+ # | NAME | ALIVE | ARCH | DISTRO | IP | MAC | CHEF VERSION | PERSIST |
11
+ # +-------------+-------+-------+--------+----------------+-------------------+--------------+---------+
12
+ # | sudo | false | amd64 | ubuntu | 192.168.99.110 | 00:00:5e:34:d6:aa | N/A | true |
13
+ # | timezone | false | amd64 | ubuntu | 192.168.122.47 | 00:00:5e:92:d7:f6 | N/A | true |
14
+ # | chef-client | false | amd64 | ubuntu | 192.168.159.98 | 00:00:5e:c7:ce:26 | N/A | true |
15
+ # | users | false | amd64 | ubuntu | 192.168.7.78 | 00:00:5e:89:f9:50 | N/A | true |
16
+ # +-------------+-------+-------+--------+----------------+-------------------+--------------+---------+
17
+ #
18
+ # @param [Array<Object>,Object] dataset A single object or an array of
19
+ # objects for which we want to generate a report
20
+ # @param [Array] headers An array of headers used for ordering the output.
21
+ # @return [OpenStruct]
22
+ def spreadsheet(dataset, headers, &block)
23
+ !block_given? and log_and_raise(ReportError, "You must supply a block!")
24
+ headers.nil? and log_and_raise(ReportError, "Headers can not be nil!")
25
+ dataset.nil? and log_and_raise(ReportError, "Dataset can not be nil!")
26
+
27
+ rows = Array.new
28
+ max_lengths = OpenStruct.new
29
+ headers = headers.map(&:to_s).map(&:downcase).map(&:to_sym)
30
+
31
+ if dataset.is_a?(Array)
32
+ dataset.each do |data|
33
+ rows << block.call(data)
34
+ end
35
+ else
36
+ rows << block.call(dataset)
37
+ end
38
+ rows.compact!
39
+
40
+ if rows.count > 0
41
+ max_lengths = max_spreadsheet_lengths(headers, rows)
42
+ header_line = headers.collect { |header| "%-#{max_lengths.send(:table)[header]}s" % header.to_s.upcase }
43
+ header_line = format_row(header_line)
44
+
45
+ config.ui.stdout.puts(format_header(headers, max_lengths))
46
+ config.ui.stdout.puts(header_line)
47
+ config.ui.stdout.puts(format_header(headers, max_lengths))
48
+
49
+ rows.each do |row|
50
+ row_line = headers.collect do |header|
51
+ header_length = max_lengths.send(:table)[header]
52
+ content = row.send(:table)[header]
53
+
54
+ "%-#{header_length}s" % content
55
+ end
56
+
57
+ row_line = format_row(row_line)
58
+ config.ui.stdout.puts(row_line)
59
+ end
60
+
61
+ config.ui.stdout.puts(format_header(headers, max_lengths))
62
+ OpenStruct.new(:rows => rows, :max_lengths => max_lengths, :width => calculate_spreadsheet_width(headers, max_lengths))
63
+ else
64
+ OpenStruct.new(:rows => rows, :max_lengths => 0, :width => 0)
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+ end
@@ -1,8 +1,3 @@
1
- require 'ostruct'
2
- require 'net/ssh'
3
- require 'net/ssh/proxy/command'
4
- require 'net/sftp'
5
-
6
1
  module ZTK
7
2
 
8
3
  # SSH Error Class
@@ -24,7 +19,7 @@ module ZTK
24
19
  #
25
20
  # If you want to specify SSH options you can:
26
21
  #
27
- # keys = File.expand_path(File.join(ENV['HOME'], '.ssh', 'id_rsa'))
22
+ # keys = File.expand_path(File.join(Dir.home, '.ssh', 'id_rsa'))
28
23
  # ssh = ZTK::SSH.new(:host_name => '127.0.0.1', :user => ENV['USER'], :keys => keys)
29
24
  #
30
25
  # = Configuration Examples:
@@ -41,8 +36,8 @@ module ZTK
41
36
  # Specify an identity file:
42
37
  #
43
38
  # ssh.config do |config|
44
- # config.keys = File.expand_path(File.join(ENV['HOME'], '.ssh', 'id_rsa'))
45
- # config.proxy_keys = File.expand_path(File.join(ENV['HOME'], '.ssh', 'id_rsa'))
39
+ # config.keys = File.expand_path(File.join(Dir.home, '.ssh', 'id_rsa'))
40
+ # config.proxy_keys = File.expand_path(File.join(Dir.home, '.ssh', 'id_rsa'))
46
41
  # end
47
42
  #
48
43
  # Specify a timeout:
@@ -65,6 +60,11 @@ module ZTK
65
60
  #
66
61
  # @author Zachary Patten <zachary AT jovelabs DOT com>
67
62
  class SSH < ZTK::Base
63
+ require 'ostruct'
64
+ require 'net/ssh'
65
+ require 'net/ssh/proxy/command'
66
+ require 'net/sftp'
67
+
68
68
  # Exit Signal Mappings
69
69
  EXIT_SIGNALS = {
70
70
  1 => "SIGHUP",
@@ -96,15 +96,20 @@ module ZTK
96
96
  27 => "SIGPROF"
97
97
  }
98
98
 
99
- autoload :Bootstrap, 'ztk/ssh/bootstrap'
100
- autoload :Command, 'ztk/ssh/command'
101
- autoload :Download, 'ztk/ssh/download'
102
- autoload :Exec, 'ztk/ssh/exec'
103
- autoload :File, 'ztk/ssh/file'
104
- autoload :Upload, 'ztk/ssh/upload'
99
+ require 'ztk/ssh/bootstrap'
100
+ require 'ztk/ssh/command'
101
+ require 'ztk/ssh/console'
102
+ require 'ztk/ssh/core'
103
+ require 'ztk/ssh/download'
104
+ require 'ztk/ssh/exec'
105
+ require 'ztk/ssh/file'
106
+ require 'ztk/ssh/private'
107
+ require 'ztk/ssh/upload'
105
108
 
106
109
  include ZTK::SSH::Bootstrap
107
110
  include ZTK::SSH::Command
111
+ include ZTK::SSH::Console
112
+ include ZTK::SSH::Core
108
113
  include ZTK::SSH::Download
109
114
  include ZTK::SSH::Exec
110
115
  include ZTK::SSH::File
@@ -155,113 +160,14 @@ module ZTK
155
160
  :exit_code => 0,
156
161
  :silence => false
157
162
  }.merge(configuration))
158
- config.ui.logger.debug { "config=#{config.send(:table).inspect}" }
159
- end
160
-
161
- # Starts an SSH session. Can also be used to get the Net::SSH object.
162
- #
163
- # Primarily used internally.
164
- def ssh
165
- @ssh ||= Net::SSH.start(config.host_name, config.user, ssh_options)
166
- end
167
-
168
- # Starts an SFTP session. Can also be used to get the Net::SFTP object.
169
- #
170
- # Primarily used internally.
171
- def sftp
172
- @sftp ||= Net::SFTP.start(config.host_name, config.user, ssh_options)
173
- end
174
-
175
- # Close our session gracefully.
176
- def close
177
- config.ui.logger.debug { "close" }
178
- ssh and !ssh.closed? and ssh.close
179
- end
180
-
181
- # The on_retry method we'll use with the RescueRetry class.
182
- def on_retry(exception)
183
- close
184
- @ssh = nil
185
- @sftp = nil
186
- end
187
163
 
188
- # Launches an SSH console, replacing the current process with the console
189
- # process.
190
- #
191
- # @example Launch a console:
192
- # ssh = ZTK::SSH.new
193
- # ssh.config do |config|
194
- # config.user = ENV["USER"]
195
- # config.host_name = "127.0.0.1"
196
- # end
197
- # ssh.console
198
- def console
199
164
  config.ui.logger.debug { "config=#{config.send(:table).inspect}" }
200
- config.ui.logger.info { "console(#{console_command.inspect})" }
201
-
202
- config.ui.logger.fatal { "REPLACING CURRENT PROCESS - GOODBYE!" }
203
- Kernel.exec(console_command)
204
165
  end
205
166
 
206
167
 
207
168
  private
208
169
 
209
- # Builds our SSH options hash.
210
- def ssh_options
211
- options = {}
212
-
213
- # These are plainly documented on the Net::SSH config class.
214
- options.merge!(:encryption => config.encryption) if config.encryption
215
- options.merge!(:compression => config.compression) if config.compression
216
- options.merge!(:compression_level => config.compression_level) if config.compression_level
217
- options.merge!(:timeout => config.timeout) if config.timeout
218
- options.merge!(:forward_agent => config.forward_agent) if config.forward_agent
219
- options.merge!(:global_known_hosts_file => config.global_known_hosts_file) if config.global_known_hosts_file
220
- options.merge!(:auth_methods => config.auth_methods) if config.auth_methods
221
- options.merge!(:host_key => config.host_key) if config.host_key
222
- options.merge!(:host_key_alias => config.host_key_alias) if config.host_key_alias
223
- options.merge!(:host_name => config.host_name) if config.host_name
224
- options.merge!(:keys => config.keys) if config.keys
225
- options.merge!(:keys_only => config.keys_only) if config.keys_only
226
- options.merge!(:hmac => config.hmac) if config.hmac
227
- options.merge!(:port => config.port) if config.port
228
- options.merge!(:proxy => Net::SSH::Proxy::Command.new(proxy_command)) if config.proxy_host_name
229
- options.merge!(:rekey_limit => config.rekey_limit) if config.rekey_limit
230
- options.merge!(:user => config.user) if config.user
231
- options.merge!(:user_known_hosts_file => config.user_known_hosts_file) if config.user_known_hosts_file
232
-
233
- # This is not plainly documented on the Net::SSH config class.
234
- options.merge!(:password => config.password) if config.password
235
-
236
- config.ui.logger.debug { "ssh_options(#{options.inspect})" }
237
- options
238
- end
239
-
240
- # Builds a human readable tag about our connection. Used for internal
241
- # logging purposes.
242
- def tag
243
- tags = Array.new
244
-
245
- if config.proxy_host_name
246
- proxy_user_host = "#{config.proxy_user}@#{config.proxy_host_name}"
247
- proxy_port = (config.proxy_port ? ":#{config.proxy_port}" : nil)
248
- tags << [proxy_user_host, proxy_port].compact.join
249
- tags << " >>> "
250
- end
251
-
252
- user_host = "#{config.user}@#{config.host_name}"
253
- port = (config.port ? ":#{config.port}" : nil)
254
- tags << [user_host, port].compact.join
255
-
256
- tags.join.strip
257
- end
258
-
259
- def log_header(what)
260
- count = 8
261
- sep = ("=" * count)
262
- header = [sep, "[ #{what} ]", sep, "[ #{tag} ]", sep, "[ #{what} ]", sep].join
263
- "#{header}\n"
264
- end
170
+ include ZTK::SSH::Private
265
171
 
266
172
  end
267
173
 
@@ -32,7 +32,7 @@ module ZTK
32
32
  tempfile = Tempfile.new("bootstrap")
33
33
 
34
34
  local_tempfile = tempfile.path
35
- remote_tempfile = ::File.join("/", "tmp", ::File.basename(local_tempfile))
35
+ remote_tempfile = ::File.join(ZTK::Locator.root, "tmp", ::File.basename(local_tempfile))
36
36
 
37
37
  ::File.open(local_tempfile, 'w') do |file|
38
38
  file.puts(content)
@@ -0,0 +1,28 @@
1
+ module ZTK
2
+ class SSH
3
+
4
+ # SSH Console Functionality
5
+ module Console
6
+
7
+ # Launches an SSH console, replacing the current process with the console
8
+ # process.
9
+ #
10
+ # @example Launch a console:
11
+ # ssh = ZTK::SSH.new
12
+ # ssh.config do |config|
13
+ # config.user = ENV["USER"]
14
+ # config.host_name = "127.0.0.1"
15
+ # end
16
+ # ssh.console
17
+ def console
18
+ config.ui.logger.debug { "config=#{config.send(:table).inspect}" }
19
+ config.ui.logger.info { "console(#{console_command.inspect})" }
20
+
21
+ config.ui.logger.fatal { "REPLACING CURRENT PROCESS - GOODBYE!" }
22
+ Kernel.exec(console_command)
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,37 @@
1
+ module ZTK
2
+ class SSH
3
+
4
+ # SSH Core Functionality
5
+ module Core
6
+
7
+ # Starts an SSH session. Can also be used to get the Net::SSH object.
8
+ #
9
+ # Primarily used internally.
10
+ def ssh
11
+ @ssh ||= Net::SSH.start(config.host_name, config.user, ssh_options)
12
+ end
13
+
14
+ # Starts an SFTP session. Can also be used to get the Net::SFTP object.
15
+ #
16
+ # Primarily used internally.
17
+ def sftp
18
+ @sftp ||= Net::SFTP.start(config.host_name, config.user, ssh_options)
19
+ end
20
+
21
+ # Close our session gracefully.
22
+ def close
23
+ config.ui.logger.debug { "close" }
24
+ ssh and !ssh.closed? and ssh.close
25
+ end
26
+
27
+ # The on_retry method we'll use with the RescueRetry class.
28
+ def on_retry(exception)
29
+ close
30
+ @ssh = nil
31
+ @sftp = nil
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+ end
@@ -21,8 +21,8 @@ module ZTK
21
21
  # config.user = ENV["USER"]
22
22
  # config.host_name = "127.0.0.1"
23
23
  # end
24
- # local = File.expand_path(File.join("/tmp", "id_rsa.pub"))
25
- # remote = File.expand_path(File.join(ENV["HOME"], ".ssh", "id_rsa.pub"))
24
+ # local = File.expand_path(File.join(ZTK::Locator.root, "tmp", "id_rsa.pub"))
25
+ # remote = File.expand_path(File.join(Dir.home, ".ssh", "id_rsa.pub"))
26
26
  # ssh.download(remote, local)
27
27
  def download(remote, local, options={})
28
28
  options = {:recursive => ::File.directory?(local) }.merge(options)