morpheus-cli 2.10.0 → 2.10.1

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