morpheus-cli 2.10.0 → 2.10.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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/bin/morpheus +27 -32
  3. data/lib/morpheus/api/accounts_interface.rb +36 -47
  4. data/lib/morpheus/api/api_client.rb +141 -110
  5. data/lib/morpheus/api/app_templates_interface.rb +56 -72
  6. data/lib/morpheus/api/apps_interface.rb +111 -132
  7. data/lib/morpheus/api/auth_interface.rb +30 -0
  8. data/lib/morpheus/api/clouds_interface.rb +71 -76
  9. data/lib/morpheus/api/custom_instance_types_interface.rb +21 -46
  10. data/lib/morpheus/api/dashboard_interface.rb +10 -17
  11. data/lib/morpheus/api/deploy_interface.rb +60 -72
  12. data/lib/morpheus/api/deployments_interface.rb +53 -71
  13. data/lib/morpheus/api/groups_interface.rb +55 -45
  14. data/lib/morpheus/api/instance_types_interface.rb +19 -23
  15. data/lib/morpheus/api/instances_interface.rb +179 -177
  16. data/lib/morpheus/api/key_pairs_interface.rb +11 -17
  17. data/lib/morpheus/api/license_interface.rb +18 -23
  18. data/lib/morpheus/api/load_balancers_interface.rb +54 -69
  19. data/lib/morpheus/api/logs_interface.rb +25 -29
  20. data/lib/morpheus/api/options_interface.rb +13 -17
  21. data/lib/morpheus/api/provision_types_interface.rb +19 -22
  22. data/lib/morpheus/api/roles_interface.rb +75 -94
  23. data/lib/morpheus/api/security_group_rules_interface.rb +28 -37
  24. data/lib/morpheus/api/security_groups_interface.rb +39 -51
  25. data/lib/morpheus/api/servers_interface.rb +113 -115
  26. data/lib/morpheus/api/setup_interface.rb +31 -0
  27. data/lib/morpheus/api/task_sets_interface.rb +36 -38
  28. data/lib/morpheus/api/tasks_interface.rb +56 -69
  29. data/lib/morpheus/api/users_interface.rb +67 -76
  30. data/lib/morpheus/api/virtual_images_interface.rb +61 -61
  31. data/lib/morpheus/api/whoami_interface.rb +12 -15
  32. data/lib/morpheus/cli.rb +71 -60
  33. data/lib/morpheus/cli/accounts.rb +254 -315
  34. data/lib/morpheus/cli/alias_command.rb +219 -0
  35. data/lib/morpheus/cli/app_templates.rb +264 -272
  36. data/lib/morpheus/cli/apps.rb +608 -671
  37. data/lib/morpheus/cli/cli_command.rb +259 -21
  38. data/lib/morpheus/cli/cli_registry.rb +99 -14
  39. data/lib/morpheus/cli/clouds.rb +599 -372
  40. data/lib/morpheus/cli/config_file.rb +126 -0
  41. data/lib/morpheus/cli/credentials.rb +141 -117
  42. data/lib/morpheus/cli/dashboard_command.rb +48 -56
  43. data/lib/morpheus/cli/deployments.rb +254 -268
  44. data/lib/morpheus/cli/deploys.rb +150 -142
  45. data/lib/morpheus/cli/error_handler.rb +38 -0
  46. data/lib/morpheus/cli/groups.rb +551 -179
  47. data/lib/morpheus/cli/hosts.rb +862 -617
  48. data/lib/morpheus/cli/instance_types.rb +103 -95
  49. data/lib/morpheus/cli/instances.rb +1335 -1009
  50. data/lib/morpheus/cli/key_pairs.rb +82 -90
  51. data/lib/morpheus/cli/library.rb +498 -499
  52. data/lib/morpheus/cli/license.rb +83 -101
  53. data/lib/morpheus/cli/load_balancers.rb +314 -300
  54. data/lib/morpheus/cli/login.rb +66 -44
  55. data/lib/morpheus/cli/logout.rb +47 -46
  56. data/lib/morpheus/cli/mixins/accounts_helper.rb +69 -31
  57. data/lib/morpheus/cli/mixins/infrastructure_helper.rb +106 -0
  58. data/lib/morpheus/cli/mixins/print_helper.rb +181 -17
  59. data/lib/morpheus/cli/mixins/provisioning_helper.rb +535 -458
  60. data/lib/morpheus/cli/mixins/whoami_helper.rb +2 -2
  61. data/lib/morpheus/cli/option_parser.rb +35 -0
  62. data/lib/morpheus/cli/option_types.rb +232 -192
  63. data/lib/morpheus/cli/recent_activity_command.rb +61 -65
  64. data/lib/morpheus/cli/remote.rb +446 -199
  65. data/lib/morpheus/cli/roles.rb +884 -906
  66. data/lib/morpheus/cli/security_group_rules.rb +213 -203
  67. data/lib/morpheus/cli/security_groups.rb +237 -192
  68. data/lib/morpheus/cli/shell.rb +338 -231
  69. data/lib/morpheus/cli/tasks.rb +326 -308
  70. data/lib/morpheus/cli/users.rb +457 -462
  71. data/lib/morpheus/cli/version.rb +1 -1
  72. data/lib/morpheus/cli/version_command.rb +16 -18
  73. data/lib/morpheus/cli/virtual_images.rb +526 -345
  74. data/lib/morpheus/cli/whoami.rb +125 -111
  75. data/lib/morpheus/cli/workflows.rb +338 -185
  76. data/lib/morpheus/formatters.rb +8 -1
  77. data/lib/morpheus/logging.rb +1 -1
  78. data/lib/morpheus/rest_client.rb +17 -8
  79. metadata +9 -3
  80. data/lib/morpheus/api/custom_instance_types.rb +0 -55
@@ -1,3 +1,4 @@
1
+ require 'uri'
1
2
  require 'term/ansicolor'
2
3
  require 'json'
3
4
 
@@ -8,26 +9,26 @@ module Morpheus::Cli::PrintHelper
8
9
  end
9
10
 
10
11
  def print_red_alert(msg)
11
- print red, bold, "\n#{msg}\n\n", reset
12
+ print "#{red}#{msg}#{reset}\n"
12
13
  end
13
14
 
14
15
  def print_yellow_warning(msg)
15
- print yellow, bold, "\n#{msg}\n\n", reset
16
+ print "#{yellow}#{msg}#{reset}\n"
16
17
  end
17
18
 
18
19
  def print_green_success(msg)
19
- print green, bold, "\n#{msg}\n\n", reset
20
+ print "#{green}#{msg}#{reset}\n"
20
21
  end
21
22
 
22
23
  def print_errors(response, options={})
23
24
  begin
24
25
  if options[:json]
25
- print red, "\n"
26
+ print red
26
27
  print JSON.pretty_generate(response)
27
- print reset, "\n\n"
28
+ print reset, "\n"
28
29
  else
29
30
  if !response['success']
30
- print red,bold, "\n"
31
+ print red,bold
31
32
  if response['msg']
32
33
  puts response['msg']
33
34
  end
@@ -36,7 +37,7 @@ module Morpheus::Cli::PrintHelper
36
37
  print "* #{key}: #{value}\n"
37
38
  end
38
39
  end
39
- print reset, "\n"
40
+ print reset
40
41
  else
41
42
  # this should not really happen
42
43
  print cyan,bold, "\nSuccess!"
@@ -49,19 +50,30 @@ module Morpheus::Cli::PrintHelper
49
50
 
50
51
  def print_rest_exception(e, options={})
51
52
  if e.response
53
+ if options[:debug]
54
+ begin
55
+ print_rest_exception_request_and_response(e)
56
+ ensure
57
+ print reset
58
+ end
59
+ return
60
+ end
52
61
  if e.response.code == 400
53
62
  response = JSON.parse(e.response.to_s)
54
63
  print_errors(response, options)
55
64
  else
56
- print_red_alert "Error Communicating with the Appliance. (#{e.response.code}) #{e}"
57
- if options[:json]
65
+ print_red_alert "Error Communicating with the Appliance. #{e}"
66
+ if options[:json] || options[:debug]
58
67
  begin
59
68
  response = JSON.parse(e.response.to_s)
60
- print red, "\n"
69
+ print red
61
70
  print JSON.pretty_generate(response)
62
- print reset, "\n\n"
71
+ print reset, "\n"
63
72
  rescue TypeError, JSON::ParserError => ex
64
- #print_red_alert "Failed to parse JSON response: #{ex}"
73
+ print_red_alert "Failed to parse JSON response: #{ex}"
74
+ print red
75
+ print response.to_s
76
+ print reset, "\n"
65
77
  ensure
66
78
  print reset
67
79
  end
@@ -72,21 +84,173 @@ module Morpheus::Cli::PrintHelper
72
84
  end
73
85
  end
74
86
 
75
- def print_dry_run(request, payload)
87
+ def print_rest_request(req)
88
+ # JD: IOError when accessing payload... we should probably just be printing at the time the request is made..
89
+ #out = []
90
+ #out << "#{req.method} #{req.url.inspect}"
91
+ #out << req.payload.short_inspect if req.payload
92
+ # payload = req.instance_variable_get("@payload")
93
+ # out << payload if payload
94
+ #out << req.processed_headers.to_a.sort.map { |(k, v)| [k.inspect, v.inspect].join("=>") }.join(", ")
95
+ #print out.join(', ') + "\n"
96
+ print "Request:"
97
+ print "\n"
98
+ print "#{req.method.to_s.upcase} #{req.url.inspect}"
99
+ print "\n"
100
+ end
101
+
102
+ def print_rest_response(res)
103
+ # size = @raw_response ? File.size(@tf.path) : (res.body.nil? ? 0 : res.body.size)
104
+ size = (res.body.nil? ? 0 : res.body.size)
105
+ print "Response:"
106
+ print "\n"
107
+ display_size = Filesize.from("#{size} B").pretty rescue size
108
+ print "HTTP #{res.net_http_res.code} - #{res.net_http_res.message} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{display_size}"
109
+ print "\n"
110
+ begin
111
+ print JSON.pretty_generate(JSON.parse(res.body))
112
+ rescue
113
+ print res.body.to_s
114
+ end
115
+ print "\n"
116
+ end
117
+
118
+ def print_rest_exception_request_and_response(e)
119
+ print_red_alert "Error Communicating with the Appliance. (#{e.response.code}) #{e}"
120
+ response = e.response
121
+ request = response.instance_variable_get("@request")
122
+ print red
123
+ print_rest_request(request)
124
+ print "\n"
125
+ print_rest_response(response)
126
+ print reset
127
+ end
128
+
129
+ def print_dry_run(opts)
130
+ http_method = opts[:method]
131
+ url = opts[:url]
132
+ params = opts[:params]
133
+ params = opts[:headers][:params] if opts[:headers] && opts[:headers][:params]
134
+ query_string = params.respond_to?(:map) ? URI.encode_www_form(params) : query_string
135
+ if query_string && !query_string.empty?
136
+ url = "#{url}?#{query_string}"
137
+ end
138
+ request_string = "#{http_method.to_s.upcase} #{url}".strip
139
+ payload = opts[:payload]
76
140
  print "\n" ,cyan, bold, "DRY RUN\n","==================", "\n\n", reset
77
141
  print cyan
78
142
  print "Request: ", "\n"
79
143
  print reset
80
- print request.to_s, "\n\n"
144
+ print request_string, "\n"
81
145
  print cyan
82
- print "JSON: ", "\n"
83
- print reset
84
- print JSON.pretty_generate(payload)
146
+ if payload
147
+ if payload.is_a?(String)
148
+ begin
149
+ payload = JSON.parse(payload)
150
+ rescue => e
151
+ #payload = "(unparsable) #{payload}"
152
+ end
153
+ end
154
+ print "\n"
155
+ print "JSON: ", "\n"
156
+ print reset
157
+ print JSON.pretty_generate(payload)
158
+ end
85
159
  print "\n"
86
160
  print reset
87
161
  end
88
162
 
163
+ def print_results_pagination(json_response)
164
+ if json_response && json_response["meta"]
165
+ print cyan,"\nViewing #{json_response['meta']['offset'].to_i + 1}-#{json_response['meta']['offset'].to_i + json_response['meta']['size'].to_i} of #{json_response['meta']['total']}\n"
166
+ end
167
+ end
168
+
89
169
  def required_blue_prompt
90
170
  "#{cyan}|#{reset}"
91
171
  end
172
+
173
+
174
+ # shows cyan, yellow, red progress bar where 50% looks like [||||| ]
175
+ # todo: render units used / available here too maybe
176
+ def generate_usage_bar(used_value, max_value, opts={})
177
+ rainbow = opts[:rainbow] != false
178
+ max_bars = opts[:max_bars] || 50
179
+ out = ""
180
+ bars = []
181
+ percent = 0
182
+ if max_value.to_i == 0
183
+ percent = 0
184
+ else
185
+ percent = ((used_value.to_f / max_value.to_f) * 100)
186
+ end
187
+ percent_label = (used_value.nil? || max_value.to_f == 0.0) ? "n/a" : "#{percent.round(2)}%".rjust(6, ' ')
188
+ bar_display = ""
189
+ if percent > 100
190
+ max_bars.times { bars << "|" }
191
+ # percent = 100
192
+ else
193
+ n_bars = ((percent / 100.0) * max_bars).ceil
194
+ n_bars.times { bars << "|" }
195
+ end
196
+
197
+ if rainbow
198
+ rainbow_bar = ""
199
+ cur_rainbow_color = white
200
+ bars.each_with_index {|bar, i|
201
+ reached_percent = (i / max_bars.to_f) * 100
202
+ new_bar_color = cur_rainbow_color
203
+ if reached_percent > 80
204
+ new_bar_color = red
205
+ elsif reached_percent > 50
206
+ new_bar_color = yellow
207
+ elsif reached_percent > 10
208
+ new_bar_color = cyan
209
+ end
210
+ if cur_rainbow_color != new_bar_color
211
+ cur_rainbow_color = new_bar_color
212
+ rainbow_bar << cur_rainbow_color
213
+ end
214
+ rainbow_bar << bar
215
+ }
216
+ padding = max_bars - bars.size
217
+ if padding > 0
218
+ padding.times { rainbow_bar << " " }
219
+ #rainbow_bar << " " * padding
220
+ end
221
+ rainbow_bar << reset
222
+ bar_display = white + "[" + rainbow_bar + white + "]" + " #{cur_rainbow_color}#{percent_label}#{reset}"
223
+ out << bar_display
224
+ else
225
+ bar_color = cyan
226
+ if percent > 80
227
+ bar_color = red
228
+ elsif percent > 50
229
+ bar_color = yellow
230
+ end
231
+ bar_display = white + "[" + bar_color + bars.join.ljust(max_bars, ' ') + white + "]" + " #{percent_label}" + reset
232
+ out << bar_display
233
+ end
234
+ return out
235
+ end
236
+
237
+ def print_stats_usage(stats, opts={})
238
+ opts[:include] ||= [:memory, :storage, :cpu]
239
+ if opts[:include].include?(:memory)
240
+ print cyan, "Memory:".ljust(10, ' ') + generate_usage_bar(stats['usedMemory'], stats['maxMemory']) + cyan + Filesize.from("#{stats['usedMemory']} B").pretty.strip.rjust(15, ' ') + " / " + Filesize.from("#{stats['maxMemory']} B").pretty.strip.ljust(15, ' ') + "\n"
241
+ end
242
+ if opts[:include].include?(:storage)
243
+ print cyan, "Storage:".ljust(10, ' ') + generate_usage_bar(stats['usedStorage'], stats['maxStorage']) + cyan + Filesize.from("#{stats['usedStorage']} B").pretty.strip.rjust(15, ' ') + " / " + Filesize.from("#{stats['maxStorage']} B").pretty.strip.ljust(15, ' ') + "\n"
244
+ end
245
+ if opts[:include].include?(:cpu)
246
+ cpu_usage = (stats['usedCpu'] || stats['cpuUsage'])
247
+ print cyan, "CPU:".ljust(10, ' ') + generate_usage_bar(cpu_usage.to_f, 100) + "\n"
248
+ end
249
+ end
250
+
251
+ def print_available_options(option_types)
252
+ option_lines = option_types.collect {|it| "\t-O #{it['fieldContext'] ? it['fieldContext'] + '.' : ''}#{it['fieldName']}=\"value\"" }.join("\n")
253
+ puts "Available Options:\n#{option_lines}\n\n"
254
+ end
255
+
92
256
  end
@@ -1,6 +1,6 @@
1
1
  require 'morpheus/cli/mixins/print_helper'
2
2
  require 'morpheus/cli/option_types'
3
- # Mixin for Morpheus::Cli command classes
3
+ # Mixin for Morpheus::Cli command classes
4
4
  # Provides common methods for provisioning instances
5
5
  module Morpheus::Cli::ProvisioningHelper
6
6
 
@@ -8,23 +8,53 @@ module Morpheus::Cli::ProvisioningHelper
8
8
  klass.send :include, Morpheus::Cli::PrintHelper
9
9
  end
10
10
 
11
+ def api_client
12
+ raise "#{self.class} has not defined @api_client" if @api_client.nil?
13
+ @api_client
14
+ end
15
+
16
+ def instances_interface
17
+ # @api_client.instances
18
+ raise "#{self.class} has not defined @instances_interface" if @instances_interface.nil?
19
+ @instances_interface
20
+ end
21
+
22
+ def options_interface
23
+ # @api_client.options
24
+ raise "#{self.class} has not defined @options_interface" if @options_interface.nil?
25
+ @options_interface
26
+ end
27
+
28
+ def instance_types_interface
29
+ # @api_client.instance_types
30
+ raise "#{self.class} has not defined @instance_types_interface" if @instance_types_interface.nil?
31
+ @instance_types_interface
32
+ end
33
+
11
34
  def get_available_groups(refresh=false)
12
35
  if !@available_groups || refresh
13
- option_results = @options_interface.options_for_source('groups',{})
36
+ option_results = options_interface.options_for_source('groups',{})
14
37
  @available_groups = option_results['data'].collect {|it|
15
38
  {"id" => it["value"], "name" => it["name"], "value" => it["value"]}
16
39
  }
17
40
  end
41
+ #puts "get_available_groups() rtn: #{@available_groups.inspect}"
18
42
  return @available_groups
19
43
  end
20
44
 
21
45
  def get_available_clouds(group_id, refresh=false)
22
- group = find_group_by_id(group_id)
46
+ if !group_id
47
+ option_results = options_interface.options_for_source('clouds', {})
48
+ return option_results['data'].collect {|it|
49
+ {"id" => it["value"], "name" => it["name"], "value" => it["value"], "zoneTypeId" => it["zoneTypeId"]}
50
+ }
51
+ end
52
+ group = find_group_by_id_for_provisioning(group_id)
23
53
  if !group
24
54
  return []
25
55
  end
26
56
  if !group["clouds"] || refresh
27
- option_results = @options_interface.options_for_source('clouds', {groupId: group_id})
57
+ option_results = options_interface.options_for_source('clouds', {groupId: group_id})
28
58
  group["clouds"] = option_results['data'].collect {|it|
29
59
  {"id" => it["value"], "name" => it["name"], "value" => it["value"], "zoneTypeId" => it["zoneTypeId"]}
30
60
  }
@@ -32,7 +62,7 @@ module Morpheus::Cli::ProvisioningHelper
32
62
  return group["clouds"]
33
63
  end
34
64
 
35
- def find_group_by_id(val)
65
+ def find_group_by_id_for_provisioning(val)
36
66
  groups = get_available_groups()
37
67
  group = groups.find {|it| it["id"].to_s == val.to_s }
38
68
  if !group
@@ -42,7 +72,7 @@ module Morpheus::Cli::ProvisioningHelper
42
72
  return group
43
73
  end
44
74
 
45
- def find_group_by_name(val)
75
+ def find_group_by_name_for_provisioning(val)
46
76
  groups = get_available_groups()
47
77
  group = groups.find {|it| it["name"].to_s.downcase == val.to_s.downcase }
48
78
  if !group
@@ -52,19 +82,15 @@ module Morpheus::Cli::ProvisioningHelper
52
82
  return group
53
83
  end
54
84
 
55
- def find_group_from_options(options)
56
- group = nil
57
- if options[:group]
58
- group = options[:group]
59
- elsif options[:group_name]
60
- group = find_group_by_name(options[:group_name])
61
- elsif options[:group_id]
62
- group = find_group_by_id(options[:group_id])
85
+ def find_group_by_name_or_id_for_provisioning(val)
86
+ if val.to_s =~ /\A\d{1,}\Z/
87
+ return find_group_by_id_for_provisioning(val)
88
+ else
89
+ return find_group_by_name_for_provisioning(val)
63
90
  end
64
- return group
65
91
  end
66
92
 
67
- def find_cloud_by_id(group_id, val)
93
+ def find_cloud_by_id_for_provisioning(group_id, val)
68
94
  clouds = get_available_clouds(group_id)
69
95
  cloud = clouds.find {|it| it["id"].to_s == val.to_s }
70
96
  if !cloud
@@ -74,7 +100,7 @@ module Morpheus::Cli::ProvisioningHelper
74
100
  return cloud
75
101
  end
76
102
 
77
- def find_cloud_by_name(group_id, val)
103
+ def find_cloud_by_name_for_provisioning(group_id, val)
78
104
  clouds = get_available_clouds(group_id)
79
105
  cloud = clouds.find {|it| it["name"].to_s.downcase == val.to_s.downcase }
80
106
  if !cloud
@@ -84,62 +110,98 @@ module Morpheus::Cli::ProvisioningHelper
84
110
  return cloud
85
111
  end
86
112
 
87
- def find_cloud_from_options(group_id, options)
88
- cloud = nil
89
- if options[:cloud]
90
- cloud = options[:cloud]
91
- elsif options[:cloud_name]
92
- cloud = find_cloud_by_name(group_id, options[:cloud_name])
93
- elsif options[:cloud_id]
94
- cloud = find_cloud_by_id(group_id, options[:cloud_id])
113
+ def find_cloud_by_name_or_id_for_provisioning(group_id, val)
114
+ if val.to_s =~ /\A\d{1,}\Z/
115
+ return find_cloud_by_id_for_provisioning(group_id, val)
116
+ else
117
+ return find_cloud_by_name_for_provisioning(group_id, val)
95
118
  end
96
- return cloud
97
119
  end
98
-
99
120
  def find_instance_type_by_code(code)
100
- results = @instance_types_interface.get({code: code})
121
+ results = instance_types_interface.get({code: code})
101
122
  if results['instanceTypes'].empty?
102
123
  print_red_alert "Instance Type not found by code #{code}"
124
+ # return nil
103
125
  exit 1
104
126
  end
105
127
  return results['instanceTypes'][0]
106
128
  end
107
129
 
130
+ def find_instance_type_by_name(name)
131
+ results = instance_types_interface.get({name: name})
132
+ if results['instanceTypes'].empty?
133
+ print_red_alert "Instance Type not found by name #{name}"
134
+ # return nil
135
+ exit 1
136
+ end
137
+ return results['instanceTypes'][0]
138
+ end
139
+
140
+ def find_instance_by_name_or_id(val)
141
+ if val.to_s =~ /\A\d{1,}\Z/
142
+ return find_instance_by_id(val)
143
+ else
144
+ return find_instance_by_name(val)
145
+ end
146
+ end
147
+
148
+ def find_instance_by_id(id)
149
+ begin
150
+ json_response = instances_interface.get(id.to_i)
151
+ return json_response['instance']
152
+ rescue RestClient::Exception => e
153
+ if e.response && e.response.code == 404
154
+ print_red_alert "Instance not found by id #{id}"
155
+ exit 1
156
+ else
157
+ raise e
158
+ end
159
+ end
160
+ end
161
+
162
+ def find_instance_by_name(name)
163
+ json_results = instances_interface.get({name: name.to_s})
164
+ if json_results['instances'].empty?
165
+ print_red_alert "Instance not found by name #{name}"
166
+ exit 1
167
+ end
168
+ instance = json_results['instances'][0]
169
+ return instance
170
+ end
171
+
108
172
  # prompts user for all the configuartion options for a particular instance
109
173
  # returns payload of data for a new instance
110
174
  def prompt_new_instance(options={})
111
175
 
112
176
  # Group
113
177
  group_id = nil
114
- group = find_group_from_options(options)
178
+ group = options[:group] ? find_group_by_name_or_id_for_provisioning(options[:group]) : nil
115
179
  if group
116
180
  group_id = group["id"]
117
181
  else
118
182
  # print_red_alert "Group not found or specified!"
119
183
  # exit 1
120
- group_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'group', 'type' => 'select', 'fieldLabel' => 'Group', 'selectOptions' => get_available_groups(), 'required' => true, 'description' => 'Select Group.'}],options[:options],@api_client,{})
121
- group_id = cloud_prompt['group']
184
+ group_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'group', 'type' => 'select', 'fieldLabel' => 'Group', 'selectOptions' => get_available_groups(), 'required' => true, 'description' => 'Select Group.'}],options[:options],api_client,{})
185
+ group_id = group_prompt['group']
122
186
  end
123
-
124
187
 
125
188
  # Cloud
126
189
  cloud_id = nil
127
- cloud = find_cloud_from_options(group_id, options)
190
+ cloud = options[:cloud] ? find_cloud_by_name_or_id_for_provisioning(group_id, options[:cloud]) : nil
128
191
  if cloud
129
192
  cloud_id = cloud["id"]
130
193
  else
131
194
  # print_red_alert "Cloud not specified!"
132
195
  # exit 1
133
- cloud_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cloud', 'type' => 'select', 'fieldLabel' => 'Cloud', 'selectOptions' => get_available_clouds(group_id), 'required' => true, 'description' => 'Select Cloud.'}],options[:options],@api_client,{groupId: group_id})
196
+ cloud_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cloud', 'type' => 'select', 'fieldLabel' => 'Cloud', 'selectOptions' => get_available_clouds(group_id), 'required' => true, 'description' => 'Select Cloud.'}],options[:options],api_client,{groupId: group_id})
134
197
  cloud_id = cloud_prompt['cloud']
135
198
  end
136
-
137
199
  # Instance Type
138
200
  instance_type_code = nil
139
201
  if options[:instance_type_code]
140
202
  instance_type_code = options[:instance_type_code]
141
203
  else
142
- instance_type_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'type' => 'select', 'fieldLabel' => 'Type', 'optionSource' => 'instanceTypes', 'required' => true, 'description' => 'Select Instance Type.'}],options[:options],@api_client,{groupId: group_id})
204
+ instance_type_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'type' => 'select', 'fieldLabel' => 'Type', 'optionSource' => 'instanceTypes', 'required' => true, 'description' => 'Select Instance Type.'}],options[:options],api_client,{groupId: group_id})
143
205
  instance_type_code = instance_type_prompt['type']
144
206
  end
145
207
  instance_type = find_instance_type_by_code(instance_type_code)
@@ -178,12 +240,11 @@ module Morpheus::Cli::ProvisioningHelper
178
240
  # Tags
179
241
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'tags', 'fieldLabel' => 'Tags', 'type' => 'text', 'required' => false}], options[:options])
180
242
  payload[:instance][:tags] = v_prompt['tags'].split(',').collect {|it| it.to_s.strip }.compact.uniq if !v_prompt['tags'].empty?
181
-
182
243
 
183
244
  # Version and Layout
184
245
 
185
- version_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'version', 'type' => 'select', 'fieldLabel' => 'Version', 'optionSource' => 'instanceVersions', 'required' => true, 'skipSingleOption' => true, 'description' => 'Select which version of the instance type to be provisioned.'}],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id']})
186
- layout_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'layout', 'type' => 'select', 'fieldLabel' => 'Layout', 'optionSource' => 'layoutsForCloud', 'required' => true, 'description' => 'Select which configuration of the instance type to be provisioned.'}],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
246
+ version_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'version', 'type' => 'select', 'fieldLabel' => 'Version', 'optionSource' => 'instanceVersions', 'required' => true, 'skipSingleOption' => true, 'description' => 'Select which version of the instance type to be provisioned.'}],options[:options],api_client,{groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id']})
247
+ layout_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'layout', 'type' => 'select', 'fieldLabel' => 'Layout', 'optionSource' => 'layoutsForCloud', 'required' => true, 'description' => 'Select which configuration of the instance type to be provisioned.'}],options[:options],api_client,{groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
187
248
  layout_id = layout_prompt['layout']
188
249
  layout = instance_type['instanceTypeLayouts'].find{ |lt| lt['id'] == layout_id.to_i}
189
250
  payload[:instance][:layout] = {id: layout['id']}
@@ -195,11 +256,11 @@ module Morpheus::Cli::ProvisioningHelper
195
256
  plan_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'servicePlan', 'type' => 'select', 'fieldLabel' => 'Plan', 'selectOptions' => service_plans_dropdown, 'required' => true, 'description' => 'Choose the appropriately sized plan for this instance'}],options[:options])
196
257
  service_plan = service_plans.find {|sp| sp["id"] == plan_prompt['servicePlan'].to_i }
197
258
  # todo: pick one of these three, let's go with the last one...
198
- payload[:servicePlan] = service_plan["id"] # pre-2.10 appliances
259
+ #payload[:servicePlan] = service_plan["id"] # pre-2.10 appliances
199
260
  payload[:instance][:plan] = {id: service_plan["id"]}
200
261
 
201
262
  # prompt for volumes
202
- volumes = prompt_volumes(service_plan, options, @api_client, {})
263
+ volumes = prompt_volumes(service_plan, options, api_client, {})
203
264
  if !volumes.empty?
204
265
  payload[:volumes] = volumes
205
266
  end
@@ -207,22 +268,20 @@ module Morpheus::Cli::ProvisioningHelper
207
268
  if layout["provisionType"] && layout["provisionType"]["id"] && layout["provisionType"]["hasNetworks"]
208
269
  # prompt for network interfaces (if supported)
209
270
  begin
210
- network_interfaces = prompt_network_interfaces(cloud_id, layout["provisionType"]["id"], options, @api_client)
271
+ network_interfaces = prompt_network_interfaces(cloud_id, layout["provisionType"]["id"], options)
211
272
  if !network_interfaces.empty?
212
273
  payload[:networkInterfaces] = network_interfaces
213
274
  end
214
275
  rescue RestClient::Exception => e
215
276
  print_yellow_warning "Unable to load network options. Proceeding..."
216
- print_rest_exception(e, options) if Morpheus::Logging.print_stacktrace?
277
+ print_rest_exception(e, options) if Morpheus::Logging.debug?
217
278
  end
218
279
  end
219
-
220
-
221
280
  type_payload = {}
222
281
  if !layout['optionTypes'].nil? && !layout['optionTypes'].empty?
223
- type_payload = Morpheus::Cli::OptionTypes.prompt(layout['optionTypes'],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
282
+ type_payload = Morpheus::Cli::OptionTypes.prompt(layout['optionTypes'],options[:options],api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
224
283
  elsif !instance_type['optionTypes'].nil? && !instance_type['optionTypes'].empty?
225
- type_payload = Morpheus::Cli::OptionTypes.prompt(instance_type['optionTypes'],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
284
+ type_payload = Morpheus::Cli::OptionTypes.prompt(instance_type['optionTypes'],options[:options],api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
226
285
  end
227
286
  if !type_payload['config'].nil?
228
287
  payload.merge!(type_payload['config'])
@@ -239,7 +298,7 @@ module Morpheus::Cli::ProvisioningHelper
239
298
  if !payload[:networkInterfaces].empty?
240
299
  instance_type_option_types = reject_networking_option_types(instance_type_option_types)
241
300
  end
242
- provision_payload = Morpheus::Cli::OptionTypes.prompt(instance_type_option_types,options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
301
+ provision_payload = Morpheus::Cli::OptionTypes.prompt(instance_type_option_types,options[:options],api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
243
302
  end
244
303
 
245
304
  payload[:config] = provision_payload['config'] || {}
@@ -247,6 +306,12 @@ module Morpheus::Cli::ProvisioningHelper
247
306
  payload[:server] = provision_payload['server'] || {}
248
307
  end
249
308
 
309
+ # prompt for environment variables
310
+ evars = prompt_evars(options)
311
+ if !evars.empty?
312
+ payload[:evars] = evars
313
+ end
314
+
250
315
  return payload
251
316
  end
252
317
 
@@ -327,7 +392,7 @@ module Morpheus::Cli::ProvisioningHelper
327
392
 
328
393
  volume_label = 'root'
329
394
  volume = {
330
- 'id' => -1,
395
+ 'id' => -1,
331
396
  'rootVolume' => true,
332
397
  'name' => volume_label,
333
398
  'size' => plan_size,
@@ -352,7 +417,7 @@ module Morpheus::Cli::ProvisioningHelper
352
417
  end
353
418
  else
354
419
  # might need different logic here ? =o
355
- volume['size'] = plan_size
420
+ volume['size'] = plan_size
356
421
  volume['sizeId'] = nil #volume.delete('sizeId')
357
422
  end
358
423
  if !datastore_options.empty?
@@ -364,502 +429,514 @@ module Morpheus::Cli::ProvisioningHelper
364
429
 
365
430
  if plan_info['addVolumes']
366
431
  volume_index = 1
367
-
368
432
  has_another_volume = options[:options] && options[:options]["dataVolume#{volume_index}"]
369
- add_another_volume = has_another_volume || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add data volume?"))
370
-
433
+ add_another_volume = has_another_volume || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add data volume?", {:default => false}))
371
434
  while add_another_volume do
372
-
373
- #puts "Configure Data #{volume_index} Volume"
435
+ #puts "Configure Data #{volume_index} Volume"
374
436
 
375
- field_context = "dataVolume#{volume_index}"
437
+ field_context = "dataVolume#{volume_index}"
376
438
 
377
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Storage Type", 'selectOptions' => storage_types, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.'}], options[:options])
378
- storage_type_id = v_prompt[field_context]['storageType']
379
- storage_type = plan_info['storageTypes'].find {|i| i['id'] == storage_type_id.to_i }
380
-
439
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Storage Type", 'selectOptions' => storage_types, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.'}], options[:options])
440
+ storage_type_id = v_prompt[field_context]['storageType']
441
+ storage_type = plan_info['storageTypes'].find {|i| i['id'] == storage_type_id.to_i }
381
442
 
382
- # sometimes the user chooses sizeId from a list of size options (AccountPrice) and other times it is free form
383
- custom_size_options = []
384
- if plan_info['customSizeOptions'] && plan_info['customSizeOptions'][storage_type_id.to_s]
385
- plan_info['customSizeOptions'][storage_type_id.to_s].each do |opt|
386
- if !opt.nil?
387
- custom_size_options << {'name' => opt['value'], 'value' => opt['key']}
443
+ # sometimes the user chooses sizeId from a list of size options (AccountPrice) and other times it is free form
444
+ custom_size_options = []
445
+ if plan_info['customSizeOptions'] && plan_info['customSizeOptions'][storage_type_id.to_s]
446
+ plan_info['customSizeOptions'][storage_type_id.to_s].each do |opt|
447
+ if !opt.nil?
448
+ custom_size_options << {'name' => opt['value'], 'value' => opt['key']}
449
+ end
388
450
  end
389
451
  end
390
- end
391
452
 
392
- volume_label = (volume_index == 1 ? 'data' : "data #{volume_index}")
393
- volume = {
394
- 'id' => -1,
395
- 'rootVolume' => false,
396
- 'name' => volume_label,
397
- 'size' => plan_size,
398
- 'sizeId' => nil,
399
- 'storageType' => storage_type_id,
400
- 'datastoreId' => nil
401
- }
453
+ volume_label = (volume_index == 1 ? 'data' : "data #{volume_index}")
454
+ volume = {
455
+ 'id' => -1,
456
+ 'rootVolume' => false,
457
+ 'name' => volume_label,
458
+ 'size' => plan_size,
459
+ 'sizeId' => nil,
460
+ 'storageType' => storage_type_id,
461
+ 'datastoreId' => nil
462
+ }
402
463
 
403
- if plan_info['customizeVolume'] && storage_type['customLabel']
404
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => "Disk #{volume_index} Volume Label", 'required' => true, 'description' => 'Enter a volume label.', 'defaultValue' => volume_label}], options[:options])
405
- volume['name'] = v_prompt[field_context]['name']
406
- end
407
- if plan_info['customizeVolume'] && storage_type['customSize']
408
- if custom_size_options.empty?
409
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'size', 'type' => 'number', 'fieldLabel' => "Disk #{volume_index} Volume Size (GB)", 'required' => true, 'description' => 'Enter a volume size (GB).', 'defaultValue' => plan_size}], options[:options])
410
- volume['size'] = v_prompt[field_context]['size']
411
- volume['sizeId'] = nil #volume.delete('sizeId')
464
+ if plan_info['customizeVolume'] && storage_type['customLabel']
465
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => "Disk #{volume_index} Volume Label", 'required' => true, 'description' => 'Enter a volume label.', 'defaultValue' => volume_label}], options[:options])
466
+ volume['name'] = v_prompt[field_context]['name']
467
+ end
468
+ if plan_info['customizeVolume'] && storage_type['customSize']
469
+ if custom_size_options.empty?
470
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'size', 'type' => 'number', 'fieldLabel' => "Disk #{volume_index} Volume Size (GB)", 'required' => true, 'description' => 'Enter a volume size (GB).', 'defaultValue' => plan_size}], options[:options])
471
+ volume['size'] = v_prompt[field_context]['size']
472
+ volume['sizeId'] = nil #volume.delete('sizeId')
473
+ else
474
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'sizeId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Volume Size", 'selectOptions' => custom_size_options, 'required' => true, 'description' => 'Choose a volume size.'}], options[:options])
475
+ volume['sizeId'] = v_prompt[field_context]['sizeId']
476
+ volume['size'] = nil #volume.delete('size')
477
+ end
412
478
  else
413
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'sizeId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Volume Size", 'selectOptions' => custom_size_options, 'required' => true, 'description' => 'Choose a volume size.'}], options[:options])
414
- volume['sizeId'] = v_prompt[field_context]['sizeId']
415
- volume['size'] = nil #volume.delete('size')
479
+ # might need different logic here ? =o
480
+ volume['size'] = plan_size
481
+ volume['sizeId'] = nil #volume.delete('sizeId')
416
482
  end
417
- else
418
- # might need different logic here ? =o
419
- volume['size'] = plan_size
420
- volume['sizeId'] = nil #volume.delete('sizeId')
421
- end
422
- if !datastore_options.empty?
423
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'datastoreId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Datastore", 'selectOptions' => datastore_options, 'required' => true, 'description' => 'Choose a datastore.'}], options[:options])
424
- volume['datastoreId'] = v_prompt[field_context]['datastoreId']
425
- end
483
+ if !datastore_options.empty?
484
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'datastoreId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Datastore", 'selectOptions' => datastore_options, 'required' => true, 'description' => 'Choose a datastore.'}], options[:options])
485
+ volume['datastoreId'] = v_prompt[field_context]['datastoreId']
486
+ end
487
+
488
+ volumes << volume
426
489
 
427
- volumes << volume
490
+ # todo: should maxDisk check consider the root volume too?
491
+ if plan_info['maxDisk'] && volume_index >= plan_info['maxDisk']
492
+ add_another_volume = false
493
+ else
494
+ volume_index += 1
495
+ has_another_volume = options[:options] && options[:options]["dataVolume#{volume_index}"]
496
+ add_another_volume = has_another_volume || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another data volume?", {:default => false}))
497
+ end
428
498
 
429
- # todo: should maxDisk check consider the root volume too?
430
- if plan_info['maxDisk'] && volume_index >= plan_info['maxDisk']
431
- add_another_volume = false
432
- else
433
- volume_index += 1
434
- has_another_volume = options[:options] && options[:options]["dataVolume#{volume_index}"]
435
- add_another_volume = has_another_volume || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another data volume?"))
436
499
  end
437
500
 
438
501
  end
439
502
 
503
+ return volumes
440
504
  end
441
505
 
442
- return volumes
443
- end
444
506
 
507
+ # This recreates the behavior of multi_disk.js
508
+ # returns array of volumes based on service plan options (plan_info)
509
+ def prompt_resize_volumes(current_volumes, plan_info, options={})
510
+ #puts "Configure Volumes:"
511
+ no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
445
512
 
446
- # This recreates the behavior of multi_disk.js
447
- # returns array of volumes based on service plan options (plan_info)
448
- def prompt_resize_volumes(current_volumes, plan_info, options={}, api_client=nil, api_params={})
449
- #puts "Configure Volumes:"
450
- no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
513
+ current_root_volume = current_volumes[0]
451
514
 
452
- current_root_volume = current_volumes[0]
515
+ volumes = []
453
516
 
454
- volumes = []
455
-
456
- plan_size = nil
457
- if plan_info['maxStorage']
458
- plan_size = plan_info['maxStorage'].to_i / (1024 * 1024 * 1024)
459
- end
517
+ plan_size = nil
518
+ if plan_info['maxStorage']
519
+ plan_size = plan_info['maxStorage'].to_i / (1024 * 1024 * 1024)
520
+ end
460
521
 
461
- root_storage_types = []
462
- if plan_info['rootStorageTypes']
463
- plan_info['rootStorageTypes'].each do |opt|
464
- if !opt.nil?
465
- root_storage_types << {'name' => opt['name'], 'value' => opt['id']}
522
+ root_storage_types = []
523
+ if plan_info['rootStorageTypes']
524
+ plan_info['rootStorageTypes'].each do |opt|
525
+ if !opt.nil?
526
+ root_storage_types << {'name' => opt['name'], 'value' => opt['id']}
527
+ end
466
528
  end
467
529
  end
468
- end
469
530
 
470
- storage_types = []
471
- if plan_info['storageTypes']
472
- plan_info['storageTypes'].each do |opt|
473
- if !opt.nil?
474
- storage_types << {'name' => opt['name'], 'value' => opt['id']}
531
+ storage_types = []
532
+ if plan_info['storageTypes']
533
+ plan_info['storageTypes'].each do |opt|
534
+ if !opt.nil?
535
+ storage_types << {'name' => opt['name'], 'value' => opt['id']}
536
+ end
475
537
  end
476
538
  end
477
- end
478
539
 
479
- datastore_options = []
480
- if plan_info['supportsAutoDatastore']
481
- if plan_info['autoOptions']
482
- plan_info['autoOptions'].each do |opt|
483
- if !opt.nil?
484
- datastore_options << {'name' => opt['name'], 'value' => opt['id']}
540
+ datastore_options = []
541
+ if plan_info['supportsAutoDatastore']
542
+ if plan_info['autoOptions']
543
+ plan_info['autoOptions'].each do |opt|
544
+ if !opt.nil?
545
+ datastore_options << {'name' => opt['name'], 'value' => opt['id']}
546
+ end
485
547
  end
486
548
  end
487
549
  end
488
- end
489
- if plan_info['datastores']
490
- plan_info['datastores'].each do |k, v|
491
- v.each do |opt|
492
- if !opt.nil?
493
- datastore_options << {'name' => "#{k}: #{opt['name']}", 'value' => opt['id']}
550
+ if plan_info['datastores']
551
+ plan_info['datastores'].each do |k, v|
552
+ v.each do |opt|
553
+ if !opt.nil?
554
+ datastore_options << {'name' => "#{k}: #{opt['name']}", 'value' => opt['id']}
555
+ end
494
556
  end
495
557
  end
496
558
  end
497
- end
498
559
 
499
- #puts "Configure Root Volume"
560
+ #puts "Configure Root Volume"
500
561
 
501
- field_context = "rootVolume"
562
+ field_context = "rootVolume"
502
563
 
503
- if root_storage_types.empty?
504
- # this means there's no configuration, just send a single root volume to the server
505
- storage_type_id = nil
506
- storage_type = nil
507
- else
508
- #v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => 'Root Storage Type', 'selectOptions' => root_storage_types, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.'}], options[:options])
509
- #storage_type_id = v_prompt[field_context]['storageType']
510
- storage_type_id = current_root_volume['type'] || current_root_volume['storageType']
511
- storage_type = plan_info['storageTypes'].find {|i| i['id'] == storage_type_id.to_i }
512
- end
564
+ if root_storage_types.empty?
565
+ # this means there's no configuration, just send a single root volume to the server
566
+ storage_type_id = nil
567
+ storage_type = nil
568
+ else
569
+ #v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => 'Root Storage Type', 'selectOptions' => root_storage_types, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.'}], options[:options])
570
+ #storage_type_id = v_prompt[field_context]['storageType']
571
+ storage_type_id = current_root_volume['type'] || current_root_volume['storageType']
572
+ storage_type = plan_info['storageTypes'].find {|i| i['id'] == storage_type_id.to_i }
573
+ end
513
574
 
514
- # sometimes the user chooses sizeId from a list of size options (AccountPrice) and other times it is free form
515
- root_custom_size_options = []
516
- if plan_info['rootCustomSizeOptions'] && plan_info['rootCustomSizeOptions'][storage_type_id.to_s]
517
- plan_info['rootCustomSizeOptions'][storage_type_id.to_s].each do |opt|
518
- if !opt.nil?
519
- root_custom_size_options << {'name' => opt['value'], 'value' => opt['key']}
575
+ # sometimes the user chooses sizeId from a list of size options (AccountPrice) and other times it is free form
576
+ root_custom_size_options = []
577
+ if plan_info['rootCustomSizeOptions'] && plan_info['rootCustomSizeOptions'][storage_type_id.to_s]
578
+ plan_info['rootCustomSizeOptions'][storage_type_id.to_s].each do |opt|
579
+ if !opt.nil?
580
+ root_custom_size_options << {'name' => opt['value'], 'value' => opt['key']}
581
+ end
520
582
  end
521
583
  end
522
- end
523
584
 
524
- volume = {
525
- 'id' => current_root_volume['id'],
526
- 'rootVolume' => true,
527
- 'name' => current_root_volume['name'],
528
- 'size' => current_root_volume['size'] > plan_size ? current_root_volume['size'] : plan_size,
529
- 'sizeId' => nil,
530
- 'storageType' => storage_type_id,
531
- 'datastoreId' => current_root_volume['datastoreId']
532
- }
585
+ volume = {
586
+ 'id' => current_root_volume['id'],
587
+ 'rootVolume' => true,
588
+ 'name' => current_root_volume['name'],
589
+ 'size' => current_root_volume['size'] > plan_size ? current_root_volume['size'] : plan_size,
590
+ 'sizeId' => nil,
591
+ 'storageType' => storage_type_id,
592
+ 'datastoreId' => current_root_volume['datastoreId']
593
+ }
533
594
 
534
- if plan_info['rootDiskCustomizable'] && storage_type && storage_type['customLabel']
535
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Root Volume Label', 'required' => true, 'description' => 'Enter a volume label.', 'defaultValue' => volume['name']}], options[:options])
536
- volume['name'] = v_prompt[field_context]['name']
537
- end
538
- if plan_info['rootDiskCustomizable'] && storage_type && storage_type['customSize']
539
- if root_custom_size_options.empty?
540
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'size', 'type' => 'number', 'fieldLabel' => 'Root Volume Size (GB)', 'required' => true, 'description' => 'Enter a volume size (GB).', 'defaultValue' => volume['size']}], options[:options])
541
- volume['size'] = v_prompt[field_context]['size']
542
- volume['sizeId'] = nil #volume.delete('sizeId')
595
+ if plan_info['rootDiskCustomizable'] && storage_type && storage_type['customLabel']
596
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Root Volume Label', 'required' => true, 'description' => 'Enter a volume label.', 'defaultValue' => volume['name']}], options[:options])
597
+ volume['name'] = v_prompt[field_context]['name']
598
+ end
599
+ if plan_info['rootDiskCustomizable'] && storage_type && storage_type['customSize']
600
+ if root_custom_size_options.empty?
601
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'size', 'type' => 'number', 'fieldLabel' => 'Root Volume Size (GB)', 'required' => true, 'description' => 'Enter a volume size (GB).', 'defaultValue' => volume['size']}], options[:options])
602
+ volume['size'] = v_prompt[field_context]['size']
603
+ volume['sizeId'] = nil #volume.delete('sizeId')
604
+ else
605
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'sizeId', 'type' => 'select', 'fieldLabel' => 'Root Volume Size', 'selectOptions' => root_custom_size_options, 'required' => true, 'description' => 'Choose a volume size.'}], options[:options])
606
+ volume['sizeId'] = v_prompt[field_context]['sizeId']
607
+ volume['size'] = nil #volume.delete('size')
608
+ end
543
609
  else
544
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'sizeId', 'type' => 'select', 'fieldLabel' => 'Root Volume Size', 'selectOptions' => root_custom_size_options, 'required' => true, 'description' => 'Choose a volume size.'}], options[:options])
545
- volume['sizeId'] = v_prompt[field_context]['sizeId']
546
- volume['size'] = nil #volume.delete('size')
610
+ # might need different logic here ? =o
611
+ volume['size'] = plan_size
612
+ volume['sizeId'] = nil #volume.delete('sizeId')
547
613
  end
548
- else
549
- # might need different logic here ? =o
550
- volume['size'] = plan_size
551
- volume['sizeId'] = nil #volume.delete('sizeId')
552
- end
553
- # if !datastore_options.empty?
554
- # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'datastoreId', 'type' => 'select', 'fieldLabel' => 'Root Datastore', 'selectOptions' => datastore_options, 'required' => true, 'description' => 'Choose a datastore.'}], options[:options])
555
- # volume['datastoreId'] = v_prompt[field_context]['datastoreId']
556
- # end
614
+ # if !datastore_options.empty?
615
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'datastoreId', 'type' => 'select', 'fieldLabel' => 'Root Datastore', 'selectOptions' => datastore_options, 'required' => true, 'description' => 'Choose a datastore.'}], options[:options])
616
+ # volume['datastoreId'] = v_prompt[field_context]['datastoreId']
617
+ # end
557
618
 
558
- volumes << volume
619
+ volumes << volume
559
620
 
560
- # modify or delete existing data volumes
561
- (1..(current_volumes.size-1)).each do |volume_index|
562
- current_volume = current_volumes[volume_index]
563
-
564
- if current_volume
621
+ # modify or delete existing data volumes
622
+ (1..(current_volumes.size-1)).each do |volume_index|
623
+ current_volume = current_volumes[volume_index]
624
+ if current_volume
565
625
 
566
- field_context = "dataVolume#{volume_index}"
626
+ field_context = "dataVolume#{volume_index}"
567
627
 
568
- if no_prompt
569
- volume_action = 'keep'
570
- else
571
- action_options = [{'name' => 'Modify', 'value' => 'modify'}, {'name' => 'Keep', 'value' => 'keep'}, {'name' => 'Delete', 'value' => 'delete'}]
572
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'action', 'type' => 'select', 'fieldLabel' => "Modify/Keep/Delete volume '#{current_volume['name']}'", 'selectOptions' => action_options, 'required' => true, 'description' => 'Modify, Keep or Delete existing data volume?'}], options[:options])
573
- volume_action = v_prompt[field_context]['action']
574
- end
628
+ if no_prompt
629
+ volume_action = 'keep'
630
+ else
631
+ action_options = [{'name' => 'Modify', 'value' => 'modify'}, {'name' => 'Keep', 'value' => 'keep'}, {'name' => 'Delete', 'value' => 'delete'}]
632
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'action', 'type' => 'select', 'fieldLabel' => "Modify/Keep/Delete volume '#{current_volume['name']}'", 'selectOptions' => action_options, 'required' => true, 'description' => 'Modify, Keep or Delete existing data volume?'}], options[:options])
633
+ volume_action = v_prompt[field_context]['action']
634
+ end
575
635
 
576
- if volume_action == 'delete'
577
- # deleted volume is just excluded from post params
578
- next
579
- elsif volume_action == 'keep'
580
- volume = {
581
- 'id' => current_volume['id'].to_i,
582
- 'rootVolume' => false,
583
- 'name' => current_volume['name'],
584
- 'size' => current_volume['size'] > plan_size ? current_volume['size'] : plan_size,
585
- 'sizeId' => nil,
586
- 'storageType' => (current_volume['type'] || current_volume['storageType']),
587
- 'datastoreId' => current_volume['datastoreId']
588
- }
589
- volumes << volume
590
- else
591
-
592
- # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Storage Type", 'selectOptions' => storage_types, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.'}], options[:options])
593
- # storage_type_id = v_prompt[field_context]['storageType']
594
- storage_type_id = current_volume['type'] || current_volume['storageType']
595
- storage_type = plan_info['storageTypes'].find {|i| i['id'] == storage_type_id.to_i }
596
-
597
- # sometimes the user chooses sizeId from a list of size options (AccountPrice) and other times it is free form
598
- custom_size_options = []
599
- if plan_info['customSizeOptions'] && plan_info['customSizeOptions'][storage_type_id.to_s]
600
- plan_info['customSizeOptions'][storage_type_id.to_s].each do |opt|
601
- if !opt.nil?
602
- custom_size_options << {'name' => opt['value'], 'value' => opt['key']}
636
+ if volume_action == 'delete'
637
+ # deleted volume is just excluded from post params
638
+ next
639
+ elsif volume_action == 'keep'
640
+ volume = {
641
+ 'id' => current_volume['id'].to_i,
642
+ 'rootVolume' => false,
643
+ 'name' => current_volume['name'],
644
+ 'size' => current_volume['size'] > plan_size ? current_volume['size'] : plan_size,
645
+ 'sizeId' => nil,
646
+ 'storageType' => (current_volume['type'] || current_volume['storageType']),
647
+ 'datastoreId' => current_volume['datastoreId']
648
+ }
649
+ volumes << volume
650
+ else
651
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Storage Type", 'selectOptions' => storage_types, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.'}], options[:options])
652
+ # storage_type_id = v_prompt[field_context]['storageType']
653
+ storage_type_id = current_volume['type'] || current_volume['storageType']
654
+ storage_type = plan_info['storageTypes'].find {|i| i['id'] == storage_type_id.to_i }
655
+ # sometimes the user chooses sizeId from a list of size options (AccountPrice) and other times it is free form
656
+ custom_size_options = []
657
+ if plan_info['customSizeOptions'] && plan_info['customSizeOptions'][storage_type_id.to_s]
658
+ plan_info['customSizeOptions'][storage_type_id.to_s].each do |opt|
659
+ if !opt.nil?
660
+ custom_size_options << {'name' => opt['value'], 'value' => opt['key']}
661
+ end
603
662
  end
604
663
  end
605
- end
606
-
607
- volume = {
608
- 'id' => current_volume['id'].to_i,
609
- 'rootVolume' => false,
610
- 'name' => current_volume['name'],
611
- 'size' => current_volume['size'] > plan_size ? current_volume['size'] : plan_size,
612
- 'sizeId' => nil,
613
- 'storageType' => (current_volume['type'] || current_volume['storageType']),
614
- 'datastoreId' => current_volume['datastoreId']
615
- }
616
664
 
617
- if plan_info['customizeVolume'] && storage_type['customLabel']
618
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => "Disk #{volume_index} Volume Label", 'required' => true, 'description' => 'Enter a volume label.', 'defaultValue' => volume['name']}], options[:options])
619
- volume['name'] = v_prompt[field_context]['name']
620
- end
621
- if plan_info['customizeVolume'] && storage_type['customSize']
622
- if custom_size_options.empty?
623
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'size', 'type' => 'number', 'fieldLabel' => "Disk #{volume_index} Volume Size (GB)", 'required' => true, 'description' => 'Enter a volume size (GB).', 'defaultValue' => volume['size']}], options[:options])
624
- volume['size'] = v_prompt[field_context]['size']
625
- volume['sizeId'] = nil #volume.delete('sizeId')
665
+ volume = {
666
+ 'id' => current_volume['id'].to_i,
667
+ 'rootVolume' => false,
668
+ 'name' => current_volume['name'],
669
+ 'size' => current_volume['size'] > plan_size ? current_volume['size'] : plan_size,
670
+ 'sizeId' => nil,
671
+ 'storageType' => (current_volume['type'] || current_volume['storageType']),
672
+ 'datastoreId' => current_volume['datastoreId']
673
+ }
674
+
675
+ if plan_info['customizeVolume'] && storage_type['customLabel']
676
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => "Disk #{volume_index} Volume Label", 'required' => true, 'description' => 'Enter a volume label.', 'defaultValue' => volume['name']}], options[:options])
677
+ volume['name'] = v_prompt[field_context]['name']
678
+ end
679
+ if plan_info['customizeVolume'] && storage_type['customSize']
680
+ if custom_size_options.empty?
681
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'size', 'type' => 'number', 'fieldLabel' => "Disk #{volume_index} Volume Size (GB)", 'required' => true, 'description' => 'Enter a volume size (GB).', 'defaultValue' => volume['size']}], options[:options])
682
+ volume['size'] = v_prompt[field_context]['size']
683
+ volume['sizeId'] = nil #volume.delete('sizeId')
684
+ else
685
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'sizeId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Volume Size", 'selectOptions' => custom_size_options, 'required' => true, 'description' => 'Choose a volume size.'}], options[:options])
686
+ volume['sizeId'] = v_prompt[field_context]['sizeId']
687
+ volume['size'] = nil #volume.delete('size')
688
+ end
626
689
  else
627
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'sizeId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Volume Size", 'selectOptions' => custom_size_options, 'required' => true, 'description' => 'Choose a volume size.'}], options[:options])
628
- volume['sizeId'] = v_prompt[field_context]['sizeId']
629
- volume['size'] = nil #volume.delete('size')
690
+ # might need different logic here ? =o
691
+ volume['size'] = plan_size
692
+ volume['sizeId'] = nil #volume.delete('sizeId')
630
693
  end
631
- else
632
- # might need different logic here ? =o
633
- volume['size'] = plan_size
634
- volume['sizeId'] = nil #volume.delete('sizeId')
635
- end
636
- # if !datastore_options.empty?
637
- # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'datastoreId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Datastore", 'selectOptions' => datastore_options, 'required' => true, 'description' => 'Choose a datastore.'}], options[:options])
638
- # volume['datastoreId'] = v_prompt[field_context]['datastoreId']
639
- # end
694
+ # if !datastore_options.empty?
695
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'datastoreId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Datastore", 'selectOptions' => datastore_options, 'required' => true, 'description' => 'Choose a datastore.'}], options[:options])
696
+ # volume['datastoreId'] = v_prompt[field_context]['datastoreId']
697
+ # end
640
698
 
641
- volumes << volume
699
+ volumes << volume
642
700
 
643
- end
701
+ end
644
702
 
703
+ end
645
704
  end
646
- end
647
705
 
648
706
 
649
- if plan_info['addVolumes']
650
- volume_index = current_volumes.size
651
-
652
- has_another_volume = options[:options] && options[:options]["dataVolume#{volume_index}"]
653
- add_another_volume = has_another_volume || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add data volume?"))
654
-
655
- while add_another_volume do
656
-
657
- #puts "Configure Data #{volume_index} Volume"
707
+ if plan_info['addVolumes']
708
+ volume_index = current_volumes.size
709
+ has_another_volume = options[:options] && options[:options]["dataVolume#{volume_index}"]
710
+ add_another_volume = has_another_volume || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add data volume?"))
711
+ while add_another_volume do
712
+ #puts "Configure Data #{volume_index} Volume"
658
713
 
659
- field_context = "dataVolume#{volume_index}"
714
+ field_context = "dataVolume#{volume_index}"
660
715
 
661
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Storage Type", 'selectOptions' => storage_types, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.'}], options[:options])
662
- storage_type_id = v_prompt[field_context]['storageType']
663
- storage_type = plan_info['storageTypes'].find {|i| i['id'] == storage_type_id.to_i }
664
-
716
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Storage Type", 'selectOptions' => storage_types, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.'}], options[:options])
717
+ storage_type_id = v_prompt[field_context]['storageType']
718
+ storage_type = plan_info['storageTypes'].find {|i| i['id'] == storage_type_id.to_i }
665
719
 
666
- # sometimes the user chooses sizeId from a list of size options (AccountPrice) and other times it is free form
667
- custom_size_options = []
668
- if plan_info['customSizeOptions'] && plan_info['customSizeOptions'][storage_type_id.to_s]
669
- plan_info['customSizeOptions'][storage_type_id.to_s].each do |opt|
670
- if !opt.nil?
671
- custom_size_options << {'name' => opt['value'], 'value' => opt['key']}
720
+ # sometimes the user chooses sizeId from a list of size options (AccountPrice) and other times it is free form
721
+ custom_size_options = []
722
+ if plan_info['customSizeOptions'] && plan_info['customSizeOptions'][storage_type_id.to_s]
723
+ plan_info['customSizeOptions'][storage_type_id.to_s].each do |opt|
724
+ if !opt.nil?
725
+ custom_size_options << {'name' => opt['value'], 'value' => opt['key']}
726
+ end
727
+ end
672
728
  end
673
- end
674
- end
675
729
 
676
- volume_label = (volume_index == 1 ? 'data' : "data #{volume_index}")
677
- volume = {
678
- 'id' => -1,
679
- 'rootVolume' => false,
680
- 'name' => volume_label,
681
- 'size' => plan_size,
682
- 'sizeId' => nil,
683
- 'storageType' => storage_type_id,
684
- 'datastoreId' => nil
685
- }
730
+ volume_label = (volume_index == 1 ? 'data' : "data #{volume_index}")
731
+ volume = {
732
+ 'id' => -1,
733
+ 'rootVolume' => false,
734
+ 'name' => volume_label,
735
+ 'size' => plan_size,
736
+ 'sizeId' => nil,
737
+ 'storageType' => storage_type_id,
738
+ 'datastoreId' => nil
739
+ }
740
+
741
+ if plan_info['customizeVolume'] && storage_type['customLabel']
742
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => "Disk #{volume_index} Volume Label", 'required' => true, 'description' => 'Enter a volume label.', 'defaultValue' => volume_label}], options[:options])
743
+ volume['name'] = v_prompt[field_context]['name']
744
+ end
745
+ if plan_info['customizeVolume'] && storage_type['customSize']
746
+ if custom_size_options.empty?
747
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'size', 'type' => 'number', 'fieldLabel' => "Disk #{volume_index} Volume Size (GB)", 'required' => true, 'description' => 'Enter a volume size (GB).', 'defaultValue' => plan_size}], options[:options])
748
+ volume['size'] = v_prompt[field_context]['size']
749
+ volume['sizeId'] = nil #volume.delete('sizeId')
750
+ else
751
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'sizeId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Volume Size", 'selectOptions' => custom_size_options, 'required' => true, 'description' => 'Choose a volume size.'}], options[:options])
752
+ volume['sizeId'] = v_prompt[field_context]['sizeId']
753
+ volume['size'] = nil #volume.delete('size')
754
+ end
755
+ else
756
+ # might need different logic here ? =o
757
+ volume['size'] = plan_size
758
+ volume['sizeId'] = nil #volume.delete('sizeId')
759
+ end
760
+ if !datastore_options.empty?
761
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'datastoreId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Datastore", 'selectOptions' => datastore_options, 'required' => true, 'description' => 'Choose a datastore.'}], options[:options])
762
+ volume['datastoreId'] = v_prompt[field_context]['datastoreId']
763
+ end
686
764
 
687
- if plan_info['customizeVolume'] && storage_type['customLabel']
688
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => "Disk #{volume_index} Volume Label", 'required' => true, 'description' => 'Enter a volume label.', 'defaultValue' => volume_label}], options[:options])
689
- volume['name'] = v_prompt[field_context]['name']
690
- end
691
- if plan_info['customizeVolume'] && storage_type['customSize']
692
- if custom_size_options.empty?
693
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'size', 'type' => 'number', 'fieldLabel' => "Disk #{volume_index} Volume Size (GB)", 'required' => true, 'description' => 'Enter a volume size (GB).', 'defaultValue' => plan_size}], options[:options])
694
- volume['size'] = v_prompt[field_context]['size']
695
- volume['sizeId'] = nil #volume.delete('sizeId')
696
- else
697
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'sizeId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Volume Size", 'selectOptions' => custom_size_options, 'required' => true, 'description' => 'Choose a volume size.'}], options[:options])
698
- volume['sizeId'] = v_prompt[field_context]['sizeId']
699
- volume['size'] = nil #volume.delete('size')
700
- end
701
- else
702
- # might need different logic here ? =o
703
- volume['size'] = plan_size
704
- volume['sizeId'] = nil #volume.delete('sizeId')
705
- end
706
- if !datastore_options.empty?
707
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'datastoreId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Datastore", 'selectOptions' => datastore_options, 'required' => true, 'description' => 'Choose a datastore.'}], options[:options])
708
- volume['datastoreId'] = v_prompt[field_context]['datastoreId']
709
- end
765
+ volumes << volume
710
766
 
711
- volumes << volume
767
+ # todo: should maxDisk check consider the root volume too?
768
+ if plan_info['maxDisk'] && volume_index >= plan_info['maxDisk']
769
+ add_another_volume = false
770
+ else
771
+ volume_index += 1
772
+ has_another_volume = options[:options] && options[:options]["dataVolume#{volume_index}"]
773
+ add_another_volume = has_another_volume || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another data volume?"))
774
+ end
775
+
776
+ end
712
777
 
713
- # todo: should maxDisk check consider the root volume too?
714
- if plan_info['maxDisk'] && volume_index >= plan_info['maxDisk']
715
- add_another_volume = false
716
- else
717
- volume_index += 1
718
- has_another_volume = options[:options] && options[:options]["dataVolume#{volume_index}"]
719
- add_another_volume = has_another_volume || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another data volume?"))
720
778
  end
721
779
 
780
+ return volumes
722
781
  end
723
782
 
724
- end
725
-
726
- return volumes
727
- end
728
-
729
-
730
- # This recreates the behavior of multi_networks.js
731
- # This is used by both `instances add` and `hosts add`
732
- # returns array of networkInterfaces based on provision type and cloud settings
733
- def prompt_network_interfaces(zone_id, provision_type_id, options={}, api_client=nil)
734
- #puts "Configure Networks:"
735
- no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
736
-
737
- network_interfaces = []
738
-
739
- zone_network_options_json = api_client.options.options_for_source('zoneNetworkOptions', {zoneId: zone_id, provisionTypeId: provision_type_id})
740
- # puts "zoneNetworkOptions JSON"
741
- # puts JSON.pretty_generate(zone_network_options_json)
742
- zone_network_data = zone_network_options_json['data'] || {}
743
- networks = zone_network_data['networks']
744
- network_interface_types = (zone_network_data['networkTypes'] || []).sort { |x,y| x['displayOrder'] <=> y['displayOrder'] }
745
- enable_network_type_selection = (zone_network_data['enableNetworkTypeSelection'] == 'on' || zone_network_data['enableNetworkTypeSelection'] == true)
746
- has_networks = zone_network_data["hasNetworks"] == true
747
- max_networks = zone_network_data["maxNetworks"] ? zone_network_data["maxNetworks"].to_i : nil
748
783
 
749
- # skip unless provision type supports networks
750
- if !has_networks
751
- return nil
752
- end
753
-
754
- # no networks available, shouldn't happen
755
- if networks.empty?
756
- return network_interfaces
757
- end
758
-
759
- network_options = []
760
- networks.each do |opt|
761
- if !opt.nil?
762
- network_options << {'name' => opt['name'], 'value' => opt['id']}
763
- end
764
- end
784
+ # This recreates the behavior of multi_networks.js
785
+ # This is used by both `instances add` and `hosts add`
786
+ # returns array of networkInterfaces based on provision type and cloud settings
787
+ def prompt_network_interfaces(zone_id, provision_type_id, options={})
788
+ #puts "Configure Networks:"
789
+ no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
790
+ network_interfaces = []
791
+
792
+ zone_network_options_json = api_client.options.options_for_source('zoneNetworkOptions', {zoneId: zone_id, provisionTypeId: provision_type_id})
793
+ # puts "zoneNetworkOptions JSON"
794
+ # puts JSON.pretty_generate(zone_network_options_json)
795
+ zone_network_data = zone_network_options_json['data'] || {}
796
+ networks = zone_network_data['networks']
797
+ network_interface_types = (zone_network_data['networkTypes'] || []).sort { |x,y| x['displayOrder'] <=> y['displayOrder'] }
798
+ enable_network_type_selection = (zone_network_data['enableNetworkTypeSelection'] == 'on' || zone_network_data['enableNetworkTypeSelection'] == true)
799
+ has_networks = zone_network_data["hasNetworks"] == true
800
+ max_networks = zone_network_data["maxNetworks"] ? zone_network_data["maxNetworks"].to_i : nil
801
+
802
+ # skip unless provision type supports networks
803
+ if !has_networks
804
+ return nil
805
+ end
765
806
 
766
- network_interface_type_options = []
767
- network_interface_types.each do |opt|
768
- if !opt.nil?
769
- network_interface_type_options << {'name' => opt['name'], 'value' => opt['id']}
770
- end
771
- end
807
+ # no networks available, shouldn't happen
808
+ if networks.empty?
809
+ return network_interfaces
810
+ end
772
811
 
812
+ network_options = []
813
+ networks.each do |opt|
814
+ if !opt.nil?
815
+ network_options << {'name' => opt['name'], 'value' => opt['id']}
816
+ end
817
+ end
773
818
 
774
- interface_index = 1
775
-
776
- # has_another_interface = options[:options] && options[:options]["networkInterface"]
777
- # add_another_interface = has_another_interface || (!no_prompt)
778
- add_another_interface = true
779
-
780
- while add_another_interface do
781
-
782
- # if !no_prompt
783
- # if interface_index == 1
784
- # puts "Configure Network Interface"
785
- # else
786
- # puts "Configure Network Interface #{interface_index}"
787
- # end
788
- # end
819
+ network_interface_type_options = []
820
+ network_interface_types.each do |opt|
821
+ if !opt.nil?
822
+ network_interface_type_options << {'name' => opt['name'], 'value' => opt['id']}
823
+ end
824
+ end
789
825
 
790
- field_context = interface_index == 1 ? "networkInterface" : "networkInterface#{interface_index}"
791
-
792
- network_interface = {}
793
826
 
794
- # choose network
795
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'networkId', 'type' => 'select', 'fieldLabel' => "Network", 'selectOptions' => network_options, 'required' => true, 'skipSingleOption' => false, 'description' => 'Choose a network for this interface.', 'defaultValue' => network_interface['networkId']}], options[:options])
796
- network_interface['network'] = {}
797
- network_interface['network']['id'] = v_prompt[field_context]['networkId'].to_i
827
+ interface_index = 1
828
+ add_another_interface = true
829
+ while add_another_interface do
830
+ # if !no_prompt
831
+ # if interface_index == 1
832
+ # puts "Configure Network Interface"
833
+ # else
834
+ # puts "Configure Network Interface #{interface_index}"
835
+ # end
836
+ # end
837
+
838
+ field_context = interface_index == 1 ? "networkInterface" : "networkInterface#{interface_index}"
839
+ network_interface = {}
840
+
841
+ # choose network
842
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'networkId', 'type' => 'select', 'fieldLabel' => "Network", 'selectOptions' => network_options, 'required' => true, 'skipSingleOption' => false, 'description' => 'Choose a network for this interface.', 'defaultValue' => network_interface['networkId']}], options[:options])
843
+ network_interface['network'] = {}
844
+ network_interface['network']['id'] = v_prompt[field_context]['networkId'].to_i
845
+ selected_network = networks.find {|it| it["id"] == network_interface['network']['id'] }
846
+
847
+ # if !selected_network
848
+ # print_red_alert "Network not found by id #{network_interface['network']['id']}!"
849
+ # exit 1
850
+ # end
851
+
852
+ # choose network interface type
853
+ if enable_network_type_selection && !network_interface_type_options.empty?
854
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'networkInterfaceTypeId', 'type' => 'select', 'fieldLabel' => "Network Interface Type", 'selectOptions' => network_interface_type_options, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a network interface type.', 'defaultValue' => network_interface['networkInterfaceTypeId']}], options[:options])
855
+ network_interface['networkInterfaceTypeId'] = v_prompt[field_context]['networkInterfaceTypeId'].to_i
856
+ end
798
857
 
799
- selected_network = networks.find {|it| it["id"] == network_interface['network']['id'] }
858
+ # choose IP unless network has a pool configured
859
+ if selected_network['pool']
860
+ puts "IP Address: Using pool '#{selected_network['pool']['name']}'" if !no_prompt
861
+ elsif selected_network['dhcpServer']
862
+ puts "IP Address: Using DHCP" if !no_prompt
863
+ else
864
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'ipAddress', 'type' => 'text', 'fieldLabel' => "IP Address", 'required' => true, 'description' => 'Enter an IP for this network interface. x.x.x.x', 'defaultValue' => network_interface['ipAddress']}], options[:options])
865
+ network_interface['ipAddress'] = v_prompt[field_context]['ipAddress']
866
+ end
867
+ network_interfaces << network_interface
868
+ interface_index += 1
869
+ has_another_interface = options[:options] && options[:options]["networkInterface#{interface_index}"]
870
+ add_another_interface = has_another_interface || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another network interface?", {:default => false}))
871
+ if max_networks && network_interfaces.size >= max_networks
872
+ add_another_interface = false
873
+ end
800
874
 
801
- # choose network interface type
802
- if enable_network_type_selection && !network_interface_type_options.empty?
803
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'networkInterfaceTypeId', 'type' => 'select', 'fieldLabel' => "Network Interface Type", 'selectOptions' => network_interface_type_options, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a network interface type.', 'defaultValue' => network_interface['networkInterfaceTypeId']}], options[:options])
804
- network_interface['networkInterfaceTypeId'] = v_prompt[field_context]['networkInterfaceTypeId'].to_i
805
- end
875
+ end
806
876
 
807
- # choose IP unless network has a pool configured
808
- if selected_network['pool']
809
- puts "IP Address: Using pool '#{selected_network['pool']['name']}'" if !no_prompt
810
- elsif selected_network['dhcpServer']
811
- puts "IP Address: Using DHCP" if !no_prompt
812
- else
813
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'ipAddress', 'type' => 'text', 'fieldLabel' => "IP Address", 'required' => true, 'description' => 'Enter an IP for this network interface. x.x.x.x', 'defaultValue' => network_interface['ipAddress']}], options[:options])
814
- network_interface['ipAddress'] = v_prompt[field_context]['ipAddress']
815
- end
816
-
817
- network_interfaces << network_interface
818
-
819
- interface_index += 1
820
- has_another_interface = options[:options] && options[:options]["networkInterface#{interface_index}"]
821
- add_another_interface = has_another_interface || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another network interface?"))
822
- if max_networks && network_interfaces.size >= max_networks
823
- add_another_interface = false
824
- end
877
+ return network_interfaces
825
878
 
826
- end
879
+ end
827
880
 
828
- return network_interfaces
881
+ # Prompts user for environment variables for new instance
882
+ # returns array of evar objects {id: null, name: "VAR", value: "somevalue"}
883
+ def prompt_evars(options={})
884
+ #puts "Configure Environment Variables:"
885
+ no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
886
+ evars = []
887
+ evar_index = 0
888
+ has_another_evar = options[:options] && options[:options]["evar#{evar_index}"]
889
+ add_another_evar = has_another_evar || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add an environment variable?", {default: false}))
890
+ while add_another_evar do
891
+ field_context = "evar#{evar_index}"
892
+ evar = {}
893
+ evar['id'] = nil
894
+ evar_label = evar_index == 0 ? "ENV" : "ENV [#{evar_index+1}]"
895
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => "#{evar_label} Name", 'required' => true, 'description' => 'Environment Variable Name.', 'defaultValue' => evar['name']}], options[:options])
896
+ evar['name'] = v_prompt[field_context]['name']
897
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'value', 'type' => 'text', 'fieldLabel' => "#{evar_label} Value", 'required' => true, 'description' => 'Environment Variable Value', 'defaultValue' => evar['value']}], options[:options])
898
+ evar['value'] = v_prompt[field_context]['value']
899
+ evars << evar
900
+ evar_index += 1
901
+ has_another_evar = options[:options] && options[:options]["evar#{evar_index}"]
902
+ add_another_evar = has_another_evar || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another environment variable?", {default: false}))
903
+ end
829
904
 
830
- end
905
+ return evars
906
+ end
831
907
 
832
- # reject old volume option types
833
- # these will eventually get removed from the associated optionTypes
834
- def reject_volume_option_types(option_types)
835
- option_types.reject {|opt|
836
- ['osDiskSize', 'osDiskType',
837
- 'diskSize', 'diskType',
838
- 'datastoreId', 'storagePodId'
839
- ].include?(opt['fieldName'])
840
- }
841
- end
908
+ # reject old volume option types
909
+ # these will eventually get removed from the associated optionTypes
910
+ def reject_volume_option_types(option_types)
911
+ option_types.reject {|opt|
912
+ ['osDiskSize', 'osDiskType',
913
+ 'diskSize', 'diskType',
914
+ 'datastoreId', 'storagePodId'
915
+ ].include?(opt['fieldName'])
916
+ }
917
+ end
842
918
 
843
- # reject old networking option types
844
- # these will eventually get removed from the associated optionTypes
845
- def reject_networking_option_types(option_types)
846
- option_types.reject {|opt|
847
- ['networkId', 'networkType', 'ipAddress', 'netmask', 'gateway', 'nameservers',
848
- 'vmwareNetworkType', 'vmwareIpAddress', 'vmwareNetmask', 'vmwareGateway', 'vmwareNameservers'
849
- ].include?(opt['fieldName'])
850
- }
851
- end
919
+ # reject old networking option types
920
+ # these will eventually get removed from the associated optionTypes
921
+ def reject_networking_option_types(option_types)
922
+ option_types.reject {|opt|
923
+ ['networkId', 'networkType', 'ipAddress', 'netmask', 'gateway', 'nameservers',
924
+ 'vmwareNetworkType', 'vmwareIpAddress', 'vmwareNetmask', 'vmwareGateway', 'vmwareNameservers',
925
+ 'subnetId'
926
+ ].include?(opt['fieldName'])
927
+ }
928
+ end
852
929
 
853
- # reject old option types that now come from the selected service plan
854
- # these will eventually get removed from the associated optionTypes
855
- def reject_service_plan_option_types(option_types)
856
- option_types.reject {|opt|
857
- ['cpuCount', 'memorySize', 'memory'].include?(opt['fieldName'])
858
- }
859
- end
930
+ # reject old option types that now come from the selected service plan
931
+ # these will eventually get removed from the associated optionTypes
932
+ def reject_service_plan_option_types(option_types)
933
+ option_types.reject {|opt|
934
+ ['cpuCount', 'memorySize', 'memory'].include?(opt['fieldName'])
935
+ }
936
+ end
860
937
 
861
- def instance_context_options
862
- [{'name' => 'Dev', 'value' => 'dev'}, {'name' => 'Test', 'value' => 'qa'}, {'name' => 'Staging', 'value' => 'staging'}, {'name' => 'Production', 'value' => 'production'}]
863
- end
938
+ def instance_context_options
939
+ [{'name' => 'Dev', 'value' => 'dev'}, {'name' => 'Test', 'value' => 'qa'}, {'name' => 'Staging', 'value' => 'staging'}, {'name' => 'Production', 'value' => 'production'}]
940
+ end
864
941
 
865
- end
942
+ end