morpheus-cli 4.2.20 → 5.0.2
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 +26 -0
- data/lib/morpheus/api/billing_interface.rb +34 -0
- data/lib/morpheus/api/catalog_item_types_interface.rb +9 -0
- data/lib/morpheus/api/deploy_interface.rb +1 -1
- data/lib/morpheus/api/deployments_interface.rb +20 -1
- data/lib/morpheus/api/forgot_password_interface.rb +17 -0
- data/lib/morpheus/api/instances_interface.rb +7 -0
- data/lib/morpheus/api/rest_interface.rb +0 -6
- data/lib/morpheus/api/roles_interface.rb +14 -0
- data/lib/morpheus/api/search_interface.rb +13 -0
- data/lib/morpheus/api/servers_interface.rb +7 -0
- data/lib/morpheus/api/usage_interface.rb +18 -0
- data/lib/morpheus/cli.rb +6 -3
- data/lib/morpheus/cli/apps.rb +3 -4
- data/lib/morpheus/cli/backup_jobs_command.rb +3 -0
- data/lib/morpheus/cli/backups_command.rb +3 -0
- data/lib/morpheus/cli/budgets_command.rb +4 -4
- data/lib/morpheus/cli/catalog_command.rb +507 -0
- data/lib/morpheus/cli/cli_command.rb +45 -20
- data/lib/morpheus/cli/commands/standard/curl_command.rb +26 -12
- data/lib/morpheus/cli/commands/standard/history_command.rb +3 -1
- data/lib/morpheus/cli/commands/standard/man_command.rb +74 -40
- data/lib/morpheus/cli/commands/standard/source_command.rb +1 -1
- data/lib/morpheus/cli/commands/standard/update_command.rb +76 -0
- data/lib/morpheus/cli/containers_command.rb +14 -0
- data/lib/morpheus/cli/deploy.rb +199 -90
- data/lib/morpheus/cli/deployments.rb +342 -29
- data/lib/morpheus/cli/deploys.rb +206 -41
- data/lib/morpheus/cli/error_handler.rb +7 -0
- data/lib/morpheus/cli/forgot_password.rb +133 -0
- data/lib/morpheus/cli/groups.rb +1 -1
- data/lib/morpheus/cli/health_command.rb +2 -2
- data/lib/morpheus/cli/hosts.rb +181 -26
- data/lib/morpheus/cli/instances.rb +102 -33
- data/lib/morpheus/cli/invoices_command.rb +33 -16
- data/lib/morpheus/cli/jobs_command.rb +28 -6
- data/lib/morpheus/cli/library_option_lists_command.rb +14 -6
- data/lib/morpheus/cli/logs_command.rb +9 -6
- data/lib/morpheus/cli/mixins/accounts_helper.rb +7 -6
- data/lib/morpheus/cli/mixins/backups_helper.rb +2 -4
- data/lib/morpheus/cli/mixins/catalog_helper.rb +66 -0
- data/lib/morpheus/cli/mixins/deployments_helper.rb +31 -3
- data/lib/morpheus/cli/mixins/option_source_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/print_helper.rb +46 -21
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +24 -4
- data/lib/morpheus/cli/network_pools_command.rb +14 -6
- data/lib/morpheus/cli/option_types.rb +266 -17
- data/lib/morpheus/cli/ping.rb +0 -1
- data/lib/morpheus/cli/provisioning_licenses_command.rb +2 -2
- data/lib/morpheus/cli/remote.rb +35 -12
- data/lib/morpheus/cli/reports_command.rb +99 -30
- data/lib/morpheus/cli/roles.rb +305 -3
- data/lib/morpheus/cli/search_command.rb +182 -0
- data/lib/morpheus/cli/service_plans_command.rb +2 -2
- data/lib/morpheus/cli/setup.rb +1 -1
- data/lib/morpheus/cli/shell.rb +33 -11
- data/lib/morpheus/cli/storage_providers_command.rb +40 -56
- data/lib/morpheus/cli/tasks.rb +20 -21
- data/lib/morpheus/cli/tenants_command.rb +1 -1
- data/lib/morpheus/cli/usage_command.rb +203 -0
- data/lib/morpheus/cli/user_settings_command.rb +1 -0
- data/lib/morpheus/cli/users.rb +12 -1
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +280 -199
- data/lib/morpheus/cli/whoami.rb +6 -6
- data/lib/morpheus/cli/workflows.rb +34 -41
- data/lib/morpheus/formatters.rb +48 -5
- data/lib/morpheus/terminal.rb +6 -2
- metadata +13 -2
data/lib/morpheus/cli/groups.rb
CHANGED
@@ -52,7 +52,7 @@ class Morpheus::Cli::Groups
|
|
52
52
|
end
|
53
53
|
json_response = @groups_interface.list(params)
|
54
54
|
exit_code, err = 0, nil
|
55
|
-
render_response(json_response, options) do
|
55
|
+
render_response(json_response, options, "groups") do
|
56
56
|
groups = json_response['groups']
|
57
57
|
subtitles = []
|
58
58
|
subtitles += parse_list_subtitles(options)
|
@@ -475,8 +475,8 @@ class Morpheus::Cli::HealthCommand
|
|
475
475
|
opts.footer = "List health logs. These are the logs of the morpheus appliance itself."
|
476
476
|
end
|
477
477
|
optparse.parse!(args)
|
478
|
-
if args.count
|
479
|
-
|
478
|
+
if args.count > 0
|
479
|
+
options[:phrase] = args.join(" ")
|
480
480
|
end
|
481
481
|
connect(options)
|
482
482
|
begin
|
data/lib/morpheus/cli/hosts.rb
CHANGED
@@ -16,10 +16,11 @@ class Morpheus::Cli::Hosts
|
|
16
16
|
include Morpheus::Cli::LogsHelper
|
17
17
|
set_command_name :hosts
|
18
18
|
set_command_description "View and manage hosts (servers)."
|
19
|
-
register_subcommands :list, :count, :get, :view, :stats, :add, :update, :remove, :logs, :start, :stop, :resize,
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
register_subcommands :list, :count, :get, :view, :stats, :add, :update, :remove, :logs, :start, :stop, :resize,
|
20
|
+
:run_workflow, :make_managed, :upgrade_agent, :snapshots,
|
21
|
+
{:'types' => :list_types},
|
22
|
+
{:exec => :execution_request},
|
23
|
+
:wiki, :update_wiki
|
23
24
|
alias_subcommand :details, :get
|
24
25
|
set_default_subcommand :list
|
25
26
|
|
@@ -108,17 +109,29 @@ class Morpheus::Cli::Hosts
|
|
108
109
|
opts.on('--details', "Display more details: memory and storage usage used / max values." ) do
|
109
110
|
options[:details] = true
|
110
111
|
end
|
112
|
+
opts.on('--tags Name=Value',String, "Filter by tags.") do |val|
|
113
|
+
val.split(",").each do |value_pair|
|
114
|
+
k,v = value_pair.strip.split("=")
|
115
|
+
options[:tags] ||= {}
|
116
|
+
options[:tags][k] ||= []
|
117
|
+
options[:tags][k] << (v || '')
|
118
|
+
end
|
119
|
+
end
|
111
120
|
opts.on('--tag-compliant', "Displays only servers that are valid according to applied tag policies. Does not show servers that do not have tag policies." ) do
|
112
121
|
params[:tagCompliant] = true
|
113
122
|
end
|
114
123
|
opts.on('--non-tag-compliant', "Displays only servers with tag compliance warnings." ) do
|
115
124
|
params[:tagCompliant] = false
|
116
125
|
end
|
117
|
-
|
126
|
+
build_standard_list_options(opts, options)
|
118
127
|
opts.footer = "List hosts."
|
119
128
|
end
|
120
129
|
optparse.parse!(args)
|
121
130
|
connect(options)
|
131
|
+
# verify_args!(args:args, optparse:optparse, count:0)
|
132
|
+
if args.count > 0
|
133
|
+
options[:phrase] = args.join(" ")
|
134
|
+
end
|
122
135
|
begin
|
123
136
|
params.merge!(parse_list_options(options))
|
124
137
|
account = nil
|
@@ -159,6 +172,11 @@ class Morpheus::Cli::Hosts
|
|
159
172
|
params['clusterId'] = cluster['id']
|
160
173
|
end
|
161
174
|
end
|
175
|
+
if options[:tags] && !options[:tags].empty?
|
176
|
+
options[:tags].each do |k,v|
|
177
|
+
params['tags.' + k] = v
|
178
|
+
end
|
179
|
+
end
|
162
180
|
|
163
181
|
@servers_interface.setopts(options)
|
164
182
|
if options[:dry_run]
|
@@ -240,31 +258,66 @@ class Morpheus::Cli::Hosts
|
|
240
258
|
end
|
241
259
|
row = {
|
242
260
|
id: server['id'],
|
243
|
-
tenant: server['account'] ? server['account']['name'] : server['accountId'],
|
244
261
|
name: server['name'],
|
262
|
+
hostname: server['hostname'],
|
245
263
|
platform: server['serverOs'] ? server['serverOs']['name'].upcase : 'N/A',
|
246
|
-
cloud: server['zone'] ? server['zone']['name'] : '',
|
247
264
|
type: server['computeServerType'] ? server['computeServerType']['name'] : 'unmanaged',
|
265
|
+
tenant: server['account'] ? server['account']['name'] : server['accountId'],
|
266
|
+
owner: server['owner'] ? server['owner']['username'] : server['owner'],
|
267
|
+
cloud: server['zone'] ? server['zone']['name'] : '',
|
268
|
+
ip: server['externalIp'],
|
269
|
+
internal_ip: server['internalIp'],
|
248
270
|
nodes: server['containers'] ? server['containers'].size : '',
|
249
|
-
status: format_server_status(server, cyan),
|
271
|
+
# status: format_server_status(server, cyan),
|
272
|
+
status: (options[:details]||options[:all_fields]) ? format_server_status(server, cyan) : format_server_status_friendly(server, cyan),
|
250
273
|
power: format_server_power_state(server, cyan),
|
251
274
|
cpu: cpu_usage_str + cyan,
|
252
275
|
memory: memory_usage_str + cyan,
|
253
|
-
storage: storage_usage_str + cyan
|
276
|
+
storage: storage_usage_str + cyan,
|
277
|
+
created: format_local_dt(server['dateCreated']),
|
278
|
+
updated: format_local_dt(server['lastUpdated']),
|
254
279
|
}
|
255
280
|
row
|
256
281
|
}
|
257
|
-
columns = [:id, :name, :type, :cloud, :nodes, :status, :power]
|
258
|
-
|
259
|
-
|
282
|
+
# columns = [:id, :name, :type, :cloud, :ip, :internal_ip, :nodes, :status, :power]
|
283
|
+
columns = {
|
284
|
+
"ID" => :id,
|
285
|
+
"Name" => :name,
|
286
|
+
"Hostname" => :hostname,
|
287
|
+
"Type" => :type,
|
288
|
+
"Owner" => :owner,
|
289
|
+
"Tenant" => :tenant,
|
290
|
+
"Cloud" => :cloud,
|
291
|
+
"IP" => :ip,
|
292
|
+
"Private IP" => :internal_ip,
|
293
|
+
"Nodes" => :nodes,
|
294
|
+
"Status" => :status,
|
295
|
+
"Power" => :power,
|
296
|
+
"CPU" => :cpu,
|
297
|
+
"Memory" => :memory,
|
298
|
+
"Storage" => :storage,
|
299
|
+
"Created" => :created,
|
300
|
+
"Updated" => :updated,
|
301
|
+
}
|
302
|
+
if options[:details] != true
|
303
|
+
columns.delete("Hostname")
|
304
|
+
columns.delete("Private IP")
|
305
|
+
columns.delete("Owner")
|
306
|
+
columns.delete("Tenant")
|
307
|
+
columns.delete("Power")
|
308
|
+
columns.delete("Created")
|
309
|
+
columns.delete("Updated")
|
260
310
|
end
|
261
|
-
|
262
|
-
|
263
|
-
if options[:include_fields]
|
264
|
-
columns = options[:include_fields]
|
311
|
+
if !multi_tenant
|
312
|
+
columns.delete("Tenant")
|
265
313
|
end
|
314
|
+
# columns += [:cpu, :memory, :storage]
|
315
|
+
# # custom pretty table columns ...
|
316
|
+
# if options[:include_fields]
|
317
|
+
# columns = options[:include_fields]
|
318
|
+
# end
|
266
319
|
print cyan
|
267
|
-
print as_pretty_table(rows, columns
|
320
|
+
print as_pretty_table(rows, columns.upcase_keys!, options)
|
268
321
|
print reset
|
269
322
|
print_results_pagination(json_response)
|
270
323
|
end
|
@@ -392,6 +445,9 @@ class Morpheus::Cli::Hosts
|
|
392
445
|
options = {}
|
393
446
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
394
447
|
opts.banner = subcommand_usage("[name]")
|
448
|
+
opts.on( nil, '--costs', "Display Cost and Price" ) do
|
449
|
+
options[:include_costs] = true
|
450
|
+
end
|
395
451
|
opts.on('--refresh [SECONDS]', String, "Refresh until status is provisioned,failed. Default interval is #{default_refresh_interval} seconds.") do |val|
|
396
452
|
options[:refresh_until_status] ||= "provisioned,failed"
|
397
453
|
if !val.to_s.empty?
|
@@ -453,22 +509,37 @@ class Morpheus::Cli::Hosts
|
|
453
509
|
title = "Host Details"
|
454
510
|
print_h1 title, [], options
|
455
511
|
print cyan
|
456
|
-
|
512
|
+
server_columns = {
|
457
513
|
"ID" => 'id',
|
458
514
|
"Name" => 'name',
|
515
|
+
"Hostname" => 'hostname',
|
459
516
|
"Description" => 'description',
|
460
|
-
"
|
517
|
+
"Owner" => lambda {|it| it['owner'] ? it['owner']['username'] : '' },
|
518
|
+
"Tenant" => lambda {|it| it['account'] ? it['account']['name'] : '' },
|
461
519
|
#"Group" => lambda {|it| it['group'] ? it['group']['name'] : '' },
|
462
520
|
"Cloud" => lambda {|it| it['zone'] ? it['zone']['name'] : '' },
|
521
|
+
"IP" => lambda {|it| it['externalIp'] },
|
522
|
+
"Private IP" => lambda {|it| it['internalIp'] },
|
463
523
|
"Type" => lambda {|it| it['computeServerType'] ? it['computeServerType']['name'] : 'unmanaged' },
|
464
524
|
"Platform" => lambda {|it| it['serverOs'] ? it['serverOs']['name'].upcase : 'N/A' },
|
465
525
|
"Plan" => lambda {|it| it['plan'] ? it['plan']['name'] : '' },
|
526
|
+
"Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
527
|
+
"Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
466
528
|
"Agent" => lambda {|it| it['agentInstalled'] ? "#{server['agentVersion'] || ''} updated at #{format_local_dt(server['lastAgentUpdate'])}" : '(not installed)' },
|
467
|
-
"Status" => lambda {|it| format_server_status(it) },
|
468
529
|
"Nodes" => lambda {|it| it['containers'] ? it['containers'].size : 0 },
|
469
|
-
"
|
470
|
-
|
471
|
-
|
530
|
+
# "Status" => lambda {|it| format_server_status(it) },
|
531
|
+
# "Power" => lambda {|it| format_server_power_state(it) },
|
532
|
+
"Status" => lambda {|it| format_server_status_friendly(it) }, # combo
|
533
|
+
}
|
534
|
+
server_columns.delete("Hostname") if server['hostname'].to_s.empty? || server['hostname'] == server['name']
|
535
|
+
server_columns.delete("IP") if server['externalIp'].to_s.empty?
|
536
|
+
server_columns.delete("Private IP") if server['internalIp'].to_s.empty?
|
537
|
+
# server_columns.delete("Tenant") if multi_tenant != true
|
538
|
+
server_columns.delete("Cost") if server['hourlyCost'].to_f == 0
|
539
|
+
server_columns.delete("Price") if server['hourlyPrice'].to_f == 0 || server['hourlyPrice'] == server['hourlyCost']
|
540
|
+
|
541
|
+
print_description_list(server_columns, server)
|
542
|
+
|
472
543
|
if server['statusMessage']
|
473
544
|
print_h2 "Status Message", options
|
474
545
|
if server['status'] == 'failed'
|
@@ -485,6 +556,16 @@ class Morpheus::Cli::Hosts
|
|
485
556
|
|
486
557
|
print_h2 "Host Usage", options
|
487
558
|
print_stats_usage(stats)
|
559
|
+
|
560
|
+
if options[:include_costs]
|
561
|
+
print_h2 "Host Cost"
|
562
|
+
cost_columns = {
|
563
|
+
"Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
564
|
+
"Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
565
|
+
}
|
566
|
+
print_description_list(cost_columns, server)
|
567
|
+
end
|
568
|
+
|
488
569
|
print reset, "\n"
|
489
570
|
|
490
571
|
|
@@ -1781,6 +1862,53 @@ class Morpheus::Cli::Hosts
|
|
1781
1862
|
end
|
1782
1863
|
end
|
1783
1864
|
|
1865
|
+
def snapshots(args)
|
1866
|
+
options = {}
|
1867
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1868
|
+
opts.banner = subcommand_usage("[host]")
|
1869
|
+
# no pagination yet
|
1870
|
+
# build_standard_list_options(opts, options)
|
1871
|
+
build_standard_get_options(opts, options)
|
1872
|
+
end
|
1873
|
+
optparse.parse!(args)
|
1874
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
1875
|
+
connect(options)
|
1876
|
+
begin
|
1877
|
+
server = find_host_by_name_or_id(args[0])
|
1878
|
+
return 1 if server.nil?
|
1879
|
+
params = {}
|
1880
|
+
@servers_interface.setopts(options)
|
1881
|
+
if options[:dry_run]
|
1882
|
+
print_dry_run @servers_interface.dry.snapshots(server['id'], params)
|
1883
|
+
return
|
1884
|
+
end
|
1885
|
+
json_response = @servers_interface.snapshots(server['id'], params)
|
1886
|
+
snapshots = json_response['snapshots']
|
1887
|
+
render_response(json_response, options, 'snapshots') do
|
1888
|
+
print_h1 "Snapshots: #{server['name']}", [], options
|
1889
|
+
if snapshots.empty?
|
1890
|
+
print cyan,"No snapshots found",reset,"\n"
|
1891
|
+
else
|
1892
|
+
snapshot_column_definitions = {
|
1893
|
+
"ID" => lambda {|it| it['id'] },
|
1894
|
+
"Name" => lambda {|it| it['name'] },
|
1895
|
+
"Description" => lambda {|it| it['snapshotType'] ? (it['snapshotType']['name'] || it['snapshotType']['code']) : '' },
|
1896
|
+
"Date Created" => lambda {|it| format_local_dt(it['snapshotCreated']) },
|
1897
|
+
"Status" => lambda {|it| format_snapshot_status(it) }
|
1898
|
+
}
|
1899
|
+
print cyan
|
1900
|
+
print as_pretty_table(snapshots, snapshot_column_definitions.upcase_keys!, options)
|
1901
|
+
print_results_pagination({size: snapshots.size, total: snapshots.size})
|
1902
|
+
end
|
1903
|
+
print reset, "\n"
|
1904
|
+
end
|
1905
|
+
return 0
|
1906
|
+
rescue RestClient::Exception => e
|
1907
|
+
print_rest_exception(e, options)
|
1908
|
+
exit 1
|
1909
|
+
end
|
1910
|
+
end
|
1911
|
+
|
1784
1912
|
private
|
1785
1913
|
|
1786
1914
|
def find_host_by_id(id)
|
@@ -1897,11 +2025,38 @@ class Morpheus::Cli::Hosts
|
|
1897
2025
|
|
1898
2026
|
def format_server_status(server, return_color=cyan)
|
1899
2027
|
out = ""
|
1900
|
-
status_string = server['status']
|
1901
|
-
|
1902
|
-
|
2028
|
+
status_string = server['status'].to_s.downcase
|
2029
|
+
if status_string == 'provisioned'
|
2030
|
+
out = "#{cyan}#{status_string.upcase}#{return_color}"
|
2031
|
+
elsif status_string == 'provisioning'
|
2032
|
+
out = "#{cyan}#{status_string.upcase}#{cyan}"
|
2033
|
+
elsif status_string == 'failed' or status_string == 'error'
|
2034
|
+
out = "#{red}#{status_string.upcase}#{return_color}"
|
2035
|
+
else
|
2036
|
+
out = "#{yellow}#{status_string.upcase}#{return_color}"
|
2037
|
+
end
|
2038
|
+
out
|
2039
|
+
end
|
2040
|
+
|
2041
|
+
def format_server_status_friendly(server, return_color=cyan)
|
2042
|
+
out = ""
|
2043
|
+
status_string = server['status'].to_s.downcase
|
2044
|
+
if status_string == 'provisioned'
|
2045
|
+
# out = format_server_power_state(server, return_color)
|
2046
|
+
# make it looks like format_instance_status
|
2047
|
+
if server['powerState'] == 'on'
|
2048
|
+
out << "#{green}RUNNING#{return_color}"
|
2049
|
+
elsif server['powerState'] == 'off'
|
2050
|
+
out << "#{red}STOPPED#{return_color}"
|
2051
|
+
else
|
2052
|
+
out << "#{white}#{server['powerState'].to_s.upcase}#{return_color}"
|
2053
|
+
end
|
2054
|
+
else
|
2055
|
+
out = format_server_status(server, return_color)
|
2056
|
+
end
|
1903
2057
|
out
|
1904
2058
|
end
|
2059
|
+
|
1905
2060
|
|
1906
2061
|
def make_managed_option_types(connected=true)
|
1907
2062
|
[
|
@@ -19,7 +19,7 @@ class Morpheus::Cli::Instances
|
|
19
19
|
:history, {:'history-details' => :history_details}, {:'history-event' => :history_event_details},
|
20
20
|
:stats, :stop, :start, :restart, :actions, :action, :suspend, :eject, :stop_service, :start_service, :restart_service,
|
21
21
|
:backup, :backups, :resize, :clone, :envs, :setenv, :delenv,
|
22
|
-
:security_groups, :apply_security_groups, :run_workflow, :import_snapshot,
|
22
|
+
:security_groups, :apply_security_groups, :run_workflow, :import_snapshot, :snapshots,
|
23
23
|
:console, :status_check, {:containers => :list_containers},
|
24
24
|
:scaling, {:'scaling-update' => :scaling_update},
|
25
25
|
:wiki, :update_wiki,
|
@@ -92,11 +92,28 @@ class Morpheus::Cli::Instances
|
|
92
92
|
opts.on('--pending-removal-only', "Only instances pending removal.") do
|
93
93
|
options[:deleted] = true
|
94
94
|
end
|
95
|
+
opts.on('--labels label',String, "Filter by labels (keywords).") do |val|
|
96
|
+
val.split(",").each do |k|
|
97
|
+
options[:labels] ||= []
|
98
|
+
options[:labels] << k.strip
|
99
|
+
end
|
100
|
+
end
|
101
|
+
opts.on('--tags Name=Value',String, "Filter by tags (metadata name value pairs).") do |val|
|
102
|
+
val.split(",").each do |value_pair|
|
103
|
+
k,v = value_pair.strip.split("=")
|
104
|
+
options[:tags] ||= {}
|
105
|
+
options[:tags][k] ||= []
|
106
|
+
options[:tags][k] << (v || '')
|
107
|
+
end
|
108
|
+
end
|
95
109
|
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
96
110
|
opts.footer = "List instances."
|
97
111
|
end
|
98
112
|
optparse.parse!(args)
|
99
|
-
verify_args!(args:args,
|
113
|
+
# verify_args!(args:args, optparse:optparse, count:0)
|
114
|
+
if args.count > 0
|
115
|
+
options[:phrase] = args.join(" ")
|
116
|
+
end
|
100
117
|
connect(options)
|
101
118
|
begin
|
102
119
|
params.merge!(parse_list_options(options))
|
@@ -129,7 +146,13 @@ class Morpheus::Cli::Instances
|
|
129
146
|
|
130
147
|
params['showDeleted'] = true if options[:showDeleted]
|
131
148
|
params['deleted'] = true if options[:deleted]
|
132
|
-
|
149
|
+
params['labels'] = options[:labels] if options[:labels]
|
150
|
+
if options[:tags]
|
151
|
+
options[:tags].each do |k,v|
|
152
|
+
params['tags.' + k] = v
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
133
156
|
@instances_interface.setopts(options)
|
134
157
|
if options[:dry_run]
|
135
158
|
print_dry_run @instances_interface.dry.list(params)
|
@@ -344,18 +367,16 @@ class Morpheus::Cli::Instances
|
|
344
367
|
opts.on("--environment ENV", String, "Environment code") do |val|
|
345
368
|
options[:environment] = val.to_s
|
346
369
|
end
|
347
|
-
opts.on('--
|
370
|
+
opts.on('--tags LIST', String, "Metadata tags in the format 'ping=pong,flash=bang'") do |val|
|
348
371
|
options[:metadata] = val
|
349
372
|
end
|
350
|
-
opts.on('--
|
351
|
-
|
352
|
-
options[:tags] = val.split(',').collect {|it| it.to_s.strip }.compact.uniq.join(',')
|
373
|
+
opts.on('--metadata LIST', String, "Metadata tags in the format 'ping=pong,flash=bang'") do |val|
|
374
|
+
options[:metadata] = val
|
353
375
|
end
|
354
|
-
opts.
|
355
|
-
|
356
|
-
options[:
|
376
|
+
opts.add_hidden_option('--metadata')
|
377
|
+
opts.on('--labels LIST', String, "Labels (keywords) in the format 'foo, bar'") do |val|
|
378
|
+
options[:labels] = val.split(',').collect {|it| it.to_s.strip }.compact.uniq.join(',')
|
357
379
|
end
|
358
|
-
opts.add_hidden_option('--tags')
|
359
380
|
opts.on("--copies NUMBER", Integer, "Number of copies to provision") do |val|
|
360
381
|
options[:copies] = val.to_i
|
361
382
|
end
|
@@ -525,18 +546,17 @@ class Morpheus::Cli::Instances
|
|
525
546
|
opts.on('--group GROUP', String, "Group Name or ID") do |val|
|
526
547
|
options[:group] = val
|
527
548
|
end
|
528
|
-
opts.on('--
|
549
|
+
opts.on('--tags LIST', String, "Metadata tags in the format 'ping=pong,flash=bang'") do |val|
|
529
550
|
options[:metadata] = val
|
530
551
|
end
|
531
|
-
opts.on('--
|
532
|
-
|
533
|
-
params['tags'] = val.split(',').collect {|it| it.to_s.strip }.compact.uniq.join(',')
|
552
|
+
opts.on('--metadata LIST', String, "Metadata tags in the format 'ping=pong,flash=bang'") do |val|
|
553
|
+
options[:metadata] = val
|
534
554
|
end
|
535
|
-
opts.
|
536
|
-
|
555
|
+
opts.add_hidden_option('--metadata')
|
556
|
+
opts.on('--labels LIST', String, "Labels (keywords) in the format 'foo, bar'") do |val|
|
557
|
+
# todo switch this from 'tags' to 'labels'
|
537
558
|
params['tags'] = val.split(',').collect {|it| it.to_s.strip }.compact.uniq.join(',')
|
538
559
|
end
|
539
|
-
opts.add_hidden_option('--tags')
|
540
560
|
opts.on('--power-schedule-type ID', String, "Power Schedule Type ID") do |val|
|
541
561
|
params['powerScheduleType'] = val == "null" ? nil : val
|
542
562
|
end
|
@@ -607,6 +627,9 @@ class Morpheus::Cli::Instances
|
|
607
627
|
metadata_list = options[:metadata].split(",").select {|it| !it.to_s.empty? }
|
608
628
|
metadata_list = metadata_list.collect do |it|
|
609
629
|
metadata_pair = it.split(":")
|
630
|
+
if metadata_pair.size == 1 && it.include?("=")
|
631
|
+
metadata_pair = it.split("=")
|
632
|
+
end
|
610
633
|
row = {}
|
611
634
|
row['name'] = metadata_pair[0].to_s.strip
|
612
635
|
row['value'] = metadata_pair[1].to_s.strip
|
@@ -1148,6 +1171,9 @@ class Morpheus::Cli::Instances
|
|
1148
1171
|
opts.on( nil, '--scaling', "Display Instance Scaling Settings" ) do
|
1149
1172
|
options[:include_scaling] = true
|
1150
1173
|
end
|
1174
|
+
opts.on( nil, '--costs', "Display Cost and Price" ) do
|
1175
|
+
options[:include_costs] = true
|
1176
|
+
end
|
1151
1177
|
opts.on('--refresh [SECONDS]', String, "Refresh until status is running,failed. Default interval is #{default_refresh_interval} seconds.") do |val|
|
1152
1178
|
options[:refresh_until_status] ||= "running,failed"
|
1153
1179
|
if !val.to_s.empty?
|
@@ -1249,6 +1275,8 @@ class Morpheus::Cli::Instances
|
|
1249
1275
|
"Layout" => lambda {|it| it['layout'] ? it['layout']['name'] : '' },
|
1250
1276
|
"Version" => lambda {|it| it['instanceVersion'] },
|
1251
1277
|
"Plan" => lambda {|it| it['plan'] ? it['plan']['name'] : '' },
|
1278
|
+
# "Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
1279
|
+
# "Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
1252
1280
|
"Environment" => 'instanceContext',
|
1253
1281
|
"Labels" => lambda {|it| it['tags'] ? it['tags'].join(',') : '' },
|
1254
1282
|
"Metadata" => lambda {|it| it['metadata'] ? it['metadata'].collect {|m| "#{m['name']}: #{m['value']}" }.join(', ') : '' },
|
@@ -1304,6 +1332,16 @@ class Morpheus::Cli::Instances
|
|
1304
1332
|
print_h2 "Instance Usage", options
|
1305
1333
|
print_stats_usage(stats)
|
1306
1334
|
end
|
1335
|
+
|
1336
|
+
if options[:include_costs]
|
1337
|
+
print_h2 "Instance Cost"
|
1338
|
+
cost_columns = {
|
1339
|
+
"Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
1340
|
+
"Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
1341
|
+
}
|
1342
|
+
print_description_list(cost_columns, instance)
|
1343
|
+
end
|
1344
|
+
|
1307
1345
|
print reset, "\n"
|
1308
1346
|
|
1309
1347
|
# if options[:include_lb]
|
@@ -2880,6 +2918,52 @@ class Morpheus::Cli::Instances
|
|
2880
2918
|
end
|
2881
2919
|
end
|
2882
2920
|
|
2921
|
+
def snapshots(args)
|
2922
|
+
options = {}
|
2923
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
2924
|
+
opts.banner = subcommand_usage("[instance]")
|
2925
|
+
# no pagination yet
|
2926
|
+
# build_standard_list_options(opts, options)
|
2927
|
+
build_standard_get_options(opts, options)
|
2928
|
+
end
|
2929
|
+
optparse.parse!(args)
|
2930
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
2931
|
+
connect(options)
|
2932
|
+
begin
|
2933
|
+
instance = find_instance_by_name_or_id(args[0])
|
2934
|
+
params = {}
|
2935
|
+
@instances_interface.setopts(options)
|
2936
|
+
if options[:dry_run]
|
2937
|
+
print_dry_run @instances_interface.dry.snapshots(instance['id'], params)
|
2938
|
+
return
|
2939
|
+
end
|
2940
|
+
json_response = @instances_interface.snapshots(instance['id'], params)
|
2941
|
+
snapshots = json_response['snapshots']
|
2942
|
+
render_response(json_response, options, 'snapshots') do
|
2943
|
+
print_h1 "Snapshots: #{instance['name']} (#{instance['instanceType']['name']})", [], options
|
2944
|
+
if snapshots.empty?
|
2945
|
+
print cyan,"No snapshots found",reset,"\n"
|
2946
|
+
else
|
2947
|
+
snapshot_column_definitions = {
|
2948
|
+
"ID" => lambda {|it| it['id'] },
|
2949
|
+
"Name" => lambda {|it| it['name'] },
|
2950
|
+
"Description" => lambda {|it| it['snapshotType'] ? (it['snapshotType']['name'] || it['snapshotType']['code']) : '' },
|
2951
|
+
"Date Created" => lambda {|it| format_local_dt(it['snapshotCreated']) },
|
2952
|
+
"Status" => lambda {|it| format_snapshot_status(it) }
|
2953
|
+
}
|
2954
|
+
print cyan
|
2955
|
+
print as_pretty_table(snapshots, snapshot_column_definitions.upcase_keys!, options)
|
2956
|
+
print_results_pagination({size: snapshots.size, total: snapshots.size})
|
2957
|
+
end
|
2958
|
+
print reset, "\n"
|
2959
|
+
end
|
2960
|
+
return 0
|
2961
|
+
rescue RestClient::Exception => e
|
2962
|
+
print_rest_exception(e, options)
|
2963
|
+
exit 1
|
2964
|
+
end
|
2965
|
+
end
|
2966
|
+
|
2883
2967
|
def import_snapshot(args)
|
2884
2968
|
options = {}
|
2885
2969
|
query_params = {}
|
@@ -4006,19 +4090,4 @@ private
|
|
4006
4090
|
}
|
4007
4091
|
end
|
4008
4092
|
|
4009
|
-
def format_app_deploy_status(status, return_color=cyan)
|
4010
|
-
out = ""
|
4011
|
-
s = status.to_s.downcase
|
4012
|
-
if s == 'deployed'
|
4013
|
-
out << "#{green}#{s.upcase}#{return_color}"
|
4014
|
-
elsif s == 'open' || s == 'archived' || s == 'committed'
|
4015
|
-
out << "#{cyan}#{s.upcase}#{return_color}"
|
4016
|
-
elsif s == 'failed'
|
4017
|
-
out << "#{red}#{s.upcase}#{return_color}"
|
4018
|
-
else
|
4019
|
-
out << "#{yellow}#{s.upcase}#{return_color}"
|
4020
|
-
end
|
4021
|
-
out
|
4022
|
-
end
|
4023
|
-
|
4024
4093
|
end
|