morpheus-cli 2.12.5 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +5 -0
- data/lib/morpheus/api/api_client.rb +15 -30
- data/lib/morpheus/api/app_templates_interface.rb +34 -7
- data/lib/morpheus/api/apps_interface.rb +20 -1
- data/lib/morpheus/api/archive_buckets_interface.rb +124 -0
- data/lib/morpheus/api/archive_files_interface.rb +182 -0
- data/lib/morpheus/api/{network_pools_interface.rb → image_builder_boot_scripts_interface.rb} +6 -6
- data/lib/morpheus/api/{policies_interface.rb → image_builder_image_builds_interface.rb} +20 -15
- data/lib/morpheus/api/image_builder_interface.rb +26 -0
- data/lib/morpheus/api/{network_proxies_interface.rb → image_builder_preseed_scripts_interface.rb} +6 -6
- data/lib/morpheus/cli.rb +10 -9
- data/lib/morpheus/cli/alias_command.rb +10 -9
- data/lib/morpheus/cli/app_templates.rb +1566 -457
- data/lib/morpheus/cli/apps.rb +284 -108
- data/lib/morpheus/cli/archives_command.rb +2184 -0
- data/lib/morpheus/cli/boot_scripts_command.rb +382 -0
- data/lib/morpheus/cli/cli_command.rb +9 -35
- data/lib/morpheus/cli/error_handler.rb +2 -0
- data/lib/morpheus/cli/hosts.rb +15 -3
- data/lib/morpheus/cli/image_builder_command.rb +1208 -0
- data/lib/morpheus/cli/instances.rb +118 -47
- data/lib/morpheus/cli/man_command.rb +27 -24
- data/lib/morpheus/cli/mixins/print_helper.rb +19 -5
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +20 -20
- data/lib/morpheus/cli/option_types.rb +45 -14
- data/lib/morpheus/cli/preseed_scripts_command.rb +381 -0
- data/lib/morpheus/cli/remote.rb +1 -0
- data/lib/morpheus/cli/roles.rb +2 -2
- data/lib/morpheus/cli/shell.rb +3 -2
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/ext/hash.rb +22 -0
- data/lib/morpheus/formatters.rb +33 -0
- data/lib/morpheus/terminal.rb +1 -1
- metadata +13 -21
- data/lib/morpheus/api/cloud_policies_interface.rb +0 -47
- data/lib/morpheus/api/group_policies_interface.rb +0 -47
- data/lib/morpheus/api/network_domains_interface.rb +0 -47
- data/lib/morpheus/api/network_groups_interface.rb +0 -47
- data/lib/morpheus/api/network_pool_servers_interface.rb +0 -47
- data/lib/morpheus/api/network_services_interface.rb +0 -47
- data/lib/morpheus/api/networks_interface.rb +0 -54
- data/lib/morpheus/cli/network_domains_command.rb +0 -571
- data/lib/morpheus/cli/network_groups_command.rb +0 -602
- data/lib/morpheus/cli/network_pool_servers_command.rb +0 -430
- data/lib/morpheus/cli/network_pools_command.rb +0 -495
- data/lib/morpheus/cli/network_proxies_command.rb +0 -594
- data/lib/morpheus/cli/network_services_command.rb +0 -148
- data/lib/morpheus/cli/networks_command.rb +0 -855
- data/lib/morpheus/cli/policies_command.rb +0 -847
- data/scripts/generate_morpheus_commands_help.morpheus +0 -1313
data/lib/morpheus/cli/apps.rb
CHANGED
@@ -36,11 +36,17 @@ class Morpheus::Cli::Apps
|
|
36
36
|
|
37
37
|
def list(args)
|
38
38
|
options = {}
|
39
|
-
optparse = OptionParser.new do|opts|
|
39
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
40
40
|
opts.banner = subcommand_usage()
|
41
41
|
build_common_options(opts, options, [:list, :json, :dry_run])
|
42
|
+
opts.footer = "List apps."
|
42
43
|
end
|
43
44
|
optparse.parse!(args)
|
45
|
+
if args.count != 0
|
46
|
+
print_error Morpheus::Terminal.angry_prompt
|
47
|
+
puts_error "#{command_name} list expects 0 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
48
|
+
return 1
|
49
|
+
end
|
44
50
|
connect(options)
|
45
51
|
begin
|
46
52
|
params = {}
|
@@ -87,51 +93,113 @@ class Morpheus::Cli::Apps
|
|
87
93
|
|
88
94
|
def add(args)
|
89
95
|
options = {}
|
90
|
-
optparse = OptionParser.new do|opts|
|
91
|
-
opts.banner = subcommand_usage("[name]")
|
92
|
-
|
96
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
97
|
+
opts.banner = subcommand_usage("[name] [options]")
|
93
98
|
build_option_type_options(opts, options, add_app_option_types(false))
|
94
|
-
opts.on( '-
|
95
|
-
|
99
|
+
# opts.on( '-t', '--template ID', "App Template ID. The app template to use. The default value is 'existing' which means no template, for creating a blank app and adding existing instances." ) do |val|
|
100
|
+
# options['template'] = val
|
101
|
+
# end
|
102
|
+
# opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
|
103
|
+
# options[:group] = val
|
104
|
+
# end
|
105
|
+
# opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID." ) do |val|
|
106
|
+
# options[:cloud] = val
|
107
|
+
# end
|
108
|
+
opts.on('--config JSON', String, "App Config JSON") do |val|
|
109
|
+
options['config'] = JSON.parse(val.to_s)
|
110
|
+
end
|
111
|
+
opts.on('--config-yaml YAML', String, "App Config YAML") do |val|
|
112
|
+
options['config'] = YAML.load(val.to_s)
|
113
|
+
end
|
114
|
+
opts.on('--config-file FILE', String, "App Config from a local JSON or YAML file") do |val|
|
115
|
+
options['configFile'] = val.to_s
|
96
116
|
end
|
97
117
|
build_common_options(opts, options, [:options, :json, :dry_run, :quiet])
|
118
|
+
opts.footer = "Create a new app.\n" +
|
119
|
+
"[name] is required. This is the name of the new app. It may also be passed as --name or inside your config."
|
98
120
|
end
|
99
121
|
optparse.parse!(args)
|
122
|
+
if args.count > 1
|
123
|
+
print_error Morpheus::Terminal.angry_prompt
|
124
|
+
puts_error "#{command_name} add expects 0-1 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
125
|
+
return 1
|
126
|
+
end
|
100
127
|
connect(options)
|
101
128
|
begin
|
102
129
|
options[:options] ||= {}
|
103
|
-
|
104
|
-
options[:options]['group'] ||= options[:group] || @active_group_id
|
105
|
-
# support [name] as first argument still
|
106
|
-
if args[0]
|
130
|
+
if args[0] && !options[:options]['name']
|
107
131
|
options[:options]['name'] = args[0]
|
108
132
|
end
|
133
|
+
# options[:options]['template'] ||= options['template']
|
134
|
+
if options[:group] # || @active_group_id
|
135
|
+
options[:options]['group'] ||= options[:group] # || @active_group_id
|
136
|
+
end
|
109
137
|
|
110
|
-
payload = {
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
138
|
+
payload = {}
|
139
|
+
config_payload = {}
|
140
|
+
if options['config']
|
141
|
+
config_payload = options['config']
|
142
|
+
payload = config_payload
|
143
|
+
elsif options['configFile']
|
144
|
+
config_file = File.expand_path(options['configFile'])
|
145
|
+
if !File.exists?(config_file) || !File.file?(config_file)
|
146
|
+
print_red_alert "File not found: #{config_file}"
|
147
|
+
return false
|
148
|
+
end
|
149
|
+
if config_file =~ /\.ya?ml\Z/
|
150
|
+
config_payload = YAML.load_file(config_file)
|
151
|
+
else
|
152
|
+
config_payload = JSON.parse(File.read(config_file))
|
153
|
+
end
|
154
|
+
payload = config_payload
|
155
|
+
else
|
156
|
+
# prompt for Name, Description, Group, Environment
|
157
|
+
payload = {}
|
158
|
+
params = Morpheus::Cli::OptionTypes.prompt(add_app_option_types, options[:options], @api_client, options[:params])
|
159
|
+
params = params.deep_compact! # remove nulls and blank strings
|
160
|
+
group = find_group_by_name_or_id_for_provisioning(params.delete('group'))
|
161
|
+
return if group.nil?
|
162
|
+
payload.merge!(params)
|
163
|
+
payload['group'] = {id: group['id'], name: group['name']}
|
164
|
+
end
|
165
|
+
|
166
|
+
# allow creating a blank app by default
|
167
|
+
# sux having go merge this into user passed config/configFile
|
168
|
+
# but it's better than making them know to enter it.
|
169
|
+
if !payload['id']
|
170
|
+
payload['id'] = 'existing'
|
171
|
+
payload['templateName'] = 'Existing Instances'
|
172
|
+
else
|
173
|
+
# maybe validate template id
|
174
|
+
# app_template = find_app_template_by_id(payload['id'])
|
175
|
+
end
|
119
176
|
|
120
177
|
if options[:dry_run]
|
121
178
|
print_dry_run @apps_interface.dry.create(payload)
|
122
179
|
return
|
123
180
|
end
|
181
|
+
|
124
182
|
json_response = @apps_interface.create(payload)
|
183
|
+
|
125
184
|
if options[:json]
|
126
|
-
|
185
|
+
puts as_json(json_response, options)
|
127
186
|
print "\n"
|
128
187
|
elsif !options[:quiet]
|
129
|
-
|
130
|
-
|
131
|
-
#
|
132
|
-
|
188
|
+
app = json_response["app"]
|
189
|
+
print_green_success "Added app #{app['name']}"
|
190
|
+
# add existing instances to blank app now?
|
191
|
+
if !options[:no_prompt] && !payload['tiers']
|
192
|
+
if ::Morpheus::Cli::OptionTypes::confirm("Would you like to add an instance now?", options.merge({default: false}))
|
193
|
+
add_instance([app['id']])
|
194
|
+
while ::Morpheus::Cli::OptionTypes::confirm("Add another instance?", options.merge({default: false})) do
|
195
|
+
add_instance([app['id']])
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
# print details
|
200
|
+
get([app['id']])
|
133
201
|
end
|
134
|
-
|
202
|
+
return 0
|
135
203
|
rescue RestClient::Exception => e
|
136
204
|
print_rest_exception(e, options)
|
137
205
|
exit 1
|
@@ -140,14 +208,17 @@ class Morpheus::Cli::Apps
|
|
140
208
|
|
141
209
|
def get(args)
|
142
210
|
options = {}
|
143
|
-
optparse = OptionParser.new do|opts|
|
144
|
-
opts.banner = subcommand_usage("[
|
211
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
212
|
+
opts.banner = subcommand_usage("[app]")
|
145
213
|
build_common_options(opts, options, [:json, :dry_run])
|
214
|
+
opts.footer = "Get details about an app.\n" +
|
215
|
+
"[app] is required. This is the name or id of an app."
|
146
216
|
end
|
147
217
|
optparse.parse!(args)
|
148
|
-
if args.count
|
149
|
-
|
150
|
-
|
218
|
+
if args.count != 1
|
219
|
+
print_error Morpheus::Terminal.angry_prompt
|
220
|
+
puts_error "#{command_name} get expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
221
|
+
return 1
|
151
222
|
end
|
152
223
|
connect(options)
|
153
224
|
begin
|
@@ -225,15 +296,18 @@ class Morpheus::Cli::Apps
|
|
225
296
|
|
226
297
|
def update(args)
|
227
298
|
options = {}
|
228
|
-
optparse = OptionParser.new do|opts|
|
229
|
-
opts.banner = subcommand_usage("[
|
299
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
300
|
+
opts.banner = subcommand_usage("[app] [options]")
|
230
301
|
build_option_type_options(opts, options, update_app_option_types(false))
|
231
302
|
build_common_options(opts, options, [:options, :json, :dry_run])
|
303
|
+
opts.footer = "Update an app.\n" +
|
304
|
+
"[app] is required. This is the name or id of an app."
|
232
305
|
end
|
233
306
|
optparse.parse!(args)
|
234
|
-
if args.count
|
235
|
-
|
236
|
-
|
307
|
+
if args.count != 1
|
308
|
+
print_error Morpheus::Terminal.angry_prompt
|
309
|
+
puts_error "#{command_name} update expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
310
|
+
return 1
|
237
311
|
end
|
238
312
|
connect(options)
|
239
313
|
|
@@ -253,7 +327,7 @@ class Morpheus::Cli::Apps
|
|
253
327
|
end
|
254
328
|
|
255
329
|
#puts "parsed params is : #{params.inspect}"
|
256
|
-
app_keys = ['name', 'description']
|
330
|
+
app_keys = ['name', 'description', 'environment']
|
257
331
|
params = params.select {|k,v| app_keys.include?(k) }
|
258
332
|
payload['app'].merge!(params)
|
259
333
|
|
@@ -282,14 +356,19 @@ class Morpheus::Cli::Apps
|
|
282
356
|
|
283
357
|
def add_instance(args)
|
284
358
|
options = {}
|
285
|
-
optparse = OptionParser.new do|opts|
|
286
|
-
opts.banner = subcommand_usage("[
|
359
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
360
|
+
opts.banner = subcommand_usage("[app] [instance] [tier]")
|
287
361
|
build_common_options(opts, options, [:options, :json, :dry_run])
|
362
|
+
opts.footer = "Add an existing instance to an app.\n" +
|
363
|
+
"[app] is required. This is the name or id of an app." + "\n" +
|
364
|
+
"[instance] is required. This is the name or id of an instance." + "\n" +
|
365
|
+
"[tier] is required. This is the name of the tier."
|
288
366
|
end
|
289
367
|
optparse.parse!(args)
|
290
|
-
if args.count < 1
|
291
|
-
|
292
|
-
|
368
|
+
if args.count < 1 || args.count > 3
|
369
|
+
print_error Morpheus::Terminal.angry_prompt
|
370
|
+
puts_error "#{command_name} add-instance expects 1-3 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
371
|
+
return 1
|
293
372
|
end
|
294
373
|
# optional [tier] and [instance] arguments
|
295
374
|
if args[1] && args[1] !~ /\A\-/
|
@@ -331,11 +410,9 @@ class Morpheus::Cli::Apps
|
|
331
410
|
print "\n"
|
332
411
|
else
|
333
412
|
print_green_success "Added instance #{instance['name']} to app #{app['name']}"
|
334
|
-
|
335
|
-
# details_options = [app['name']]
|
336
|
-
# details(details_options)
|
413
|
+
#get(app['id'])
|
337
414
|
end
|
338
|
-
|
415
|
+
return 0
|
339
416
|
rescue RestClient::Exception => e
|
340
417
|
print_rest_exception(e, options)
|
341
418
|
exit 1
|
@@ -344,27 +421,46 @@ class Morpheus::Cli::Apps
|
|
344
421
|
|
345
422
|
def remove(args)
|
346
423
|
options = {}
|
347
|
-
|
348
|
-
|
424
|
+
query_params = {keepBackups: 'off', force: 'off'}
|
425
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
426
|
+
opts.banner = subcommand_usage("[app] [-fB]")
|
427
|
+
opts.on( '-f', '--force', "Force Delete" ) do
|
428
|
+
query_params[:force] = 'on'
|
429
|
+
end
|
430
|
+
opts.on( '-B', '--keep-backups', "Preserve copy of backups" ) do
|
431
|
+
query_params[:keepBackups] = 'on'
|
432
|
+
end
|
433
|
+
opts.on('--remove-instances [on|off]', ['on','off'], "Remove instances. Default is on.") do |val|
|
434
|
+
query_params[:removeInstances] = val
|
435
|
+
end
|
436
|
+
opts.on('--remove-volumes [on|off]', ['on','off'], "Remove Volumes. Default is on. Applies to certain types only.") do |val|
|
437
|
+
query_params[:removeVolumes] = val
|
438
|
+
end
|
439
|
+
opts.on('--releaseEIPs', ['on','off'], "Release EIPs. Default is false. Applies to Amazon only.") do |val|
|
440
|
+
query_params[:releaseEIPs] = val
|
441
|
+
end
|
349
442
|
build_common_options(opts, options, [:json, :dry_run, :quiet, :auto_confirm])
|
443
|
+
opts.footer = "Delete an app.\n" +
|
444
|
+
"[app] is required. This is the name or id of an app."
|
350
445
|
end
|
351
446
|
optparse.parse!(args)
|
352
|
-
if args.count
|
353
|
-
|
354
|
-
|
447
|
+
if args.count != 1
|
448
|
+
print_error Morpheus::Terminal.angry_prompt
|
449
|
+
puts_error "#{command_name} remove expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
450
|
+
return 1
|
355
451
|
end
|
356
452
|
connect(options)
|
357
453
|
|
358
454
|
begin
|
359
455
|
app = find_app_by_name_or_id(args[0])
|
360
456
|
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove the app '#{app['name']}'?", options)
|
361
|
-
|
457
|
+
return 9
|
362
458
|
end
|
363
459
|
if options[:dry_run]
|
364
|
-
print_dry_run @apps_interface.dry.destroy(app['id'])
|
460
|
+
print_dry_run @apps_interface.dry.destroy(app['id'], query_params)
|
365
461
|
return
|
366
462
|
end
|
367
|
-
json_response = @apps_interface.destroy(app['id'])
|
463
|
+
json_response = @apps_interface.destroy(app['id'], query_params)
|
368
464
|
if options[:json]
|
369
465
|
print JSON.pretty_generate(json_response)
|
370
466
|
print "\n"
|
@@ -380,14 +476,18 @@ class Morpheus::Cli::Apps
|
|
380
476
|
|
381
477
|
def remove_instance(args)
|
382
478
|
options = {}
|
383
|
-
optparse = OptionParser.new do|opts|
|
384
|
-
opts.banner = subcommand_usage("[
|
479
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
480
|
+
opts.banner = subcommand_usage("[app] [instance]")
|
385
481
|
build_common_options(opts, options, [:options, :json, :dry_run])
|
482
|
+
opts.footer = "Remove an instance from an app.\n" +
|
483
|
+
"[app] is required. This is the name or id of an app." + "\n" +
|
484
|
+
"[instance] is required. This is the name or id of an instance."
|
386
485
|
end
|
387
486
|
optparse.parse!(args)
|
388
|
-
if args.count < 1
|
389
|
-
|
390
|
-
|
487
|
+
if args.count < 1 || args.count > 2
|
488
|
+
print_error Morpheus::Terminal.angry_prompt
|
489
|
+
puts_error "#{command_name} remove-instance expects 1-2 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
490
|
+
return 1
|
391
491
|
end
|
392
492
|
# optional [tier] and [instance] arguments
|
393
493
|
if args[1] && args[1] !~ /\A\-/
|
@@ -432,14 +532,17 @@ class Morpheus::Cli::Apps
|
|
432
532
|
|
433
533
|
def logs(args)
|
434
534
|
options = {}
|
435
|
-
optparse = OptionParser.new do|opts|
|
436
|
-
opts.banner = subcommand_usage("[
|
535
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
536
|
+
opts.banner = subcommand_usage("[app]")
|
437
537
|
build_common_options(opts, options, [:list, :json, :dry_run])
|
538
|
+
opts.footer = "List logs for an app.\n" +
|
539
|
+
"[app] is required. This is the name or id of an app."
|
438
540
|
end
|
439
541
|
optparse.parse!(args)
|
440
|
-
if args.count
|
441
|
-
|
442
|
-
|
542
|
+
if args.count !=1
|
543
|
+
print_error Morpheus::Terminal.angry_prompt
|
544
|
+
puts_error "#{command_name} logs expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
545
|
+
return 1
|
443
546
|
end
|
444
547
|
connect(options)
|
445
548
|
begin
|
@@ -454,15 +557,23 @@ class Morpheus::Cli::Apps
|
|
454
557
|
[:phrase, :offset, :max, :sort, :direction].each do |k|
|
455
558
|
params[k] = options[k] unless options[k].nil?
|
456
559
|
end
|
560
|
+
params[:query] = params.delete(:phrase) unless params[:phrase].nil?
|
457
561
|
if options[:dry_run]
|
458
562
|
print_dry_run @logs_interface.dry.container_logs(containers, params)
|
459
563
|
return
|
460
564
|
end
|
461
565
|
logs = @logs_interface.container_logs(containers, params)
|
462
566
|
if options[:json]
|
463
|
-
|
464
|
-
|
567
|
+
puts as_json(logs, options)
|
568
|
+
return 0
|
465
569
|
else
|
570
|
+
title = "App Logs: #{app['name']}"
|
571
|
+
subtitles = []
|
572
|
+
if params[:query]
|
573
|
+
subtitles << "Search: #{params[:query]}".strip
|
574
|
+
end
|
575
|
+
# todo: startMs, endMs, sorts insteaad of sort..etc
|
576
|
+
print_h1 title, subtitles
|
466
577
|
logs['data'].reverse.each do |log_entry|
|
467
578
|
log_level = ''
|
468
579
|
case log_entry['level']
|
@@ -477,9 +588,10 @@ class Morpheus::Cli::Apps
|
|
477
588
|
when 'FATAL'
|
478
589
|
log_level = "#{red}#{bold}FATAL#{reset}"
|
479
590
|
end
|
480
|
-
puts "[#{log_entry['ts']}] #{log_level} - #{log_entry['message']}"
|
591
|
+
puts "[#{log_entry['ts']}] #{log_level} - #{log_entry['message'].to_s.strip}"
|
481
592
|
end
|
482
593
|
print reset,"\n"
|
594
|
+
return 0
|
483
595
|
end
|
484
596
|
rescue RestClient::Exception => e
|
485
597
|
print_rest_exception(e, options)
|
@@ -490,14 +602,15 @@ class Morpheus::Cli::Apps
|
|
490
602
|
=begin
|
491
603
|
def stop(args)
|
492
604
|
options = {}
|
493
|
-
optparse = OptionParser.new do|opts|
|
494
|
-
opts.banner = subcommand_usage("[
|
605
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
606
|
+
opts.banner = subcommand_usage("[app]")
|
495
607
|
build_common_options(opts, options, [:json, :dry_run])
|
496
608
|
end
|
497
609
|
optparse.parse!(args)
|
498
|
-
if args.count
|
499
|
-
|
500
|
-
|
610
|
+
if args.count != 1
|
611
|
+
print_error Morpheus::Terminal.angry_prompt
|
612
|
+
puts_error "#{command_name} stop expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
613
|
+
return 1
|
501
614
|
end
|
502
615
|
connect(options)
|
503
616
|
begin
|
@@ -516,14 +629,15 @@ class Morpheus::Cli::Apps
|
|
516
629
|
|
517
630
|
def start(args)
|
518
631
|
options = {}
|
519
|
-
optparse = OptionParser.new do|opts|
|
520
|
-
opts.banner = subcommand_usage("[
|
632
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
633
|
+
opts.banner = subcommand_usage("[app]")
|
521
634
|
build_common_options(opts, options, [:json, :dry_run])
|
522
635
|
end
|
523
636
|
optparse.parse!(args)
|
524
|
-
if args.count
|
525
|
-
|
526
|
-
|
637
|
+
if args.count != 1
|
638
|
+
print_error Morpheus::Terminal.angry_prompt
|
639
|
+
puts_error "#{command_name} start expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
640
|
+
return 1
|
527
641
|
end
|
528
642
|
connect(options)
|
529
643
|
begin
|
@@ -542,14 +656,15 @@ class Morpheus::Cli::Apps
|
|
542
656
|
|
543
657
|
def restart(args)
|
544
658
|
options = {}
|
545
|
-
optparse = OptionParser.new do|opts|
|
546
|
-
opts.banner = subcommand_usage("[
|
659
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
660
|
+
opts.banner = subcommand_usage("[app]")
|
547
661
|
build_common_options(opts, options, [:json, :dry_run])
|
548
662
|
end
|
549
663
|
optparse.parse!(args)
|
550
|
-
if args.count
|
551
|
-
|
552
|
-
|
664
|
+
if args.count != 1
|
665
|
+
print_error Morpheus::Terminal.angry_prompt
|
666
|
+
puts_error "#{command_name} restart expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
667
|
+
return 1
|
553
668
|
end
|
554
669
|
connect(options)
|
555
670
|
begin
|
@@ -569,14 +684,15 @@ class Morpheus::Cli::Apps
|
|
569
684
|
|
570
685
|
def firewall_disable(args)
|
571
686
|
options = {}
|
572
|
-
optparse = OptionParser.new do|opts|
|
573
|
-
opts.banner = subcommand_usage("[
|
687
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
688
|
+
opts.banner = subcommand_usage("[app]")
|
574
689
|
build_common_options(opts, options, [:json, :dry_run])
|
575
690
|
end
|
576
691
|
optparse.parse!(args)
|
577
|
-
if args.count
|
578
|
-
|
579
|
-
|
692
|
+
if args.count != 1
|
693
|
+
print_error Morpheus::Terminal.angry_prompt
|
694
|
+
puts_error "#{command_name} firewall-disable expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
695
|
+
return 1
|
580
696
|
end
|
581
697
|
connect(options)
|
582
698
|
|
@@ -596,14 +712,15 @@ class Morpheus::Cli::Apps
|
|
596
712
|
|
597
713
|
def firewall_enable(args)
|
598
714
|
options = {}
|
599
|
-
optparse = OptionParser.new do|opts|
|
600
|
-
opts.banner = subcommand_usage("[
|
715
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
716
|
+
opts.banner = subcommand_usage("[app]")
|
601
717
|
build_common_options(opts, options, [:json, :dry_run])
|
602
718
|
end
|
603
719
|
optparse.parse!(args)
|
604
|
-
if args.count
|
605
|
-
|
606
|
-
|
720
|
+
if args.count != 1
|
721
|
+
print_error Morpheus::Terminal.angry_prompt
|
722
|
+
puts_error "#{command_name} firewall-enable expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
723
|
+
return 1
|
607
724
|
end
|
608
725
|
connect(options)
|
609
726
|
|
@@ -623,14 +740,15 @@ class Morpheus::Cli::Apps
|
|
623
740
|
|
624
741
|
def security_groups(args)
|
625
742
|
options = {}
|
626
|
-
optparse = OptionParser.new do|opts|
|
627
|
-
opts.banner = subcommand_usage("[
|
743
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
744
|
+
opts.banner = subcommand_usage("[app]")
|
628
745
|
build_common_options(opts, options, [:json, :dry_run])
|
629
746
|
end
|
630
747
|
optparse.parse!(args)
|
631
|
-
if args.count
|
632
|
-
|
633
|
-
|
748
|
+
if args.count != 1
|
749
|
+
print_error Morpheus::Terminal.angry_prompt
|
750
|
+
puts_error "#{command_name} security-groups expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
751
|
+
return 1
|
634
752
|
end
|
635
753
|
connect(options)
|
636
754
|
|
@@ -646,7 +764,7 @@ class Morpheus::Cli::Apps
|
|
646
764
|
print cyan
|
647
765
|
print_description_list({"Firewall Enabled" => lambda {|it| format_boolean it['firewallEnabled'] } }, json_response)
|
648
766
|
if securityGroups.empty?
|
649
|
-
print
|
767
|
+
print cyan,"\n","No security groups currently applied.",reset,"\n"
|
650
768
|
else
|
651
769
|
print "\n"
|
652
770
|
securityGroups.each do |securityGroup|
|
@@ -664,8 +782,8 @@ class Morpheus::Cli::Apps
|
|
664
782
|
def apply_security_groups(args)
|
665
783
|
options = {}
|
666
784
|
clear_or_secgroups_specified = false
|
667
|
-
optparse = OptionParser.new do|opts|
|
668
|
-
opts.banner = subcommand_usage("[
|
785
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
786
|
+
opts.banner = subcommand_usage("[app] [--clear] [-s]")
|
669
787
|
opts.on( '-c', '--clear', "Clear all security groups" ) do
|
670
788
|
options[:securityGroupIds] = []
|
671
789
|
clear_or_secgroups_specified = true
|
@@ -681,13 +799,15 @@ class Morpheus::Cli::Apps
|
|
681
799
|
build_common_options(opts, options, [:json, :dry_run])
|
682
800
|
end
|
683
801
|
optparse.parse!(args)
|
684
|
-
if args.count
|
685
|
-
|
686
|
-
|
802
|
+
if args.count != 1
|
803
|
+
print_error Morpheus::Terminal.angry_prompt
|
804
|
+
puts_error "#{command_name} apply-security-groups expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
805
|
+
return 1
|
687
806
|
end
|
688
807
|
if !clear_or_secgroups_specified
|
689
|
-
|
690
|
-
|
808
|
+
print_error Morpheus::Terminal.angry_prompt
|
809
|
+
puts_error "#{command_name} apply-security-groups requires either --clear or --secgroups\n#{optparse}"
|
810
|
+
return 1
|
691
811
|
end
|
692
812
|
|
693
813
|
connect(options)
|
@@ -710,15 +830,17 @@ class Morpheus::Cli::Apps
|
|
710
830
|
|
711
831
|
def add_app_option_types(connected=true)
|
712
832
|
[
|
833
|
+
{'fieldName' => 'template', 'fieldLabel' => 'Template', 'type' => 'select', 'selectOptions' => (connected ? get_available_app_templates() : []), 'required' => true, 'defaultValue' => 'existing', 'description' => "The app template to use. The default value is 'existing' which means no template, for creating a blank app and adding existing instances."},
|
713
834
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Enter a name for this app'},
|
714
835
|
{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false},
|
715
836
|
{'fieldName' => 'group', 'fieldLabel' => 'Group', 'type' => 'select', 'selectOptions' => (connected ? get_available_groups() : []), 'required' => true},
|
837
|
+
{'fieldName' => 'environment', 'fieldLabel' => 'Environment', 'type' => 'text', 'required' => false},
|
716
838
|
]
|
717
839
|
end
|
718
840
|
|
719
841
|
def update_app_option_types(connected=true)
|
720
842
|
list = add_app_option_types(connected)
|
721
|
-
list = list.reject {|it| ["group"].include? it['fieldName'] }
|
843
|
+
list = list.reject {|it| ["template", "group"].include? it['fieldName'] }
|
722
844
|
list.each {|it| it['required'] = false }
|
723
845
|
list
|
724
846
|
end
|
@@ -750,11 +872,16 @@ class Morpheus::Cli::Apps
|
|
750
872
|
end
|
751
873
|
|
752
874
|
def print_apps_table(apps, opts={})
|
753
|
-
|
875
|
+
|
754
876
|
table_color = opts[:color] || cyan
|
755
877
|
rows = apps.collect do |app|
|
756
878
|
instances_str = (app['instanceCount'].to_i == 1) ? "1 Instance" : "#{app['instanceCount']} Instances"
|
757
879
|
containers_str = (app['containerCount'].to_i == 1) ? "1 Container" : "#{app['containerCount']} Containers"
|
880
|
+
stats = app['stats']
|
881
|
+
# app_stats = app['appStats']
|
882
|
+
cpu_usage_str = !stats ? "" : generate_usage_bar((stats['cpuUsage'] || stats['cpuUsagePeak']).to_f, 100, {max_bars: 10})
|
883
|
+
memory_usage_str = !stats ? "" : generate_usage_bar(stats['usedMemory'], stats['maxMemory'], {max_bars: 10})
|
884
|
+
storage_usage_str = !stats ? "" : generate_usage_bar(stats['usedStorage'], stats['maxStorage'], {max_bars: 10})
|
758
885
|
{
|
759
886
|
id: app['id'],
|
760
887
|
name: app['name'],
|
@@ -762,11 +889,14 @@ class Morpheus::Cli::Apps
|
|
762
889
|
containers: containers_str,
|
763
890
|
account: app['account'] ? app['account']['name'] : nil,
|
764
891
|
status: format_app_status(app, table_color),
|
892
|
+
cpu: cpu_usage_str + cyan,
|
893
|
+
memory: memory_usage_str + table_color,
|
894
|
+
storage: storage_usage_str + table_color
|
765
895
|
#dateCreated: format_local_dt(app['dateCreated'])
|
766
896
|
}
|
767
897
|
end
|
768
|
-
|
769
|
-
|
898
|
+
|
899
|
+
columns = [
|
770
900
|
:id,
|
771
901
|
:name,
|
772
902
|
:instances,
|
@@ -775,6 +905,20 @@ class Morpheus::Cli::Apps
|
|
775
905
|
:status,
|
776
906
|
#{:dateCreated => {:display_name => "Date Created"} }
|
777
907
|
]
|
908
|
+
term_width = current_terminal_width()
|
909
|
+
if term_width > 120
|
910
|
+
columns += [
|
911
|
+
{:cpu => {:display_name => "MAX CPU"} },
|
912
|
+
:memory,
|
913
|
+
:storage
|
914
|
+
]
|
915
|
+
end
|
916
|
+
# custom pretty table columns ...
|
917
|
+
# if options[:include_fields]
|
918
|
+
# columns = options[:include_fields]
|
919
|
+
# end
|
920
|
+
# print cyan
|
921
|
+
print as_pretty_table(rows, columns, opts) #{color: table_color}
|
778
922
|
print reset
|
779
923
|
end
|
780
924
|
|
@@ -795,4 +939,36 @@ class Morpheus::Cli::Apps
|
|
795
939
|
end
|
796
940
|
out
|
797
941
|
end
|
942
|
+
|
943
|
+
def get_available_app_templates(refresh=false)
|
944
|
+
if !@available_app_templates || refresh
|
945
|
+
results = @options_interface.options_for_source('appTemplates',{})
|
946
|
+
@available_app_templates = results['data'].collect {|it|
|
947
|
+
{"id" => it["value"], "name" => it["name"], "value" => it["value"]}
|
948
|
+
}
|
949
|
+
default_option = {"id" => "existing", "name" => "Existing Instances", "value" => "existing"}
|
950
|
+
@available_app_templates.unshift(default_option)
|
951
|
+
end
|
952
|
+
#puts "get_available_app_templates() rtn: #{@available_app_templates.inspect}"
|
953
|
+
return @available_app_templates
|
954
|
+
end
|
955
|
+
|
956
|
+
def get_available_environments(refresh=false)
|
957
|
+
if !@available_environments || refresh
|
958
|
+
# results = @options_interface.options_for_source('environments',{})
|
959
|
+
# @available_environments = results['data'].collect {|it|
|
960
|
+
# {"id" => it["value"], "name" => it["name"], "value" => it["value"]}
|
961
|
+
# }
|
962
|
+
# todo: api call
|
963
|
+
@available_environments = [
|
964
|
+
{'name' => 'Dev', 'value' => 'Dev'},
|
965
|
+
{'name' => 'Test', 'value' => 'Test'},
|
966
|
+
{'name' => 'Staging', 'value' => 'Staging'},
|
967
|
+
{'name' => 'Production', 'value' => 'Production'}
|
968
|
+
]
|
969
|
+
end
|
970
|
+
#puts "get_available_environments() rtn: #{@available_environments.inspect}"
|
971
|
+
return @available_environments
|
972
|
+
end
|
973
|
+
|
798
974
|
end
|