morpheus-cli 5.0.0 → 5.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +16 -0
- data/lib/morpheus/api/billing_interface.rb +1 -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 +16 -2
- data/lib/morpheus/api/invoices_interface.rb +12 -3
- data/lib/morpheus/api/search_interface.rb +13 -0
- data/lib/morpheus/api/servers_interface.rb +14 -0
- data/lib/morpheus/api/service_catalog_interface.rb +89 -0
- data/lib/morpheus/api/usage_interface.rb +18 -0
- data/lib/morpheus/cli.rb +6 -2
- 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 +51 -10
- data/lib/morpheus/cli/commands/standard/curl_command.rb +26 -13
- data/lib/morpheus/cli/commands/standard/history_command.rb +9 -3
- data/lib/morpheus/cli/commands/standard/man_command.rb +74 -40
- 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/deploy.rb +199 -90
- data/lib/morpheus/cli/deployments.rb +341 -28
- 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 +59 -2
- data/lib/morpheus/cli/hosts.rb +271 -39
- data/lib/morpheus/cli/instances.rb +228 -129
- data/lib/morpheus/cli/invoices_command.rb +100 -20
- 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/logs_command.rb +9 -6
- data/lib/morpheus/cli/mixins/accounts_helper.rb +5 -1
- data/lib/morpheus/cli/mixins/deployments_helper.rb +31 -2
- data/lib/morpheus/cli/mixins/print_helper.rb +13 -27
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +108 -5
- data/lib/morpheus/cli/option_types.rb +271 -22
- data/lib/morpheus/cli/remote.rb +35 -10
- data/lib/morpheus/cli/reports_command.rb +99 -30
- data/lib/morpheus/cli/roles.rb +193 -155
- data/lib/morpheus/cli/search_command.rb +182 -0
- data/lib/morpheus/cli/service_catalog_command.rb +1474 -0
- data/lib/morpheus/cli/setup.rb +1 -1
- data/lib/morpheus/cli/shell.rb +33 -11
- data/lib/morpheus/cli/tasks.rb +29 -32
- data/lib/morpheus/cli/usage_command.rb +64 -11
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +429 -254
- data/lib/morpheus/cli/whoami.rb +6 -6
- data/lib/morpheus/cli/workflows.rb +33 -40
- data/lib/morpheus/formatters.rb +75 -18
- data/lib/morpheus/terminal.rb +6 -2
- metadata +10 -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?
|
@@ -475,8 +532,8 @@ class Morpheus::Cli::HealthCommand
|
|
475
532
|
opts.footer = "List health logs. These are the logs of the morpheus appliance itself."
|
476
533
|
end
|
477
534
|
optparse.parse!(args)
|
478
|
-
if args.count
|
479
|
-
|
535
|
+
if args.count > 0
|
536
|
+
options[:phrase] = args.join(" ")
|
480
537
|
end
|
481
538
|
connect(options)
|
482
539
|
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, :software,
|
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
|
|
@@ -53,9 +54,6 @@ class Morpheus::Cli::Hosts
|
|
53
54
|
params = {}
|
54
55
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
55
56
|
opts.banner = subcommand_usage()
|
56
|
-
opts.on( '-a', '--account ACCOUNT', "Account Name or ID" ) do |val|
|
57
|
-
options[:account] = val
|
58
|
-
end
|
59
57
|
opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
|
60
58
|
options[:group] = val
|
61
59
|
end
|
@@ -81,6 +79,17 @@ class Morpheus::Cli::Hosts
|
|
81
79
|
# params[:clusterId] = val
|
82
80
|
options[:cluster] = val
|
83
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
|
84
93
|
opts.on( '', '--vm', "Show only virtual machines" ) do |val|
|
85
94
|
params[:vm] = true
|
86
95
|
end
|
@@ -105,8 +114,16 @@ class Morpheus::Cli::Hosts
|
|
105
114
|
opts.on( '--created-by USER', "Created By User Username or ID" ) do |val|
|
106
115
|
options[:created_by] = val
|
107
116
|
end
|
108
|
-
opts.on('--
|
109
|
-
options[:
|
117
|
+
opts.on( '--tenant TENANT', "Tenant Name or ID" ) do |val|
|
118
|
+
options[:account] = val
|
119
|
+
end
|
120
|
+
opts.on('--tags Name=Value',String, "Filter by tags.") do |val|
|
121
|
+
val.split(",").each do |value_pair|
|
122
|
+
k,v = value_pair.strip.split("=")
|
123
|
+
options[:tags] ||= {}
|
124
|
+
options[:tags][k] ||= []
|
125
|
+
options[:tags][k] << (v || '')
|
126
|
+
end
|
110
127
|
end
|
111
128
|
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
129
|
params[:tagCompliant] = true
|
@@ -114,7 +131,13 @@ class Morpheus::Cli::Hosts
|
|
114
131
|
opts.on('--non-tag-compliant', "Displays only servers with tag compliance warnings." ) do
|
115
132
|
params[:tagCompliant] = false
|
116
133
|
end
|
117
|
-
|
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
|
140
|
+
build_standard_list_options(opts, options)
|
118
141
|
opts.footer = "List hosts."
|
119
142
|
end
|
120
143
|
optparse.parse!(args)
|
@@ -163,6 +186,11 @@ class Morpheus::Cli::Hosts
|
|
163
186
|
params['clusterId'] = cluster['id']
|
164
187
|
end
|
165
188
|
end
|
189
|
+
if options[:tags] && !options[:tags].empty?
|
190
|
+
options[:tags].each do |k,v|
|
191
|
+
params['tags.' + k] = v
|
192
|
+
end
|
193
|
+
end
|
166
194
|
|
167
195
|
@servers_interface.setopts(options)
|
168
196
|
if options[:dry_run]
|
@@ -194,6 +222,9 @@ class Morpheus::Cli::Hosts
|
|
194
222
|
multi_tenant = json_response['multiTenant'] == true
|
195
223
|
title = "Morpheus Hosts"
|
196
224
|
subtitles = []
|
225
|
+
if account
|
226
|
+
subtitles << "Tenant: #{account['name']}".strip
|
227
|
+
end
|
197
228
|
if group
|
198
229
|
subtitles << "Group: #{group['name']}".strip
|
199
230
|
end
|
@@ -234,7 +265,7 @@ class Morpheus::Cli::Hosts
|
|
234
265
|
cpu_usage_str = !stats ? "" : generate_usage_bar((stats['usedCpu'] || stats['cpuUsage']).to_f, 100, {max_bars: 10})
|
235
266
|
memory_usage_str = !stats ? "" : generate_usage_bar(stats['usedMemory'], stats['maxMemory'], {max_bars: 10})
|
236
267
|
storage_usage_str = !stats ? "" : generate_usage_bar(stats['usedStorage'], stats['maxStorage'], {max_bars: 10})
|
237
|
-
if options[:details]
|
268
|
+
if options[:details] || options[:stats]
|
238
269
|
if stats['maxMemory'] && stats['maxMemory'].to_i != 0
|
239
270
|
memory_usage_str = memory_usage_str + cyan + format_bytes_short(stats['usedMemory']).strip.rjust(8, ' ') + " / " + format_bytes_short(stats['maxMemory']).strip
|
240
271
|
end
|
@@ -244,31 +275,76 @@ class Morpheus::Cli::Hosts
|
|
244
275
|
end
|
245
276
|
row = {
|
246
277
|
id: server['id'],
|
247
|
-
tenant: server['account'] ? server['account']['name'] : server['accountId'],
|
248
278
|
name: server['name'],
|
279
|
+
external_name: server['externalName'],
|
280
|
+
hostname: server['hostname'],
|
249
281
|
platform: server['serverOs'] ? server['serverOs']['name'].upcase : 'N/A',
|
250
|
-
cloud: server['zone'] ? server['zone']['name'] : '',
|
251
282
|
type: server['computeServerType'] ? server['computeServerType']['name'] : 'unmanaged',
|
283
|
+
tenant: server['account'] ? server['account']['name'] : server['accountId'],
|
284
|
+
owner: server['owner'] ? server['owner']['username'] : server['owner'],
|
285
|
+
cloud: server['zone'] ? server['zone']['name'] : '',
|
286
|
+
plan: server['plan'] ? server['plan']['name'] : '',
|
287
|
+
ip: server['externalIp'],
|
288
|
+
internal_ip: server['internalIp'],
|
252
289
|
nodes: server['containers'] ? server['containers'].size : '',
|
253
|
-
status: format_server_status(server, cyan),
|
290
|
+
# status: format_server_status(server, cyan),
|
291
|
+
status: (options[:details]||options[:all_fields]) ? format_server_status(server, cyan) : format_server_status_friendly(server, cyan),
|
254
292
|
power: format_server_power_state(server, cyan),
|
255
293
|
cpu: cpu_usage_str + cyan,
|
256
294
|
memory: memory_usage_str + cyan,
|
257
|
-
storage: storage_usage_str + cyan
|
295
|
+
storage: storage_usage_str + cyan,
|
296
|
+
created: format_local_dt(server['dateCreated']),
|
297
|
+
updated: format_local_dt(server['lastUpdated']),
|
258
298
|
}
|
259
299
|
row
|
260
300
|
}
|
261
|
-
columns = [:id, :name, :type, :cloud, :nodes, :status, :power]
|
262
|
-
|
263
|
-
|
301
|
+
# columns = [:id, :name, :type, :cloud, :ip, :internal_ip, :nodes, :status, :power]
|
302
|
+
columns = {
|
303
|
+
"ID" => :id,
|
304
|
+
"Name" => :name,
|
305
|
+
"External Name" => :external_name,
|
306
|
+
"Hostname" => :hostname,
|
307
|
+
"Type" => :type,
|
308
|
+
"Owner" => :owner,
|
309
|
+
"Tenant" => :tenant,
|
310
|
+
"Cloud" => :cloud,
|
311
|
+
"Plan" => :plan,
|
312
|
+
"IP" => :ip,
|
313
|
+
"Private IP" => :internal_ip,
|
314
|
+
"Nodes" => :nodes,
|
315
|
+
"Status" => :status,
|
316
|
+
"Power" => :power,
|
317
|
+
"CPU" => :cpu,
|
318
|
+
"Memory" => :memory,
|
319
|
+
"Storage" => :storage,
|
320
|
+
"Created" => :created,
|
321
|
+
"Updated" => :updated,
|
322
|
+
}
|
323
|
+
if options[:details] != true
|
324
|
+
columns.delete("External Name")
|
325
|
+
columns.delete("Hostname")
|
326
|
+
columns.delete("Plan")
|
327
|
+
columns.delete("Private IP")
|
328
|
+
columns.delete("Owner")
|
329
|
+
columns.delete("Tenant")
|
330
|
+
columns.delete("Power")
|
331
|
+
columns.delete("Created")
|
332
|
+
columns.delete("Updated")
|
264
333
|
end
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
columns = options[:include_fields]
|
334
|
+
# hide External Name if there are none
|
335
|
+
if !servers.find {|it| it['externalName'] && it['externalName'] != it['name']}
|
336
|
+
columns.delete("External Name")
|
269
337
|
end
|
338
|
+
if !multi_tenant
|
339
|
+
columns.delete("Tenant")
|
340
|
+
end
|
341
|
+
# columns += [:cpu, :memory, :storage]
|
342
|
+
# # custom pretty table columns ...
|
343
|
+
# if options[:include_fields]
|
344
|
+
# columns = options[:include_fields]
|
345
|
+
# end
|
270
346
|
print cyan
|
271
|
-
print as_pretty_table(rows, columns
|
347
|
+
print as_pretty_table(rows, columns.upcase_keys!, options)
|
272
348
|
print reset
|
273
349
|
print_results_pagination(json_response)
|
274
350
|
end
|
@@ -285,7 +361,7 @@ class Morpheus::Cli::Hosts
|
|
285
361
|
options = {}
|
286
362
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
287
363
|
opts.banner = subcommand_usage("[options]")
|
288
|
-
opts.on( '
|
364
|
+
opts.on( '--tenant TENANT', "Tenant Name or ID" ) do |val|
|
289
365
|
options[:account] = val
|
290
366
|
end
|
291
367
|
opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
|
@@ -454,36 +530,43 @@ class Morpheus::Cli::Hosts
|
|
454
530
|
puts records_as_csv([json_response['server']], options)
|
455
531
|
return 0
|
456
532
|
end
|
457
|
-
server = json_response['server']
|
533
|
+
server = json_response['server'] || json_response['host'] || {}
|
458
534
|
#stats = server['stats'] || json_response['stats'] || {}
|
459
535
|
stats = json_response['stats'] || {}
|
536
|
+
tags = server['tags'] || server['metadata']
|
460
537
|
title = "Host Details"
|
461
538
|
print_h1 title, [], options
|
462
539
|
print cyan
|
463
540
|
server_columns = {
|
464
541
|
"ID" => 'id',
|
465
542
|
"Name" => 'name',
|
543
|
+
"Hostname" => 'hostname',
|
466
544
|
"Description" => 'description',
|
467
|
-
"
|
545
|
+
"Tags" => lambda {|it| tags ? format_metadata(tags) : '' },
|
546
|
+
"Owner" => lambda {|it| it['owner'] ? it['owner']['username'] : '' },
|
547
|
+
"Tenant" => lambda {|it| it['account'] ? it['account']['name'] : '' },
|
468
548
|
#"Group" => lambda {|it| it['group'] ? it['group']['name'] : '' },
|
469
549
|
"Cloud" => lambda {|it| it['zone'] ? it['zone']['name'] : '' },
|
550
|
+
"IP" => lambda {|it| it['externalIp'] },
|
551
|
+
"Private IP" => lambda {|it| it['internalIp'] },
|
470
552
|
"Type" => lambda {|it| it['computeServerType'] ? it['computeServerType']['name'] : 'unmanaged' },
|
471
553
|
"Platform" => lambda {|it| it['serverOs'] ? it['serverOs']['name'].upcase : 'N/A' },
|
472
554
|
"Plan" => lambda {|it| it['plan'] ? it['plan']['name'] : '' },
|
473
555
|
"Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
474
556
|
"Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
475
557
|
"Agent" => lambda {|it| it['agentInstalled'] ? "#{server['agentVersion'] || ''} updated at #{format_local_dt(server['lastAgentUpdate'])}" : '(not installed)' },
|
476
|
-
"Status" => lambda {|it| format_server_status(it) },
|
477
558
|
"Nodes" => lambda {|it| it['containers'] ? it['containers'].size : 0 },
|
478
|
-
"
|
559
|
+
# "Status" => lambda {|it| format_server_status(it) },
|
560
|
+
# "Power" => lambda {|it| format_server_power_state(it) },
|
561
|
+
"Status" => lambda {|it| format_server_status_friendly(it) }, # combo
|
479
562
|
}
|
480
|
-
|
481
|
-
if server['
|
482
|
-
|
483
|
-
|
484
|
-
if server['
|
485
|
-
|
486
|
-
|
563
|
+
server_columns.delete("Hostname") if server['hostname'].to_s.empty? || server['hostname'] == server['name']
|
564
|
+
server_columns.delete("IP") if server['externalIp'].to_s.empty?
|
565
|
+
server_columns.delete("Private IP") if server['internalIp'].to_s.empty?
|
566
|
+
# server_columns.delete("Tenant") if multi_tenant != true
|
567
|
+
server_columns.delete("Cost") if server['hourlyCost'].to_f == 0
|
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?
|
487
570
|
|
488
571
|
print_description_list(server_columns, server)
|
489
572
|
|
@@ -910,6 +993,19 @@ class Morpheus::Cli::Hosts
|
|
910
993
|
opts.on('--power-schedule-type ID', String, "Power Schedule Type ID") do |val|
|
911
994
|
params['powerScheduleType'] = val == "null" ? nil : val
|
912
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
|
913
1009
|
# opts.on('--created-by ID', String, "Created By User ID") do |val|
|
914
1010
|
# params['createdById'] = val
|
915
1011
|
# end
|
@@ -928,6 +1024,18 @@ class Morpheus::Cli::Hosts
|
|
928
1024
|
new_group = nil
|
929
1025
|
passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
|
930
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
|
931
1039
|
payload = nil
|
932
1040
|
if options[:payload]
|
933
1041
|
payload = options[:payload]
|
@@ -1809,6 +1917,103 @@ class Morpheus::Cli::Hosts
|
|
1809
1917
|
end
|
1810
1918
|
end
|
1811
1919
|
|
1920
|
+
def snapshots(args)
|
1921
|
+
options = {}
|
1922
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1923
|
+
opts.banner = subcommand_usage("[host]")
|
1924
|
+
# no pagination yet
|
1925
|
+
# build_standard_list_options(opts, options)
|
1926
|
+
build_standard_get_options(opts, options)
|
1927
|
+
end
|
1928
|
+
optparse.parse!(args)
|
1929
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
1930
|
+
connect(options)
|
1931
|
+
begin
|
1932
|
+
server = find_host_by_name_or_id(args[0])
|
1933
|
+
return 1 if server.nil?
|
1934
|
+
params = {}
|
1935
|
+
@servers_interface.setopts(options)
|
1936
|
+
if options[:dry_run]
|
1937
|
+
print_dry_run @servers_interface.dry.snapshots(server['id'], params)
|
1938
|
+
return
|
1939
|
+
end
|
1940
|
+
json_response = @servers_interface.snapshots(server['id'], params)
|
1941
|
+
snapshots = json_response['snapshots']
|
1942
|
+
render_response(json_response, options, 'snapshots') do
|
1943
|
+
print_h1 "Snapshots: #{server['name']}", [], options
|
1944
|
+
if snapshots.empty?
|
1945
|
+
print cyan,"No snapshots found",reset,"\n"
|
1946
|
+
else
|
1947
|
+
snapshot_column_definitions = {
|
1948
|
+
"ID" => lambda {|it| it['id'] },
|
1949
|
+
"Name" => lambda {|it| it['name'] },
|
1950
|
+
"Description" => lambda {|it| it['description'] },
|
1951
|
+
# "Type" => lambda {|it| it['snapshotType'] },
|
1952
|
+
"Date Created" => lambda {|it| format_local_dt(it['snapshotCreated']) },
|
1953
|
+
"Status" => lambda {|it| format_snapshot_status(it) }
|
1954
|
+
}
|
1955
|
+
print cyan
|
1956
|
+
print as_pretty_table(snapshots, snapshot_column_definitions.upcase_keys!, options)
|
1957
|
+
print_results_pagination({size: snapshots.size, total: snapshots.size})
|
1958
|
+
end
|
1959
|
+
print reset, "\n"
|
1960
|
+
end
|
1961
|
+
return 0
|
1962
|
+
rescue RestClient::Exception => e
|
1963
|
+
print_rest_exception(e, options)
|
1964
|
+
exit 1
|
1965
|
+
end
|
1966
|
+
end
|
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
|
+
|
1812
2017
|
private
|
1813
2018
|
|
1814
2019
|
def find_host_by_id(id)
|
@@ -1925,16 +2130,43 @@ class Morpheus::Cli::Hosts
|
|
1925
2130
|
|
1926
2131
|
def format_server_status(server, return_color=cyan)
|
1927
2132
|
out = ""
|
1928
|
-
status_string = server['status']
|
1929
|
-
|
1930
|
-
|
2133
|
+
status_string = server['status'].to_s.downcase
|
2134
|
+
if status_string == 'provisioned'
|
2135
|
+
out = "#{cyan}#{status_string.upcase}#{return_color}"
|
2136
|
+
elsif status_string == 'provisioning'
|
2137
|
+
out = "#{cyan}#{status_string.upcase}#{cyan}"
|
2138
|
+
elsif status_string == 'failed' or status_string == 'error'
|
2139
|
+
out = "#{red}#{status_string.upcase}#{return_color}"
|
2140
|
+
else
|
2141
|
+
out = "#{yellow}#{status_string.upcase}#{return_color}"
|
2142
|
+
end
|
2143
|
+
out
|
2144
|
+
end
|
2145
|
+
|
2146
|
+
def format_server_status_friendly(server, return_color=cyan)
|
2147
|
+
out = ""
|
2148
|
+
status_string = server['status'].to_s.downcase
|
2149
|
+
if status_string == 'provisioned'
|
2150
|
+
# out = format_server_power_state(server, return_color)
|
2151
|
+
# make it looks like format_instance_status
|
2152
|
+
if server['powerState'] == 'on'
|
2153
|
+
out << "#{green}RUNNING#{return_color}"
|
2154
|
+
elsif server['powerState'] == 'off'
|
2155
|
+
out << "#{red}STOPPED#{return_color}"
|
2156
|
+
else
|
2157
|
+
out << "#{white}#{server['powerState'].to_s.upcase}#{return_color}"
|
2158
|
+
end
|
2159
|
+
else
|
2160
|
+
out = format_server_status(server, return_color)
|
2161
|
+
end
|
1931
2162
|
out
|
1932
2163
|
end
|
2164
|
+
|
1933
2165
|
|
1934
2166
|
def make_managed_option_types(connected=true)
|
1935
2167
|
[
|
1936
2168
|
#{'fieldName' => 'account', 'fieldLabel' => 'Account', 'type' => 'select', 'optionSource' => 'accounts', 'required' => true},
|
1937
|
-
{'fieldName' => 'sshUsername', 'fieldLabel' => 'SSH Username', 'type' => 'text'
|
2169
|
+
{'fieldName' => 'sshUsername', 'fieldLabel' => 'SSH Username', 'type' => 'text'},
|
1938
2170
|
{'fieldName' => 'sshPassword', 'fieldLabel' => 'SSH Password', 'type' => 'password', 'required' => false},
|
1939
2171
|
{'fieldName' => 'serverOs', 'fieldLabel' => 'OS Type', 'type' => 'select', 'optionSource' => 'osTypes', 'required' => false},
|
1940
2172
|
]
|