opennebula-cli 5.8.5 → 5.9.80.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/oneacct +6 -0
- data/bin/oneacl +8 -1
- data/bin/onecluster +8 -1
- data/bin/onedatastore +8 -1
- data/bin/oneflow +28 -17
- data/bin/oneflow-template +6 -0
- data/bin/onegroup +6 -0
- data/bin/onehook +303 -0
- data/bin/onehost +9 -3
- data/bin/oneimage +16 -0
- data/bin/onemarket +6 -0
- data/bin/onemarketapp +6 -0
- data/bin/onesecgroup +6 -0
- data/bin/oneshowback +6 -0
- data/bin/onetemplate +6 -0
- data/bin/oneuser +11 -6
- data/bin/onevcenter +17 -3
- data/bin/onevdc +6 -0
- data/bin/onevm +18 -5
- data/bin/onevmgroup +6 -0
- data/bin/onevnet +19 -1
- data/bin/onevntemplate +6 -0
- data/bin/onevrouter +6 -0
- data/bin/onezone +6 -0
- data/lib/cli_helper.rb +589 -195
- data/lib/one_helper.rb +37 -2
- data/lib/one_helper/oneacl_helper.rb +99 -84
- data/lib/one_helper/onehook_helper.rb +250 -0
- data/lib/one_helper/onehost_helper.rb +200 -0
- data/lib/one_helper/oneimage_helper.rb +23 -0
- data/lib/one_helper/onesecgroup_helper.rb +2 -2
- data/lib/one_helper/oneuser_helper.rb +3 -3
- data/lib/one_helper/onevcenter_helper.rb +2 -1
- data/lib/one_helper/onevm_helper.rb +729 -599
- data/lib/one_helper/onevnet_helper.rb +24 -2
- data/lib/one_helper/onevrouter_helper.rb +1 -1
- metadata +9 -6
data/bin/onehost
CHANGED
@@ -20,10 +20,16 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
-
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
24
|
+
REMOTES_LOCATION = '/var/lib/one/remotes/'
|
24
25
|
else
|
25
26
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
-
|
27
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
28
|
+
REMOTES_LOCATION = ONE_LOCATION + '/var/remotes/'
|
29
|
+
end
|
30
|
+
|
31
|
+
if File.directory?(GEMS_LOCATION)
|
32
|
+
Gem.use_paths(GEMS_LOCATION)
|
27
33
|
end
|
28
34
|
|
29
35
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
@@ -230,7 +236,7 @@ CommandParser::CmdParser.new(ARGV) do
|
|
230
236
|
EOT
|
231
237
|
|
232
238
|
command :show, show_desc, :hostid,
|
233
|
-
:options => OpenNebulaHelper::XML do
|
239
|
+
:options => [OpenNebulaHelper::XML, OpenNebulaHelper::DECRYPT] do
|
234
240
|
helper.show_resource(args[0], options)
|
235
241
|
end
|
236
242
|
|
data/bin/oneimage
CHANGED
@@ -20,8 +20,14 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
23
24
|
else
|
24
25
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
27
|
+
end
|
28
|
+
|
29
|
+
if File.directory?(GEMS_LOCATION)
|
30
|
+
Gem.use_paths(GEMS_LOCATION)
|
25
31
|
end
|
26
32
|
|
27
33
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
@@ -432,4 +438,14 @@ CommandParser::CmdParser.new(ARGV) do
|
|
432
438
|
i.unlock
|
433
439
|
end
|
434
440
|
end
|
441
|
+
|
442
|
+
show_desc = <<-EOT.unindent
|
443
|
+
Shows orphans images (i.e images not referenced in any template).
|
444
|
+
EOT
|
445
|
+
|
446
|
+
command :orphans, show_desc do
|
447
|
+
puts helper.check_orphans
|
448
|
+
|
449
|
+
return 0
|
450
|
+
end
|
435
451
|
end
|
data/bin/onemarket
CHANGED
@@ -20,8 +20,14 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
23
24
|
else
|
24
25
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
27
|
+
end
|
28
|
+
|
29
|
+
if File.directory?(GEMS_LOCATION)
|
30
|
+
Gem.use_paths(GEMS_LOCATION)
|
25
31
|
end
|
26
32
|
|
27
33
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
data/bin/onemarketapp
CHANGED
@@ -20,12 +20,18 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
23
24
|
VAR_LOCATION = '/var/lib/one'
|
24
25
|
else
|
25
26
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
27
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
26
28
|
VAR_LOCATION = ONE_LOCATION + '/var'
|
27
29
|
end
|
28
30
|
|
31
|
+
if File.directory?(GEMS_LOCATION)
|
32
|
+
Gem.use_paths(GEMS_LOCATION)
|
33
|
+
end
|
34
|
+
|
29
35
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
30
36
|
$LOAD_PATH << RUBY_LIB_LOCATION + '/cli'
|
31
37
|
|
data/bin/onesecgroup
CHANGED
@@ -20,8 +20,14 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
23
24
|
else
|
24
25
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
27
|
+
end
|
28
|
+
|
29
|
+
if File.directory?(GEMS_LOCATION)
|
30
|
+
Gem.use_paths(GEMS_LOCATION)
|
25
31
|
end
|
26
32
|
|
27
33
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
data/bin/oneshowback
CHANGED
@@ -20,8 +20,14 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
23
24
|
else
|
24
25
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
27
|
+
end
|
28
|
+
|
29
|
+
if File.directory?(GEMS_LOCATION)
|
30
|
+
Gem.use_paths(GEMS_LOCATION)
|
25
31
|
end
|
26
32
|
|
27
33
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
data/bin/onetemplate
CHANGED
@@ -20,8 +20,14 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
23
24
|
else
|
24
25
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
27
|
+
end
|
28
|
+
|
29
|
+
if File.directory?(GEMS_LOCATION)
|
30
|
+
Gem.use_paths(GEMS_LOCATION)
|
25
31
|
end
|
26
32
|
|
27
33
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
data/bin/oneuser
CHANGED
@@ -20,8 +20,14 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
23
24
|
else
|
24
25
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
27
|
+
end
|
28
|
+
|
29
|
+
if File.directory?(GEMS_LOCATION)
|
30
|
+
Gem.use_paths(GEMS_LOCATION)
|
25
31
|
end
|
26
32
|
|
27
33
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
@@ -72,11 +78,10 @@ CommandParser::CmdParser.new(ARGV) do
|
|
72
78
|
:description => 'Read password from file'
|
73
79
|
}
|
74
80
|
|
75
|
-
|
76
|
-
:name => '
|
77
|
-
:large => '--
|
78
|
-
:description =>
|
79
|
-
' ' * 31 << 'algorithm'
|
81
|
+
SHA256 = {
|
82
|
+
:name => 'sha256',
|
83
|
+
:large => '--sha256',
|
84
|
+
:description => 'The password will be hashed using the sha256 algorithm'
|
80
85
|
}
|
81
86
|
|
82
87
|
SSH = {
|
@@ -203,7 +208,7 @@ CommandParser::CmdParser.new(ARGV) do
|
|
203
208
|
:description => 'enable stdin password'
|
204
209
|
}
|
205
210
|
|
206
|
-
auth_options = [READ_FILE,
|
211
|
+
auth_options = [READ_FILE, SHA256, SSH, X509, KEY, CERT, DRIVER]
|
207
212
|
|
208
213
|
create_options = auth_options.clone.unshift(GROUP_CREATE)
|
209
214
|
|
data/bin/onevcenter
CHANGED
@@ -20,10 +20,16 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
-
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
24
|
+
REMOTES_LOCATION = '/var/lib/one/remotes/'
|
24
25
|
else
|
25
26
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
-
|
27
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
28
|
+
REMOTES_LOCATION = ONE_LOCATION + '/var/remotes/'
|
29
|
+
end
|
30
|
+
|
31
|
+
if File.directory?(GEMS_LOCATION)
|
32
|
+
Gem.use_paths(GEMS_LOCATION)
|
27
33
|
end
|
28
34
|
|
29
35
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
@@ -97,6 +103,14 @@ CommandParser::CmdParser.new(ARGV) do
|
|
97
103
|
:format => String
|
98
104
|
}
|
99
105
|
|
106
|
+
PORT = {
|
107
|
+
:name => 'port',
|
108
|
+
:short => '-p port',
|
109
|
+
:large => '--port port',
|
110
|
+
:format => String,
|
111
|
+
:description => 'vCenter API port, defaults to 443 (SSL) or 80'
|
112
|
+
}
|
113
|
+
|
100
114
|
USE_DEFAULTS = {
|
101
115
|
:name => 'defaults',
|
102
116
|
:large => '--use-defaults',
|
@@ -234,7 +248,7 @@ CommandParser::CmdParser.new(ARGV) do
|
|
234
248
|
EOT
|
235
249
|
command :hosts,
|
236
250
|
host_desc,
|
237
|
-
:options => [VCENTER, USER, PASS, USE_DEFAULTS] do
|
251
|
+
:options => [VCENTER, USER, PASS, USE_DEFAULTS, PORT] do
|
238
252
|
con_ops = helper.connection_options('Hosts', options)
|
239
253
|
|
240
254
|
VCenterDriver::VcImporter.import_clusters(con_ops, options)
|
data/bin/onevdc
CHANGED
@@ -20,8 +20,14 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
23
24
|
else
|
24
25
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
27
|
+
end
|
28
|
+
|
29
|
+
if File.directory?(GEMS_LOCATION)
|
30
|
+
Gem.use_paths(GEMS_LOCATION)
|
25
31
|
end
|
26
32
|
|
27
33
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
data/bin/onevm
CHANGED
@@ -20,8 +20,14 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
23
24
|
else
|
24
25
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
27
|
+
end
|
28
|
+
|
29
|
+
if File.directory?(GEMS_LOCATION)
|
30
|
+
Gem.use_paths(GEMS_LOCATION)
|
25
31
|
end
|
26
32
|
|
27
33
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
@@ -220,6 +226,10 @@ CommandParser::CmdParser.new(ARGV) do
|
|
220
226
|
helper.retrieve_snapshot_id(@current_vm, arg)
|
221
227
|
end
|
222
228
|
|
229
|
+
format :disk_snapshot_id, 'Disk_snapshot identifier' do |arg|
|
230
|
+
helper.retrieve_disk_snapshot_id(@current_vm, arg)
|
231
|
+
end
|
232
|
+
|
223
233
|
########################################################################
|
224
234
|
# Commands
|
225
235
|
########################################################################
|
@@ -869,7 +879,7 @@ CommandParser::CmdParser.new(ARGV) do
|
|
869
879
|
resched_desc = <<-EOT.unindent
|
870
880
|
Sets the rescheduling flag for the VM.
|
871
881
|
|
872
|
-
States: RUNNING
|
882
|
+
States: RUNNING, POWEROFF
|
873
883
|
EOT
|
874
884
|
|
875
885
|
command :resched, resched_desc, [:range, :vmid_list] do
|
@@ -881,7 +891,7 @@ CommandParser::CmdParser.new(ARGV) do
|
|
881
891
|
unresched_desc = <<-EOT.unindent
|
882
892
|
Clears the rescheduling flag for the VM.
|
883
893
|
|
884
|
-
States: RUNNING
|
894
|
+
States: RUNNING, POWEROFF
|
885
895
|
EOT
|
886
896
|
|
887
897
|
command :unresched, unresched_desc, [:range, :vmid_list] do
|
@@ -1045,8 +1055,9 @@ CommandParser::CmdParser.new(ARGV) do
|
|
1045
1055
|
table = helper.format_pool(options)
|
1046
1056
|
pool = OpenNebula::VirtualMachinePool.new(OneVMHelper.get_client)
|
1047
1057
|
|
1048
|
-
rc = pool.info_search(
|
1049
|
-
|
1058
|
+
rc = pool.info_search(
|
1059
|
+
:extended => options[:extended], :query => options[:search]
|
1060
|
+
)
|
1050
1061
|
|
1051
1062
|
if !rc.nil?
|
1052
1063
|
puts rc.message
|
@@ -1068,7 +1079,9 @@ CommandParser::CmdParser.new(ARGV) do
|
|
1068
1079
|
EOT
|
1069
1080
|
|
1070
1081
|
command :show, show_desc, :vmid,
|
1071
|
-
:options => [OpenNebulaHelper::XML,
|
1082
|
+
:options => [OpenNebulaHelper::XML,
|
1083
|
+
OpenNebulaHelper::DECRYPT,
|
1084
|
+
OneVMHelper::ALL_TEMPLATE] do
|
1072
1085
|
helper.show_resource(args[0], options)
|
1073
1086
|
end
|
1074
1087
|
|
data/bin/onevmgroup
CHANGED
@@ -20,8 +20,14 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
23
24
|
else
|
24
25
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
27
|
+
end
|
28
|
+
|
29
|
+
if File.directory?(GEMS_LOCATION)
|
30
|
+
Gem.use_paths(GEMS_LOCATION)
|
25
31
|
end
|
26
32
|
|
27
33
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
data/bin/onevnet
CHANGED
@@ -20,8 +20,14 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
23
24
|
else
|
24
25
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
27
|
+
end
|
28
|
+
|
29
|
+
if File.directory?(GEMS_LOCATION)
|
30
|
+
Gem.use_paths(GEMS_LOCATION)
|
25
31
|
end
|
26
32
|
|
27
33
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
@@ -305,7 +311,9 @@ CommandParser::CmdParser.new(ARGV) do
|
|
305
311
|
EOT
|
306
312
|
|
307
313
|
command :show, show_desc, :vnetid,
|
308
|
-
:options => [OpenNebulaHelper::XML,
|
314
|
+
:options => [OpenNebulaHelper::XML,
|
315
|
+
OpenNebulaHelper::DECRYPT,
|
316
|
+
OneVNetHelper::SHOW_AR] do
|
309
317
|
helper.show_resource(args[0], options)
|
310
318
|
end
|
311
319
|
|
@@ -421,4 +429,14 @@ CommandParser::CmdParser.new(ARGV) do
|
|
421
429
|
vnet.unlock
|
422
430
|
end
|
423
431
|
end
|
432
|
+
|
433
|
+
show_desc = <<-EOT.unindent
|
434
|
+
Shows orphans vnets (i.e vnets not referenced in any template).
|
435
|
+
EOT
|
436
|
+
|
437
|
+
command :orphans, show_desc do
|
438
|
+
puts helper.check_orphans
|
439
|
+
|
440
|
+
return 0
|
441
|
+
end
|
424
442
|
end
|
data/bin/onevntemplate
CHANGED
@@ -20,8 +20,14 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
23
24
|
else
|
24
25
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
27
|
+
end
|
28
|
+
|
29
|
+
if File.directory?(GEMS_LOCATION)
|
30
|
+
Gem.use_paths(GEMS_LOCATION)
|
25
31
|
end
|
26
32
|
|
27
33
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
data/bin/onevrouter
CHANGED
@@ -20,8 +20,14 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
23
24
|
else
|
24
25
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
27
|
+
end
|
28
|
+
|
29
|
+
if File.directory?(GEMS_LOCATION)
|
30
|
+
Gem.use_paths(GEMS_LOCATION)
|
25
31
|
end
|
26
32
|
|
27
33
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
data/bin/onezone
CHANGED
@@ -20,8 +20,14 @@ ONE_LOCATION = ENV['ONE_LOCATION']
|
|
20
20
|
|
21
21
|
if !ONE_LOCATION
|
22
22
|
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
23
|
+
GEMS_LOCATION = '/usr/share/one/gems'
|
23
24
|
else
|
24
25
|
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
26
|
+
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
27
|
+
end
|
28
|
+
|
29
|
+
if File.directory?(GEMS_LOCATION)
|
30
|
+
Gem.use_paths(GEMS_LOCATION)
|
25
31
|
end
|
26
32
|
|
27
33
|
$LOAD_PATH << RUBY_LIB_LOCATION
|
data/lib/cli_helper.rb
CHANGED
@@ -16,355 +16,753 @@
|
|
16
16
|
|
17
17
|
require 'csv'
|
18
18
|
|
19
|
+
# CLI Helper
|
19
20
|
module CLIHelper
|
21
|
+
|
22
|
+
# CLI general options
|
20
23
|
LIST = {
|
21
|
-
:name
|
22
|
-
:short =>
|
23
|
-
:large =>
|
24
|
+
:name => 'list',
|
25
|
+
:short => '-l x,y,z',
|
26
|
+
:large => '--list x,y,z',
|
24
27
|
:format => Array,
|
25
|
-
:description =>
|
28
|
+
:description => 'Selects columns to display with list command'
|
26
29
|
}
|
27
30
|
|
28
31
|
LISTCONF = {
|
29
|
-
:name
|
30
|
-
:short
|
31
|
-
:large
|
32
|
+
:name => 'listconf',
|
33
|
+
:short => '-c conf',
|
34
|
+
:large => '--listconf conf',
|
32
35
|
:format => String,
|
33
|
-
:description =>
|
36
|
+
:description => 'Selects a predefined column list'
|
34
37
|
}
|
35
38
|
|
36
39
|
CSV_OPT = {
|
37
|
-
:name
|
38
|
-
:large =>
|
39
|
-
:description =>
|
40
|
+
:name => 'csv',
|
41
|
+
:large => '--csv',
|
42
|
+
:description => 'Write table in csv format'
|
43
|
+
}
|
44
|
+
|
45
|
+
CSV_DEL = {
|
46
|
+
:name => 'csv_del',
|
47
|
+
:large => '--csv-del del',
|
48
|
+
:format => String,
|
49
|
+
:description => 'Set delimiter for csv output'
|
40
50
|
}
|
41
51
|
|
42
|
-
#ORDER = {
|
43
|
-
# :name => "order",
|
44
|
-
# :short => "-o x,y,z",
|
45
|
-
# :large => "--order x,y,z",
|
46
|
-
# :format => Array,
|
47
|
-
# :description => "Order by these columns, column starting with - means decreasing order"
|
48
|
-
#}
|
49
|
-
#
|
50
52
|
FILTER = {
|
51
|
-
:name
|
52
|
-
:short =>
|
53
|
-
:large =>
|
53
|
+
:name => 'filter',
|
54
|
+
:short => '-f x,y,z',
|
55
|
+
:large => '--filter x,y,z',
|
54
56
|
:format => Array,
|
55
|
-
:description => "Filter data. An array is specified with\n"<<
|
56
|
-
|
57
|
+
:description => "Filter data. An array is specified with\n" <<
|
58
|
+
' ' * 31 << 'column=value pairs.'
|
57
59
|
}
|
60
|
+
|
58
61
|
OPERATOR = {
|
59
|
-
:name
|
60
|
-
:large =>
|
62
|
+
:name => 'operator',
|
63
|
+
:large => '--operator operator',
|
61
64
|
:format => String,
|
62
|
-
:description =>
|
63
|
-
|
65
|
+
:description => 'Logical operator used on filters: AND, OR. ' \
|
66
|
+
'Default: AND.'
|
67
|
+
}
|
68
|
+
|
69
|
+
NO_HEADER = {
|
70
|
+
:name => 'no_header',
|
71
|
+
:large => '--no-header',
|
72
|
+
:description => 'Hides the header of the table'
|
64
73
|
}
|
65
|
-
|
66
|
-
#
|
67
|
-
#HEADER = {
|
68
|
-
# :name => "header",
|
69
|
-
# :short => "-H",
|
70
|
-
# :large => "--header",
|
71
|
-
# :description => "Shows the header of the table"
|
72
|
-
#}
|
73
74
|
|
74
75
|
DELAY = {
|
75
|
-
:name
|
76
|
-
:short =>
|
77
|
-
:large =>
|
76
|
+
:name => 'delay',
|
77
|
+
:short => '-d x',
|
78
|
+
:large => '--delay x',
|
78
79
|
:format => Integer,
|
79
|
-
:description =>
|
80
|
+
:description => 'Sets the delay in seconds for top command'
|
80
81
|
}
|
81
82
|
|
82
83
|
NO_PAGER = {
|
83
|
-
:name
|
84
|
-
:large =>
|
85
|
-
:
|
86
|
-
:
|
87
|
-
|
88
|
-
ENV['ONE_PAGER'] = 'cat' if File.exists?('/bin/cat')
|
84
|
+
:name => 'no_pager',
|
85
|
+
:large => '--no-pager',
|
86
|
+
:description => 'Disable pagination',
|
87
|
+
:proc => lambda {|_o, _options|
|
88
|
+
ENV['ONE_PAGER'] = 'cat' if File.exist?('/bin/cat')
|
89
89
|
}
|
90
90
|
}
|
91
91
|
|
92
|
-
|
93
|
-
|
92
|
+
ADJUST = {
|
93
|
+
:name => 'adjust',
|
94
|
+
:large => '--adjust x,y,z',
|
95
|
+
:format => Array,
|
96
|
+
:description => 'Adjust size to not truncate selected columns'
|
97
|
+
}
|
98
|
+
|
99
|
+
SIZE = {
|
100
|
+
:name => 'size',
|
101
|
+
:short => '-s x=size,y=size',
|
102
|
+
:large => '--size x=size,y=size',
|
103
|
+
:format => Array,
|
104
|
+
:description => 'Change the size of selected columns. ' \
|
105
|
+
'For example: ' \
|
106
|
+
'$ onevm list --size "name=20" ' \
|
107
|
+
'will make column name size 20.'
|
108
|
+
}
|
109
|
+
|
110
|
+
EXPAND = {
|
111
|
+
:name => 'expand',
|
112
|
+
:large => '--expand [x=prop,y=prop]',
|
113
|
+
:format => Array,
|
114
|
+
:description => 'Expands the columns size to fill the terminal. ' \
|
115
|
+
'For example: ' \
|
116
|
+
'$onevm list --expand name=0.4,group=0.6 ' \
|
117
|
+
'will expand name 40% and group 60%. ' \
|
118
|
+
'$onevm list --expand name,group ' \
|
119
|
+
'will expand name and group based on its size.' \
|
120
|
+
'$onevm list --expand will expand all columns.'
|
121
|
+
}
|
122
|
+
|
123
|
+
NO_EXPAND = {
|
124
|
+
:name => 'no_expand',
|
125
|
+
:large => '--no-expand',
|
126
|
+
:description => 'Disable expand'
|
127
|
+
}
|
128
|
+
|
129
|
+
OPTIONS = [LIST,
|
130
|
+
LISTCONF,
|
131
|
+
DELAY,
|
132
|
+
FILTER,
|
133
|
+
OPERATOR,
|
134
|
+
CSV_OPT,
|
135
|
+
CSV_DEL,
|
136
|
+
NO_PAGER,
|
137
|
+
NO_HEADER,
|
138
|
+
ADJUST,
|
139
|
+
SIZE,
|
140
|
+
EXPAND,
|
141
|
+
NO_EXPAND]
|
94
142
|
|
95
143
|
# Sets bold font
|
96
|
-
def
|
144
|
+
def self.scr_bold
|
97
145
|
print "\33[1m"
|
98
146
|
end
|
99
147
|
|
100
148
|
# Sets underline
|
101
|
-
def
|
149
|
+
def self.scr_underline
|
102
150
|
print "\33[4m"
|
103
151
|
end
|
104
152
|
|
105
153
|
# Restore normal font
|
106
|
-
def
|
154
|
+
def self.scr_restore
|
107
155
|
print "\33[0m"
|
108
156
|
end
|
109
157
|
|
110
158
|
# Clears screen
|
111
|
-
def
|
159
|
+
def self.scr_cls
|
112
160
|
print "\33[2J\33[H"
|
113
161
|
end
|
114
162
|
|
115
163
|
# Moves the cursor
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
print "\33[31m"
|
122
|
-
end
|
123
|
-
|
124
|
-
def CLIHelper.scr_green
|
125
|
-
print "\33[32m"
|
164
|
+
#
|
165
|
+
# @param cord_x [Integer] Coordinate x
|
166
|
+
# @param cord_y [Integer] Coordinate y
|
167
|
+
def self.scr_move(cord_x, cord_y)
|
168
|
+
print "\33[#{cord_x};#{cord_y}H"
|
126
169
|
end
|
127
170
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
171
|
+
# CLI state colors
|
172
|
+
ANSI_RED = "\33[31m"
|
173
|
+
ANSI_GREEN = "\33[32m"
|
174
|
+
ANSI_RESET = "\33[0m"
|
175
|
+
ANSI_YELLOW = "\33[33m"
|
132
176
|
|
133
|
-
|
134
|
-
|
135
|
-
|
177
|
+
# CLI states
|
178
|
+
OK_STATES = %w[runn rdy on configured SUCCESS]
|
179
|
+
BAD_STATES = %w[fail err error ERROR]
|
180
|
+
REGULAR_STATES = %w[pending]
|
136
181
|
|
137
|
-
|
182
|
+
# Set state color
|
183
|
+
#
|
184
|
+
# @param stat [String] Current state
|
185
|
+
def self.color_state(state)
|
138
186
|
if $stdout.tty?
|
139
|
-
case
|
187
|
+
case state.strip
|
140
188
|
when *OK_STATES
|
141
|
-
ANSI_GREEN+
|
189
|
+
ANSI_GREEN + state + ANSI_RESET
|
142
190
|
when *BAD_STATES
|
143
|
-
ANSI_RED+
|
191
|
+
ANSI_RED + state + ANSI_RESET
|
144
192
|
when *REGULAR_STATES
|
145
|
-
ANSI_YELLOW+
|
193
|
+
ANSI_YELLOW + state + ANSI_RESET
|
146
194
|
else
|
147
|
-
|
195
|
+
state
|
148
196
|
end
|
149
197
|
else
|
150
|
-
|
198
|
+
state
|
151
199
|
end
|
152
200
|
end
|
153
201
|
|
154
202
|
# Print header
|
155
|
-
|
203
|
+
#
|
204
|
+
# @param str [String] String with header content
|
205
|
+
# @param underline [Boolean] True to underline the header
|
206
|
+
def self.print_header(str, underline = true)
|
156
207
|
if $stdout.tty?
|
157
208
|
print_tty_header(str, underline)
|
158
209
|
else
|
159
210
|
print str
|
160
211
|
end
|
212
|
+
|
161
213
|
puts
|
162
214
|
end
|
163
215
|
|
164
|
-
#
|
165
|
-
|
216
|
+
# Print pretty header
|
217
|
+
#
|
218
|
+
# @param str [String] String with header content
|
219
|
+
# @param underline [Boolean] True to underline the header
|
220
|
+
def self.print_tty_header(str, underline = true)
|
166
221
|
scr_bold
|
167
222
|
scr_underline if underline
|
168
223
|
print str
|
169
224
|
scr_restore
|
170
225
|
end
|
171
226
|
|
227
|
+
# Show error message and exit with error
|
228
|
+
#
|
229
|
+
# @param message [String] Error message to show
|
230
|
+
def self.fail(message)
|
231
|
+
STDERR.puts message
|
232
|
+
|
233
|
+
exit(-1)
|
234
|
+
end
|
235
|
+
|
236
|
+
# Check if value is in base64
|
237
|
+
#
|
238
|
+
# @param value [String] Value to check
|
239
|
+
#
|
240
|
+
# @return [Boolean] True if it's base64
|
241
|
+
def self.base64?(value)
|
242
|
+
re = %r(^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)?$)
|
243
|
+
|
244
|
+
!value.match(re).nil?
|
245
|
+
end
|
246
|
+
|
247
|
+
# Hash with search
|
172
248
|
module HashWithSearch
|
249
|
+
|
250
|
+
# Search inside path
|
251
|
+
#
|
252
|
+
# @param path [String] Path to search on
|
173
253
|
def dsearch(path)
|
174
|
-
stems=path.split('/')
|
175
|
-
hash=self
|
254
|
+
stems = path.split('/')
|
255
|
+
hash = self
|
176
256
|
|
177
257
|
stems.delete_if {|s| s.nil? || s.empty? }
|
178
258
|
|
179
259
|
stems.each do |stem|
|
180
|
-
if Hash
|
260
|
+
if hash.is_a? Hash
|
181
261
|
if hash[stem]
|
182
|
-
hash=hash[stem]
|
262
|
+
hash = hash[stem]
|
183
263
|
else
|
184
|
-
hash=nil
|
264
|
+
hash = nil
|
185
265
|
break
|
186
266
|
end
|
187
267
|
else
|
188
|
-
hash=nil
|
268
|
+
hash = nil
|
189
269
|
break
|
190
270
|
end
|
191
271
|
end
|
192
272
|
|
193
273
|
hash
|
194
274
|
end
|
275
|
+
|
195
276
|
end
|
196
277
|
|
278
|
+
# Show table
|
197
279
|
class ShowTable
|
280
|
+
|
198
281
|
require 'yaml'
|
199
282
|
|
200
283
|
attr_reader :default_columns
|
201
284
|
|
202
|
-
|
203
|
-
|
204
|
-
|
285
|
+
# Class constructor
|
286
|
+
#
|
287
|
+
# @param conf [String] Configuration file
|
288
|
+
# @param ext [Helper] Cli helper information
|
289
|
+
def initialize(conf = nil, ext = nil, &block)
|
290
|
+
@columns = {}
|
291
|
+
@default_columns = []
|
205
292
|
|
206
|
-
@ext
|
293
|
+
@ext = ext
|
207
294
|
@conf = conf
|
208
295
|
|
209
296
|
instance_eval(&block)
|
210
297
|
end
|
211
298
|
|
299
|
+
# Get the helper
|
212
300
|
def helper
|
213
301
|
@ext
|
214
302
|
end
|
215
303
|
|
304
|
+
# Fill column attributes
|
305
|
+
#
|
306
|
+
# @param name [String] Column name
|
307
|
+
# @param desc [String] Column description
|
308
|
+
# @param conf [Array] Configutation attributes
|
216
309
|
def column(name, desc, *conf, &block)
|
217
|
-
column =
|
310
|
+
column = {}
|
311
|
+
|
218
312
|
column[:desc] = desc
|
219
313
|
column[:size] = 5
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
314
|
+
|
315
|
+
conf.each do |c|
|
316
|
+
if c.is_a? Symbol
|
317
|
+
column[c] = true
|
318
|
+
elsif c.is_a? Hash
|
319
|
+
c.each do |key, value|
|
320
|
+
column[key] = value
|
321
|
+
end
|
227
322
|
end
|
228
|
-
|
323
|
+
end
|
324
|
+
|
229
325
|
column[:proc] = block
|
326
|
+
|
230
327
|
@columns[name.to_sym] = column
|
231
|
-
|
328
|
+
|
329
|
+
@default_columns << name
|
232
330
|
end
|
233
331
|
|
332
|
+
# Get default columns
|
333
|
+
#
|
334
|
+
# @param args [Array] Array with default columns
|
234
335
|
def default(*args)
|
235
|
-
args.map!{|a| a.to_sym }
|
236
|
-
|
336
|
+
args.map! {|a| a.to_sym }
|
337
|
+
|
338
|
+
@default_columns = args
|
237
339
|
end
|
238
340
|
|
239
|
-
|
240
|
-
|
341
|
+
# Show resource
|
342
|
+
#
|
343
|
+
# @param data [Hash/Object] Data to show
|
344
|
+
# @param options [Hash] Object with CLI user options
|
345
|
+
# @param top [Boolean] True to not update columns again
|
346
|
+
def show(data, options = {}, top = false)
|
347
|
+
update_columns(options) unless top
|
348
|
+
|
349
|
+
if data.is_a? Hash
|
350
|
+
@data = data
|
241
351
|
|
242
|
-
if Hash===data
|
243
|
-
@data=data
|
244
352
|
@data.extend(HashWithSearch)
|
245
353
|
|
246
|
-
pool
|
247
|
-
return print_table(nil, options) if !pool
|
354
|
+
pool = @data.keys.first
|
248
355
|
|
249
|
-
|
356
|
+
return print_table(data, options) unless pool
|
250
357
|
|
251
|
-
|
252
|
-
|
358
|
+
element = pool.split('_')[0..-2].join('_')
|
359
|
+
|
360
|
+
pool_data = @data.dsearch("#{pool}/#{element}")
|
361
|
+
|
362
|
+
if pool_data
|
363
|
+
pool_data = [pool_data].flatten
|
364
|
+
else
|
365
|
+
pool_data = []
|
366
|
+
end
|
253
367
|
|
254
368
|
print_table(pool_data, options)
|
255
369
|
else
|
370
|
+
data ||= []
|
371
|
+
|
256
372
|
print_table(data, options)
|
257
373
|
end
|
258
374
|
end
|
259
375
|
|
260
|
-
|
261
|
-
|
376
|
+
# Show resource continuosly
|
377
|
+
#
|
378
|
+
# @param options [Hash] Object with CLI user options
|
379
|
+
def top(options = {})
|
380
|
+
delay = options[:delay] || 1
|
381
|
+
top = false
|
262
382
|
|
263
383
|
begin
|
264
|
-
|
265
|
-
data =
|
384
|
+
loop do
|
385
|
+
data = yield
|
266
386
|
|
267
387
|
CLIHelper.scr_cls
|
268
|
-
CLIHelper.scr_move(0,0)
|
388
|
+
CLIHelper.scr_move(0, 0)
|
389
|
+
|
390
|
+
show(data, options, top)
|
269
391
|
|
270
|
-
show(data, options)
|
271
392
|
sleep delay
|
393
|
+
|
394
|
+
top = true
|
272
395
|
end
|
273
|
-
rescue
|
274
|
-
|
396
|
+
rescue SystemExit, Interrupt, StandardError => e
|
397
|
+
CLIHelper.fail(e.message)
|
275
398
|
end
|
276
399
|
end
|
277
400
|
|
401
|
+
# Show column description
|
278
402
|
def describe_columns
|
279
|
-
str=
|
403
|
+
str = '%-20s: %-20s'
|
280
404
|
|
281
405
|
@columns.each do |column, d|
|
282
|
-
puts str
|
406
|
+
puts format(str, column, d[:desc])
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
# Get maximum string lenght in column
|
411
|
+
#
|
412
|
+
# @param index [Integer] Column index to search
|
413
|
+
#
|
414
|
+
# @return [Integer] Maximum length
|
415
|
+
def max_size(index)
|
416
|
+
sizes = []
|
417
|
+
|
418
|
+
@res_data.each do |d|
|
419
|
+
sizes << d[index].size
|
420
|
+
end
|
421
|
+
|
422
|
+
sizes.max
|
423
|
+
end
|
424
|
+
|
425
|
+
# Get total size of all columns
|
426
|
+
#
|
427
|
+
# @param columns [Array] Array with columns name
|
428
|
+
#
|
429
|
+
# @return [Integer] Total size
|
430
|
+
def total_columns_size(columns)
|
431
|
+
size = 0
|
432
|
+
|
433
|
+
columns.each do |c|
|
434
|
+
size += @columns[c[:name]][:size]
|
283
435
|
end
|
436
|
+
|
437
|
+
size
|
284
438
|
end
|
285
439
|
|
440
|
+
# Get columns information
|
441
|
+
#
|
442
|
+
# @param columns [Array] Array with columns information
|
443
|
+
#
|
444
|
+
# @return [Array] Array with columns objects
|
445
|
+
def columns_info(columns)
|
446
|
+
ret = []
|
447
|
+
|
448
|
+
columns.each do |column|
|
449
|
+
data = column.to_s.split('=')
|
450
|
+
|
451
|
+
ret << { :name => data[0].upcase.to_sym, :prop => data[1] }
|
452
|
+
end
|
453
|
+
|
454
|
+
ret
|
455
|
+
end
|
456
|
+
|
457
|
+
# Print tty header
|
286
458
|
def print_tty_header
|
287
459
|
CLIHelper.print_tty_header(header_str)
|
460
|
+
|
288
461
|
puts
|
289
462
|
end
|
290
463
|
|
291
464
|
private
|
292
465
|
|
466
|
+
# Get header in string format
|
467
|
+
def header_str
|
468
|
+
@default_columns.collect do |c|
|
469
|
+
if @columns[c]
|
470
|
+
format_str(c, c.to_s)
|
471
|
+
else
|
472
|
+
CLIHelper.fail("Column #{c} not defined.")
|
473
|
+
end
|
474
|
+
end.compact.join(' ')
|
475
|
+
end
|
476
|
+
|
477
|
+
# Print data in table format
|
478
|
+
#
|
479
|
+
# @param data [Array] Array with data to show
|
480
|
+
# @param options [Hash] Object with CLI user options
|
293
481
|
def print_table(data, options)
|
294
|
-
|
482
|
+
@res_data = data_array(data, options)
|
483
|
+
|
484
|
+
update_columns_size(options)
|
485
|
+
|
486
|
+
if !options[:csv] && (!options.key? :no_header)
|
295
487
|
CLIHelper.print_header(header_str)
|
296
488
|
end
|
297
489
|
|
298
|
-
|
490
|
+
if options[:csv] && (!options.key? :no_header)
|
491
|
+
print_csv_data([@default_columns], options[:csv_del])
|
492
|
+
end
|
493
|
+
|
494
|
+
@res_data ? print_data(@res_data, options) : puts
|
299
495
|
end
|
300
496
|
|
497
|
+
# Print data
|
498
|
+
#
|
499
|
+
# @param data [Array] Array with data to show
|
500
|
+
# @param options [Hash] Object with CLI user options
|
301
501
|
def print_data(data, options)
|
302
|
-
|
303
|
-
|
502
|
+
if options[:csv]
|
503
|
+
print_csv_data(data, options[:csv_del])
|
504
|
+
else
|
505
|
+
print_normal_data(data, options[:stat_column])
|
506
|
+
end
|
507
|
+
rescue Errno::EPIPE => e
|
508
|
+
CLIHelper.fail(e.message)
|
509
|
+
end
|
304
510
|
|
305
|
-
|
306
|
-
|
307
|
-
|
511
|
+
# Print data in CSV format
|
512
|
+
#
|
513
|
+
# @param data [Array] Array with data to show
|
514
|
+
# @param del [Char] CSV delimiter
|
515
|
+
def print_csv_data(data, del)
|
516
|
+
del ? del = del : del = ','
|
517
|
+
|
518
|
+
data.each do |l|
|
519
|
+
puts CSV.generate_line(l, :col_sep => del)
|
520
|
+
end
|
521
|
+
end
|
522
|
+
|
523
|
+
# Print data in normal format
|
524
|
+
#
|
525
|
+
# @param data [Array] Array with data to show
|
526
|
+
# @param stat_column [String] Name of the state column
|
527
|
+
def print_normal_data(data, stat_column)
|
528
|
+
ncolumns = @default_columns.length
|
529
|
+
|
530
|
+
if stat_column
|
531
|
+
stat = stat_column.upcase.to_sym
|
532
|
+
stat_column = @default_columns.index(stat)
|
308
533
|
else
|
309
|
-
stat_column
|
534
|
+
stat_column = @default_columns.index(:STAT)
|
310
535
|
end
|
311
536
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
col=@default_columns[i]
|
537
|
+
data.each do |l|
|
538
|
+
result = []
|
539
|
+
|
540
|
+
ncolumns.times do |i|
|
541
|
+
dat = l[i]
|
542
|
+
col = @default_columns[i]
|
543
|
+
|
544
|
+
str = format_str(col, dat)
|
321
545
|
|
322
|
-
|
323
|
-
str=CLIHelper.color_state(str) if i==stat_column
|
546
|
+
str = CLIHelper.color_state(str) if i == stat_column
|
324
547
|
|
325
|
-
|
326
|
-
}.join(' ').rstrip
|
327
|
-
}
|
548
|
+
result << str
|
328
549
|
end
|
329
|
-
|
550
|
+
puts result.join(' ').rstrip
|
330
551
|
end
|
331
552
|
end
|
332
553
|
|
554
|
+
# Get data in array format
|
555
|
+
#
|
556
|
+
# @param data [Array] Array with data to show
|
557
|
+
# @param options [Hash] Object with CLI user options
|
558
|
+
#
|
559
|
+
# @return [Array] Array with selected columns information
|
333
560
|
def data_array(data, options)
|
334
|
-
res_data=data.collect
|
335
|
-
@default_columns.collect
|
561
|
+
res_data = data.collect do |d|
|
562
|
+
@default_columns.collect do |c|
|
336
563
|
@columns[c][:proc].call(d).to_s if @columns[c]
|
337
|
-
|
338
|
-
|
564
|
+
end
|
565
|
+
end
|
339
566
|
|
340
567
|
if options
|
341
568
|
filter_data!(res_data, options) if options[:filter]
|
342
|
-
sort_data!(res_data, options[:order]) if options[:order]
|
343
569
|
end
|
344
570
|
|
345
571
|
res_data
|
346
572
|
end
|
347
573
|
|
574
|
+
# Format data as string
|
575
|
+
#
|
576
|
+
# @param field [Symbol] Name of the column to format
|
577
|
+
# @param data [String] Data to format
|
348
578
|
def format_str(field, data)
|
349
579
|
if @columns[field]
|
350
|
-
|
351
|
-
size
|
352
|
-
|
353
|
-
|
580
|
+
@columns[field][:left] ? minus = '-' : minus = ''
|
581
|
+
size = @columns[field][:size]
|
582
|
+
|
583
|
+
if @columns[field][:adjust]
|
584
|
+
format("%#{minus}#{size}s", data.to_s)
|
585
|
+
else
|
586
|
+
format("%#{minus}#{size}.#{size}s", data.to_s)
|
354
587
|
end
|
355
|
-
return "%#{minus}#{size}.#{size}s" % [ data.to_s ]
|
356
588
|
else
|
357
|
-
|
589
|
+
CLIHelper.fail("Column #{field} not defined.")
|
358
590
|
end
|
359
591
|
end
|
360
592
|
|
593
|
+
# Get expand information from configuration files
|
594
|
+
#
|
595
|
+
# @return [Array] Array with columns data
|
596
|
+
def config_expand_data
|
597
|
+
ret = []
|
598
|
+
|
599
|
+
@default_columns.each do |column|
|
600
|
+
expand_c = @columns[column][:expand]
|
601
|
+
|
602
|
+
next unless expand_c
|
603
|
+
|
604
|
+
column = column.to_s.downcase
|
605
|
+
|
606
|
+
ret << "#{column}=#{expand_c}" if expand_c.is_a? Numeric
|
607
|
+
|
608
|
+
ret << column.to_s.downcase unless expand_c.is_a? Numeric
|
609
|
+
end
|
610
|
+
|
611
|
+
ret
|
612
|
+
end
|
613
|
+
|
614
|
+
# Get adjust information from configuration files
|
615
|
+
#
|
616
|
+
# @return [Array] Array with columns data
|
617
|
+
def config_adjust_data
|
618
|
+
ret = []
|
619
|
+
|
620
|
+
@default_columns.each do |column|
|
621
|
+
next unless @columns[column][:adjust]
|
622
|
+
|
623
|
+
ret << column.to_s.downcase
|
624
|
+
end
|
625
|
+
|
626
|
+
ret
|
627
|
+
end
|
628
|
+
|
629
|
+
# Change the size of expand columns
|
630
|
+
#
|
631
|
+
# @param expand_columns [Array] Array with expand columns names
|
632
|
+
# @param all [Boolean] True to expand all columns
|
633
|
+
def expand_columns(expand_columns, all = false)
|
634
|
+
return if expand_columns.empty?
|
635
|
+
|
636
|
+
if $stdout.tty?
|
637
|
+
terminal_size = IO.console.winsize[1]
|
638
|
+
else
|
639
|
+
terminal_size = nil
|
640
|
+
end
|
641
|
+
|
642
|
+
return if terminal_size.nil?
|
643
|
+
|
644
|
+
default_columns = columns_info(@default_columns)
|
645
|
+
expand_columns = columns_info(expand_columns)
|
646
|
+
|
647
|
+
total_size = total_columns_size(default_columns)
|
648
|
+
columns_size = total_columns_size(expand_columns)
|
649
|
+
|
650
|
+
terminal_size -= (@default_columns.size - 1)
|
651
|
+
left_size = terminal_size - total_size
|
652
|
+
remaining_size = left_size
|
653
|
+
|
654
|
+
return if left_size <= 0
|
655
|
+
|
656
|
+
expand_columns.each do |c|
|
657
|
+
column = c[:name]
|
658
|
+
prop = c[:prop]
|
659
|
+
|
660
|
+
if @columns[column].nil?
|
661
|
+
CLIHelper.fail("Unknown column #{column}")
|
662
|
+
end
|
663
|
+
|
664
|
+
if all
|
665
|
+
prop = @columns[column][:size] / total_size.to_f
|
666
|
+
elsif !prop
|
667
|
+
prop = @columns[column][:size] / columns_size.to_f
|
668
|
+
end
|
669
|
+
|
670
|
+
size = (left_size * prop.to_f).round
|
671
|
+
|
672
|
+
@columns[column][:adjust] = false
|
673
|
+
@columns[column][:size] += size
|
674
|
+
|
675
|
+
remaining_size -= size
|
676
|
+
end
|
677
|
+
|
678
|
+
if remaining_size > 0
|
679
|
+
# If there is some left space, add it to the last column
|
680
|
+
@columns[expand_columns[-1][:name]][:size] += remaining_size
|
681
|
+
end
|
682
|
+
|
683
|
+
return if terminal_size == total_columns_size(default_columns)
|
684
|
+
|
685
|
+
# If there is extra space, sub it from the last column
|
686
|
+
diff = total_columns_size(default_columns) - terminal_size
|
687
|
+
|
688
|
+
@columns[expand_columns[-1][:name]][:size] -= diff
|
689
|
+
end
|
690
|
+
|
691
|
+
# Change columns size
|
692
|
+
#
|
693
|
+
# @param options [Array] Array with size information for each column
|
694
|
+
def size_columns(options)
|
695
|
+
options[:size].each do |column|
|
696
|
+
data = column.split('=')
|
697
|
+
column = data[0].upcase.to_sym
|
698
|
+
size = data[1].to_i
|
699
|
+
|
700
|
+
@columns[column][:adjust] = false
|
701
|
+
@columns[column][:size] = size
|
702
|
+
end
|
703
|
+
end
|
704
|
+
|
705
|
+
# Update columns size information
|
706
|
+
#
|
707
|
+
# @param options [Hash] Object with CLI user options
|
708
|
+
def update_columns_size(options)
|
709
|
+
adjust = options[:adjust]
|
710
|
+
|
711
|
+
if adjust
|
712
|
+
adjust += config_adjust_data
|
713
|
+
else
|
714
|
+
adjust = config_adjust_data
|
715
|
+
end
|
716
|
+
|
717
|
+
expand_all = (options.key? :expand) && options[:expand].nil?
|
718
|
+
expand = !options[:expand].nil?
|
719
|
+
expand_data = []
|
720
|
+
|
721
|
+
if expand_all
|
722
|
+
expand_data = @default_columns
|
723
|
+
elsif expand
|
724
|
+
expand_data += options[:expand]
|
725
|
+
end
|
726
|
+
|
727
|
+
expand_data += config_expand_data
|
728
|
+
|
729
|
+
c_size = options[:size]
|
730
|
+
|
731
|
+
# Update adjust attribute to not truncate the column
|
732
|
+
# If expand all columns adjust is ignored
|
733
|
+
unless expand_all
|
734
|
+
adjust.each do |column|
|
735
|
+
column = column.upcase.to_sym
|
736
|
+
size = max_size(@default_columns.index(column))
|
737
|
+
|
738
|
+
if size && size > @columns[column][:size]
|
739
|
+
@columns[column][:adjust] = true
|
740
|
+
@columns[column][:size] = size
|
741
|
+
end
|
742
|
+
end
|
743
|
+
end
|
744
|
+
|
745
|
+
# Update size attribute if size
|
746
|
+
size_columns(options) if c_size
|
747
|
+
|
748
|
+
# Update size attribute if expand
|
749
|
+
expand_columns(expand_data) unless options.key? :no_expand
|
750
|
+
end
|
751
|
+
|
752
|
+
# Update columns information
|
753
|
+
#
|
754
|
+
# @param options [Hash] Object with CLI user options
|
361
755
|
def update_columns(options)
|
362
756
|
begin
|
363
|
-
|
757
|
+
if @conf
|
758
|
+
config = YAML.load_file(@conf)
|
759
|
+
else
|
760
|
+
config = {}
|
761
|
+
end
|
364
762
|
|
365
|
-
default
|
763
|
+
default = config.delete(:default) || {}
|
366
764
|
default_conf = config.delete(:default_conf) || {}
|
367
|
-
listconf
|
765
|
+
listconf = options[:listconf]
|
368
766
|
|
369
767
|
listconf = default_conf[listconf.to_sym] if listconf
|
370
768
|
|
@@ -381,75 +779,69 @@ module CLIHelper
|
|
381
779
|
# Filter show options with available columns
|
382
780
|
@default_columns &= @columns.keys
|
383
781
|
|
384
|
-
@columns.merge!(config)
|
782
|
+
@columns.merge!(config) do |_key, oldval, newval|
|
385
783
|
oldval.merge(newval)
|
386
|
-
|
387
|
-
rescue
|
784
|
+
end
|
785
|
+
rescue StandardError => e
|
786
|
+
CLIHelper.fail(e.message)
|
388
787
|
end
|
389
788
|
|
390
|
-
|
391
|
-
end
|
789
|
+
return unless options[:list]
|
392
790
|
|
393
|
-
|
394
|
-
@default_columns.collect {|c|
|
395
|
-
if @columns[c]
|
396
|
-
format_str(c, c.to_s)
|
397
|
-
else
|
398
|
-
puts "Column #{c} not defined."
|
399
|
-
exit -1
|
400
|
-
end
|
401
|
-
}.compact.join(' ')
|
791
|
+
@default_columns = options[:list].collect {|o| o.upcase.to_sym }
|
402
792
|
end
|
403
793
|
|
794
|
+
# Filter data
|
795
|
+
#
|
796
|
+
# @param data [Array] Array with data to filter
|
797
|
+
# @param options [Hash] Object with CLI user options
|
404
798
|
def filter_data!(data, options)
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
filter = options[:filter]
|
799
|
+
operators = /(=|!=|<|<=|>|>=)/
|
800
|
+
filter = options[:filter]
|
801
|
+
|
409
802
|
if options.key?(:operator)
|
410
|
-
|
803
|
+
log_operator = options[:operator].upcase
|
411
804
|
else
|
412
|
-
log_operator =
|
805
|
+
log_operator = 'AND'
|
413
806
|
end
|
414
807
|
|
415
|
-
stems=filter.map do |s|
|
416
|
-
m=s.match(/^(.*?)#{operators}(.*?)$/)
|
808
|
+
stems = filter.map do |s|
|
809
|
+
m = s.match(/^(.*?)#{operators}(.*?)$/)
|
810
|
+
|
417
811
|
if m
|
418
|
-
|
419
|
-
index=@default_columns.index(left.to_sym)
|
812
|
+
index = @default_columns.index(m[1].to_sym)
|
420
813
|
|
421
814
|
if index
|
422
815
|
{
|
423
|
-
:left =>
|
424
|
-
:operator =>
|
425
|
-
:right =>
|
816
|
+
:left => m[1],
|
817
|
+
:operator => m[2],
|
818
|
+
:right => m[3],
|
426
819
|
:index => index
|
427
820
|
}
|
428
821
|
else
|
429
|
-
|
430
|
-
exit(-1)
|
822
|
+
CLIHelper.fail("Column '#{left}' not found")
|
431
823
|
end
|
432
824
|
else
|
433
|
-
|
434
|
-
exit(-1)
|
825
|
+
CLIHelper.fail("Expression '#{s}' incorrect")
|
435
826
|
end
|
436
827
|
end
|
437
828
|
|
438
829
|
data.select! do |d|
|
439
|
-
pass=true
|
830
|
+
pass = true
|
440
831
|
|
441
832
|
stems.each do |s|
|
833
|
+
s[:operator] == '=' ? op = '==' : op = s[:operator]
|
442
834
|
|
443
|
-
if d[s[:index]].public_send(
|
444
|
-
if log_operator ==
|
835
|
+
if d[s[:index]].public_send(op, s[:right])
|
836
|
+
if log_operator == 'OR'
|
445
837
|
pass = true
|
838
|
+
|
446
839
|
break
|
447
840
|
end
|
448
841
|
else
|
449
842
|
pass = false
|
450
|
-
|
451
|
-
|
452
|
-
end
|
843
|
+
|
844
|
+
break if log_operator == 'AND'
|
453
845
|
end
|
454
846
|
end
|
455
847
|
|
@@ -457,6 +849,8 @@ module CLIHelper
|
|
457
849
|
end
|
458
850
|
end
|
459
851
|
|
460
|
-
#
|
852
|
+
# TODO: def sort_data!(data, options)
|
853
|
+
|
461
854
|
end
|
855
|
+
|
462
856
|
end
|