morpheus-cli 2.11.0 → 2.11.1
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/lib/morpheus/api/api_client.rb +4 -0
- data/lib/morpheus/api/containers_interface.rb +128 -0
- data/lib/morpheus/api/instances_interface.rb +63 -0
- data/lib/morpheus/cli.rb +1 -0
- data/lib/morpheus/cli/cli_command.rb +15 -3
- data/lib/morpheus/cli/containers_command.rb +519 -0
- data/lib/morpheus/cli/credentials.rb +4 -13
- data/lib/morpheus/cli/error_handler.rb +9 -0
- data/lib/morpheus/cli/instances.rb +964 -178
- data/lib/morpheus/cli/logout.rb +1 -1
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +153 -139
- data/lib/morpheus/cli/option_types.rb +27 -10
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/whoami.rb +8 -7
- metadata +4 -2
@@ -14,7 +14,7 @@ module Morpheus
|
|
14
14
|
@@appliance_credentials_map = nil
|
15
15
|
|
16
16
|
def initialize(appliance_name, appliance_url)
|
17
|
-
@appliance_name = appliance_name
|
17
|
+
@appliance_name = appliance_name ? appliance_name.to_sym : nil
|
18
18
|
@appliance_url = appliance_url
|
19
19
|
end
|
20
20
|
|
@@ -148,22 +148,12 @@ module Morpheus
|
|
148
148
|
end
|
149
149
|
|
150
150
|
def load_saved_credentials(reload=false)
|
151
|
-
if
|
152
|
-
|
151
|
+
if reload || !defined?(@@appliance_credentials_map) || @@appliance_credentials_map.nil?
|
152
|
+
@@appliance_credentials_map = load_credentials_file || {}
|
153
153
|
end
|
154
|
-
#Morpheus::Logging::DarkPrinter.puts "loading credentials for #{appliance_name}" if Morpheus::Logging.debug?
|
155
|
-
@@appliance_credentials_map = load_credentials_file || {}
|
156
154
|
return @@appliance_credentials_map[@appliance_name]
|
157
155
|
end
|
158
156
|
|
159
|
-
# Provides the current credential information, simply :appliance_name => "access_token"
|
160
|
-
def saved_credentials
|
161
|
-
if !defined?(@@appliance_credentials_map)
|
162
|
-
@@appliance_credentials_map = load_credentials_file
|
163
|
-
end
|
164
|
-
return @@appliance_credentials_map ? @@appliance_credentials_map[@appliance_name.to_sym] : nil
|
165
|
-
end
|
166
|
-
|
167
157
|
def load_credentials_file
|
168
158
|
fn = credentials_file_path
|
169
159
|
if File.exist? fn
|
@@ -194,6 +184,7 @@ module Morpheus
|
|
194
184
|
Morpheus::Logging::DarkPrinter.puts "adding credentials for #{appliance_name} to #{fn}" if Morpheus::Logging.debug?
|
195
185
|
File.open(fn, 'w') {|f| f.write credential_map.to_yaml } #Store
|
196
186
|
FileUtils.chmod(0600, fn)
|
187
|
+
@@appliance_credentials_map = credential_map
|
197
188
|
rescue => e
|
198
189
|
puts "failed to save #{fn}. #{e}" if Morpheus::Logging.debug?
|
199
190
|
end
|
@@ -50,6 +50,11 @@ class Morpheus::Cli::ErrorHandler
|
|
50
50
|
@stderr.puts "#{red}#{err.message}#{reset}"
|
51
51
|
when RestClient::Exception
|
52
52
|
print_rest_exception(err, options)
|
53
|
+
# no stacktrace for now...
|
54
|
+
return exit_code
|
55
|
+
# if !options[:debug]
|
56
|
+
# return exit_code
|
57
|
+
# end
|
53
58
|
else
|
54
59
|
@stderr.puts "#{red}Unexpected Error#{reset}"
|
55
60
|
end
|
@@ -85,6 +90,10 @@ class Morpheus::Cli::ErrorHandler
|
|
85
90
|
|
86
91
|
def print_rest_exception(err, options)
|
87
92
|
e = err
|
93
|
+
# heh
|
94
|
+
if Morpheus::Logging.debug? && options[:debug].nil?
|
95
|
+
options[:debug] = true
|
96
|
+
end
|
88
97
|
if err.response
|
89
98
|
if options[:debug]
|
90
99
|
begin
|
@@ -11,7 +11,8 @@ class Morpheus::Cli::Instances
|
|
11
11
|
include Morpheus::Cli::CliCommand
|
12
12
|
include Morpheus::Cli::ProvisioningHelper
|
13
13
|
|
14
|
-
register_subcommands :list, :get, :add, :update, :remove, :logs, :stats, :stop, :start, :restart, :suspend, :eject, :backup, :backups, :stop_service, :start_service, :restart_service, :resize, :clone, :envs, :setenv, :delenv, :security_groups, :apply_security_groups, :firewall_enable, :firewall_disable, :run_workflow, :import_snapshot, :console, :status_check
|
14
|
+
register_subcommands :list, :get, :add, :update, :remove, :logs, :stats, :stop, :start, :restart, :actions, :action, :suspend, :eject, :backup, :backups, :stop_service, :start_service, :restart_service, :resize, :clone, :envs, :setenv, :delenv, :security_groups, :apply_security_groups, :firewall_enable, :firewall_disable, :run_workflow, :import_snapshot, :console, :status_check, {:containers => :list_containers}, :scaling, {:'scaling-update' => :scaling_update}
|
15
|
+
# register_subcommands {:'lb-update' => :load_balancer_update}
|
15
16
|
alias_subcommand :details, :get
|
16
17
|
set_default_subcommand :list
|
17
18
|
|
@@ -36,6 +37,137 @@ class Morpheus::Cli::Instances
|
|
36
37
|
handle_subcommand(args)
|
37
38
|
end
|
38
39
|
|
40
|
+
def list(args)
|
41
|
+
options = {}
|
42
|
+
optparse = OptionParser.new do|opts|
|
43
|
+
opts.banner = subcommand_usage()
|
44
|
+
opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
|
45
|
+
options[:group] = val
|
46
|
+
end
|
47
|
+
opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
|
48
|
+
options[:cloud] = val
|
49
|
+
end
|
50
|
+
build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
51
|
+
end
|
52
|
+
optparse.parse!(args)
|
53
|
+
connect(options)
|
54
|
+
begin
|
55
|
+
params = {}
|
56
|
+
group = options[:group] ? find_group_by_name_or_id_for_provisioning(options[:group]) : nil
|
57
|
+
if group
|
58
|
+
params['siteId'] = group['id']
|
59
|
+
end
|
60
|
+
|
61
|
+
# argh, this doesn't work because group_id is required for options/clouds
|
62
|
+
# cloud = options[:cloud] ? find_cloud_by_name_or_id_for_provisioning(group_id, options[:cloud]) : nil
|
63
|
+
cloud = options[:cloud] ? find_zone_by_name_or_id(nil, options[:cloud]) : nil
|
64
|
+
if cloud
|
65
|
+
params['zoneId'] = cloud['id']
|
66
|
+
end
|
67
|
+
|
68
|
+
[:phrase, :offset, :max, :sort, :direction].each do |k|
|
69
|
+
params[k] = options[k] unless options[k].nil?
|
70
|
+
end
|
71
|
+
|
72
|
+
if options[:dry_run]
|
73
|
+
print_dry_run @instances_interface.dry.list(params)
|
74
|
+
return
|
75
|
+
end
|
76
|
+
json_response = @instances_interface.get(params)
|
77
|
+
if options[:json]
|
78
|
+
if options[:include_fields]
|
79
|
+
json_response = {"instances" => filter_data(json_response["instances"], options[:include_fields]) }
|
80
|
+
end
|
81
|
+
puts as_json(json_response, options)
|
82
|
+
return 0
|
83
|
+
elsif options[:yaml]
|
84
|
+
if options[:include_fields]
|
85
|
+
json_response = {"instances" => filter_data(json_response["instances"], options[:include_fields]) }
|
86
|
+
end
|
87
|
+
puts as_yaml(json_response, options)
|
88
|
+
return 0
|
89
|
+
elsif options[:csv]
|
90
|
+
# merge stats to be nice here..
|
91
|
+
if json_response['instances']
|
92
|
+
all_stats = json_response['stats'] || {}
|
93
|
+
json_response['instances'].each do |it|
|
94
|
+
it['stats'] ||= all_stats[it['id'].to_s] || all_stats[it['id']]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
puts records_as_csv(json_response['instances'], options)
|
98
|
+
else
|
99
|
+
instances = json_response['instances']
|
100
|
+
|
101
|
+
title = "Morpheus Instances"
|
102
|
+
subtitles = []
|
103
|
+
if group
|
104
|
+
subtitles << "Group: #{group['name']}".strip
|
105
|
+
end
|
106
|
+
if cloud
|
107
|
+
subtitles << "Cloud: #{cloud['name']}".strip
|
108
|
+
end
|
109
|
+
if params[:phrase]
|
110
|
+
subtitles << "Search: #{params[:phrase]}".strip
|
111
|
+
end
|
112
|
+
print_h1 title, subtitles
|
113
|
+
if instances.empty?
|
114
|
+
print yellow,"No instances found.",reset,"\n"
|
115
|
+
else
|
116
|
+
# print_instances_table(instances)
|
117
|
+
# server returns stats in a separate key stats => {"id" => {} }
|
118
|
+
# the id is a string right now..for some reason..
|
119
|
+
all_stats = json_response['stats'] || {}
|
120
|
+
instances.each do |it|
|
121
|
+
if !it['stats']
|
122
|
+
found_stats = all_stats[it['id'].to_s] || all_stats[it['id']]
|
123
|
+
it['stats'] = found_stats # || {}
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
rows = instances.collect {|instance|
|
128
|
+
stats = instance['stats']
|
129
|
+
cpu_usage_str = !stats ? "" : generate_usage_bar((stats['usedCpu'] || stats['cpuUsage']).to_f, 100, {max_bars: 10})
|
130
|
+
memory_usage_str = !stats ? "" : generate_usage_bar(stats['usedMemory'], stats['maxMemory'], {max_bars: 10})
|
131
|
+
storage_usage_str = !stats ? "" : generate_usage_bar(stats['usedStorage'], stats['maxStorage'], {max_bars: 10})
|
132
|
+
row = {
|
133
|
+
id: instance['id'],
|
134
|
+
name: instance['name'],
|
135
|
+
connection: format_instance_connection_string(instance),
|
136
|
+
environment: instance['instanceContext'],
|
137
|
+
nodes: instance['containers'].count,
|
138
|
+
status: format_instance_status(instance, cyan),
|
139
|
+
type: instance['instanceType']['name'],
|
140
|
+
group: !instance['group'].nil? ? instance['group']['name'] : nil,
|
141
|
+
cloud: !instance['cloud'].nil? ? instance['cloud']['name'] : nil,
|
142
|
+
version: instance['instanceVersion'] ? instance['instanceVersion'] : '',
|
143
|
+
cpu: cpu_usage_str + cyan,
|
144
|
+
memory: memory_usage_str + cyan,
|
145
|
+
storage: storage_usage_str + cyan
|
146
|
+
}
|
147
|
+
row
|
148
|
+
}
|
149
|
+
columns = [:id, :name, :group, :cloud, :type, :version, :environment, :nodes, {:connection => {max_width: 30}}, :status]
|
150
|
+
term_width = current_terminal_width()
|
151
|
+
if term_width > 190
|
152
|
+
columns += [:cpu, :memory, :storage]
|
153
|
+
end
|
154
|
+
# custom pretty table columns ...
|
155
|
+
if options[:include_fields]
|
156
|
+
columns = options[:include_fields]
|
157
|
+
end
|
158
|
+
print cyan
|
159
|
+
print as_pretty_table(rows, columns, options)
|
160
|
+
print reset
|
161
|
+
print_results_pagination(json_response)
|
162
|
+
end
|
163
|
+
print reset,"\n"
|
164
|
+
end
|
165
|
+
rescue RestClient::Exception => e
|
166
|
+
print_rest_exception(e, options)
|
167
|
+
exit 1
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
39
171
|
def add(args)
|
40
172
|
options = {}
|
41
173
|
optparse = OptionParser.new do|opts|
|
@@ -76,7 +208,7 @@ class Morpheus::Cli::Instances
|
|
76
208
|
|
77
209
|
payload = prompt_new_instance(options)
|
78
210
|
payload[:copies] = options[:copies] if options[:copies] && options[:copies] > 0
|
79
|
-
payload[:layoutSize] = options[:layout_size] if options[:layout_size] && options[:layout_size] > 0
|
211
|
+
payload[:layoutSize] = options[:layout_size] if options[:layout_size] && options[:layout_size] > 0 # aka Scale Factor
|
80
212
|
if options[:dry_run]
|
81
213
|
print_dry_run @instances_interface.dry.create(payload)
|
82
214
|
return
|
@@ -87,7 +219,7 @@ class Morpheus::Cli::Instances
|
|
87
219
|
else
|
88
220
|
instance_name = json_response["instance"]["name"]
|
89
221
|
print_green_success "Provisioning instance #{instance_name}"
|
90
|
-
list([])
|
222
|
+
#list([])
|
91
223
|
end
|
92
224
|
rescue RestClient::Exception => e
|
93
225
|
print_rest_exception(e, options)
|
@@ -133,7 +265,7 @@ class Morpheus::Cli::Instances
|
|
133
265
|
exit 1
|
134
266
|
end
|
135
267
|
|
136
|
-
instance_keys = ['name', 'description', 'instanceContext', 'tags']
|
268
|
+
instance_keys = ['name', 'description', 'instanceContext', 'tags','configId','configRole','configGroup']
|
137
269
|
params = params.select {|k,v| instance_keys.include?(k) }
|
138
270
|
params['tags'] = params['tags'].split(',').collect {|it| it.to_s.strip }.compact.uniq if params['tags']
|
139
271
|
payload['instance'].merge!(params)
|
@@ -147,7 +279,7 @@ class Morpheus::Cli::Instances
|
|
147
279
|
puts as_json(json_response, options)
|
148
280
|
else
|
149
281
|
print_green_success "Updated instance #{instance['name']}"
|
150
|
-
list([])
|
282
|
+
#list([])
|
151
283
|
end
|
152
284
|
|
153
285
|
rescue RestClient::Exception => e
|
@@ -357,6 +489,24 @@ class Morpheus::Cli::Instances
|
|
357
489
|
options = {}
|
358
490
|
optparse = OptionParser.new do|opts|
|
359
491
|
opts.banner = subcommand_usage("[name]")
|
492
|
+
opts.on( nil, '--containers', "Display Instance Containers" ) do
|
493
|
+
options[:include_containers] = true
|
494
|
+
end
|
495
|
+
opts.on( nil, '--nodes', "Alias for --containers" ) do
|
496
|
+
options[:include_containers] = true
|
497
|
+
end
|
498
|
+
opts.on( nil, '--vms', "Alias for --containers" ) do
|
499
|
+
options[:include_containers] = true
|
500
|
+
end
|
501
|
+
opts.on( nil, '--scaling', "Display Instance Scaling Settings" ) do
|
502
|
+
options[:include_scaling] = true
|
503
|
+
end
|
504
|
+
# opts.on( nil, '--threshold', "Alias for --scaling" ) do
|
505
|
+
# options[:include_scaling] = true
|
506
|
+
# end
|
507
|
+
opts.on( nil, '--lb', "Display Load Balancer Details" ) do
|
508
|
+
options[:include_lb] = true
|
509
|
+
end
|
360
510
|
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
361
511
|
end
|
362
512
|
optparse.parse!(args)
|
@@ -403,7 +553,32 @@ class Morpheus::Cli::Instances
|
|
403
553
|
end
|
404
554
|
instance = json_response['instance']
|
405
555
|
stats = json_response['stats'] || {}
|
406
|
-
# load_balancers =
|
556
|
+
# load_balancers = json_response['loadBalancers'] || {}
|
557
|
+
|
558
|
+
# containers are fetched via separate api call
|
559
|
+
containers = nil
|
560
|
+
if options[:include_containers]
|
561
|
+
containers = @instances_interface.containers(instance['id'])['containers']
|
562
|
+
end
|
563
|
+
|
564
|
+
# threshold is fetched via separate api call too
|
565
|
+
instance_threshold = nil
|
566
|
+
if options[:include_scaling]
|
567
|
+
instance_threshold = @instances_interface.threshold(instance['id'])['instanceThreshold']
|
568
|
+
end
|
569
|
+
|
570
|
+
# loadBalancers is returned via show
|
571
|
+
# parse the current api format of loadBalancers.first.lbs.first
|
572
|
+
current_instance_lb = nil
|
573
|
+
current_load_balancer_port = nil
|
574
|
+
# if options[:include_lb]
|
575
|
+
# #load_balancers = @instances_interface.load_balancers(instance['id'])['loadBalancers']
|
576
|
+
# end
|
577
|
+
if json_response['loadBalancers'] && json_response['loadBalancers'][0] && json_response['loadBalancers'][0]['lbs'] && json_response['loadBalancers'][0]['lbs'][0]
|
578
|
+
current_instance_lb = json_response['loadBalancers'][0]['lbs'][0]
|
579
|
+
#current_load_balancer = current_instance_lb['loadBalancer']
|
580
|
+
#current_load_balancer_port = current_instance_lb['port']
|
581
|
+
end
|
407
582
|
|
408
583
|
print_h1 "Instance Details"
|
409
584
|
print cyan
|
@@ -423,13 +598,179 @@ class Morpheus::Cli::Instances
|
|
423
598
|
}
|
424
599
|
print_description_list(description_cols, instance)
|
425
600
|
|
426
|
-
if
|
601
|
+
if stats
|
427
602
|
print_h2 "Instance Usage"
|
428
603
|
print_stats_usage(stats)
|
429
604
|
end
|
430
605
|
print reset, "\n"
|
431
606
|
|
432
|
-
|
607
|
+
if options[:include_containers]
|
608
|
+
print_h2 "Instance Containers"
|
609
|
+
|
610
|
+
if containers.empty?
|
611
|
+
print yellow,"No containers found for instance.",reset,"\n"
|
612
|
+
else
|
613
|
+
|
614
|
+
rows = containers.collect {|container|
|
615
|
+
stats = container['stats']
|
616
|
+
cpu_usage_str = !stats ? "" : generate_usage_bar((stats['usedCpu'] || stats['cpuUsage']).to_f, 100, {max_bars: 10})
|
617
|
+
memory_usage_str = !stats ? "" : generate_usage_bar(stats['usedMemory'], stats['maxMemory'], {max_bars: 10})
|
618
|
+
storage_usage_str = !stats ? "" : generate_usage_bar(stats['usedStorage'], stats['maxStorage'], {max_bars: 10})
|
619
|
+
row = {
|
620
|
+
id: container['id'],
|
621
|
+
status: format_container_status(container),
|
622
|
+
name: container['server'] ? container['server']['name'] : '(no server)', # there is a server.displayName too?
|
623
|
+
type: container['containerType'] ? container['containerType']['name'] : '',
|
624
|
+
cloud: container['cloud'] ? container['cloud']['name'] : '',
|
625
|
+
location: format_container_connection_string(container),
|
626
|
+
cpu: cpu_usage_str + cyan,
|
627
|
+
memory: memory_usage_str + cyan,
|
628
|
+
storage: storage_usage_str + cyan
|
629
|
+
}
|
630
|
+
row
|
631
|
+
}
|
632
|
+
columns = [:id, :status, :name, :type, :cloud, :location]
|
633
|
+
term_width = current_terminal_width()
|
634
|
+
if term_width > 190
|
635
|
+
columns += [:cpu, :memory, :storage]
|
636
|
+
end
|
637
|
+
# custom pretty table columns ...
|
638
|
+
if options[:include_fields]
|
639
|
+
columns = options[:include_fields]
|
640
|
+
end
|
641
|
+
print cyan
|
642
|
+
print as_pretty_table(rows, columns, options)
|
643
|
+
print reset
|
644
|
+
#print_results_pagination({size: containers.size, total: containers.size}) # mock pagination
|
645
|
+
end
|
646
|
+
print reset,"\n"
|
647
|
+
end
|
648
|
+
|
649
|
+
# if options[:include_lb]
|
650
|
+
if current_instance_lb
|
651
|
+
print_h2 "Load Balancer"
|
652
|
+
print cyan
|
653
|
+
description_cols = {
|
654
|
+
"LB ID" => lambda {|it| it['loadBalancer']['id'] },
|
655
|
+
"Name" => lambda {|it| it['loadBalancer']['name'] },
|
656
|
+
"Type" => lambda {|it| it['loadBalancer']['type'] ? it['loadBalancer']['type']['name'] : '' },
|
657
|
+
"Host Name" => lambda {|it| it['loadBalancer']['host'] }, # instance.hostName ?
|
658
|
+
"Port" => lambda {|it| it['port']['port'] },
|
659
|
+
"Protocol" => lambda {|it| it['port']['proxyProtocol'] },
|
660
|
+
"SSL Enabled" => lambda {|it| format_boolean it['port']['sslEnabled'] },
|
661
|
+
"Cert" => lambda {|it| it['port']['sslCert'] ? it['port']['sslCert']['name'] : 'N/A' } # api needs to return this too..
|
662
|
+
}
|
663
|
+
print_description_list(description_cols, current_instance_lb)
|
664
|
+
print "\n", reset
|
665
|
+
end
|
666
|
+
# end
|
667
|
+
|
668
|
+
if options[:include_scaling]
|
669
|
+
print_h2 "Instance Scaling"
|
670
|
+
if instance_threshold.nil? || instance_threshold.empty?
|
671
|
+
print yellow,"No scaling settings applied to this instance.",reset,"\n"
|
672
|
+
else
|
673
|
+
print cyan
|
674
|
+
print_instance_threshold_description_list(instance_threshold)
|
675
|
+
print reset,"\n"
|
676
|
+
end
|
677
|
+
end
|
678
|
+
return 0
|
679
|
+
rescue RestClient::Exception => e
|
680
|
+
print_rest_exception(e, options)
|
681
|
+
exit 1
|
682
|
+
end
|
683
|
+
end
|
684
|
+
|
685
|
+
def list_containers(args)
|
686
|
+
options = {}
|
687
|
+
optparse = OptionParser.new do|opts|
|
688
|
+
opts.banner = subcommand_usage("[name]")
|
689
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
690
|
+
end
|
691
|
+
optparse.parse!(args)
|
692
|
+
if args.count < 1
|
693
|
+
puts optparse
|
694
|
+
exit 1
|
695
|
+
end
|
696
|
+
connect(options)
|
697
|
+
id_list = parse_id_list(args)
|
698
|
+
return run_command_for_each_arg(id_list) do |arg|
|
699
|
+
_list_containers(arg, options)
|
700
|
+
end
|
701
|
+
end
|
702
|
+
|
703
|
+
def _list_containers(arg, options)
|
704
|
+
begin
|
705
|
+
instance = find_instance_by_name_or_id(arg)
|
706
|
+
return 1 if instance.nil?
|
707
|
+
if options[:dry_run]
|
708
|
+
print_dry_run @instances_interface.dry.containers(instance['id'], params)
|
709
|
+
return
|
710
|
+
end
|
711
|
+
json_response = @instances_interface.containers(instance['id'])
|
712
|
+
if options[:json]
|
713
|
+
if options[:include_fields]
|
714
|
+
json_response = {"containers" => filter_data(json_response["containers"], options[:include_fields]) }
|
715
|
+
end
|
716
|
+
puts as_json(json_response, options)
|
717
|
+
return 0
|
718
|
+
elsif options[:yaml]
|
719
|
+
if options[:include_fields]
|
720
|
+
json_response = {"containers" => filter_data(json_response["containers"], options[:include_fields]) }
|
721
|
+
end
|
722
|
+
puts as_yaml(json_response, options)
|
723
|
+
return 0
|
724
|
+
end
|
725
|
+
|
726
|
+
if options[:csv]
|
727
|
+
puts records_as_csv(json_response['containers'], options)
|
728
|
+
return 0
|
729
|
+
end
|
730
|
+
|
731
|
+
|
732
|
+
containers = json_response['containers']
|
733
|
+
|
734
|
+
title = "Instance Containers: #{instance['name']} (#{instance['instanceType']['name']})"
|
735
|
+
print_h1 title
|
736
|
+
if containers.empty?
|
737
|
+
print yellow,"No containers found for instance.",reset,"\n"
|
738
|
+
else
|
739
|
+
|
740
|
+
rows = containers.collect {|container|
|
741
|
+
stats = container['stats']
|
742
|
+
cpu_usage_str = !stats ? "" : generate_usage_bar((stats['usedCpu'] || stats['cpuUsage']).to_f, 100, {max_bars: 10})
|
743
|
+
memory_usage_str = !stats ? "" : generate_usage_bar(stats['usedMemory'], stats['maxMemory'], {max_bars: 10})
|
744
|
+
storage_usage_str = !stats ? "" : generate_usage_bar(stats['usedStorage'], stats['maxStorage'], {max_bars: 10})
|
745
|
+
row = {
|
746
|
+
id: container['id'],
|
747
|
+
status: format_container_status(container),
|
748
|
+
name: container['server'] ? container['server']['name'] : '(no server)', # there is a server.displayName too?
|
749
|
+
type: container['containerType'] ? container['containerType']['name'] : '',
|
750
|
+
cloud: container['cloud'] ? container['cloud']['name'] : '',
|
751
|
+
location: format_container_connection_string(container),
|
752
|
+
cpu: cpu_usage_str + cyan,
|
753
|
+
memory: memory_usage_str + cyan,
|
754
|
+
storage: storage_usage_str + cyan
|
755
|
+
}
|
756
|
+
row
|
757
|
+
}
|
758
|
+
columns = [:id, :status, :name, :type, :cloud, :location]
|
759
|
+
term_width = current_terminal_width()
|
760
|
+
if term_width > 190
|
761
|
+
columns += [:cpu, :memory, :storage]
|
762
|
+
end
|
763
|
+
# custom pretty table columns ...
|
764
|
+
if options[:include_fields]
|
765
|
+
columns = options[:include_fields]
|
766
|
+
end
|
767
|
+
print cyan
|
768
|
+
print as_pretty_table(rows, columns, options)
|
769
|
+
print reset
|
770
|
+
print_results_pagination({size: containers.size, total: containers.size}) # mock pagination
|
771
|
+
end
|
772
|
+
print reset,"\n"
|
773
|
+
|
433
774
|
rescue RestClient::Exception => e
|
434
775
|
print_rest_exception(e, options)
|
435
776
|
exit 1
|
@@ -461,13 +802,14 @@ class Morpheus::Cli::Instances
|
|
461
802
|
return
|
462
803
|
end
|
463
804
|
backups = json_response['backups']
|
464
|
-
stats = json_response['stats'] || {}
|
465
|
-
# load_balancers = stats = json_response['loadBalancers'] || {}
|
466
805
|
|
467
806
|
print_h1 "Instance Backups: #{instance['name']} (#{instance['instanceType']['name']})"
|
468
|
-
backup_rows = backups.collect {|
|
807
|
+
backup_rows = backups.collect {|r|
|
808
|
+
it = r['backup']
|
809
|
+
{id: it['id'], name: it['name'], dateCreated: format_local_dt(it['dateCreated'])}
|
810
|
+
}
|
469
811
|
print cyan
|
470
|
-
|
812
|
+
puts as_pretty_table backup_rows, [
|
471
813
|
:id,
|
472
814
|
:name,
|
473
815
|
{:dateCreated => {:display_name => "Date Created"} }
|
@@ -656,7 +998,7 @@ class Morpheus::Cli::Instances
|
|
656
998
|
options = {}
|
657
999
|
optparse = OptionParser.new do|opts|
|
658
1000
|
opts.banner = subcommand_usage("[name]")
|
659
|
-
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
|
1001
|
+
build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
|
660
1002
|
end
|
661
1003
|
optparse.parse!(args)
|
662
1004
|
if args.count < 1
|
@@ -676,9 +1018,10 @@ class Morpheus::Cli::Instances
|
|
676
1018
|
json_response = @instances_interface.stop(instance['id'])
|
677
1019
|
if options[:json]
|
678
1020
|
puts as_json(json_response, options)
|
679
|
-
|
1021
|
+
elsif !options[:quiet]
|
1022
|
+
print green, "Stopping instance #{instance['name']}", reset, "\n"
|
680
1023
|
end
|
681
|
-
return
|
1024
|
+
return 0
|
682
1025
|
rescue RestClient::Exception => e
|
683
1026
|
print_rest_exception(e, options)
|
684
1027
|
exit 1
|
@@ -701,14 +1044,16 @@ class Morpheus::Cli::Instances
|
|
701
1044
|
instance = find_instance_by_name_or_id(args[0])
|
702
1045
|
if options[:dry_run]
|
703
1046
|
print_dry_run @instances_interface.dry.start(instance['id'])
|
704
|
-
return
|
1047
|
+
return 0
|
705
1048
|
end
|
706
1049
|
json_response = @instances_interface.start(instance['id'])
|
707
1050
|
if options[:json]
|
708
1051
|
puts as_json(json_response, options)
|
709
1052
|
return 0
|
1053
|
+
elsif !options[:quiet]
|
1054
|
+
print green, "Starting instance #{instance['name']}", reset, "\n"
|
710
1055
|
end
|
711
|
-
return
|
1056
|
+
return 0
|
712
1057
|
rescue RestClient::Exception => e
|
713
1058
|
print_rest_exception(e, options)
|
714
1059
|
exit 1
|
@@ -719,7 +1064,7 @@ class Morpheus::Cli::Instances
|
|
719
1064
|
options = {}
|
720
1065
|
optparse = OptionParser.new do|opts|
|
721
1066
|
opts.banner = subcommand_usage("[name]")
|
722
|
-
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
|
1067
|
+
build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
|
723
1068
|
end
|
724
1069
|
optparse.parse!(args)
|
725
1070
|
if args.count < 1
|
@@ -734,13 +1079,15 @@ class Morpheus::Cli::Instances
|
|
734
1079
|
end
|
735
1080
|
if options[:dry_run]
|
736
1081
|
print_dry_run @instances_interface.dry.restart(instance['id'])
|
737
|
-
return
|
1082
|
+
return 0
|
738
1083
|
end
|
739
1084
|
json_response = @instances_interface.restart(instance['id'])
|
740
1085
|
if options[:json]
|
741
1086
|
puts as_json(json_response, options)
|
1087
|
+
elsif !options[:quiet]
|
1088
|
+
print green, "Stopping instance #{instance['name']}", reset, "\n"
|
742
1089
|
end
|
743
|
-
return
|
1090
|
+
return 0
|
744
1091
|
rescue RestClient::Exception => e
|
745
1092
|
print_rest_exception(e, options)
|
746
1093
|
exit 1
|
@@ -751,7 +1098,7 @@ class Morpheus::Cli::Instances
|
|
751
1098
|
options = {}
|
752
1099
|
optparse = OptionParser.new do|opts|
|
753
1100
|
opts.banner = subcommand_usage("[name]")
|
754
|
-
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
|
1101
|
+
build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
|
755
1102
|
end
|
756
1103
|
optparse.parse!(args)
|
757
1104
|
if args.count < 1
|
@@ -782,8 +1129,8 @@ class Morpheus::Cli::Instances
|
|
782
1129
|
def eject(args)
|
783
1130
|
options = {}
|
784
1131
|
optparse = OptionParser.new do|opts|
|
785
|
-
opts.banner = subcommand_usage("
|
786
|
-
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
|
1132
|
+
opts.banner = subcommand_usage("[name]")
|
1133
|
+
build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
|
787
1134
|
end
|
788
1135
|
optparse.parse!(args)
|
789
1136
|
if args.count < 1
|
@@ -793,9 +1140,9 @@ class Morpheus::Cli::Instances
|
|
793
1140
|
connect(options)
|
794
1141
|
begin
|
795
1142
|
instance = find_instance_by_name_or_id(args[0])
|
796
|
-
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to eject this instance?", options)
|
797
|
-
|
798
|
-
end
|
1143
|
+
# unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to eject this instance?", options)
|
1144
|
+
# exit 1
|
1145
|
+
# end
|
799
1146
|
if options[:dry_run]
|
800
1147
|
print_dry_run @instances_interface.dry.eject(instance['id'])
|
801
1148
|
return
|
@@ -815,7 +1162,7 @@ class Morpheus::Cli::Instances
|
|
815
1162
|
options = {}
|
816
1163
|
optparse = OptionParser.new do|opts|
|
817
1164
|
opts.banner = subcommand_usage("[name]")
|
818
|
-
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
|
1165
|
+
build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
|
819
1166
|
end
|
820
1167
|
optparse.parse!(args)
|
821
1168
|
if args.count < 1
|
@@ -825,18 +1172,18 @@ class Morpheus::Cli::Instances
|
|
825
1172
|
connect(options)
|
826
1173
|
begin
|
827
1174
|
instance = find_instance_by_name_or_id(args[0])
|
828
|
-
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to stop this instance?", options)
|
1175
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to stop service on this instance?", options)
|
829
1176
|
exit 1
|
830
1177
|
end
|
831
1178
|
if options[:dry_run]
|
832
1179
|
print_dry_run @instances_interface.dry.stop(instance['id'],false)
|
833
|
-
return
|
1180
|
+
return 0
|
834
1181
|
end
|
835
1182
|
json_response = @instances_interface.stop(instance['id'],false)
|
836
1183
|
if options[:json]
|
837
1184
|
puts as_json(json_response, options)
|
838
|
-
|
839
|
-
|
1185
|
+
elsif !options[:quiet]
|
1186
|
+
print green, "Stopping service on instance #{instance['name']}", reset, "\n"
|
840
1187
|
end
|
841
1188
|
return 0
|
842
1189
|
rescue RestClient::Exception => e
|
@@ -849,7 +1196,7 @@ class Morpheus::Cli::Instances
|
|
849
1196
|
options = {}
|
850
1197
|
optparse = OptionParser.new do|opts|
|
851
1198
|
opts.banner = subcommand_usage("[name]")
|
852
|
-
build_common_options(opts, options, [:json, :dry_run, :remote])
|
1199
|
+
build_common_options(opts, options, [:quiet, :json, :dry_run, :remote])
|
853
1200
|
end
|
854
1201
|
optparse.parse!(args)
|
855
1202
|
if args.count < 1
|
@@ -861,15 +1208,14 @@ class Morpheus::Cli::Instances
|
|
861
1208
|
instance = find_instance_by_name_or_id(args[0])
|
862
1209
|
if options[:dry_run]
|
863
1210
|
print_dry_run @instances_interface.dry.start(instance['id'], false)
|
864
|
-
return
|
1211
|
+
return 0
|
865
1212
|
end
|
866
1213
|
json_response = @instances_interface.start(instance['id'],false)
|
867
1214
|
if options[:json]
|
868
1215
|
puts as_json(json_response, options)
|
869
|
-
|
870
|
-
|
1216
|
+
elsif !options[:quiet]
|
1217
|
+
print green, "Starting service on instance #{instance['name']}", reset, "\n"
|
871
1218
|
end
|
872
|
-
return 0
|
873
1219
|
rescue RestClient::Exception => e
|
874
1220
|
print_rest_exception(e, options)
|
875
1221
|
exit 1
|
@@ -880,7 +1226,7 @@ class Morpheus::Cli::Instances
|
|
880
1226
|
options = {}
|
881
1227
|
optparse = OptionParser.new do|opts|
|
882
1228
|
opts.banner = subcommand_usage("[name]")
|
883
|
-
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
|
1229
|
+
build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
|
884
1230
|
end
|
885
1231
|
optparse.parse!(args)
|
886
1232
|
if args.count < 1
|
@@ -890,26 +1236,168 @@ class Morpheus::Cli::Instances
|
|
890
1236
|
connect(options)
|
891
1237
|
begin
|
892
1238
|
instance = find_instance_by_name_or_id(args[0])
|
893
|
-
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to restart this instance?", options)
|
1239
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to restart service on this instance?", options)
|
894
1240
|
exit 1
|
895
1241
|
end
|
896
1242
|
if options[:dry_run]
|
897
1243
|
print_dry_run @instances_interface.dry.restart(instance['id'],false)
|
898
|
-
return
|
1244
|
+
return 0
|
899
1245
|
end
|
900
1246
|
json_response = @instances_interface.restart(instance['id'],false)
|
901
1247
|
if options[:json]
|
902
1248
|
puts as_json(json_response, options)
|
1249
|
+
elsif !options[:quiet]
|
1250
|
+
print green, "Restarting service on instance #{instance['name']}", reset, "\n"
|
1251
|
+
end
|
1252
|
+
return 0
|
1253
|
+
rescue RestClient::Exception => e
|
1254
|
+
print_rest_exception(e, options)
|
1255
|
+
exit 1
|
1256
|
+
end
|
1257
|
+
end
|
1258
|
+
|
1259
|
+
def actions(args)
|
1260
|
+
options = {}
|
1261
|
+
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
1262
|
+
opts.banner = subcommand_usage("[id or name list]")
|
1263
|
+
opts.footer = "This outputs the list of the actions available to specified instance(s)."
|
1264
|
+
build_common_options(opts, options, [:json, :dry_run, :remote])
|
1265
|
+
end
|
1266
|
+
optparse.parse!(args)
|
1267
|
+
if args.count < 1
|
1268
|
+
print_error Morpheus::Terminal.angry_prompt
|
1269
|
+
puts_error "#{command_name} actions requires argument [id or name list]\n#{optparse}"
|
1270
|
+
return 1
|
1271
|
+
end
|
1272
|
+
connect(options)
|
1273
|
+
id_list = parse_id_list(args)
|
1274
|
+
instances = []
|
1275
|
+
id_list.each do |instance_id|
|
1276
|
+
instance = find_instance_by_name_or_id(instance_id)
|
1277
|
+
if instance.nil?
|
1278
|
+
# return 1
|
903
1279
|
else
|
904
|
-
|
1280
|
+
instances << instance
|
905
1281
|
end
|
906
|
-
|
1282
|
+
end
|
1283
|
+
if instances.size != id_list.size
|
1284
|
+
#puts_error "instances not found"
|
1285
|
+
return 1
|
1286
|
+
end
|
1287
|
+
instance_ids = instances.collect {|instance| instance["id"] }
|
1288
|
+
begin
|
1289
|
+
# instance = find_instance_by_name_or_id(args[0])
|
1290
|
+
if options[:dry_run]
|
1291
|
+
print_dry_run @instances_interface.dry.available_actions(instance_ids)
|
1292
|
+
return 0
|
1293
|
+
end
|
1294
|
+
json_response = @instances_interface.available_actions(instance_ids)
|
1295
|
+
if options[:json]
|
1296
|
+
puts as_json(json_response, options)
|
1297
|
+
else
|
1298
|
+
title = "Instance Actions: #{anded_list(id_list)}"
|
1299
|
+
print_h1 title
|
1300
|
+
available_actions = json_response["actions"]
|
1301
|
+
if (available_actions && available_actions.size > 0)
|
1302
|
+
print as_pretty_table(available_actions, [:name, :code])
|
1303
|
+
print reset, "\n"
|
1304
|
+
else
|
1305
|
+
print "#{yellow}No available actions#{reset}\n\n"
|
1306
|
+
end
|
1307
|
+
end
|
1308
|
+
return 0
|
907
1309
|
rescue RestClient::Exception => e
|
908
1310
|
print_rest_exception(e, options)
|
909
1311
|
exit 1
|
910
1312
|
end
|
911
1313
|
end
|
912
1314
|
|
1315
|
+
def action(args)
|
1316
|
+
options = {}
|
1317
|
+
action_id = nil
|
1318
|
+
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
1319
|
+
opts.banner = subcommand_usage("[id list] -a CODE")
|
1320
|
+
opts.on('-a', '--action CODE', "Instance Action CODE to execute") do |val|
|
1321
|
+
action_id = val.to_s
|
1322
|
+
end
|
1323
|
+
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
|
1324
|
+
opts.footer = "Execute an action for a instance or instances"
|
1325
|
+
end
|
1326
|
+
optparse.parse!(args)
|
1327
|
+
if args.count < 1
|
1328
|
+
print_error Morpheus::Terminal.angry_prompt
|
1329
|
+
puts_error "[id] argument is required"
|
1330
|
+
puts_error optparse
|
1331
|
+
return 1
|
1332
|
+
end
|
1333
|
+
connect(options)
|
1334
|
+
id_list = parse_id_list(args)
|
1335
|
+
instances = []
|
1336
|
+
id_list.each do |instance_id|
|
1337
|
+
instance = find_instance_by_name_or_id(instance_id)
|
1338
|
+
if instance.nil?
|
1339
|
+
# return 1
|
1340
|
+
else
|
1341
|
+
instances << instance
|
1342
|
+
end
|
1343
|
+
end
|
1344
|
+
if instances.size != id_list.size
|
1345
|
+
#puts_error "instances not found"
|
1346
|
+
return 1
|
1347
|
+
end
|
1348
|
+
instance_ids = instances.collect {|instance| instance["id"] }
|
1349
|
+
|
1350
|
+
# figure out what action to run
|
1351
|
+
available_actions = @instances_interface.available_actions(instance_ids)["actions"]
|
1352
|
+
if available_actions.empty?
|
1353
|
+
if instance_ids.size > 1
|
1354
|
+
print_red_alert "The specified instances have no available actions in common."
|
1355
|
+
else
|
1356
|
+
print_red_alert "The specified instance has no available actions."
|
1357
|
+
end
|
1358
|
+
return 1
|
1359
|
+
end
|
1360
|
+
instance_action = nil
|
1361
|
+
if action_id.nil?
|
1362
|
+
available_actions_dropdown = available_actions.collect {|act| {'name' => act["name"], 'value' => act["code"]} } # already sorted
|
1363
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'code', 'type' => 'select', 'fieldLabel' => 'Instance Action', 'selectOptions' => available_actions_dropdown, 'required' => true, 'description' => 'Choose the instance action to execute'}], options[:options])
|
1364
|
+
action_id = v_prompt['code']
|
1365
|
+
instance_action = available_actions.find {|act| act['code'].to_s == action_id.to_s }
|
1366
|
+
else
|
1367
|
+
instance_action = available_actions.find {|act| act['code'].to_s == action_id.to_s || act['name'].to_s.downcase == action_id.to_s.downcase }
|
1368
|
+
action_id = instance_action["code"] if instance_action
|
1369
|
+
end
|
1370
|
+
if !instance_action
|
1371
|
+
# for testing bogus actions..
|
1372
|
+
# instance_action = {"id" => action_id, "name" => "Unknown"}
|
1373
|
+
raise_command_error "Instance Action '#{action_id}' not found."
|
1374
|
+
end
|
1375
|
+
|
1376
|
+
action_display_name = "#{instance_action['name']} [#{instance_action['code']}]"
|
1377
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to perform action #{action_display_name} on #{id_list.size == 1 ? 'instance' : 'instances'} #{anded_list(id_list)}?", options)
|
1378
|
+
return 9, "aborted command"
|
1379
|
+
end
|
1380
|
+
|
1381
|
+
# return run_command_for_each_arg(containers) do |arg|
|
1382
|
+
# _action(arg, action_id, options)
|
1383
|
+
# end
|
1384
|
+
if options[:dry_run]
|
1385
|
+
print_dry_run @instances_interface.dry.action(instance_ids, action_id)
|
1386
|
+
return 0
|
1387
|
+
end
|
1388
|
+
json_response = @instances_interface.action(instance_ids, action_id)
|
1389
|
+
# just assume json_response["success"] == true, it always is with 200 OK
|
1390
|
+
if options[:json]
|
1391
|
+
puts as_json(json_response, options)
|
1392
|
+
elsif !options[:quiet]
|
1393
|
+
# containers.each do |container|
|
1394
|
+
# print green, "Action #{action_display_name} performed on container #{container['id']}", reset, "\n"
|
1395
|
+
# end
|
1396
|
+
print green, "Action #{action_display_name} performed on #{id_list.size == 1 ? 'instance' : 'instances'} #{anded_list(id_list)}", reset, "\n"
|
1397
|
+
end
|
1398
|
+
return 0
|
1399
|
+
end
|
1400
|
+
|
913
1401
|
def resize(args)
|
914
1402
|
options = {}
|
915
1403
|
optparse = OptionParser.new do|opts|
|
@@ -978,7 +1466,7 @@ class Morpheus::Cli::Instances
|
|
978
1466
|
return 0
|
979
1467
|
else
|
980
1468
|
print_green_success "Resizing instance #{instance['name']}"
|
981
|
-
list([])
|
1469
|
+
#list([])
|
982
1470
|
end
|
983
1471
|
rescue RestClient::Exception => e
|
984
1472
|
print_rest_exception(e, options)
|
@@ -1021,137 +1509,6 @@ class Morpheus::Cli::Instances
|
|
1021
1509
|
end
|
1022
1510
|
end
|
1023
1511
|
|
1024
|
-
def list(args)
|
1025
|
-
options = {}
|
1026
|
-
optparse = OptionParser.new do|opts|
|
1027
|
-
opts.banner = subcommand_usage()
|
1028
|
-
opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
|
1029
|
-
options[:group] = val
|
1030
|
-
end
|
1031
|
-
opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
|
1032
|
-
options[:cloud] = val
|
1033
|
-
end
|
1034
|
-
build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
1035
|
-
end
|
1036
|
-
optparse.parse!(args)
|
1037
|
-
connect(options)
|
1038
|
-
begin
|
1039
|
-
params = {}
|
1040
|
-
group = options[:group] ? find_group_by_name_or_id_for_provisioning(options[:group]) : nil
|
1041
|
-
if group
|
1042
|
-
params['siteId'] = group['id']
|
1043
|
-
end
|
1044
|
-
|
1045
|
-
# argh, this doesn't work because group_id is required for options/clouds
|
1046
|
-
# cloud = options[:cloud] ? find_cloud_by_name_or_id_for_provisioning(group_id, options[:cloud]) : nil
|
1047
|
-
cloud = options[:cloud] ? find_zone_by_name_or_id(nil, options[:cloud]) : nil
|
1048
|
-
if cloud
|
1049
|
-
params['zoneId'] = cloud['id']
|
1050
|
-
end
|
1051
|
-
|
1052
|
-
[:phrase, :offset, :max, :sort, :direction].each do |k|
|
1053
|
-
params[k] = options[k] unless options[k].nil?
|
1054
|
-
end
|
1055
|
-
|
1056
|
-
if options[:dry_run]
|
1057
|
-
print_dry_run @instances_interface.dry.list(params)
|
1058
|
-
return
|
1059
|
-
end
|
1060
|
-
json_response = @instances_interface.get(params)
|
1061
|
-
if options[:json]
|
1062
|
-
if options[:include_fields]
|
1063
|
-
json_response = {"instances" => filter_data(json_response["instances"], options[:include_fields]) }
|
1064
|
-
end
|
1065
|
-
puts as_json(json_response, options)
|
1066
|
-
return 0
|
1067
|
-
elsif options[:yaml]
|
1068
|
-
if options[:include_fields]
|
1069
|
-
json_response = {"instances" => filter_data(json_response["instances"], options[:include_fields]) }
|
1070
|
-
end
|
1071
|
-
puts as_yaml(json_response, options)
|
1072
|
-
return 0
|
1073
|
-
elsif options[:csv]
|
1074
|
-
# merge stats to be nice here..
|
1075
|
-
if json_response['instances']
|
1076
|
-
all_stats = json_response['stats'] || {}
|
1077
|
-
json_response['instances'].each do |it|
|
1078
|
-
it['stats'] ||= all_stats[it['id'].to_s] || all_stats[it['id']]
|
1079
|
-
end
|
1080
|
-
end
|
1081
|
-
puts records_as_csv(json_response['instances'], options)
|
1082
|
-
else
|
1083
|
-
instances = json_response['instances']
|
1084
|
-
|
1085
|
-
title = "Morpheus Instances"
|
1086
|
-
subtitles = []
|
1087
|
-
if group
|
1088
|
-
subtitles << "Group: #{group['name']}".strip
|
1089
|
-
end
|
1090
|
-
if cloud
|
1091
|
-
subtitles << "Cloud: #{cloud['name']}".strip
|
1092
|
-
end
|
1093
|
-
if params[:phrase]
|
1094
|
-
subtitles << "Search: #{params[:phrase]}".strip
|
1095
|
-
end
|
1096
|
-
print_h1 title, subtitles
|
1097
|
-
if instances.empty?
|
1098
|
-
print yellow,"No instances found.",reset,"\n"
|
1099
|
-
else
|
1100
|
-
# print_instances_table(instances)
|
1101
|
-
# server returns stats in a separate key stats => {"id" => {} }
|
1102
|
-
# the id is a string right now..for some reason..
|
1103
|
-
all_stats = json_response['stats'] || {}
|
1104
|
-
instances.each do |it|
|
1105
|
-
if !it['stats']
|
1106
|
-
found_stats = all_stats[it['id'].to_s] || all_stats[it['id']]
|
1107
|
-
it['stats'] = found_stats # || {}
|
1108
|
-
end
|
1109
|
-
end
|
1110
|
-
|
1111
|
-
rows = instances.collect {|instance|
|
1112
|
-
stats = instance['stats']
|
1113
|
-
cpu_usage_str = !stats ? "" : generate_usage_bar((stats['usedCpu'] || stats['cpuUsage']).to_f, 100, {max_bars: 10})
|
1114
|
-
memory_usage_str = !stats ? "" : generate_usage_bar(stats['usedMemory'], stats['maxMemory'], {max_bars: 10})
|
1115
|
-
storage_usage_str = !stats ? "" : generate_usage_bar(stats['usedStorage'], stats['maxStorage'], {max_bars: 10})
|
1116
|
-
row = {
|
1117
|
-
id: instance['id'],
|
1118
|
-
name: instance['name'],
|
1119
|
-
connection: format_instance_connection_string(instance),
|
1120
|
-
environment: instance['instanceContext'],
|
1121
|
-
nodes: instance['containers'].count,
|
1122
|
-
status: format_instance_status(instance, cyan),
|
1123
|
-
type: instance['instanceType']['name'],
|
1124
|
-
group: !instance['group'].nil? ? instance['group']['name'] : nil,
|
1125
|
-
cloud: !instance['cloud'].nil? ? instance['cloud']['name'] : nil,
|
1126
|
-
version: instance['instanceVersion'] ? instance['instanceVersion'] : '',
|
1127
|
-
cpu: cpu_usage_str + cyan,
|
1128
|
-
memory: memory_usage_str + cyan,
|
1129
|
-
storage: storage_usage_str + cyan
|
1130
|
-
}
|
1131
|
-
row
|
1132
|
-
}
|
1133
|
-
columns = [:id, :name, :group, :cloud, :type, :version, :environment, :nodes, {:connection => {max_width: 20}}, :status]
|
1134
|
-
term_width = current_terminal_width()
|
1135
|
-
if term_width > 190
|
1136
|
-
columns += [:cpu, :memory, :storage]
|
1137
|
-
end
|
1138
|
-
# custom pretty table columns ...
|
1139
|
-
if options[:include_fields]
|
1140
|
-
columns = options[:include_fields]
|
1141
|
-
end
|
1142
|
-
print cyan
|
1143
|
-
print as_pretty_table(rows, columns, options)
|
1144
|
-
print reset
|
1145
|
-
print_results_pagination(json_response)
|
1146
|
-
end
|
1147
|
-
print reset,"\n"
|
1148
|
-
end
|
1149
|
-
rescue RestClient::Exception => e
|
1150
|
-
print_rest_exception(e, options)
|
1151
|
-
exit 1
|
1152
|
-
end
|
1153
|
-
end
|
1154
|
-
|
1155
1512
|
def remove(args)
|
1156
1513
|
options = {}
|
1157
1514
|
query_params = {keepBackups: 'off', force: 'off'}
|
@@ -1186,7 +1543,8 @@ class Morpheus::Cli::Instances
|
|
1186
1543
|
print as_json(json_response, options), "\n"
|
1187
1544
|
return
|
1188
1545
|
elsif !options[:quiet]
|
1189
|
-
|
1546
|
+
print_green_success "Removing instance #{instance['name']}"
|
1547
|
+
#list([])
|
1190
1548
|
end
|
1191
1549
|
rescue RestClient::Exception => e
|
1192
1550
|
print_rest_exception(e, options)
|
@@ -1459,11 +1817,322 @@ class Morpheus::Cli::Instances
|
|
1459
1817
|
end
|
1460
1818
|
end
|
1461
1819
|
|
1462
|
-
|
1463
|
-
def
|
1820
|
+
|
1821
|
+
def scaling(args)
|
1822
|
+
options = {}
|
1823
|
+
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
1824
|
+
opts.banner = subcommand_usage("[name]")
|
1825
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
1826
|
+
opts.footer = "Show scaling threshold information for an instance."
|
1827
|
+
end
|
1828
|
+
optparse.parse!(args)
|
1829
|
+
if args.count < 1
|
1830
|
+
print_error Morpheus::Terminal.angry_prompt
|
1831
|
+
puts_error "#{command_name} scaling requires argument [id or name list]\n#{optparse}"
|
1832
|
+
return 1
|
1833
|
+
end
|
1834
|
+
connect(options)
|
1835
|
+
id_list = parse_id_list(args)
|
1836
|
+
return run_command_for_each_arg(id_list) do |arg|
|
1837
|
+
_scaling(arg, options)
|
1838
|
+
end
|
1839
|
+
end
|
1840
|
+
|
1841
|
+
def _scaling(arg, options)
|
1842
|
+
instance = find_instance_by_name_or_id(arg)
|
1843
|
+
return 1 if instance.nil?
|
1844
|
+
if options[:dry_run]
|
1845
|
+
print_dry_run @instances_interface.dry.threshold(instance['id'], params)
|
1846
|
+
return 0
|
1847
|
+
end
|
1848
|
+
json_response = @instances_interface.threshold(instance['id'])
|
1849
|
+
if options[:include_fields]
|
1850
|
+
json_response = {"instanceThreshold" => filter_data(json_response["instanceThreshold"], options[:include_fields]) }
|
1851
|
+
end
|
1852
|
+
if options[:json]
|
1853
|
+
puts as_json(json_response, options)
|
1854
|
+
return 0
|
1855
|
+
elsif options[:yaml]
|
1856
|
+
puts as_yaml(json_response, options)
|
1857
|
+
return 0
|
1858
|
+
elsif options[:csv]
|
1859
|
+
puts records_as_csv([json_response['instanceThreshold']], options)
|
1860
|
+
return 0
|
1861
|
+
end
|
1862
|
+
|
1863
|
+
instance_threshold = json_response['instanceThreshold']
|
1864
|
+
|
1865
|
+
title = "Instance Scaling: [#{instance['id']}] #{instance['name']} (#{instance['instanceType']['name']})"
|
1866
|
+
print_h1 title
|
1867
|
+
if instance_threshold.empty?
|
1868
|
+
print yellow,"No scaling settings applied to this instance.",reset,"\n"
|
1869
|
+
else
|
1870
|
+
# print_h1 "Threshold Settings"
|
1871
|
+
print cyan
|
1872
|
+
print_instance_threshold_description_list(instance_threshold)
|
1873
|
+
end
|
1874
|
+
print reset, "\n"
|
1875
|
+
return 0
|
1876
|
+
|
1877
|
+
end
|
1878
|
+
|
1879
|
+
def scaling_update(args)
|
1880
|
+
usage = "Usage: morpheus instances scaling-update [name] [options]"
|
1881
|
+
options = {}
|
1882
|
+
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
1883
|
+
opts.banner = subcommand_usage("[name]")
|
1884
|
+
build_option_type_options(opts, options, instance_scaling_option_types(nil))
|
1885
|
+
build_common_options(opts, options, [:options, :json, :dry_run, :remote])
|
1886
|
+
opts.footer = "Update scaling threshold information for an instance."
|
1887
|
+
end
|
1888
|
+
optparse.parse!(args)
|
1889
|
+
# if args.count < 1
|
1890
|
+
if args.count != 1
|
1891
|
+
print_error Morpheus::Terminal.angry_prompt
|
1892
|
+
puts_error "#{command_name} scaling-update requires only one argument [id or name]\n#{optparse}"
|
1893
|
+
return 1
|
1894
|
+
end
|
1895
|
+
connect(options)
|
1896
|
+
|
1897
|
+
begin
|
1898
|
+
|
1899
|
+
instance = find_instance_by_name_or_id(args[0])
|
1900
|
+
return 1 if instance.nil?
|
1901
|
+
instance_threshold = @instances_interface.threshold(instance['id'])['instanceThreshold'] || {}
|
1902
|
+
my_option_types = instance_scaling_option_types(instance)
|
1903
|
+
|
1904
|
+
# preserve current values by setting the prompt options defaultValue attribute
|
1905
|
+
# note: checkbox type converts true,false to 'on','off'
|
1906
|
+
my_option_types.each do |opt|
|
1907
|
+
field_key = opt['fieldName'] # .sub('instanceThreshold.', '')
|
1908
|
+
if instance_threshold[field_key] != nil
|
1909
|
+
opt['defaultValue'] = instance_threshold[field_key]
|
1910
|
+
end
|
1911
|
+
end
|
1912
|
+
|
1913
|
+
# params = Morpheus::Cli::OptionTypes.prompt(my_option_types, options[:options], @api_client, {})
|
1914
|
+
|
1915
|
+
# ok, gotta split these inputs into sections with conditional logic
|
1916
|
+
params = {}
|
1917
|
+
|
1918
|
+
option_types_group = my_option_types.select {|opt| ['autoUp', 'autoDown'].include?(opt['fieldName']) }
|
1919
|
+
params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
|
1920
|
+
|
1921
|
+
option_types_group = my_option_types.select {|opt| ['zoneId'].include?(opt['fieldName']) }
|
1922
|
+
params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
|
1923
|
+
if params['zoneId']
|
1924
|
+
if params['zoneId'] == '' || params['zoneId'] == 'null' || params['zoneId'].to_s == '0'
|
1925
|
+
params['zoneId'] = 0
|
1926
|
+
else
|
1927
|
+
params['zoneId'] = params['zoneId'].to_i
|
1928
|
+
end
|
1929
|
+
end
|
1930
|
+
|
1931
|
+
option_types_group = my_option_types.select {|opt| ['minCount', 'maxCount'].include?(opt['fieldName']) }
|
1932
|
+
params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
|
1933
|
+
|
1934
|
+
option_types_group = my_option_types.select {|opt| ['memoryEnabled'].include?(opt['fieldName']) }
|
1935
|
+
params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
|
1936
|
+
if params['memoryEnabled'] == 'on' || params['memoryEnabled'] == true
|
1937
|
+
option_types_group = my_option_types.select {|opt| ['minMemory', 'maxMemory'].include?(opt['fieldName']) }
|
1938
|
+
params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
|
1939
|
+
else
|
1940
|
+
params['minMemory'] = nil
|
1941
|
+
params['maxMemory'] = nil
|
1942
|
+
end
|
1943
|
+
|
1944
|
+
option_types_group = my_option_types.select {|opt| ['diskEnabled'].include?(opt['fieldName']) }
|
1945
|
+
params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
|
1946
|
+
if params['diskEnabled'] == 'on' || params['diskEnabled'] == true
|
1947
|
+
option_types_group = my_option_types.select {|opt| ['minDisk', 'maxDisk'].include?(opt['fieldName']) }
|
1948
|
+
params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
|
1949
|
+
else
|
1950
|
+
params['minDisk'] = nil
|
1951
|
+
params['maxDisk'] = nil
|
1952
|
+
end
|
1953
|
+
|
1954
|
+
option_types_group = my_option_types.select {|opt| ['cpuEnabled'].include?(opt['fieldName']) }
|
1955
|
+
params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
|
1956
|
+
if params['cpuEnabled'] == 'on' || params['cpuEnabled'] == true
|
1957
|
+
option_types_group = my_option_types.select {|opt| ['minCpu', 'maxCpu'].include?(opt['fieldName']) }
|
1958
|
+
params.merge! Morpheus::Cli::OptionTypes.prompt(option_types_group, options[:options], @api_client, {})
|
1959
|
+
else
|
1960
|
+
params['minCpu'] = nil
|
1961
|
+
params['maxCpu'] = nil
|
1962
|
+
end
|
1963
|
+
|
1964
|
+
# argh, convert on/off to true/false
|
1965
|
+
# this needs a global solution...
|
1966
|
+
params.each do |k,v|
|
1967
|
+
if v == 'on' || v == 'true' || v == 'yes'
|
1968
|
+
params[k] = true
|
1969
|
+
elsif v == 'off' || v == 'false' || v == 'no'
|
1970
|
+
params[k] = false
|
1971
|
+
end
|
1972
|
+
end
|
1973
|
+
|
1974
|
+
payload = {
|
1975
|
+
'instanceThreshold' => {}
|
1976
|
+
}
|
1977
|
+
payload['instanceThreshold'].merge!(params)
|
1978
|
+
|
1979
|
+
# unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to update the scaling settings for instance '#{instance['name']}'?", options)
|
1980
|
+
# return 9, "aborted command"
|
1981
|
+
# end
|
1982
|
+
|
1983
|
+
if options[:dry_run]
|
1984
|
+
print_dry_run @instances_interface.dry.update_threshold(instance['id'], payload)
|
1985
|
+
return
|
1986
|
+
end
|
1987
|
+
json_response = @instances_interface.update_threshold(instance['id'], payload)
|
1988
|
+
if options[:json]
|
1989
|
+
puts as_json(json_response, options)
|
1990
|
+
else
|
1991
|
+
print_green_success "Updated scaling settings for instance #{instance['name']}"
|
1992
|
+
end
|
1993
|
+
return 0
|
1994
|
+
rescue RestClient::Exception => e
|
1995
|
+
print_rest_exception(e, options)
|
1996
|
+
exit 1
|
1997
|
+
end
|
1998
|
+
end
|
1999
|
+
|
2000
|
+
def load_balancer_update(args)
|
2001
|
+
raise "Not Yet Implemented"
|
2002
|
+
usage = "Usage: morpheus instances lb-update [name] [options]"
|
2003
|
+
options = {}
|
2004
|
+
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
2005
|
+
opts.banner = subcommand_usage("[name]")
|
2006
|
+
#build_option_type_options(opts, options, instance_load_balancer_option_types(nil))
|
2007
|
+
build_common_options(opts, options, [:options, :json, :dry_run, :remote])
|
2008
|
+
opts.footer = "Assign a load balancer for an instance."
|
2009
|
+
end
|
2010
|
+
optparse.parse!(args)
|
2011
|
+
# if args.count < 1
|
2012
|
+
if args.count != 1
|
2013
|
+
print_error Morpheus::Terminal.angry_prompt
|
2014
|
+
puts_error "#{command_name} lb-update requires only one argument [id or name]\n#{optparse}"
|
2015
|
+
return 1
|
2016
|
+
end
|
2017
|
+
connect(options)
|
2018
|
+
|
2019
|
+
begin
|
2020
|
+
|
2021
|
+
instance = find_instance_by_name_or_id(args[0])
|
2022
|
+
return 1 if instance.nil?
|
2023
|
+
# refetch to get loadBalancers from show()
|
2024
|
+
json_response = @instances_interface.get(instance['id'])
|
2025
|
+
|
2026
|
+
current_instance_lb = nil
|
2027
|
+
# refetch to get current load balancer info from show()
|
2028
|
+
json_response = @instances_interface.get(instance['id'])
|
2029
|
+
#load_balancers = @instances_interface.threshold(instance['id'])['loadBalancers'] || {}
|
2030
|
+
if json_response['loadBalancers'] && json_response['loadBalancers'][0] && json_response['loadBalancers'][0]['lbs'] && json_response['loadBalancers'][0]['lbs'][0]
|
2031
|
+
current_instance_lb = json_response['loadBalancers'][0]['lbs'][0]
|
2032
|
+
#current_load_balancer = current_instance_lb['loadBalancer']
|
2033
|
+
#current_load_balancer_port = current_instance_lb['port']
|
2034
|
+
end
|
2035
|
+
|
2036
|
+
#my_option_types = instance_load_balancer_option_types(instance)
|
2037
|
+
|
2038
|
+
# todo...
|
2039
|
+
|
2040
|
+
# Host Name
|
2041
|
+
# Load Balancer
|
2042
|
+
# Protocol
|
2043
|
+
# Port
|
2044
|
+
# SSL Cert
|
2045
|
+
# Scheme
|
2046
|
+
|
2047
|
+
current_instance_lb = json_response['loadBalancers'][0]['lbs'][0]
|
2048
|
+
|
2049
|
+
params = {}
|
2050
|
+
|
2051
|
+
payload = {
|
2052
|
+
'instance' => {},
|
2053
|
+
'networkLoadBalancer' => {}
|
2054
|
+
}
|
2055
|
+
|
2056
|
+
cur_host_name = instance['hostName']
|
2057
|
+
#host_name = params = Morpheus::Cli::OptionTypes.prompt([{fieldName:'hostName'}], options[:options], @api_client, {})
|
2058
|
+
payload['instance']['hostName'] = instance['hostName']
|
2059
|
+
|
2060
|
+
payload['loadBalancerId'] = 9999
|
2061
|
+
|
2062
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to update the load balancer for instance '#{instance['name']}'?", options)
|
2063
|
+
return 9, "aborted command"
|
2064
|
+
end
|
2065
|
+
|
2066
|
+
if options[:dry_run]
|
2067
|
+
print_dry_run @instances_interface.dry.update_threshold(instance['id'], payload)
|
2068
|
+
return
|
2069
|
+
end
|
2070
|
+
json_response = @instances_interface.update_threshold(instance['id'], payload)
|
2071
|
+
if options[:json]
|
2072
|
+
puts as_json(json_response, options)
|
2073
|
+
else
|
2074
|
+
print_green_success "Updated scaling settings for instance #{instance['name']}"
|
2075
|
+
end
|
2076
|
+
return 0
|
2077
|
+
rescue RestClient::Exception => e
|
2078
|
+
print_rest_exception(e, options)
|
2079
|
+
exit 1
|
2080
|
+
end
|
2081
|
+
end
|
2082
|
+
|
2083
|
+
def load_balancer_remove(args)
|
2084
|
+
usage = "Usage: morpheus instances lb-remove [name] [options]"
|
2085
|
+
options = {}
|
2086
|
+
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
2087
|
+
opts.banner = subcommand_usage("[name]")
|
2088
|
+
build_option_type_options(opts, options, instance_scaling_option_types(nil))
|
2089
|
+
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
|
2090
|
+
opts.footer = "Remove a load balancer from an instance."
|
2091
|
+
end
|
2092
|
+
optparse.parse!(args)
|
2093
|
+
# if args.count < 1
|
2094
|
+
if args.count != 1
|
2095
|
+
print_error Morpheus::Terminal.angry_prompt
|
2096
|
+
puts_error "#{command_name} lb-remove requires only one argument [id or name]\n#{optparse}"
|
2097
|
+
return 1
|
2098
|
+
end
|
2099
|
+
connect(options)
|
2100
|
+
|
2101
|
+
begin
|
2102
|
+
|
2103
|
+
instance = find_instance_by_name_or_id(args[0])
|
2104
|
+
return 1 if instance.nil?
|
2105
|
+
|
2106
|
+
# re-fetch via show() get loadBalancers
|
2107
|
+
json_response = @instances_interface.get(instance['id'])
|
2108
|
+
load_balancers = json_response['instance']['loadBalancers']
|
2109
|
+
|
2110
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove the load balancer for instance '#{instance['name']}'?", options)
|
2111
|
+
return 9, "aborted command"
|
2112
|
+
end
|
2113
|
+
|
2114
|
+
# no options here, just send DELETE request
|
2115
|
+
payload = {}
|
2116
|
+
|
2117
|
+
if options[:dry_run]
|
2118
|
+
print_dry_run @instances_interface.dry.remove_load_balancer(instance['id'], payload)
|
2119
|
+
return
|
2120
|
+
end
|
2121
|
+
json_response = @instances_interface.remove_load_balancer(instance['id'], payload)
|
2122
|
+
if options[:json]
|
2123
|
+
puts as_json(json_response, options)
|
2124
|
+
else
|
2125
|
+
print_green_success "Removed load balancer from instance #{instance['name']}"
|
2126
|
+
end
|
2127
|
+
return 0
|
2128
|
+
rescue RestClient::Exception => e
|
2129
|
+
print_rest_exception(e, options)
|
2130
|
+
exit 1
|
2131
|
+
end
|
1464
2132
|
end
|
1465
2133
|
|
1466
|
-
|
2134
|
+
private
|
2135
|
+
|
1467
2136
|
def find_zone_by_name_or_id(group_id, val)
|
1468
2137
|
zone = nil
|
1469
2138
|
if val.to_s =~ /\A\d{1,}\Z/
|
@@ -1516,7 +2185,7 @@ class Morpheus::Cli::Instances
|
|
1516
2185
|
|
1517
2186
|
def format_instance_status(instance, return_color=cyan)
|
1518
2187
|
out = ""
|
1519
|
-
status_string = instance['status']
|
2188
|
+
status_string = instance['status'].to_s
|
1520
2189
|
if status_string == 'running'
|
1521
2190
|
out << "#{green}#{status_string.upcase}#{return_color}"
|
1522
2191
|
elsif status_string == 'stopped' or status_string == 'failed'
|
@@ -1535,10 +2204,127 @@ class Morpheus::Cli::Instances
|
|
1535
2204
|
end
|
1536
2205
|
end
|
1537
2206
|
|
2207
|
+
def format_container_status(container, return_color=cyan)
|
2208
|
+
out = ""
|
2209
|
+
status_string = container['status'].to_s
|
2210
|
+
if status_string == 'running'
|
2211
|
+
out << "#{green}#{status_string.upcase}#{return_color}"
|
2212
|
+
elsif status_string == 'stopped' or status_string == 'failed'
|
2213
|
+
out << "#{red}#{status_string.upcase}#{return_color}"
|
2214
|
+
elsif status_string == 'unknown'
|
2215
|
+
out << "#{white}#{status_string.upcase}#{return_color}"
|
2216
|
+
else
|
2217
|
+
out << "#{yellow}#{status_string.upcase}#{return_color}"
|
2218
|
+
end
|
2219
|
+
out
|
2220
|
+
end
|
2221
|
+
|
2222
|
+
def format_container_connection_string(container)
|
2223
|
+
if !container['ports'].nil? && container['ports'].empty? == false
|
2224
|
+
connection_string = "#{container['ip']}:#{container['ports'][0]['external']}"
|
2225
|
+
else
|
2226
|
+
# eh? more logic needed here i think, see taglib morph:containerLocationMenu
|
2227
|
+
connection_string = "#{container['ip']}"
|
2228
|
+
end
|
2229
|
+
end
|
2230
|
+
|
1538
2231
|
def clone_instance_option_types(connected=true)
|
1539
2232
|
[
|
1540
2233
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Enter a name for the new instance'},
|
1541
2234
|
{'fieldName' => 'group', 'fieldLabel' => 'Group', 'type' => 'select', 'selectOptions' => (connected ? get_available_groups() : []), 'required' => true},
|
1542
2235
|
]
|
1543
2236
|
end
|
2237
|
+
|
2238
|
+
def instance_scaling_option_types(instance=nil)
|
2239
|
+
|
2240
|
+
# Group
|
2241
|
+
group_id = nil
|
2242
|
+
if instance && instance['group']
|
2243
|
+
group_id = instance['group']['id']
|
2244
|
+
end
|
2245
|
+
|
2246
|
+
available_clouds = group_id ? get_available_clouds(group_id) : []
|
2247
|
+
zone_dropdown = [{'name' => 'Use Scale Priority', 'value' => 0}]
|
2248
|
+
zone_dropdown += available_clouds.collect {|cloud| {'name' => cloud['name'], 'value' => cloud['id']} }
|
2249
|
+
|
2250
|
+
list = []
|
2251
|
+
list << {'fieldName' => 'autoUp', 'fieldLabel' => 'Auto Upscale', 'type' => 'checkbox', 'description' => 'Enable auto upscaling', 'required' => true, 'defaultValue' => false}
|
2252
|
+
list << {'fieldName' => 'autoDown', 'fieldLabel' => 'Auto Downscale', 'type' => 'checkbox', 'description' => 'Enable auto downscaling', 'required' => true, 'defaultValue' => false}
|
2253
|
+
|
2254
|
+
list << {'fieldName' => 'zoneId', 'fieldLabel' => 'Cloud', 'type' => 'select', 'selectOptions' => zone_dropdown, 'description' => "Choose a cloud to scale into.", 'placeHolder' => 'ID'}
|
2255
|
+
|
2256
|
+
list << {'fieldName' => 'minCount', 'fieldLabel' => 'Min Count', 'type' => 'number', 'description' => 'Minimum number of nodes', 'placeHolder' => 'NUMBER'}
|
2257
|
+
list << {'fieldName' => 'maxCount', 'fieldLabel' => 'Max Count', 'type' => 'number', 'description' => 'Maximum number of nodes', 'placeHolder' => 'NUMBER'}
|
2258
|
+
|
2259
|
+
|
2260
|
+
list << {'fieldName' => 'memoryEnabled', 'fieldLabel' => 'Enable Memory Threshold', 'type' => 'checkbox', 'description' => 'Scale when memory thresholds are met.', 'required' => true, 'defaultValue' => false}
|
2261
|
+
list << {'fieldName' => 'minMemory', 'fieldLabel' => 'Min Memory', 'type' => 'number', 'description' => 'Minimum memory percent (0-100)', 'placeHolder' => 'PERCENT'}
|
2262
|
+
list << {'fieldName' => 'maxMemory', 'fieldLabel' => 'Max Memory', 'type' => 'number', 'description' => 'Maximum memory percent (0-100)', 'placeHolder' => 'PERCENT'}
|
2263
|
+
|
2264
|
+
list << {'fieldName' => 'diskEnabled', 'fieldLabel' => 'Enable Disk Threshold', 'type' => 'checkbox', 'description' => 'Scale when disk thresholds are met.', 'required' => true, 'defaultValue' => false}
|
2265
|
+
list << {'fieldName' => 'minDisk', 'fieldLabel' => 'Min Disk', 'type' => 'number', 'description' => 'Minimum storage percent (0-100)', 'placeHolder' => 'PERCENT'}
|
2266
|
+
list << {'fieldName' => 'maxDisk', 'fieldLabel' => 'Max Disk', 'type' => 'number', 'description' => 'Maximum storage percent (0-100)', 'placeHolder' => 'PERCENT'}
|
2267
|
+
|
2268
|
+
list << {'fieldName' => 'cpuEnabled', 'fieldLabel' => 'Enable CPU Threshold', 'type' => 'checkbox', 'description' => 'Scale when cpu thresholds are met.', 'required' => true, 'defaultValue' => false}
|
2269
|
+
list << {'fieldName' => 'minCpu', 'fieldLabel' => 'Min CPU', 'type' => 'number', 'description' => 'Minimum CPU percent (0-100)', 'placeHolder' => 'PERCENT'}
|
2270
|
+
list << {'fieldName' => 'maxCpu', 'fieldLabel' => 'Max CPU', 'type' => 'number', 'description' => 'Maximum CPU percent (0-100)', 'placeHolder' => 'PERCENT'}
|
2271
|
+
|
2272
|
+
# list << {'fieldName' => 'iopsEnabled', 'fieldLabel' => 'Enable Iops Threshold', 'type' => 'checkbox', 'description' => 'Scale when iops thresholds are met.'}
|
2273
|
+
# list << {'fieldName' => 'minIops', 'fieldLabel' => 'Min Iops', 'type' => 'number', 'description' => 'Minimum iops'}
|
2274
|
+
# list << {'fieldName' => 'maxIops', 'fieldLabel' => 'Max Iops', 'type' => 'number', 'description' => 'Maximum iops'}
|
2275
|
+
|
2276
|
+
# list << {'fieldName' => 'networkEnabled', 'fieldLabel' => 'Enable Iops Threshold', 'type' => 'checkbox', 'description' => 'Scale when network thresholds are met.'}
|
2277
|
+
# list << {'fieldName' => 'minNetwork', 'fieldLabel' => 'Min Network', 'type' => 'number', 'description' => 'Minimum networking'}
|
2278
|
+
|
2279
|
+
# list << {'fieldName' => 'comment', 'fieldLabel' => 'Comment', 'type' => 'text', 'description' => 'Comment on these scaling settings.'}
|
2280
|
+
|
2281
|
+
list
|
2282
|
+
end
|
2283
|
+
|
2284
|
+
def instance_load_balancer_option_types(instance=nil)
|
2285
|
+
list = []
|
2286
|
+
list << {'fieldContext' => 'instance', 'fieldName' => 'hostName', 'fieldLabel' => 'Host Name', 'type' => 'checkbox', 'description' => 'Enable auto upscaling', 'required' => true, 'defaultValue' => instance ? instance['hostName'] : nil}
|
2287
|
+
list << {'fieldName' => 'proxyProtocol', 'fieldLabel' => 'Protocol', 'type' => 'checkbox', 'description' => 'Enable auto downscaling', 'required' => true, 'defaultValue' => false}
|
2288
|
+
list
|
2289
|
+
end
|
2290
|
+
|
2291
|
+
def format_instance_container_display_name(instance, plural=false)
|
2292
|
+
#<span class="info-label">${[null,'docker'].contains(instance.layout?.provisionType?.code) ? 'Containers' : 'Virtual Machines'}:</span> <span class="info-value">${instance.containers?.size()}</span>
|
2293
|
+
v = plural ? "Containers" : "Container"
|
2294
|
+
if instance && instance['layout'] && instance['layout'].key?("provisionTypeCode")
|
2295
|
+
if [nil, 'docker'].include?(instance['layout']["provisionTypeCode"])
|
2296
|
+
v = plural ? "Virtual Machines" : "Virtual Machine"
|
2297
|
+
end
|
2298
|
+
end
|
2299
|
+
return v
|
2300
|
+
end
|
2301
|
+
|
2302
|
+
def print_instance_threshold_description_list(instance_threshold)
|
2303
|
+
description_cols = {
|
2304
|
+
# "Instance" => lambda {|it| "#{instance['id']} - #{instance['name']}" },
|
2305
|
+
"Auto Upscale" => lambda {|it| format_boolean(it['autoUp']) },
|
2306
|
+
"Auto Downscale" => lambda {|it| format_boolean(it['autoDown']) },
|
2307
|
+
"Cloud" => lambda {|it| it['zoneId'] ? "#{it['zoneId']}" : 'Use Scale Priority' },
|
2308
|
+
"Min Count" => lambda {|it| it['minCount'] },
|
2309
|
+
"Max Count" => lambda {|it| it['maxCount'] },
|
2310
|
+
"Memory Enabled" => lambda {|it| format_boolean(it['memoryEnabled']) },
|
2311
|
+
"Min Memory" => lambda {|it| it['memoryEnabled'] ? (it['minMemory'] ? "#{it['minMemory']}%" : '') : '' },
|
2312
|
+
"Max Memory" => lambda {|it| it['memoryEnabled'] ? (it['maxMemory'] ? "#{it['maxMemory']}%" : '') : '' },
|
2313
|
+
"Disk Enabled" => lambda {|it| format_boolean(it['diskEnabled']) },
|
2314
|
+
"Min Disk" => lambda {|it| it['diskEnabled'] ? (it['minDisk'] ? "#{it['minDisk']}%" : '') : '' },
|
2315
|
+
"Max Disk" => lambda {|it| it['diskEnabled'] ? (it['maxDisk'] ? "#{it['maxDisk']}%" : '') : '' },
|
2316
|
+
"CPU Enabled" => lambda {|it| format_boolean(it['cpuEnabled']) },
|
2317
|
+
"Min CPU" => lambda {|it| it['cpuEnabled'] ? (it['minCpu'] ? "#{it['minCpu']}%" : '') : '' },
|
2318
|
+
"Max CPU" => lambda {|it| it['cpuEnabled'] ? (it['maxCpu'] ? "#{it['maxCpu']}%" : '') : '' },
|
2319
|
+
# "Iops Enabled" => lambda {|it| format_boolean(it['iopsEnabled']) },
|
2320
|
+
# "Min Iops" => lambda {|it| it['minIops'] },
|
2321
|
+
# "Max Iops" => lambda {|it| it['maxDisk'] },
|
2322
|
+
# "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
2323
|
+
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
2324
|
+
}
|
2325
|
+
print_description_list(description_cols, instance_threshold)
|
2326
|
+
end
|
2327
|
+
|
2328
|
+
|
2329
|
+
|
1544
2330
|
end
|