morpheus-cli 4.1.8 → 4.1.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|