morpheus-cli 5.0.1 → 5.2.3
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/.gitignore +1 -0
- data/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +4 -0
- data/lib/morpheus/api/instances_interface.rb +9 -2
- data/lib/morpheus/api/invoices_interface.rb +12 -3
- data/lib/morpheus/api/servers_interface.rb +7 -0
- data/lib/morpheus/api/service_catalog_interface.rb +89 -0
- data/lib/morpheus/cli.rb +2 -1
- data/lib/morpheus/cli/apps.rb +3 -23
- data/lib/morpheus/cli/budgets_command.rb +389 -319
- data/lib/morpheus/cli/{catalog_command.rb → catalog_item_types_command.rb} +182 -67
- data/lib/morpheus/cli/cli_command.rb +25 -1
- data/lib/morpheus/cli/commands/standard/curl_command.rb +25 -10
- data/lib/morpheus/cli/commands/standard/history_command.rb +6 -2
- data/lib/morpheus/cli/containers_command.rb +0 -24
- data/lib/morpheus/cli/cypher_command.rb +6 -2
- data/lib/morpheus/cli/dashboard_command.rb +260 -20
- data/lib/morpheus/cli/groups.rb +1 -1
- data/lib/morpheus/cli/health_command.rb +57 -0
- data/lib/morpheus/cli/hosts.rb +111 -16
- data/lib/morpheus/cli/instances.rb +156 -108
- data/lib/morpheus/cli/invoices_command.rb +67 -4
- data/lib/morpheus/cli/jobs_command.rb +94 -92
- data/lib/morpheus/cli/library_option_lists_command.rb +1 -1
- data/lib/morpheus/cli/library_option_types_command.rb +10 -5
- data/lib/morpheus/cli/mixins/accounts_helper.rb +5 -1
- data/lib/morpheus/cli/mixins/print_helper.rb +13 -6
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +88 -5
- data/lib/morpheus/cli/option_types.rb +10 -10
- data/lib/morpheus/cli/projects_command.rb +1 -1
- data/lib/morpheus/cli/roles.rb +193 -155
- data/lib/morpheus/cli/service_catalog_command.rb +1474 -0
- data/lib/morpheus/cli/tasks.rb +9 -11
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +162 -68
- data/lib/morpheus/formatters.rb +55 -20
- metadata +5 -4
- data/lib/morpheus/cli/mixins/catalog_helper.rb +0 -66
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)
|
|
@@ -30,6 +30,7 @@ class Morpheus::Cli::HealthCommand
|
|
|
30
30
|
opts.on('-a', '--all', "Display all details: CPU, Memory, Database, etc." ) do
|
|
31
31
|
options[:details] = true
|
|
32
32
|
options[:show_cpu] = true
|
|
33
|
+
options[:show_threads] = true
|
|
33
34
|
options[:show_memory] = true
|
|
34
35
|
options[:show_database] = true
|
|
35
36
|
options[:show_elastic] = true
|
|
@@ -47,6 +48,9 @@ class Morpheus::Cli::HealthCommand
|
|
|
47
48
|
opts.on('--cpu', "Display CPU details" ) do
|
|
48
49
|
options[:show_cpu] = true
|
|
49
50
|
end
|
|
51
|
+
opts.on('--threads', "Display Thread details" ) do
|
|
52
|
+
options[:show_threads] = true
|
|
53
|
+
end
|
|
50
54
|
opts.on('--memory', "Display Memory details" ) do
|
|
51
55
|
options[:show_memory] = true
|
|
52
56
|
end
|
|
@@ -184,6 +188,59 @@ class Morpheus::Cli::HealthCommand
|
|
|
184
188
|
end
|
|
185
189
|
end
|
|
186
190
|
|
|
191
|
+
# Threads ()
|
|
192
|
+
if options[:show_threads]
|
|
193
|
+
print_h2 "Threads", options
|
|
194
|
+
if health['threads'].nil?
|
|
195
|
+
print yellow,"No thread information returned.",reset,"\n\n"
|
|
196
|
+
else
|
|
197
|
+
print cyan
|
|
198
|
+
|
|
199
|
+
thread_summary_columns = {
|
|
200
|
+
"Thread Count" => lambda {|it| it['totalThreads'].size rescue '' },
|
|
201
|
+
"Busy Threads" => lambda {|it| it['busyThreads'].size rescue '' },
|
|
202
|
+
"Running Threads" => lambda {|it| it['runningThreads'].size rescue '' },
|
|
203
|
+
"Blocked Threads" => lambda {|it| it['blockedThreads'].size rescue '' },
|
|
204
|
+
}
|
|
205
|
+
print_description_list(thread_summary_columns, health['threads'], options)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
thread_columns = [
|
|
209
|
+
{"Name".upcase => lambda {|it| it['name']} },
|
|
210
|
+
{"Status".upcase => lambda {|it|
|
|
211
|
+
# hrmm
|
|
212
|
+
status_string = (it['status'] || it['state']).to_s.downcase
|
|
213
|
+
status_color = cyan
|
|
214
|
+
# if status_string.include?('waiting')
|
|
215
|
+
# status_color = yellow
|
|
216
|
+
# end
|
|
217
|
+
"#{status_color}#{status_string.upcase}#{cyan}"
|
|
218
|
+
} },
|
|
219
|
+
# {"CPU Time" => lambda {|it| it['cpuTime'].to_s } },
|
|
220
|
+
# {"CPU Time" => lambda {|it| format_human_duration(it['cpuTime'].to_f / 1000) rescue '' } },
|
|
221
|
+
{"CPU Percent" => lambda {|it| it['cpuPercent'].to_i.to_s + '%' } }
|
|
222
|
+
]
|
|
223
|
+
|
|
224
|
+
if health['threads']['busyThreads'] && health['threads']['busyThreads'].size > 0
|
|
225
|
+
print_h2 "Busy Threads"
|
|
226
|
+
print cyan
|
|
227
|
+
print as_pretty_table(health['threads']['busyThreads'], thread_columns, options)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
if health['threads']['runningThreads'] && health['threads']['runningThreads'].size > 0
|
|
231
|
+
print_h2 "Running Threads"
|
|
232
|
+
print cyan
|
|
233
|
+
print as_pretty_table(health['threads']['runningThreads'], thread_columns, options)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
if health['threads']['blockedThreads'] && health['threads']['blockedThreads'].size > 0
|
|
237
|
+
print_h2 "Blocked Threads"
|
|
238
|
+
print cyan
|
|
239
|
+
print as_pretty_table(health['threads']['blockedThreads'], thread_columns, options)
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
187
244
|
# Memory
|
|
188
245
|
if options[:show_memory]
|
|
189
246
|
if health['memory'].nil?
|
data/lib/morpheus/cli/hosts.rb
CHANGED
|
@@ -17,7 +17,7 @@ class Morpheus::Cli::Hosts
|
|
|
17
17
|
set_command_name :hosts
|
|
18
18
|
set_command_description "View and manage hosts (servers)."
|
|
19
19
|
register_subcommands :list, :count, :get, :view, :stats, :add, :update, :remove, :logs, :start, :stop, :resize,
|
|
20
|
-
:run_workflow, :make_managed, :upgrade_agent, :snapshots,
|
|
20
|
+
:run_workflow, :make_managed, :upgrade_agent, :snapshots, :software,
|
|
21
21
|
{:'types' => :list_types},
|
|
22
22
|
{:exec => :execution_request},
|
|
23
23
|
:wiki, :update_wiki
|
|
@@ -54,13 +54,6 @@ class Morpheus::Cli::Hosts
|
|
|
54
54
|
params = {}
|
|
55
55
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
56
56
|
opts.banner = subcommand_usage()
|
|
57
|
-
opts.on('-a', '--all', "Display all details: memory and storage usage used / max values." ) do
|
|
58
|
-
options[:details] = true
|
|
59
|
-
end
|
|
60
|
-
opts.on('--details', "Display all details: alias for --all" ) do
|
|
61
|
-
options[:details] = true
|
|
62
|
-
end
|
|
63
|
-
opts.add_hidden_option('--details')
|
|
64
57
|
opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
|
|
65
58
|
options[:group] = val
|
|
66
59
|
end
|
|
@@ -86,6 +79,17 @@ class Morpheus::Cli::Hosts
|
|
|
86
79
|
# params[:clusterId] = val
|
|
87
80
|
options[:cluster] = val
|
|
88
81
|
end
|
|
82
|
+
opts.on( '--plan NAME', String, "Filter by Plan name(s)" ) do |val|
|
|
83
|
+
# commas used in names a lot so use --plan one --plan two
|
|
84
|
+
params['plan'] ||= []
|
|
85
|
+
params['plan'] << val
|
|
86
|
+
end
|
|
87
|
+
opts.on( '--plan-id ID', String, "Filter by Plan id(s)" ) do |val|
|
|
88
|
+
params['planId'] = parse_id_list(val)
|
|
89
|
+
end
|
|
90
|
+
opts.on( '--plan-code CODE', String, "Filter by Plan code(s)" ) do |val|
|
|
91
|
+
params['planCode'] = parse_id_list(val)
|
|
92
|
+
end
|
|
89
93
|
opts.on( '', '--vm', "Show only virtual machines" ) do |val|
|
|
90
94
|
params[:vm] = true
|
|
91
95
|
end
|
|
@@ -113,9 +117,6 @@ class Morpheus::Cli::Hosts
|
|
|
113
117
|
opts.on( '--tenant TENANT', "Tenant Name or ID" ) do |val|
|
|
114
118
|
options[:account] = val
|
|
115
119
|
end
|
|
116
|
-
opts.on('--details', "Display more details: memory and storage usage used / max values." ) do
|
|
117
|
-
options[:details] = true
|
|
118
|
-
end
|
|
119
120
|
opts.on('--tags Name=Value',String, "Filter by tags.") do |val|
|
|
120
121
|
val.split(",").each do |value_pair|
|
|
121
122
|
k,v = value_pair.strip.split("=")
|
|
@@ -130,6 +131,12 @@ class Morpheus::Cli::Hosts
|
|
|
130
131
|
opts.on('--non-tag-compliant', "Displays only servers with tag compliance warnings." ) do
|
|
131
132
|
params[:tagCompliant] = false
|
|
132
133
|
end
|
|
134
|
+
opts.on('--stats', "Display values for memory and storage usage used / max values." ) do
|
|
135
|
+
options[:stats] = true
|
|
136
|
+
end
|
|
137
|
+
opts.on('-a', '--details', "Display all details: hostname, private ip, plan, stats, etc." ) do
|
|
138
|
+
options[:details] = true
|
|
139
|
+
end
|
|
133
140
|
build_standard_list_options(opts, options)
|
|
134
141
|
opts.footer = "List hosts."
|
|
135
142
|
end
|
|
@@ -258,7 +265,7 @@ class Morpheus::Cli::Hosts
|
|
|
258
265
|
cpu_usage_str = !stats ? "" : generate_usage_bar((stats['usedCpu'] || stats['cpuUsage']).to_f, 100, {max_bars: 10})
|
|
259
266
|
memory_usage_str = !stats ? "" : generate_usage_bar(stats['usedMemory'], stats['maxMemory'], {max_bars: 10})
|
|
260
267
|
storage_usage_str = !stats ? "" : generate_usage_bar(stats['usedStorage'], stats['maxStorage'], {max_bars: 10})
|
|
261
|
-
if options[:details]
|
|
268
|
+
if options[:details] || options[:stats]
|
|
262
269
|
if stats['maxMemory'] && stats['maxMemory'].to_i != 0
|
|
263
270
|
memory_usage_str = memory_usage_str + cyan + format_bytes_short(stats['usedMemory']).strip.rjust(8, ' ') + " / " + format_bytes_short(stats['maxMemory']).strip
|
|
264
271
|
end
|
|
@@ -269,12 +276,14 @@ class Morpheus::Cli::Hosts
|
|
|
269
276
|
row = {
|
|
270
277
|
id: server['id'],
|
|
271
278
|
name: server['name'],
|
|
279
|
+
external_name: server['externalName'],
|
|
272
280
|
hostname: server['hostname'],
|
|
273
281
|
platform: server['serverOs'] ? server['serverOs']['name'].upcase : 'N/A',
|
|
274
282
|
type: server['computeServerType'] ? server['computeServerType']['name'] : 'unmanaged',
|
|
275
283
|
tenant: server['account'] ? server['account']['name'] : server['accountId'],
|
|
276
284
|
owner: server['owner'] ? server['owner']['username'] : server['owner'],
|
|
277
285
|
cloud: server['zone'] ? server['zone']['name'] : '',
|
|
286
|
+
plan: server['plan'] ? server['plan']['name'] : '',
|
|
278
287
|
ip: server['externalIp'],
|
|
279
288
|
internal_ip: server['internalIp'],
|
|
280
289
|
nodes: server['containers'] ? server['containers'].size : '',
|
|
@@ -293,11 +302,13 @@ class Morpheus::Cli::Hosts
|
|
|
293
302
|
columns = {
|
|
294
303
|
"ID" => :id,
|
|
295
304
|
"Name" => :name,
|
|
305
|
+
"External Name" => :external_name,
|
|
296
306
|
"Hostname" => :hostname,
|
|
297
307
|
"Type" => :type,
|
|
298
308
|
"Owner" => :owner,
|
|
299
309
|
"Tenant" => :tenant,
|
|
300
310
|
"Cloud" => :cloud,
|
|
311
|
+
"Plan" => :plan,
|
|
301
312
|
"IP" => :ip,
|
|
302
313
|
"Private IP" => :internal_ip,
|
|
303
314
|
"Nodes" => :nodes,
|
|
@@ -310,7 +321,9 @@ class Morpheus::Cli::Hosts
|
|
|
310
321
|
"Updated" => :updated,
|
|
311
322
|
}
|
|
312
323
|
if options[:details] != true
|
|
324
|
+
columns.delete("External Name")
|
|
313
325
|
columns.delete("Hostname")
|
|
326
|
+
columns.delete("Plan")
|
|
314
327
|
columns.delete("Private IP")
|
|
315
328
|
columns.delete("Owner")
|
|
316
329
|
columns.delete("Tenant")
|
|
@@ -318,6 +331,10 @@ class Morpheus::Cli::Hosts
|
|
|
318
331
|
columns.delete("Created")
|
|
319
332
|
columns.delete("Updated")
|
|
320
333
|
end
|
|
334
|
+
# hide External Name if there are none
|
|
335
|
+
if !servers.find {|it| it['externalName'] && it['externalName'] != it['name']}
|
|
336
|
+
columns.delete("External Name")
|
|
337
|
+
end
|
|
321
338
|
if !multi_tenant
|
|
322
339
|
columns.delete("Tenant")
|
|
323
340
|
end
|
|
@@ -344,7 +361,7 @@ class Morpheus::Cli::Hosts
|
|
|
344
361
|
options = {}
|
|
345
362
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
346
363
|
opts.banner = subcommand_usage("[options]")
|
|
347
|
-
opts.on( '
|
|
364
|
+
opts.on( '--tenant TENANT', "Tenant Name or ID" ) do |val|
|
|
348
365
|
options[:account] = val
|
|
349
366
|
end
|
|
350
367
|
opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
|
|
@@ -513,9 +530,10 @@ class Morpheus::Cli::Hosts
|
|
|
513
530
|
puts records_as_csv([json_response['server']], options)
|
|
514
531
|
return 0
|
|
515
532
|
end
|
|
516
|
-
server = json_response['server']
|
|
533
|
+
server = json_response['server'] || json_response['host'] || {}
|
|
517
534
|
#stats = server['stats'] || json_response['stats'] || {}
|
|
518
535
|
stats = json_response['stats'] || {}
|
|
536
|
+
tags = server['tags'] || server['metadata']
|
|
519
537
|
title = "Host Details"
|
|
520
538
|
print_h1 title, [], options
|
|
521
539
|
print cyan
|
|
@@ -524,6 +542,7 @@ class Morpheus::Cli::Hosts
|
|
|
524
542
|
"Name" => 'name',
|
|
525
543
|
"Hostname" => 'hostname',
|
|
526
544
|
"Description" => 'description',
|
|
545
|
+
"Tags" => lambda {|it| tags ? format_metadata(tags) : '' },
|
|
527
546
|
"Owner" => lambda {|it| it['owner'] ? it['owner']['username'] : '' },
|
|
528
547
|
"Tenant" => lambda {|it| it['account'] ? it['account']['name'] : '' },
|
|
529
548
|
#"Group" => lambda {|it| it['group'] ? it['group']['name'] : '' },
|
|
@@ -547,6 +566,7 @@ class Morpheus::Cli::Hosts
|
|
|
547
566
|
# server_columns.delete("Tenant") if multi_tenant != true
|
|
548
567
|
server_columns.delete("Cost") if server['hourlyCost'].to_f == 0
|
|
549
568
|
server_columns.delete("Price") if server['hourlyPrice'].to_f == 0 || server['hourlyPrice'] == server['hourlyCost']
|
|
569
|
+
server_columns.delete("Tags") if tags.nil? || tags.empty?
|
|
550
570
|
|
|
551
571
|
print_description_list(server_columns, server)
|
|
552
572
|
|
|
@@ -973,6 +993,19 @@ class Morpheus::Cli::Hosts
|
|
|
973
993
|
opts.on('--power-schedule-type ID', String, "Power Schedule Type ID") do |val|
|
|
974
994
|
params['powerScheduleType'] = val == "null" ? nil : val
|
|
975
995
|
end
|
|
996
|
+
opts.on('--tags LIST', String, "Tags in the format 'name:value, name:value'. This will add and remove tags.") do |val|
|
|
997
|
+
options[:tags] = val
|
|
998
|
+
end
|
|
999
|
+
opts.on('--metadata LIST', String, "Alias for --tags.") do |val|
|
|
1000
|
+
options[:tags] = val
|
|
1001
|
+
end
|
|
1002
|
+
opts.add_hidden_option('--metadata')
|
|
1003
|
+
opts.on('--add-tags TAGS', String, "Add Tags in the format 'name:value, name:value'. This will only add/update tags.") do |val|
|
|
1004
|
+
options[:add_tags] = val
|
|
1005
|
+
end
|
|
1006
|
+
opts.on('--remove-tags TAGS', String, "Remove Tags in the format 'name, name:value'. This removes tags, the :value component is optional and must match if passed.") do |val|
|
|
1007
|
+
options[:remove_tags] = val
|
|
1008
|
+
end
|
|
976
1009
|
# opts.on('--created-by ID', String, "Created By User ID") do |val|
|
|
977
1010
|
# params['createdById'] = val
|
|
978
1011
|
# end
|
|
@@ -991,6 +1024,18 @@ class Morpheus::Cli::Hosts
|
|
|
991
1024
|
new_group = nil
|
|
992
1025
|
passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
|
|
993
1026
|
params.deep_merge!(passed_options) unless passed_options.empty?
|
|
1027
|
+
# metadata tags
|
|
1028
|
+
if options[:tags]
|
|
1029
|
+
params['tags'] = parse_metadata(options[:tags])
|
|
1030
|
+
else
|
|
1031
|
+
# params['tags'] = prompt_metadata(options)
|
|
1032
|
+
end
|
|
1033
|
+
if options[:add_tags]
|
|
1034
|
+
params['addTags'] = parse_metadata(options[:add_tags])
|
|
1035
|
+
end
|
|
1036
|
+
if options[:remove_tags]
|
|
1037
|
+
params['removeTags'] = parse_metadata(options[:remove_tags])
|
|
1038
|
+
end
|
|
994
1039
|
payload = nil
|
|
995
1040
|
if options[:payload]
|
|
996
1041
|
payload = options[:payload]
|
|
@@ -1902,7 +1947,8 @@ class Morpheus::Cli::Hosts
|
|
|
1902
1947
|
snapshot_column_definitions = {
|
|
1903
1948
|
"ID" => lambda {|it| it['id'] },
|
|
1904
1949
|
"Name" => lambda {|it| it['name'] },
|
|
1905
|
-
"Description" => lambda {|it| it['
|
|
1950
|
+
"Description" => lambda {|it| it['description'] },
|
|
1951
|
+
# "Type" => lambda {|it| it['snapshotType'] },
|
|
1906
1952
|
"Date Created" => lambda {|it| format_local_dt(it['snapshotCreated']) },
|
|
1907
1953
|
"Status" => lambda {|it| format_snapshot_status(it) }
|
|
1908
1954
|
}
|
|
@@ -1919,6 +1965,55 @@ class Morpheus::Cli::Hosts
|
|
|
1919
1965
|
end
|
|
1920
1966
|
end
|
|
1921
1967
|
|
|
1968
|
+
def software(args)
|
|
1969
|
+
options = {}
|
|
1970
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
1971
|
+
opts.banner = subcommand_usage("[host]")
|
|
1972
|
+
build_standard_list_options(opts, options)
|
|
1973
|
+
end
|
|
1974
|
+
optparse.parse!(args)
|
|
1975
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
1976
|
+
connect(options)
|
|
1977
|
+
begin
|
|
1978
|
+
server = find_host_by_name_or_id(args[0])
|
|
1979
|
+
return 1 if server.nil?
|
|
1980
|
+
params = {}
|
|
1981
|
+
params.merge!(parse_list_options(options))
|
|
1982
|
+
@servers_interface.setopts(options)
|
|
1983
|
+
if options[:dry_run]
|
|
1984
|
+
print_dry_run @servers_interface.dry.software(server['id'], params)
|
|
1985
|
+
return
|
|
1986
|
+
end
|
|
1987
|
+
json_response = @servers_interface.software(server['id'], params)
|
|
1988
|
+
software = json_response['software']
|
|
1989
|
+
render_response(json_response, options, 'software') do
|
|
1990
|
+
print_h1 "Software: #{server['name']}", [], options
|
|
1991
|
+
if software.empty?
|
|
1992
|
+
print cyan,"No software found",reset,"\n"
|
|
1993
|
+
else
|
|
1994
|
+
software_column_definitions = {
|
|
1995
|
+
# "ID" => lambda {|it| it['id'] },
|
|
1996
|
+
"Name" => lambda {|it| it['name'] },
|
|
1997
|
+
"Version" => lambda {|it| it['packageVersion'] },
|
|
1998
|
+
"Publisher" => lambda {|it| it['packagePublisher'] },
|
|
1999
|
+
# "Release" => lambda {|it| it['packageRelease'] },
|
|
2000
|
+
# "Type" => lambda {|it| it['packageType'] },
|
|
2001
|
+
# "Architecture" => lambda {|it| it['architecture'] },
|
|
2002
|
+
# "Install Date" => lambda {|it| format_local_dt(it['installDate']) },
|
|
2003
|
+
}
|
|
2004
|
+
print cyan
|
|
2005
|
+
print as_pretty_table(software, software_column_definitions.upcase_keys!, options)
|
|
2006
|
+
print_results_pagination({size: software.size, total: software.size})
|
|
2007
|
+
end
|
|
2008
|
+
print reset, "\n"
|
|
2009
|
+
end
|
|
2010
|
+
return 0
|
|
2011
|
+
rescue RestClient::Exception => e
|
|
2012
|
+
print_rest_exception(e, options)
|
|
2013
|
+
exit 1
|
|
2014
|
+
end
|
|
2015
|
+
end
|
|
2016
|
+
|
|
1922
2017
|
private
|
|
1923
2018
|
|
|
1924
2019
|
def find_host_by_id(id)
|
|
@@ -2071,7 +2166,7 @@ class Morpheus::Cli::Hosts
|
|
|
2071
2166
|
def make_managed_option_types(connected=true)
|
|
2072
2167
|
[
|
|
2073
2168
|
#{'fieldName' => 'account', 'fieldLabel' => 'Account', 'type' => 'select', 'optionSource' => 'accounts', 'required' => true},
|
|
2074
|
-
{'fieldName' => 'sshUsername', 'fieldLabel' => 'SSH Username', 'type' => 'text'
|
|
2169
|
+
{'fieldName' => 'sshUsername', 'fieldLabel' => 'SSH Username', 'type' => 'text'},
|
|
2075
2170
|
{'fieldName' => 'sshPassword', 'fieldLabel' => 'SSH Password', 'type' => 'password', 'required' => false},
|
|
2076
2171
|
{'fieldName' => 'serverOs', 'fieldLabel' => 'OS Type', 'type' => 'select', 'optionSource' => 'osTypes', 'required' => false},
|
|
2077
2172
|
]
|
|
@@ -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, :snapshots,
|
|
22
|
+
:security_groups, :apply_security_groups, :run_workflow, :import_snapshot, :snapshot, :snapshots,
|
|
23
23
|
:console, :status_check, {:containers => :list_containers},
|
|
24
24
|
:scaling, {:'scaling-update' => :scaling_update},
|
|
25
25
|
:wiki, :update_wiki,
|
|
@@ -80,9 +80,6 @@ class Morpheus::Cli::Instances
|
|
|
80
80
|
options[:owner] = val
|
|
81
81
|
end
|
|
82
82
|
opts.add_hidden_option('--created-by')
|
|
83
|
-
opts.on('--details', "Display more details: memory and storage usage used / max values." ) do
|
|
84
|
-
options[:details] = true
|
|
85
|
-
end
|
|
86
83
|
opts.on('--status STATUS', "Filter by status i.e. provisioning,running,starting,stopping") do |val|
|
|
87
84
|
params['status'] = (params['status'] || []) + val.to_s.split(',').collect {|s| s.strip }.select {|s| s != "" }
|
|
88
85
|
end
|
|
@@ -92,6 +89,17 @@ class Morpheus::Cli::Instances
|
|
|
92
89
|
opts.on('--pending-removal-only', "Only instances pending removal.") do
|
|
93
90
|
options[:deleted] = true
|
|
94
91
|
end
|
|
92
|
+
opts.on( '--plan NAME', String, "Filter by Plan name(s)" ) do |val|
|
|
93
|
+
# commas used in names a lot so use --plan one --plan two
|
|
94
|
+
params['plan'] ||= []
|
|
95
|
+
params['plan'] << val
|
|
96
|
+
end
|
|
97
|
+
opts.on( '--plan-id ID', String, "Filter by Plan id(s)" ) do |val|
|
|
98
|
+
params['planId'] = parse_id_list(val)
|
|
99
|
+
end
|
|
100
|
+
opts.on( '--plan-code CODE', String, "Filter by Plan code(s)" ) do |val|
|
|
101
|
+
params['planCode'] = parse_id_list(val)
|
|
102
|
+
end
|
|
95
103
|
opts.on('--labels label',String, "Filter by labels (keywords).") do |val|
|
|
96
104
|
val.split(",").each do |k|
|
|
97
105
|
options[:labels] ||= []
|
|
@@ -106,6 +114,12 @@ class Morpheus::Cli::Instances
|
|
|
106
114
|
options[:tags][k] << (v || '')
|
|
107
115
|
end
|
|
108
116
|
end
|
|
117
|
+
opts.on('--stats', "Display values for memory and storage usage used / max values." ) do
|
|
118
|
+
options[:stats] = true
|
|
119
|
+
end
|
|
120
|
+
opts.on('-a', '--details', "Display all details: plan, stats, etc" ) do
|
|
121
|
+
options[:details] = true
|
|
122
|
+
end
|
|
109
123
|
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
|
110
124
|
opts.footer = "List instances."
|
|
111
125
|
end
|
|
@@ -216,7 +230,7 @@ class Morpheus::Cli::Instances
|
|
|
216
230
|
cpu_usage_str = !stats ? "" : generate_usage_bar((stats['usedCpu'] || stats['cpuUsage']).to_f, 100, {max_bars: 10})
|
|
217
231
|
memory_usage_str = !stats ? "" : generate_usage_bar(stats['usedMemory'], stats['maxMemory'], {max_bars: 10})
|
|
218
232
|
storage_usage_str = !stats ? "" : generate_usage_bar(stats['usedStorage'], stats['maxStorage'], {max_bars: 10})
|
|
219
|
-
if options[:details]
|
|
233
|
+
if options[:details] || options[:stats]
|
|
220
234
|
if stats['maxMemory'] && stats['maxMemory'].to_i != 0
|
|
221
235
|
memory_usage_str = memory_usage_str + cyan + format_bytes_short(stats['usedMemory']).strip.rjust(8, ' ') + " / " + format_bytes_short(stats['maxMemory']).strip
|
|
222
236
|
end
|
|
@@ -234,8 +248,9 @@ class Morpheus::Cli::Instances
|
|
|
234
248
|
nodes: instance['containers'].count,
|
|
235
249
|
status: format_instance_status(instance, cyan),
|
|
236
250
|
type: instance['instanceType']['name'],
|
|
237
|
-
group:
|
|
238
|
-
cloud:
|
|
251
|
+
group: instance['group'] ? instance['group']['name'] : nil,
|
|
252
|
+
cloud: instance['cloud'] ? instance['cloud']['name'] : nil,
|
|
253
|
+
plan: instance['plan'] ? instance['plan']['name'] : '',
|
|
239
254
|
version: instance['instanceVersion'] ? instance['instanceVersion'] : '',
|
|
240
255
|
created: format_local_dt(instance['dateCreated']),
|
|
241
256
|
cpu: cpu_usage_str + cyan,
|
|
@@ -249,12 +264,13 @@ class Morpheus::Cli::Instances
|
|
|
249
264
|
{:created => {:display_name => "CREATED"}},
|
|
250
265
|
# {:tenant => {:display_name => "TENANT"}},
|
|
251
266
|
{:user => {:display_name => "OWNER", :max_width => 20}},
|
|
267
|
+
:plan,
|
|
252
268
|
:nodes, {:connection => {:max_width => 30}}, :status, :cpu, :memory, :storage]
|
|
253
269
|
# custom pretty table columns ... this is handled in as_pretty_table now(),
|
|
254
270
|
# todo: remove all these.. and try to always pass rows as the json data itself..
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
271
|
+
if options[:details] != true
|
|
272
|
+
columns.delete(:plan)
|
|
273
|
+
end
|
|
258
274
|
print cyan
|
|
259
275
|
print as_pretty_table(rows, columns, options)
|
|
260
276
|
print reset
|
|
@@ -443,17 +459,58 @@ class Morpheus::Cli::Instances
|
|
|
443
459
|
options[:instance_name] = args[0]
|
|
444
460
|
end
|
|
445
461
|
|
|
446
|
-
# use active group by default
|
|
447
|
-
options[:group] ||= @active_group_id
|
|
448
|
-
options[:select_datastore] = true
|
|
449
|
-
options[:name_required] = true
|
|
450
462
|
begin
|
|
451
463
|
payload = nil
|
|
452
464
|
if options[:payload]
|
|
453
465
|
payload = options[:payload]
|
|
454
466
|
# support -O OPTION switch on top of --payload
|
|
455
467
|
payload.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
|
|
468
|
+
# obviously should support every option that prompt supports on top of -- payload as well
|
|
469
|
+
# group, cloud and type for now
|
|
470
|
+
# todo: also support :layout, service_plan, :resource_pool, etc.
|
|
471
|
+
group = nil
|
|
472
|
+
if options[:group]
|
|
473
|
+
group = find_group_by_name_or_id_for_provisioning(options[:group])
|
|
474
|
+
if group.nil?
|
|
475
|
+
return 1, "group not found by #{options[:group]}"
|
|
476
|
+
end
|
|
477
|
+
#payload["siteId"] = group["id"]
|
|
478
|
+
payload.deep_merge!({"instance" => {"site" => {"id" => group["id"]} } })
|
|
479
|
+
end
|
|
480
|
+
if options[:cloud]
|
|
481
|
+
group_id = group ? group["id"] : ((payload["instance"] && payload["instance"]["site"].is_a?(Hash)) ? payload["instance"]["site"]["id"] : nil)
|
|
482
|
+
cloud = find_cloud_by_name_or_id_for_provisioning(group_id, options[:cloud])
|
|
483
|
+
if cloud.nil?
|
|
484
|
+
return 1, "cloud not found by #{options[:cloud]}"
|
|
485
|
+
end
|
|
486
|
+
payload["zoneId"] = cloud["id"]
|
|
487
|
+
payload.deep_merge!({"instance" => {"cloud" => cloud["name"] } })
|
|
488
|
+
end
|
|
489
|
+
if options[:cloud]
|
|
490
|
+
group_id = group ? group["id"] : ((payload["instance"] && payload["instance"]["site"].is_a?(Hash)) ? payload["instance"]["site"]["id"] : nil)
|
|
491
|
+
cloud = find_cloud_by_name_or_id_for_provisioning(group_id, options[:cloud])
|
|
492
|
+
if cloud.nil?
|
|
493
|
+
return 1, "cloud not found by #{options[:cloud]}"
|
|
494
|
+
end
|
|
495
|
+
payload["zoneId"] = cloud["id"]
|
|
496
|
+
payload.deep_merge!({"instance" => {"cloud" => cloud["name"] } })
|
|
497
|
+
end
|
|
498
|
+
if options[:instance_type_code]
|
|
499
|
+
# should just use find_instance_type_by_name_or_id
|
|
500
|
+
# note that the api actually will match name name or code
|
|
501
|
+
instance_type = (options[:instance_type_code].to_s =~ /\A\d{1,}\Z/) ? find_instance_type_by_id(options[:instance_type_code]) : find_instance_type_by_code(options[:instance_type_code])
|
|
502
|
+
if instance_type.nil?
|
|
503
|
+
return 1, "instance type not found by #{options[:cloud]}"
|
|
504
|
+
end
|
|
505
|
+
payload.deep_merge!({"instance" => {"type" => instance_type["code"] } })
|
|
506
|
+
payload.deep_merge!({"instance" => {"instanceType" => {"code" => instance_type["code"]} } })
|
|
507
|
+
end
|
|
508
|
+
|
|
456
509
|
else
|
|
510
|
+
# use active group by default
|
|
511
|
+
options[:group] ||= @active_group_id
|
|
512
|
+
options[:select_datastore] = true
|
|
513
|
+
options[:name_required] = true
|
|
457
514
|
# prompt for all the instance configuration options
|
|
458
515
|
# this provisioning helper method handles all (most) of the parsing and prompting
|
|
459
516
|
# and it relies on the method to exit non-zero on error, like a bad CLOUD or TYPE value
|
|
@@ -546,16 +603,17 @@ class Morpheus::Cli::Instances
|
|
|
546
603
|
opts.on('--group GROUP', String, "Group Name or ID") do |val|
|
|
547
604
|
options[:group] = val
|
|
548
605
|
end
|
|
549
|
-
opts.on('--
|
|
550
|
-
|
|
606
|
+
opts.on('--labels LIST', String, "Labels (keywords) in the format 'foo, bar'") do |val|
|
|
607
|
+
params['labels'] = val.split(',').collect {|it| it.to_s.strip }.compact.uniq.join(',')
|
|
551
608
|
end
|
|
552
|
-
opts.on('--
|
|
553
|
-
options[:
|
|
609
|
+
opts.on('--tags LIST', String, "Tags in the format 'name:value, name:value'. This will add and remove tags.") do |val|
|
|
610
|
+
options[:tags] = val
|
|
554
611
|
end
|
|
555
|
-
opts.
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
612
|
+
opts.on('--add-tags TAGS', String, "Add Tags in the format 'name:value, name:value'. This will only add/update tags.") do |val|
|
|
613
|
+
options[:add_tags] = val
|
|
614
|
+
end
|
|
615
|
+
opts.on('--remove-tags TAGS', String, "Remove Tags in the format 'name, name:value'. This removes tags, the :value component is optional and must match if passed.") do |val|
|
|
616
|
+
options[:remove_tags] = val
|
|
559
617
|
end
|
|
560
618
|
opts.on('--power-schedule-type ID', String, "Power Schedule Type ID") do |val|
|
|
561
619
|
params['powerScheduleType'] = val == "null" ? nil : val
|
|
@@ -611,32 +669,17 @@ class Morpheus::Cli::Instances
|
|
|
611
669
|
payload['instance']['site'] = {'id' => group['id']}
|
|
612
670
|
end
|
|
613
671
|
# metadata tags
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
metadata = []
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
# merge IDs from current metadata
|
|
626
|
-
# todo: should allow quoted semicolons..
|
|
627
|
-
metadata_list = options[:metadata].split(",").select {|it| !it.to_s.empty? }
|
|
628
|
-
metadata_list = metadata_list.collect do |it|
|
|
629
|
-
metadata_pair = it.split(":")
|
|
630
|
-
if metadata_pair.size == 1 && it.include?("=")
|
|
631
|
-
metadata_pair = it.split("=")
|
|
632
|
-
end
|
|
633
|
-
row = {}
|
|
634
|
-
row['name'] = metadata_pair[0].to_s.strip
|
|
635
|
-
row['value'] = metadata_pair[1].to_s.strip
|
|
636
|
-
row
|
|
637
|
-
end
|
|
638
|
-
payload['instance']['metadata'] = metadata_list
|
|
639
|
-
end
|
|
672
|
+
if options[:tags]
|
|
673
|
+
# api version 4.2.5 and later supports tags, older versions expect metadata
|
|
674
|
+
# todo: use tags instead like everywhere else
|
|
675
|
+
# payload['instance']['tags'] = parse_metadata(options[:tags])
|
|
676
|
+
payload['instance']['metadata'] = parse_metadata(options[:tags])
|
|
677
|
+
end
|
|
678
|
+
if options[:add_tags]
|
|
679
|
+
payload['instance']['addTags'] = parse_metadata(options[:add_tags])
|
|
680
|
+
end
|
|
681
|
+
if options[:remove_tags]
|
|
682
|
+
payload['instance']['removeTags'] = parse_metadata(options[:remove_tags])
|
|
640
683
|
end
|
|
641
684
|
if payload['instance'].empty? && params.empty? && options[:owner].nil?
|
|
642
685
|
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
|
@@ -1237,7 +1280,18 @@ class Morpheus::Cli::Instances
|
|
|
1237
1280
|
instance = json_response['instance']
|
|
1238
1281
|
stats = instance['stats'] || json_response['stats'] || {}
|
|
1239
1282
|
# load_balancers = json_response['loadBalancers'] || {}
|
|
1240
|
-
|
|
1283
|
+
# metadata tags used to be returned as metadata and are now returned as tags
|
|
1284
|
+
# the problem is tags is what we used to call Labels (keywords)
|
|
1285
|
+
# the api will change to tags and labels, so handle the old format as long as metadata is returned.
|
|
1286
|
+
labels = nil
|
|
1287
|
+
tags = nil
|
|
1288
|
+
if instance.key?('labels')
|
|
1289
|
+
labels = instance['labels']
|
|
1290
|
+
tags = instance['tags']
|
|
1291
|
+
else
|
|
1292
|
+
labels = instance['tags']
|
|
1293
|
+
tags = instance['metadata']
|
|
1294
|
+
end
|
|
1241
1295
|
# containers are fetched via separate api call
|
|
1242
1296
|
containers = nil
|
|
1243
1297
|
if options[:include_containers]
|
|
@@ -1278,8 +1332,8 @@ class Morpheus::Cli::Instances
|
|
|
1278
1332
|
# "Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
|
1279
1333
|
# "Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
|
1280
1334
|
"Environment" => 'instanceContext',
|
|
1281
|
-
"Labels" => lambda {|it|
|
|
1282
|
-
"
|
|
1335
|
+
"Labels" => lambda {|it| labels ? labels.join(',') : '' },
|
|
1336
|
+
"Tags" => lambda {|it| tags ? tags.collect {|m| "#{m['name']}: #{m['value']}" }.join(', ') : '' },
|
|
1283
1337
|
"Owner" => lambda {|it|
|
|
1284
1338
|
if it['owner']
|
|
1285
1339
|
(it['owner']['username'] || it['owner']['id'])
|
|
@@ -1298,11 +1352,14 @@ class Morpheus::Cli::Instances
|
|
|
1298
1352
|
"Connection" => lambda {|it| format_instance_connection_string(it) },
|
|
1299
1353
|
"Status" => lambda {|it| format_instance_status(it) }
|
|
1300
1354
|
}
|
|
1355
|
+
description_cols.delete("Labels") if labels.nil? || labels.empty?
|
|
1356
|
+
description_cols.delete("Tags") if tags.nil? || tags.empty?
|
|
1301
1357
|
description_cols.delete("Power Schedule") if instance['powerSchedule'].nil?
|
|
1302
1358
|
description_cols.delete("Expire Date") if instance['expireDate'].nil?
|
|
1303
1359
|
description_cols.delete("Shutdown Date") if instance['shutdownDate'].nil?
|
|
1304
1360
|
description_cols["Removal Date"] = lambda {|it| format_local_dt(it['removalDate'])} if instance['status'] == 'pendingRemoval'
|
|
1305
1361
|
description_cols.delete("Last Deployment") if instance['lastDeploy'].nil?
|
|
1362
|
+
#description_cols.delete("Environment") if instance['instanceContext'].nil?
|
|
1306
1363
|
print_description_list(description_cols, instance)
|
|
1307
1364
|
|
|
1308
1365
|
if instance['statusMessage']
|
|
@@ -2616,6 +2673,48 @@ class Morpheus::Cli::Instances
|
|
|
2616
2673
|
end
|
|
2617
2674
|
end
|
|
2618
2675
|
|
|
2676
|
+
def snapshot(args)
|
|
2677
|
+
options = {}
|
|
2678
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
2679
|
+
opts.banner = subcommand_usage("[instance]")
|
|
2680
|
+
opts.on( '--name VALUE', String, "Snapshot Name. Default is server name + timestamp" ) do |val|
|
|
2681
|
+
options[:options]['name'] = val
|
|
2682
|
+
end
|
|
2683
|
+
opts.on( '--description VALUE', String, "Snapshot Description." ) do |val|
|
|
2684
|
+
options[:options]['description'] = val
|
|
2685
|
+
end
|
|
2686
|
+
build_standard_add_options(opts, options, [:auto_confirm])
|
|
2687
|
+
opts.footer = <<-EOT
|
|
2688
|
+
Create a snapshot for an instance.
|
|
2689
|
+
[instance] is required. This is the name or id of an instance
|
|
2690
|
+
EOT
|
|
2691
|
+
end
|
|
2692
|
+
optparse.parse!(args)
|
|
2693
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
2694
|
+
connect(options)
|
|
2695
|
+
instance = find_instance_by_name_or_id(args[0])
|
|
2696
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to snapshot the instance '#{instance['name']}'?", options)
|
|
2697
|
+
exit 1
|
|
2698
|
+
end
|
|
2699
|
+
payload = {}
|
|
2700
|
+
if options[:payload]
|
|
2701
|
+
payload = options[:payload]
|
|
2702
|
+
payload.deep_merge!({'snapshot' => parse_passed_options(options)})
|
|
2703
|
+
else
|
|
2704
|
+
payload.deep_merge!({'snapshot' => parse_passed_options(options)})
|
|
2705
|
+
end
|
|
2706
|
+
@instances_interface.setopts(options)
|
|
2707
|
+
if options[:dry_run]
|
|
2708
|
+
print_dry_run @instances_interface.dry.snapshot(instance['id'], payload)
|
|
2709
|
+
return
|
|
2710
|
+
end
|
|
2711
|
+
json_response = @instances_interface.snapshot(instance['id'], payload)
|
|
2712
|
+
render_response(json_response, options, 'snapshots') do
|
|
2713
|
+
print_green_success "Snapshot initiated."
|
|
2714
|
+
end
|
|
2715
|
+
return 0, nil
|
|
2716
|
+
end
|
|
2717
|
+
|
|
2619
2718
|
def remove(args)
|
|
2620
2719
|
options = {}
|
|
2621
2720
|
query_params = {}
|
|
@@ -2925,6 +3024,10 @@ class Morpheus::Cli::Instances
|
|
|
2925
3024
|
# no pagination yet
|
|
2926
3025
|
# build_standard_list_options(opts, options)
|
|
2927
3026
|
build_standard_get_options(opts, options)
|
|
3027
|
+
opts.footer = <<-EOT
|
|
3028
|
+
List snapshots for an instance.
|
|
3029
|
+
[instance] is required. This is the name or id of an instance
|
|
3030
|
+
EOT
|
|
2928
3031
|
end
|
|
2929
3032
|
optparse.parse!(args)
|
|
2930
3033
|
verify_args!(args:args, optparse:optparse, count:1)
|
|
@@ -2947,7 +3050,8 @@ class Morpheus::Cli::Instances
|
|
|
2947
3050
|
snapshot_column_definitions = {
|
|
2948
3051
|
"ID" => lambda {|it| it['id'] },
|
|
2949
3052
|
"Name" => lambda {|it| it['name'] },
|
|
2950
|
-
"Description" => lambda {|it| it['
|
|
3053
|
+
"Description" => lambda {|it| it['description'] },
|
|
3054
|
+
# "Type" => lambda {|it| it['snapshotType'] },
|
|
2951
3055
|
"Date Created" => lambda {|it| format_local_dt(it['snapshotCreated']) },
|
|
2952
3056
|
"Status" => lambda {|it| format_snapshot_status(it) }
|
|
2953
3057
|
}
|
|
@@ -3876,51 +3980,6 @@ private
|
|
|
3876
3980
|
end
|
|
3877
3981
|
end
|
|
3878
3982
|
|
|
3879
|
-
def format_instance_status(instance, return_color=cyan)
|
|
3880
|
-
out = ""
|
|
3881
|
-
status_string = instance['status'].to_s
|
|
3882
|
-
if status_string == 'running'
|
|
3883
|
-
out << "#{green}#{status_string.upcase}#{return_color}"
|
|
3884
|
-
elsif status_string == 'provisioning'
|
|
3885
|
-
out << "#{cyan}#{status_string.upcase}#{return_color}"
|
|
3886
|
-
elsif status_string == 'stopped' or status_string == 'failed'
|
|
3887
|
-
out << "#{red}#{status_string.upcase}#{return_color}"
|
|
3888
|
-
else
|
|
3889
|
-
out << "#{yellow}#{status_string.upcase}#{return_color}"
|
|
3890
|
-
end
|
|
3891
|
-
out
|
|
3892
|
-
end
|
|
3893
|
-
|
|
3894
|
-
def format_instance_connection_string(instance)
|
|
3895
|
-
if !instance['connectionInfo'].nil? && instance['connectionInfo'].empty? == false
|
|
3896
|
-
connection_string = "#{instance['connectionInfo'][0]['ip']}:#{instance['connectionInfo'][0]['port']}"
|
|
3897
|
-
end
|
|
3898
|
-
end
|
|
3899
|
-
|
|
3900
|
-
def format_container_status(container, return_color=cyan)
|
|
3901
|
-
out = ""
|
|
3902
|
-
status_string = container['status'].to_s
|
|
3903
|
-
if status_string == 'running'
|
|
3904
|
-
out << "#{green}#{status_string.upcase}#{return_color}"
|
|
3905
|
-
elsif status_string == 'provisioning'
|
|
3906
|
-
out << "#{cyan}#{status_string.upcase}#{return_color}"
|
|
3907
|
-
elsif status_string == 'stopped' or status_string == 'failed'
|
|
3908
|
-
out << "#{red}#{status_string.upcase}#{return_color}"
|
|
3909
|
-
else
|
|
3910
|
-
out << "#{yellow}#{status_string.upcase}#{return_color}"
|
|
3911
|
-
end
|
|
3912
|
-
out
|
|
3913
|
-
end
|
|
3914
|
-
|
|
3915
|
-
def format_container_connection_string(container)
|
|
3916
|
-
if !container['ports'].nil? && container['ports'].empty? == false
|
|
3917
|
-
connection_string = "#{container['ip']}:#{container['ports'][0]['external']}"
|
|
3918
|
-
else
|
|
3919
|
-
# eh? more logic needed here i think, see taglib morph:containerLocationMenu
|
|
3920
|
-
connection_string = "#{container['ip']}"
|
|
3921
|
-
end
|
|
3922
|
-
end
|
|
3923
|
-
|
|
3924
3983
|
def instance_scaling_option_types(instance=nil)
|
|
3925
3984
|
|
|
3926
3985
|
# Group
|
|
@@ -3974,17 +4033,6 @@ private
|
|
|
3974
4033
|
list
|
|
3975
4034
|
end
|
|
3976
4035
|
|
|
3977
|
-
def format_instance_container_display_name(instance, plural=false)
|
|
3978
|
-
#<span class="info-label">${[null,'docker'].contains(instance.layout?.provisionType?.code) ? 'Containers' : 'Virtual Machines'}:</span> <span class="info-value">${instance.containers?.size()}</span>
|
|
3979
|
-
v = plural ? "Containers" : "Container"
|
|
3980
|
-
if instance && instance['layout'] && instance['layout'].key?("provisionTypeCode")
|
|
3981
|
-
if [nil, 'docker'].include?(instance['layout']["provisionTypeCode"])
|
|
3982
|
-
v = plural ? "Virtual Machines" : "Virtual Machine"
|
|
3983
|
-
end
|
|
3984
|
-
end
|
|
3985
|
-
return v
|
|
3986
|
-
end
|
|
3987
|
-
|
|
3988
4036
|
def print_instance_threshold_description_list(instance_threshold)
|
|
3989
4037
|
description_cols = {
|
|
3990
4038
|
# "Instance" => lambda {|it| "#{instance['id']} - #{instance['name']}" },
|