morpheus-cli 2.11.0 → 2.11.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|