opennebula-cli 5.8.5 → 5.9.80.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|