morpheus-cli 4.1.8 → 4.1.9
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/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +24 -0
- data/lib/morpheus/api/{old_cypher_interface.rb → budgets_interface.rb} +10 -11
- data/lib/morpheus/api/cloud_datastores_interface.rb +7 -0
- data/lib/morpheus/api/cloud_resource_pools_interface.rb +2 -2
- data/lib/morpheus/api/cypher_interface.rb +18 -12
- data/lib/morpheus/api/health_interface.rb +72 -0
- data/lib/morpheus/api/instances_interface.rb +1 -1
- data/lib/morpheus/api/library_instance_types_interface.rb +7 -0
- data/lib/morpheus/api/log_settings_interface.rb +6 -0
- data/lib/morpheus/api/network_security_servers_interface.rb +30 -0
- data/lib/morpheus/api/price_sets_interface.rb +42 -0
- data/lib/morpheus/api/prices_interface.rb +68 -0
- data/lib/morpheus/api/provisioning_settings_interface.rb +29 -0
- data/lib/morpheus/api/servers_interface.rb +1 -1
- data/lib/morpheus/api/service_plans_interface.rb +34 -11
- data/lib/morpheus/api/task_sets_interface.rb +8 -0
- data/lib/morpheus/api/tasks_interface.rb +8 -0
- data/lib/morpheus/cli.rb +6 -3
- data/lib/morpheus/cli/appliance_settings_command.rb +13 -5
- data/lib/morpheus/cli/approvals_command.rb +1 -1
- data/lib/morpheus/cli/apps.rb +88 -28
- data/lib/morpheus/cli/backup_settings_command.rb +1 -1
- data/lib/morpheus/cli/blueprints_command.rb +2 -0
- data/lib/morpheus/cli/budgets_command.rb +672 -0
- data/lib/morpheus/cli/cli_command.rb +13 -2
- data/lib/morpheus/cli/cli_registry.rb +1 -0
- data/lib/morpheus/cli/clusters.rb +40 -274
- data/lib/morpheus/cli/commands/standard/benchmark_command.rb +114 -66
- data/lib/morpheus/cli/commands/standard/coloring_command.rb +12 -0
- data/lib/morpheus/cli/commands/standard/curl_command.rb +31 -6
- data/lib/morpheus/cli/commands/standard/echo_command.rb +8 -3
- data/lib/morpheus/cli/commands/standard/set_prompt_command.rb +1 -1
- data/lib/morpheus/cli/containers_command.rb +37 -24
- data/lib/morpheus/cli/cypher_command.rb +191 -150
- data/lib/morpheus/cli/health_command.rb +903 -0
- data/lib/morpheus/cli/hosts.rb +43 -32
- data/lib/morpheus/cli/instances.rb +119 -68
- data/lib/morpheus/cli/jobs_command.rb +1 -1
- data/lib/morpheus/cli/library_instance_types_command.rb +61 -11
- data/lib/morpheus/cli/library_option_types_command.rb +2 -2
- data/lib/morpheus/cli/log_settings_command.rb +46 -3
- data/lib/morpheus/cli/logs_command.rb +24 -17
- data/lib/morpheus/cli/mixins/accounts_helper.rb +2 -0
- data/lib/morpheus/cli/mixins/logs_helper.rb +73 -19
- data/lib/morpheus/cli/mixins/print_helper.rb +29 -1
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +554 -96
- data/lib/morpheus/cli/mixins/whoami_helper.rb +13 -1
- data/lib/morpheus/cli/networks_command.rb +3 -0
- data/lib/morpheus/cli/option_types.rb +83 -53
- data/lib/morpheus/cli/price_sets_command.rb +543 -0
- data/lib/morpheus/cli/prices_command.rb +669 -0
- data/lib/morpheus/cli/processes_command.rb +0 -2
- data/lib/morpheus/cli/provisioning_settings_command.rb +237 -0
- data/lib/morpheus/cli/remote.rb +9 -4
- data/lib/morpheus/cli/reports_command.rb +10 -4
- data/lib/morpheus/cli/roles.rb +93 -38
- data/lib/morpheus/cli/security_groups.rb +10 -0
- data/lib/morpheus/cli/service_plans_command.rb +736 -0
- data/lib/morpheus/cli/tasks.rb +220 -8
- data/lib/morpheus/cli/tenants_command.rb +3 -16
- data/lib/morpheus/cli/users.rb +2 -25
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/whitelabel_settings_command.rb +18 -18
- data/lib/morpheus/cli/whoami.rb +28 -10
- data/lib/morpheus/cli/workflows.rb +488 -36
- data/lib/morpheus/formatters.rb +22 -0
- data/morpheus-cli.gemspec +1 -0
- metadata +28 -5
- data/lib/morpheus/cli/accounts.rb +0 -335
- data/lib/morpheus/cli/old_cypher_command.rb +0 -412
@@ -321,89 +321,137 @@ EOT
|
|
321
321
|
return 1
|
322
322
|
end
|
323
323
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
324
|
+
exit_code = 0
|
325
|
+
out = ""
|
326
|
+
|
327
|
+
original_stdout = nil
|
328
|
+
begin
|
329
|
+
# --quiet actually unhooks stdout for this command
|
330
|
+
if options[:quiet]
|
331
|
+
original_stdout = my_terminal.stdout
|
332
|
+
my_terminal.set_stdout(Morpheus::Terminal::Blackhole.new)
|
333
|
+
end
|
334
|
+
|
335
|
+
cmd = args.join(' ')
|
336
|
+
benchmark_name ||= cmd
|
337
|
+
|
338
|
+
|
339
|
+
if n == 1
|
336
340
|
start_benchmark(benchmark_name)
|
337
341
|
# exit_code, err = my_terminal.execute(cmd)
|
338
342
|
cmd_result = Morpheus::Cli::CliRegistry.exec_expression(cmd)
|
339
343
|
exit_code, err = Morpheus::Cli::CliRegistry.parse_command_result(cmd_result)
|
340
344
|
benchmark_record = stop_benchmark(exit_code, err)
|
341
|
-
Morpheus::Logging::DarkPrinter.puts(cyan + dark + benchmark_record.msg) if
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
345
|
+
# Morpheus::Logging::DarkPrinter.puts(cyan + dark + benchmark_record.msg) if benchmark_record
|
346
|
+
# return 0
|
347
|
+
if original_stdout
|
348
|
+
my_terminal.set_stdout(original_stdout)
|
349
|
+
original_stdout = nil
|
350
|
+
end
|
351
|
+
out = ""
|
352
|
+
# <benchmark name or command>
|
353
|
+
out << "#{benchmark_name.ljust(30, ' ')}"
|
354
|
+
# exit: 0
|
355
|
+
exit_code = benchmark_record.exit_code
|
356
|
+
bad_benchmark = benchmark_record.exit_code && benchmark_record.exit_code != 0
|
357
|
+
if bad_benchmark
|
358
|
+
out << "\texit: #{bad_benchmark.exit_code.to_s.ljust(2, ' ')}"
|
359
|
+
out << "\terror: #{bad_benchmark.error.to_s.ljust(12, ' ')}"
|
360
|
+
else
|
361
|
+
out << "\texit: 0 "
|
362
|
+
end
|
363
|
+
else
|
364
|
+
benchmark_records = []
|
365
|
+
n.times do |iteration_index|
|
366
|
+
start_benchmark(benchmark_name)
|
367
|
+
# exit_code, err = my_terminal.execute(cmd)
|
368
|
+
cmd_result = Morpheus::Cli::CliRegistry.exec_expression(cmd)
|
369
|
+
exit_code, err = Morpheus::Cli::CliRegistry.parse_command_result(cmd_result)
|
370
|
+
benchmark_record = stop_benchmark(exit_code, err)
|
371
|
+
Morpheus::Logging::DarkPrinter.puts(cyan + dark + benchmark_record.msg) if Morpheus::Logging.debug?
|
372
|
+
benchmark_records << benchmark_record
|
373
|
+
end
|
374
|
+
if original_stdout
|
375
|
+
my_terminal.set_stdout(original_stdout)
|
376
|
+
original_stdout = nil
|
377
|
+
end
|
378
|
+
# calc total and mean and print it
|
379
|
+
# all_durations = benchmark_records.collect {|benchmark_record| benchmark_record.duration }
|
380
|
+
# total_duration = all_durations.inject(0.0) {|acc, i| acc + i }
|
381
|
+
# avg_duration = total_duration / all_durations.size
|
382
|
+
# total_time_str = "#{total_duration.round((total_duration > 0.002) ? 3 : 6)}s"
|
383
|
+
# avg_time_str = "#{avg_duration.round((total_duration > 0.002) ? 3 : 6)}s"
|
350
384
|
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
385
|
+
all_durations = []
|
386
|
+
stats = {total: 0, avg: nil, min: nil, max: nil}
|
387
|
+
benchmark_records.each do |benchmark_record|
|
388
|
+
duration = benchmark_record.duration
|
389
|
+
if duration
|
390
|
+
all_durations << duration
|
391
|
+
stats[:total] += duration
|
392
|
+
if stats[:min].nil? || stats[:min] > duration
|
393
|
+
stats[:min] = duration
|
394
|
+
end
|
395
|
+
if stats[:max].nil? || stats[:max] < duration
|
396
|
+
stats[:max] = duration
|
397
|
+
end
|
363
398
|
end
|
364
399
|
end
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
end
|
400
|
+
if all_durations.size > 0
|
401
|
+
stats[:avg] = stats[:total].to_f / all_durations.size
|
402
|
+
end
|
369
403
|
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
404
|
+
total_time_str = "#{stats[:total].round((stats[:total] > 0.002) ? 3 : 6)}s"
|
405
|
+
min_time_str = stats[:min] ? "#{stats[:min].round((stats[:min] > 0.002) ? 3 : 6)}s" : ""
|
406
|
+
max_time_str = stats[:max] ? "#{stats[:max].round((stats[:max] > 0.002) ? 3 : 6)}s" : ""
|
407
|
+
avg_time_str = stats[:avg] ? "#{stats[:avg].round((stats[:avg] > 0.002) ? 3 : 6)}s" : ""
|
374
408
|
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
end
|
409
|
+
out = ""
|
410
|
+
# <benchmark name or command>
|
411
|
+
out << "#{benchmark_name.ljust(30, ' ')}"
|
412
|
+
# exit: 0
|
413
|
+
bad_benchmark = benchmark_records.find {|benchmark_record| benchmark_record.exit_code && benchmark_record.exit_code != 0 }
|
414
|
+
if bad_benchmark
|
415
|
+
exit_code = bad_benchmark.exit_code.to_i
|
416
|
+
out << "\texit: #{bad_benchmark.exit_code.to_s.ljust(2, ' ')}"
|
417
|
+
out << "\terror: #{bad_benchmark.error.to_s.ljust(12, ' ')}"
|
418
|
+
else
|
419
|
+
out << "\texit: 0 "
|
420
|
+
end
|
388
421
|
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
422
|
+
out << "\tn: #{n.to_s.ljust(4, ' ')}"
|
423
|
+
out << "\ttotal: #{total_time_str.ljust(9, ' ')}"
|
424
|
+
out << "\tmin: #{min_time_str.ljust(9, ' ')}"
|
425
|
+
out << "\tmax: #{max_time_str.ljust(9, ' ')}"
|
426
|
+
out << "\tavg: #{avg_time_str.ljust(9, ' ')}"
|
394
427
|
|
395
428
|
|
396
|
-
|
397
|
-
|
398
|
-
return 1
|
399
|
-
|
429
|
+
# if bad_benchmark
|
430
|
+
# print_error red,out,reset,"\n"
|
431
|
+
# return 1
|
432
|
+
# else
|
433
|
+
# print cyan,out,reset,"\n"
|
434
|
+
# return 0
|
435
|
+
# end
|
436
|
+
end
|
437
|
+
if exit_code == 0
|
400
438
|
print cyan,out,reset,"\n"
|
401
439
|
return 0
|
440
|
+
else
|
441
|
+
print_error red,out,reset,"\n"
|
442
|
+
return exit_code
|
443
|
+
end
|
444
|
+
rescue => ex
|
445
|
+
raise ex
|
446
|
+
#raise_command_error "benchmark exec failed with error: #{ex}"
|
447
|
+
#puts_error "benchmark exec failed with error: #{ex}"
|
448
|
+
#return 1
|
449
|
+
ensure
|
450
|
+
if original_stdout
|
451
|
+
my_terminal.set_stdout(original_stdout)
|
452
|
+
original_stdout = nil
|
402
453
|
end
|
403
|
-
|
404
454
|
end
|
405
|
-
|
406
|
-
return 0
|
407
455
|
end
|
408
456
|
|
409
457
|
end
|
@@ -57,11 +57,13 @@ class Morpheus::Cli::ColoringCommand
|
|
57
57
|
if Term::ANSIColor::coloring?
|
58
58
|
if coloring_was_enabled == false
|
59
59
|
Morpheus::Logging::DarkPrinter.puts "coloring enabled" if Morpheus::Logging.debug?
|
60
|
+
recalculate_after_color_change()
|
60
61
|
end
|
61
62
|
puts "#{cyan}coloring: #{bold}#{green}on#{reset}"
|
62
63
|
else
|
63
64
|
if coloring_was_enabled == true
|
64
65
|
Morpheus::Logging::DarkPrinter.puts "coloring disabled" if Morpheus::Logging.debug?
|
66
|
+
recalculate_after_color_change()
|
65
67
|
end
|
66
68
|
puts "coloring: off"
|
67
69
|
end
|
@@ -69,4 +71,14 @@ class Morpheus::Cli::ColoringCommand
|
|
69
71
|
return exit_code
|
70
72
|
end
|
71
73
|
|
74
|
+
protected
|
75
|
+
|
76
|
+
def recalculate_after_color_change()
|
77
|
+
# recalculate shell prompt after this change
|
78
|
+
Morpheus::Cli::Echo.recalculate_variable_map()
|
79
|
+
if Morpheus::Cli::Shell.has_instance?
|
80
|
+
Morpheus::Cli::Shell.instance.recalculate_prompt()
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
72
84
|
end
|
@@ -12,6 +12,9 @@ class Morpheus::Cli::CurlCommand
|
|
12
12
|
split_args = args.join(" ").split(" -- ")
|
13
13
|
args = split_args[0].split(" ")
|
14
14
|
curl_args = split_args[1] ? split_args[1].split(" ") : []
|
15
|
+
curl_method = nil
|
16
|
+
curl_data = nil
|
17
|
+
show_progress = false
|
15
18
|
# puts "args is : #{args}"
|
16
19
|
# puts "curl_args is : #{curl_args}"
|
17
20
|
options = {}
|
@@ -20,11 +23,20 @@ class Morpheus::Cli::CurlCommand
|
|
20
23
|
opts.on( '-p', '--pretty', "Print result as parsed JSON." ) do
|
21
24
|
options[:pretty] = true
|
22
25
|
end
|
26
|
+
opts.on( '-X', '--request METHOD', "HTTP request method. Default is GET" ) do |val|
|
27
|
+
curl_method = val
|
28
|
+
end
|
29
|
+
opts.on( '--data DATA', String, "HTTP request body for use with POST and PUT, typically JSON." ) do |val|
|
30
|
+
curl_data = val
|
31
|
+
end
|
32
|
+
opts.on( '--progress', '--progress', "Display progress output by excluding the -s option." ) do
|
33
|
+
show_progress = true
|
34
|
+
end
|
23
35
|
build_common_options(opts, options, [:dry_run, :remote])
|
24
36
|
opts.add_hidden_option('--curl')
|
25
37
|
#opts.add_hidden_option('--scrub')
|
26
38
|
opts.footer = <<-EOT
|
27
|
-
This invokes the `curl` command with url "appliance_url
|
39
|
+
This invokes the `curl` command with url "appliance_url/$0
|
28
40
|
and includes the authorization header -H "Authorization: Bearer access_token"
|
29
41
|
Arguments for the curl command should be passed after ' -- '
|
30
42
|
Example: morpheus curl "/api/servers/1" -- -XGET -sv
|
@@ -71,10 +83,21 @@ EOT
|
|
71
83
|
api_path = api_path.sub(/^\//, "") # strip leading slash
|
72
84
|
url = "#{@appliance_url.chomp('/')}/#{api_path}"
|
73
85
|
end
|
74
|
-
curl_cmd = "curl
|
86
|
+
curl_cmd = "curl"
|
87
|
+
if show_progress == false
|
88
|
+
curl_cmd << " -s"
|
89
|
+
end
|
90
|
+
if curl_method
|
91
|
+
curl_cmd << " -X#{curl_method}"
|
92
|
+
end
|
93
|
+
curl_cmd << " \"#{url}\""
|
75
94
|
if @access_token
|
76
95
|
curl_cmd << " -H \"Authorization: Bearer #{@access_token}\""
|
77
96
|
end
|
97
|
+
if curl_data
|
98
|
+
#todo: curl_data.gsub("'","\\'")
|
99
|
+
curl_cmd << " --data '#{curl_data}'"
|
100
|
+
end
|
78
101
|
if !curl_args.empty?
|
79
102
|
curl_cmd << " " + curl_args.join(' ')
|
80
103
|
end
|
@@ -89,16 +112,18 @@ EOT
|
|
89
112
|
print reset
|
90
113
|
return 0
|
91
114
|
end
|
92
|
-
print cyan
|
93
|
-
print "#{cyan}#{curl_cmd_str}#{reset}"
|
94
|
-
print "\n\n"
|
115
|
+
# print cyan
|
116
|
+
# print "#{cyan}#{curl_cmd_str}#{reset}"
|
117
|
+
# print "\n\n"
|
95
118
|
print reset
|
96
119
|
# print result
|
97
120
|
curl_output = `#{curl_cmd}`
|
98
121
|
if options[:pretty]
|
99
122
|
output_lines = curl_output.split("\n")
|
100
123
|
last_line = output_lines.pop
|
101
|
-
|
124
|
+
if output_lines.size > 0
|
125
|
+
puts output_lines.join("\n")
|
126
|
+
end
|
102
127
|
begin
|
103
128
|
json_data = JSON.parse(last_line)
|
104
129
|
json_string = JSON.pretty_generate(json_data)
|
@@ -10,8 +10,8 @@ class Morpheus::Cli::Echo
|
|
10
10
|
set_command_name :echo
|
11
11
|
set_command_hidden
|
12
12
|
|
13
|
-
unless defined?(
|
14
|
-
|
13
|
+
unless defined?(COLOR_VARIABLE_MAP)
|
14
|
+
COLOR_VARIABLE_MAP = {'%cyan' => Term::ANSIColor.cyan, '%magenta' => Term::ANSIColor.magenta, '%red' => Term::ANSIColor.red, '%green' => Term::ANSIColor.green, '%yellow' => Term::ANSIColor.yellow, '%white' => Term::ANSIColor.white, '%dark' => Term::ANSIColor.dark, '%reset' => Term::ANSIColor.reset}
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.variable_map
|
@@ -20,7 +20,12 @@ class Morpheus::Cli::Echo
|
|
20
20
|
|
21
21
|
def self.recalculate_variable_map()
|
22
22
|
var_map = {}
|
23
|
-
|
23
|
+
if Term::ANSIColor.coloring?
|
24
|
+
var_map.merge!(COLOR_VARIABLE_MAP)
|
25
|
+
else
|
26
|
+
COLOR_VARIABLE_MAP.each {|k,v| var_map[k] = "" }
|
27
|
+
end
|
28
|
+
|
24
29
|
appliance = ::Morpheus::Cli::Remote.load_active_remote()
|
25
30
|
if appliance
|
26
31
|
var_map.merge!({'%remote' => appliance[:name], '%remote_url' => (appliance[:host].to_s || appliance[:url].to_s), '%username' => appliance[:username].to_s})
|
@@ -27,7 +27,7 @@ Examples:
|
|
27
27
|
set-prompt "morpheus $ "
|
28
28
|
set-prompt "%cyanmorpheus> "
|
29
29
|
set-prompt "[%magenta%remote%reset] %cyan%username> "
|
30
|
-
set-prompt "%green%username%reset@%remote
|
30
|
+
set-prompt "%green%username%reset@%remote %magenta> %reset"
|
31
31
|
set-prompt "%cyan%username%reset@%magenta%remote %cyanmorpheus> %reset"
|
32
32
|
|
33
33
|
The available variables are:
|
@@ -4,11 +4,13 @@ require 'optparse'
|
|
4
4
|
require 'filesize'
|
5
5
|
require 'morpheus/cli/cli_command'
|
6
6
|
require 'morpheus/cli/mixins/provisioning_helper'
|
7
|
+
require 'morpheus/cli/mixins/logs_helper'
|
7
8
|
require 'morpheus/cli/option_types'
|
8
9
|
|
9
10
|
class Morpheus::Cli::ContainersCommand
|
10
11
|
include Morpheus::Cli::CliCommand
|
11
12
|
include Morpheus::Cli::ProvisioningHelper
|
13
|
+
include Morpheus::Cli::LogsHelper
|
12
14
|
|
13
15
|
set_command_name :containers
|
14
16
|
|
@@ -507,8 +509,24 @@ class Morpheus::Cli::ContainersCommand
|
|
507
509
|
|
508
510
|
def logs(args)
|
509
511
|
options = {}
|
512
|
+
params = {}
|
510
513
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
511
514
|
opts.banner = subcommand_usage("[id]")
|
515
|
+
opts.on('--start TIMESTAMP','--start TIMESTAMP', "Start timestamp. Default is 30 days ago.") do |val|
|
516
|
+
options[:start] = parse_time(val) #.utc.iso8601
|
517
|
+
end
|
518
|
+
opts.on('--end TIMESTAMP','--end TIMESTAMP', "End timestamp. Default is now.") do |val|
|
519
|
+
options[:end] = parse_time(val) #.utc.iso8601
|
520
|
+
end
|
521
|
+
opts.on('--level VALUE', String, "Log Level. DEBUG,INFO,WARN,ERROR") do |val|
|
522
|
+
params['level'] = params['level'] ? [params['level'], val].flatten : val
|
523
|
+
end
|
524
|
+
opts.on('--table', '--table', "Format ouput as a table.") do
|
525
|
+
options[:table] = true
|
526
|
+
end
|
527
|
+
opts.on('-a', '--all', "Display all details: entire message." ) do
|
528
|
+
options[:details] = true
|
529
|
+
end
|
512
530
|
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
513
531
|
opts.footer = "List logs for a container.\n" +
|
514
532
|
"[id] is required. This is the id of a container."
|
@@ -523,47 +541,42 @@ class Morpheus::Cli::ContainersCommand
|
|
523
541
|
id_list = parse_id_list(args)
|
524
542
|
begin
|
525
543
|
containers = id_list # heh
|
526
|
-
params = {}
|
527
544
|
params.merge!(parse_list_options(options))
|
528
|
-
params[
|
529
|
-
params[
|
545
|
+
params['query'] = params.delete('phrase') if params['phrase']
|
546
|
+
params[:order] = params[:direction] unless params[:direction].nil? # old api version expects order instead of direction
|
547
|
+
params['startMs'] = (options[:start].to_i * 1000) if options[:start]
|
548
|
+
params['endMs'] = (options[:end].to_i * 1000) if options[:end]
|
530
549
|
@logs_interface.setopts(options)
|
531
550
|
if options[:dry_run]
|
532
551
|
print_dry_run @logs_interface.dry.container_logs(containers, params)
|
533
552
|
return
|
534
553
|
end
|
535
554
|
json_response = @logs_interface.container_logs(containers, params)
|
536
|
-
render_result = render_with_format(json_response, options, 'data')
|
555
|
+
render_result = json_response['logs'] ? render_with_format(json_response, options, 'logs') : render_with_format(json_response, options, 'data')
|
537
556
|
return 0 if render_result
|
538
557
|
|
539
558
|
logs = json_response
|
540
559
|
title = "Container Logs: #{containers.join(', ')}"
|
541
560
|
subtitles = parse_list_subtitles(options)
|
561
|
+
if options[:start]
|
562
|
+
subtitles << "Start: #{options[:start]}".strip
|
563
|
+
end
|
564
|
+
if options[:end]
|
565
|
+
subtitles << "End: #{options[:end]}".strip
|
566
|
+
end
|
542
567
|
if params[:query]
|
543
568
|
subtitles << "Search: #{params[:query]}".strip
|
544
569
|
end
|
545
|
-
|
570
|
+
if params['level']
|
571
|
+
subtitles << "Level: #{params['level']}"
|
572
|
+
end
|
573
|
+
logs = json_response['data'] || json_response['logs']
|
546
574
|
print_h1 title, subtitles, options
|
547
|
-
if logs
|
548
|
-
|
575
|
+
if logs.empty?
|
576
|
+
print "#{cyan}No logs found.#{reset}\n"
|
549
577
|
else
|
550
|
-
logs
|
551
|
-
|
552
|
-
case log_entry['level']
|
553
|
-
when 'INFO'
|
554
|
-
log_level = "#{blue}#{bold}INFO#{reset}"
|
555
|
-
when 'DEBUG'
|
556
|
-
log_level = "#{white}#{bold}DEBUG#{reset}"
|
557
|
-
when 'WARN'
|
558
|
-
log_level = "#{yellow}#{bold}WARN#{reset}"
|
559
|
-
when 'ERROR'
|
560
|
-
log_level = "#{red}#{bold}ERROR#{reset}"
|
561
|
-
when 'FATAL'
|
562
|
-
log_level = "#{red}#{bold}FATAL#{reset}"
|
563
|
-
end
|
564
|
-
puts "[#{log_entry['ts']}] #{log_level} - #{log_entry['message'].to_s.strip}"
|
565
|
-
end
|
566
|
-
print_results_pagination({'meta'=>{'total'=>json_response['total'],'size'=>json_response['data'].size,'max'=>(json_response['max'] || options[:max]),'offset'=>(json_response['offset'] || options[:offset] || 0)}})
|
578
|
+
print format_log_records(logs, options)
|
579
|
+
print_results_pagination({'meta'=>{'total'=>(json_response['total']['value'] rescue json_response['total']),'size'=>logs.size,'max'=>(json_response['max'] || options[:max]),'offset'=>(json_response['offset'] || options[:offset] || 0)}})
|
567
580
|
end
|
568
581
|
print reset,"\n"
|
569
582
|
return 0
|
@@ -66,6 +66,7 @@ class Morpheus::Cli::CypherCommand
|
|
66
66
|
puts records_as_csv([json_response], options)
|
67
67
|
return 0
|
68
68
|
end
|
69
|
+
cypher_items = json_response["cypherItems"] || json_response["cyphers"]
|
69
70
|
cypher_data = json_response["data"]
|
70
71
|
title = "Morpheus Cypher Key List"
|
71
72
|
subtitles = []
|
@@ -93,13 +94,15 @@ class Morpheus::Cli::CypherCommand
|
|
93
94
|
"EXPIRATION" => lambda {|it|
|
94
95
|
format_expiration_date(it["expireDate"])
|
95
96
|
},
|
96
|
-
"DATE CREATED" => lambda {|it| format_local_dt(it["dateCreated"]) },
|
97
|
-
"LAST
|
97
|
+
# "DATE CREATED" => lambda {|it| format_local_dt(it["dateCreated"]) },
|
98
|
+
"LAST UPDATED" => lambda {|it| format_local_dt(it["lastUpdated"]) },
|
99
|
+
"LAST ACCESSED" => lambda {|it| format_local_dt(it["lastAccessed"]) }
|
98
100
|
}
|
99
101
|
print cyan
|
100
|
-
print as_pretty_table(
|
102
|
+
print as_pretty_table(cypher_items, cypher_columns, options)
|
101
103
|
print reset
|
102
|
-
print_results_pagination({size:cypher_keys.size,total:cypher_keys.size.to_i})
|
104
|
+
# print_results_pagination({size:cypher_keys.size,total:cypher_keys.size.to_i})
|
105
|
+
print_results_pagination(json_response)
|
103
106
|
end
|
104
107
|
print reset,"\n"
|
105
108
|
return 0
|
@@ -114,7 +117,7 @@ class Morpheus::Cli::CypherCommand
|
|
114
117
|
params = {}
|
115
118
|
value_only = false
|
116
119
|
do_decrypt = false
|
117
|
-
|
120
|
+
ttl = nil
|
118
121
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
119
122
|
opts.banner = subcommand_usage("[key]")
|
120
123
|
# opts.on(nil, '--decrypt', 'Display the decrypted value') do
|
@@ -127,14 +130,14 @@ class Morpheus::Cli::CypherCommand
|
|
127
130
|
value_only = true
|
128
131
|
end
|
129
132
|
opts.on( '-t', '--ttl SECONDS', "Time to live, the lease duration before this key expires. Use if creating new key." ) do |val|
|
130
|
-
|
133
|
+
ttl = val
|
131
134
|
if val.to_s.empty? || val.to_s == '0'
|
132
|
-
|
135
|
+
ttl = 0
|
133
136
|
else
|
134
|
-
|
137
|
+
ttl = val
|
135
138
|
end
|
136
139
|
end
|
137
|
-
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :quiet, :remote])
|
140
|
+
build_common_options(opts, options, [:query, :json, :yaml, :csv, :fields, :outfile, :dry_run, :quiet, :remote])
|
138
141
|
opts.footer = "Read a cypher item and display the decrypted value." + "\n" +
|
139
142
|
"[key] is required. This is the cypher key to read." + "\n" +
|
140
143
|
"Use --ttl to specify a ttl if expecting cypher engine to automatically create the key."
|
@@ -148,33 +151,24 @@ class Morpheus::Cli::CypherCommand
|
|
148
151
|
connect(options)
|
149
152
|
begin
|
150
153
|
item_key = args[0]
|
151
|
-
if
|
152
|
-
params["ttl"] =
|
154
|
+
if ttl
|
155
|
+
params["ttl"] = ttl
|
153
156
|
end
|
154
157
|
@cypher_interface.setopts(options)
|
155
158
|
if options[:dry_run]
|
156
159
|
print_dry_run @cypher_interface.dry.get(item_key, params)
|
157
160
|
return 0
|
158
161
|
end
|
162
|
+
params.merge!(parse_list_options(options))
|
159
163
|
json_response = @cypher_interface.get(item_key, params)
|
160
|
-
|
161
|
-
if
|
164
|
+
render_result = render_with_format(json_response, options)
|
165
|
+
if render_result
|
162
166
|
return 0
|
163
167
|
end
|
164
|
-
|
165
|
-
if options[:json]
|
166
|
-
puts as_json(json_response, options)
|
167
|
-
return 0
|
168
|
-
elsif options[:yaml]
|
169
|
-
puts as_yaml(json_response, options)
|
170
|
-
return 0
|
171
|
-
elsif options[:csv]
|
172
|
-
puts records_as_csv([json_response], options)
|
173
|
-
return 0
|
174
|
-
end
|
175
|
-
|
168
|
+
|
176
169
|
cypher_item = json_response['cypher']
|
177
170
|
decrypted_value = json_response["data"]
|
171
|
+
data_type = decrypted_value.is_a?(String) ? 'string' : 'object'
|
178
172
|
|
179
173
|
if value_only
|
180
174
|
print cyan
|
@@ -201,19 +195,24 @@ class Morpheus::Cli::CypherCommand
|
|
201
195
|
"TTL" => lambda {|it|
|
202
196
|
format_expiration_ttl(it["expireDate"])
|
203
197
|
},
|
198
|
+
# "Type" => lambda {|it|
|
199
|
+
# data_type
|
200
|
+
# },
|
204
201
|
"Expiration" => lambda {|it|
|
205
202
|
format_expiration_date(it["expireDate"])
|
206
203
|
},
|
207
|
-
"Date Created" => lambda {|it| format_local_dt(it["dateCreated"]) },
|
208
|
-
"Last
|
204
|
+
# "Date Created" => lambda {|it| format_local_dt(it["dateCreated"]) },
|
205
|
+
"Last Updated" => lambda {|it| format_local_dt(it["lastUpdated"]) },
|
206
|
+
"Last Accessed" => lambda {|it| format_local_dt(it["lastAccessed"]) }
|
209
207
|
}
|
210
208
|
if cypher_item["expireDate"].nil?
|
211
209
|
description_cols.delete("Expires")
|
212
210
|
end
|
213
211
|
print_description_list(description_cols, cypher_item)
|
214
212
|
|
215
|
-
print_h2 "Value", options
|
216
|
-
# print_h2 "
|
213
|
+
# print_h2 "Value", options
|
214
|
+
# print_h2 "Data", options
|
215
|
+
print_h2 "Data (#{data_type})", options
|
217
216
|
|
218
217
|
if decrypted_value
|
219
218
|
print cyan
|
@@ -247,36 +246,44 @@ class Morpheus::Cli::CypherCommand
|
|
247
246
|
end
|
248
247
|
|
249
248
|
def put(args)
|
249
|
+
usage = <<-EOT
|
250
|
+
Usage: morpheus #{command_name} put [key] [value] [options] to store a string.
|
251
|
+
morpheus #{command_name} put [key] [k=v] [k=v] [options] to store an object.
|
252
|
+
EOT
|
250
253
|
options = {}
|
251
254
|
params = {}
|
252
255
|
item_key = nil
|
253
256
|
item_value = nil
|
254
|
-
|
257
|
+
ttl = nil
|
255
258
|
no_overwrite = nil
|
256
259
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
257
|
-
opts.banner = subcommand_usage("[key] [value]")
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
260
|
+
# opts.banner = subcommand_usage("[key] [value]\n\t[key] [k=v] [k=v] [k=v]")
|
261
|
+
opts.banner = usage
|
262
|
+
opts.on( '--key KEY', String, "Key. This can also be passed as the first argument." ) do |val|
|
263
|
+
item_key = val
|
264
|
+
end
|
265
|
+
opts.on( '-v', '--value VALUE', "Secret value. This can be used to store a string instead of an object, and can also be passed as the second argument." ) do |val|
|
262
266
|
item_value = val
|
263
267
|
end
|
264
268
|
opts.on( '-t', '--ttl SECONDS', "Time to live, the lease duration before this key expires." ) do |val|
|
265
|
-
|
269
|
+
ttl = val
|
266
270
|
if val.to_s.empty? || val.to_s == '0'
|
267
|
-
|
271
|
+
ttl = 0
|
268
272
|
else
|
269
|
-
|
273
|
+
ttl = val
|
270
274
|
end
|
271
275
|
end
|
272
276
|
# opts.on( '--no-overwrite', '--no-overwrite', "Do not overwrite existing keys. Existing keys are overwritten by default." ) do
|
273
277
|
# params['overwrite'] = false
|
274
278
|
# end
|
275
|
-
build_common_options(opts, options, [:auto_confirm, :options, :payload, :json, :dry_run, :quiet, :remote])
|
279
|
+
build_common_options(opts, options, [:auto_confirm, :options, :payload, :json, :yaml, :csv, :fields, :outfile, :dry_run, :quiet, :remote])
|
276
280
|
opts.footer = "Create or update a cypher key." + "\n" +
|
277
|
-
"[key] is required. This is the key of the cypher being created or updated." + "\n" +
|
278
|
-
"[value] is required. This is the
|
279
|
-
"
|
281
|
+
"[key] is required. This is the key of the cypher being created or updated. The key includes the mount prefix eg. secret/hello" + "\n" +
|
282
|
+
"[value] is required for some cypher engines, such as secret. This is the secret value or k=v pairs being stored. Supports 1-N arguments." + "\n" +
|
283
|
+
"If a single [value] is passed, it is stored as type string." + "\n" +
|
284
|
+
"If more than one [value] is passed, the format is expected to be k=v and the value will be stored as an object." + "\n" +
|
285
|
+
"The --value option can be used to store a string value." + "\n" +
|
286
|
+
"The --payload option can be used to store an object."
|
280
287
|
end
|
281
288
|
optparse.parse!(args)
|
282
289
|
# if args.count < 1
|
@@ -285,126 +292,160 @@ class Morpheus::Cli::CypherCommand
|
|
285
292
|
# return 1
|
286
293
|
# end
|
287
294
|
connect(options)
|
288
|
-
|
289
|
-
|
290
|
-
|
295
|
+
|
296
|
+
# parse arguments like [value] or [k=v]
|
297
|
+
item_key = args[0]
|
298
|
+
item_value = args[1]
|
299
|
+
if args.count == 0
|
300
|
+
# prompt for key and value
|
301
|
+
elsif args.count == 1
|
302
|
+
# prompt for value
|
303
|
+
elsif args.count == 2
|
304
|
+
# expecting [value] or [k=v]
|
305
|
+
item_value_object = {}
|
306
|
+
item_value_pair = item_value.split("=")
|
307
|
+
if item_value_pair.size == 2
|
308
|
+
item_value_object[item_value_pair[0].to_s] = item_value_pair[1]
|
309
|
+
item_value = item_value_object
|
310
|
+
else
|
311
|
+
# item_value = item_value
|
312
|
+
end
|
313
|
+
elsif args.count > 2
|
314
|
+
# expecting [k=v] [k=v]
|
315
|
+
item_value_object = {}
|
316
|
+
args[1..(args.size-1)].each do |arg|
|
317
|
+
item_value_pair = arg.split("=")
|
318
|
+
item_value_object[item_value_pair[0].to_s] = item_value_pair[1]
|
291
319
|
end
|
292
|
-
|
293
|
-
|
294
|
-
|
320
|
+
item_value = item_value_object
|
321
|
+
end
|
322
|
+
|
323
|
+
# this is redunant and silly, refactor soon
|
324
|
+
|
325
|
+
# Key prompt
|
326
|
+
if item_key
|
327
|
+
options[:options]['key'] = item_key
|
328
|
+
end
|
329
|
+
if item_key.nil?
|
295
330
|
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'key', 'fieldLabel' => 'Key', 'type' => 'text', 'required' => true, 'description' => cypher_key_help}], options[:options])
|
296
331
|
item_key = v_prompt['key']
|
332
|
+
end
|
297
333
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
334
|
+
payload = nil
|
335
|
+
if options[:payload]
|
336
|
+
payload = options[:payload]
|
337
|
+
payload.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) || ['key','value'].include?(k)}) if options[:options] && options[:options].keys.size > 0
|
338
|
+
else
|
339
|
+
# merge -O options into normally parsed options
|
340
|
+
params.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) || ['key','value'].include?(k)}) if options[:options] && options[:options].keys.size > 0
|
341
|
+
|
342
|
+
# Value prompt
|
343
|
+
value_is_required = false
|
344
|
+
cypher_mount_type = item_key.split("/").first
|
345
|
+
if ["secret","tfvars"].include?(cypher_mount_type)
|
346
|
+
value_is_required = true
|
347
|
+
end
|
312
348
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
end
|
328
|
-
item_value = value_arguments_map
|
329
|
-
end
|
330
|
-
else
|
331
|
-
# Prompt for a single text value to be sent as {"value":"my secret"}
|
332
|
-
if value_is_required
|
333
|
-
options[:options]['value'] = item_value if item_value
|
334
|
-
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'value', 'fieldLabel' => 'Value', 'type' => 'text', 'required' => value_is_required, 'description' => "Secret value for this cypher"}], options[:options])
|
335
|
-
item_value = v_prompt['value']
|
349
|
+
# todo: read value from STDIN shall we?
|
350
|
+
|
351
|
+
# cool, we got value as arguments like foo=bar
|
352
|
+
if args.count > 1
|
353
|
+
# parse one and only arg as the value like password/mine mypassword123
|
354
|
+
if args.count == 2 && args[1].split("=").size() == 1
|
355
|
+
item_value = args[1]
|
356
|
+
elsif args.count > 1
|
357
|
+
# parse args as key value pairs like secret/config foo=bar thing=myvalue
|
358
|
+
value_arguments = args[1..-1]
|
359
|
+
value_arguments_map = {}
|
360
|
+
value_arguments.each do |value_argument|
|
361
|
+
value_pair = value_argument.split("=")
|
362
|
+
value_arguments_map[value_pair[0]] = value_pair[1] ? value_pair[1..-1].join("=") : nil
|
336
363
|
end
|
364
|
+
item_value = value_arguments_map
|
337
365
|
end
|
338
|
-
|
339
|
-
#
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
# if value is valid json, then the payload IS the value
|
345
|
-
if item_value.is_a?(String) && item_value.to_s[0] == '{' && item_value.to_s[-1] == '}'
|
346
|
-
begin
|
347
|
-
json_object = JSON.parse(item_value)
|
348
|
-
item_value = json_object
|
349
|
-
rescue => ex
|
350
|
-
Morpheus::Logging::DarkPrinter.puts "Failed to parse cypher value '#{item_value}' as JSON. Error: #{ex}" if Morpheus::Logging.debug?
|
351
|
-
raise_command_error "Failed to parse cypher value as JSON: #{item_value}"
|
352
|
-
# return 1
|
353
|
-
end
|
354
|
-
else
|
355
|
-
# it is just a string
|
356
|
-
if item_value.is_a?(String)
|
357
|
-
payload = {"value" => item_value}
|
358
|
-
elsif item_value.nil?
|
359
|
-
payload = {}
|
360
|
-
else item_value
|
361
|
-
# great, a Hash I hope
|
362
|
-
payload = item_value
|
363
|
-
end
|
366
|
+
else
|
367
|
+
# Prompt for a single text value to be sent as {"value":"my secret"}
|
368
|
+
if value_is_required
|
369
|
+
options[:options]['value'] = item_value if item_value
|
370
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'value', 'fieldLabel' => 'Value', 'type' => 'text', 'required' => value_is_required, 'description' => "Secret value for this cypher"}], options[:options])
|
371
|
+
item_value = v_prompt['value']
|
364
372
|
end
|
365
373
|
end
|
366
374
|
|
367
|
-
#
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
375
|
+
# make sure not to pass a value for these or it will not save them.
|
376
|
+
# if ['uuid','key','password'].include?(cypher_mount_type)
|
377
|
+
# item_value = nil
|
378
|
+
# end
|
372
379
|
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
if
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
380
|
+
# construct payload
|
381
|
+
# payload = {
|
382
|
+
# 'cypher' => params
|
383
|
+
# }
|
384
|
+
payload = {}
|
385
|
+
# if value is valid json, then the payload IS the value
|
386
|
+
if item_value.is_a?(String) && item_value.to_s[0] == '{' && item_value.to_s[-1] == '}'
|
387
|
+
begin
|
388
|
+
json_object = JSON.parse(item_value)
|
389
|
+
item_value = json_object
|
390
|
+
rescue => ex
|
391
|
+
Morpheus::Logging::DarkPrinter.puts "Failed to parse cypher value '#{item_value}' as JSON. Error: #{ex}" if Morpheus::Logging.debug?
|
392
|
+
raise_command_error "Failed to parse cypher value as JSON: #{item_value}"
|
393
|
+
# return 1
|
394
|
+
end
|
395
|
+
else
|
396
|
+
# it is just a string
|
397
|
+
if item_value.is_a?(String)
|
398
|
+
params['type'] = 'string'
|
399
|
+
#params["value"] = item_value
|
400
|
+
payload["value"] = item_value
|
401
|
+
elsif item_value.nil?
|
402
|
+
payload = {}
|
403
|
+
else item_value
|
404
|
+
# great, a Hash I hope
|
405
|
+
payload = item_value
|
390
406
|
end
|
391
407
|
end
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
408
|
+
end
|
409
|
+
|
410
|
+
# prompt for Lease
|
411
|
+
options[:options]['ttl'] = ttl if ttl
|
412
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'ttl', 'fieldLabel' => 'Lease (TTL in seconds)', 'type' => 'text', 'required' => false, 'description' => cypher_ttl_help, 'defaultValue' => '0'}], options[:options])
|
413
|
+
ttl = v_prompt['ttl']
|
414
|
+
|
415
|
+
if ttl
|
416
|
+
params['ttl'] = ttl
|
417
|
+
#payload["ttl"] = ttl
|
418
|
+
end
|
419
|
+
@cypher_interface.setopts(options)
|
420
|
+
if options[:dry_run]
|
421
|
+
print_dry_run @cypher_interface.dry.create(item_key, params, payload)
|
422
|
+
return
|
423
|
+
end
|
424
|
+
existing_cypher = nil
|
425
|
+
json_response = @cypher_interface.list(item_key)
|
426
|
+
if json_response["data"] && json_response["data"]["keys"]
|
427
|
+
existing_cypher = json_response["data"]["keys"].find {|k| k == item_key }
|
428
|
+
end
|
429
|
+
if existing_cypher
|
430
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to overwrite the cypher key #{item_key}?")
|
431
|
+
return 9, "aborted command"
|
400
432
|
end
|
433
|
+
end
|
434
|
+
json_response = @cypher_interface.create(item_key, params, payload)
|
435
|
+
render_result = render_with_format(json_response, options)
|
436
|
+
if render_result
|
401
437
|
return 0
|
402
|
-
rescue RestClient::Exception => e
|
403
|
-
print_rest_exception(e, options)
|
404
|
-
exit 1
|
405
438
|
end
|
439
|
+
#print_green_success "Cypher #{item_key} updated"
|
440
|
+
# print_green_success "Wrote cypher #{item_key}"
|
441
|
+
print_green_success "Success! Data written to: #{item_key}"
|
442
|
+
# should print without doing get, because that can use a token.
|
443
|
+
cypher_item = json_response['cypher']
|
444
|
+
get_args = [item_key] + (options[:remote] ? ["-r",options[:remote]] : [])
|
445
|
+
get(get_args)
|
446
|
+
return 0
|
406
447
|
end
|
407
|
-
|
448
|
+
|
408
449
|
def remove(args)
|
409
450
|
options = {}
|
410
451
|
params = {}
|
@@ -412,7 +453,7 @@ class Morpheus::Cli::CypherCommand
|
|
412
453
|
opts.banner = subcommand_usage("[key]")
|
413
454
|
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
|
414
455
|
opts.footer = "Delete a cypher." + "\n" +
|
415
|
-
"[key] is required. This is the key
|
456
|
+
"[key] is required. This is the cypher key to be deleted."
|
416
457
|
end
|
417
458
|
optparse.parse!(args)
|
418
459
|
|
@@ -478,16 +519,16 @@ key - Generates a Base 64 encoded AES Key of specified bit length in the key pat
|
|
478
519
|
|
479
520
|
def cypher_ttl_help
|
480
521
|
"""
|
481
|
-
|
522
|
+
TTL in seconds
|
482
523
|
Quick Second Time Reference:
|
483
524
|
Hour: 3600
|
484
525
|
Day: 86400
|
485
526
|
Week: 604800
|
486
527
|
Month (30 days): 2592000
|
487
528
|
Year: 31536000
|
488
|
-
|
489
|
-
This can be passed
|
490
|
-
The default is
|
529
|
+
Unlimited: 0
|
530
|
+
This can be passed in abbreviated duration format. eg. 32d, 90s, 5y
|
531
|
+
The default is 0, meaning Unlimited.
|
491
532
|
"""
|
492
533
|
end
|
493
534
|
|