morpheus-cli 5.4.0 → 5.4.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api/account_users_interface.rb +68 -0
- data/lib/morpheus/api/api_client.rb +55 -10
- data/lib/morpheus/api/audit_interface.rb +9 -0
- data/lib/morpheus/api/catalog_item_types_interface.rb +20 -0
- data/lib/morpheus/api/instances_interface.rb +49 -0
- data/lib/morpheus/api/load_balancer_monitors_interface.rb +9 -0
- data/lib/morpheus/api/load_balancer_pools_interface.rb +4 -4
- data/lib/morpheus/api/load_balancer_profiles_interface.rb +4 -5
- data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +13 -4
- data/lib/morpheus/api/load_balancers_interface.rb +5 -0
- data/lib/morpheus/api/network_routers_interface.rb +9 -0
- data/lib/morpheus/api/network_static_routes_interface.rb +36 -0
- data/lib/morpheus/api/ping_interface.rb +2 -0
- data/lib/morpheus/api/read_interface.rb +4 -3
- data/lib/morpheus/api/rest_interface.rb +3 -3
- data/lib/morpheus/api/secondary_read_interface.rb +1 -1
- data/lib/morpheus/api/secondary_rest_interface.rb +19 -19
- data/lib/morpheus/api/setup_interface.rb +4 -0
- data/lib/morpheus/api/snapshots_interface.rb +19 -0
- data/lib/morpheus/api/storage_server_types_interface.rb +14 -0
- data/lib/morpheus/api/storage_servers_interface.rb +9 -0
- data/lib/morpheus/api/storage_volume_types_interface.rb +9 -0
- data/lib/morpheus/api/storage_volumes_interface.rb +9 -0
- data/lib/morpheus/api/users_interface.rb +16 -63
- data/lib/morpheus/cli/cli_command.rb +253 -5
- data/lib/morpheus/cli/cli_registry.rb +1 -1
- data/lib/morpheus/cli/commands/alias_command.rb +1 -1
- data/lib/morpheus/cli/commands/apps.rb +14 -78
- data/lib/morpheus/cli/commands/audit.rb +188 -0
- data/lib/morpheus/cli/commands/blueprints_command.rb +1 -1
- data/lib/morpheus/cli/commands/catalog_item_types_command.rb +88 -0
- data/lib/morpheus/cli/commands/change_password_command.rb +4 -4
- data/lib/morpheus/cli/commands/clusters.rb +96 -58
- data/lib/morpheus/cli/commands/hosts.rb +27 -15
- data/lib/morpheus/cli/commands/image_builder_command.rb +4 -8
- data/lib/morpheus/cli/commands/instances.rb +359 -3
- data/lib/morpheus/cli/commands/integrations_command.rb +1 -12
- data/lib/morpheus/cli/commands/library_instance_types_command.rb +3 -0
- data/lib/morpheus/cli/commands/load_balancer_monitors.rb +70 -0
- data/lib/morpheus/cli/commands/load_balancer_pools.rb +29 -50
- data/lib/morpheus/cli/commands/load_balancer_profiles.rb +64 -0
- data/lib/morpheus/cli/commands/load_balancer_types.rb +9 -4
- data/lib/morpheus/cli/commands/load_balancer_virtual_servers.rb +69 -58
- data/lib/morpheus/cli/commands/load_balancers.rb +109 -6
- data/lib/morpheus/cli/commands/network_firewalls_command.rb +22 -5
- data/lib/morpheus/cli/commands/network_routers_command.rb +96 -45
- data/lib/morpheus/cli/commands/network_static_routes_command.rb +451 -0
- data/lib/morpheus/cli/commands/network_transport_zones_command.rb +4 -4
- data/lib/morpheus/cli/commands/networks_command.rb +2 -2
- data/lib/morpheus/cli/commands/open_command.rb +30 -0
- data/lib/morpheus/cli/commands/options.rb +98 -0
- data/lib/morpheus/cli/commands/ping.rb +3 -5
- data/lib/morpheus/cli/commands/policies_command.rb +2 -2
- data/lib/morpheus/cli/commands/prices_command.rb +7 -7
- data/lib/morpheus/cli/commands/provisioning_settings_command.rb +1 -0
- data/lib/morpheus/cli/commands/remote.rb +20 -12
- data/lib/morpheus/cli/commands/roles.rb +1 -1
- data/lib/morpheus/cli/commands/security_groups.rb +2 -2
- data/lib/morpheus/cli/commands/service_plans_command.rb +1 -1
- data/lib/morpheus/cli/commands/setup.rb +1 -1
- data/lib/morpheus/cli/commands/shell.rb +2 -2
- data/lib/morpheus/cli/commands/snapshots.rb +139 -0
- data/lib/morpheus/cli/commands/storage_server_types.rb +50 -0
- data/lib/morpheus/cli/commands/storage_servers.rb +122 -0
- data/lib/morpheus/cli/commands/storage_volume_types.rb +50 -0
- data/lib/morpheus/cli/commands/storage_volumes.rb +103 -0
- data/lib/morpheus/cli/commands/tasks.rb +5 -5
- data/lib/morpheus/cli/commands/tenants_command.rb +1 -1
- data/lib/morpheus/cli/commands/user_groups_command.rb +1 -1
- data/lib/morpheus/cli/commands/user_settings_command.rb +3 -2
- data/lib/morpheus/cli/commands/user_sources_command.rb +1 -1
- data/lib/morpheus/cli/commands/users.rb +28 -28
- data/lib/morpheus/cli/commands/view.rb +102 -0
- data/lib/morpheus/cli/commands/virtual_images.rb +4 -1
- data/lib/morpheus/cli/mixins/accounts_helper.rb +5 -5
- data/lib/morpheus/cli/mixins/load_balancers_helper.rb +24 -4
- data/lib/morpheus/cli/mixins/print_helper.rb +50 -18
- data/lib/morpheus/cli/mixins/processes_helper.rb +1 -2
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +96 -6
- data/lib/morpheus/cli/mixins/rest_command.rb +148 -74
- data/lib/morpheus/cli/mixins/secondary_rest_command.rb +174 -82
- data/lib/morpheus/cli/mixins/storage_servers_helper.rb +156 -0
- data/lib/morpheus/cli/mixins/storage_volumes_helper.rb +119 -0
- data/lib/morpheus/cli/option_types.rb +95 -28
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli.rb +1 -0
- data/lib/morpheus/ext/string.rb +29 -6
- data/lib/morpheus/routes.rb +238 -0
- data/lib/morpheus/util.rb +6 -1
- metadata +26 -2
|
@@ -85,6 +85,37 @@ module Morpheus::Cli::SecondaryRestCommand
|
|
|
85
85
|
|
|
86
86
|
alias :set_rest_parent_arg :rest_parent_arg=
|
|
87
87
|
|
|
88
|
+
def rest_parent_param
|
|
89
|
+
@rest_parent_param || default_rest_parent_param
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def default_rest_parent_param
|
|
93
|
+
param = rest_parent_key.to_s.split('_').collect(&:capitalize).join
|
|
94
|
+
"#{param[0].downcase}#{param[1..-1]}Id"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def rest_parent_param=(v)
|
|
98
|
+
@rest_parent_param = v.to_s
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
alias :set_rest_parent_param :rest_parent_param=
|
|
102
|
+
|
|
103
|
+
# rest_parent_has_name indicates a resource has a name and can be retrieved by name or id
|
|
104
|
+
# true by default, set to false for lookups by only id
|
|
105
|
+
def rest_parent_has_name
|
|
106
|
+
@rest_parent_has_name != nil ? @rest_parent_has_name : default_rest_parent_has_name
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def default_rest_parent_has_name
|
|
110
|
+
true
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def rest_parent_has_name=(v)
|
|
114
|
+
@rest_parent_has_name = !!v
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
alias :set_rest_parent_has_name :rest_parent_has_name=
|
|
118
|
+
|
|
88
119
|
# rest_parent_label is the capitalized resource label eg. "Neat Thing"
|
|
89
120
|
def rest_parent_label
|
|
90
121
|
@rest_parent_label || default_rest_parent_label
|
|
@@ -147,6 +178,14 @@ module Morpheus::Cli::SecondaryRestCommand
|
|
|
147
178
|
self.class.rest_parent_arg
|
|
148
179
|
end
|
|
149
180
|
|
|
181
|
+
def rest_parent_param
|
|
182
|
+
self.class.rest_parent_param
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def rest_parent_has_name
|
|
186
|
+
self.class.rest_parent_has_name
|
|
187
|
+
end
|
|
188
|
+
|
|
150
189
|
def rest_parent_label
|
|
151
190
|
self.class.rest_parent_label
|
|
152
191
|
end
|
|
@@ -164,23 +203,56 @@ module Morpheus::Cli::SecondaryRestCommand
|
|
|
164
203
|
end
|
|
165
204
|
|
|
166
205
|
def rest_parent_object_key
|
|
167
|
-
|
|
206
|
+
send("#{rest_parent_key}_object_key")
|
|
168
207
|
end
|
|
169
208
|
|
|
170
209
|
def rest_parent_list_key
|
|
171
|
-
|
|
210
|
+
send("#{rest_parent_key}_list_key")
|
|
172
211
|
end
|
|
173
212
|
|
|
174
|
-
def rest_parent_column_definitions
|
|
175
|
-
|
|
213
|
+
def rest_parent_column_definitions(options)
|
|
214
|
+
send("#{rest_parent_key}_column_definitions", options)
|
|
176
215
|
end
|
|
177
216
|
|
|
178
|
-
def rest_parent_list_column_definitions
|
|
179
|
-
|
|
217
|
+
def rest_parent_list_column_definitions(options)
|
|
218
|
+
send("#{rest_parent_key}_list_column_definitions", options)
|
|
180
219
|
end
|
|
181
220
|
|
|
182
|
-
def rest_parent_find_by_name_or_id(
|
|
183
|
-
|
|
221
|
+
def rest_parent_find_by_name_or_id(val)
|
|
222
|
+
# use explicitly defined finders
|
|
223
|
+
# else default to new generic CliCommand find_by methods
|
|
224
|
+
if rest_parent_has_name
|
|
225
|
+
if respond_to?("find_#{rest_parent_key}_by_name_or_id", true)
|
|
226
|
+
send("find_#{rest_parent_key}_by_name_or_id", val)
|
|
227
|
+
else
|
|
228
|
+
find_by_name_or_id(rest_parent_key, val)
|
|
229
|
+
end
|
|
230
|
+
else
|
|
231
|
+
if respond_to?("find_#{rest_parent_key}_by_id", true)
|
|
232
|
+
send("find_#{rest_parent_key}_by_id", val)
|
|
233
|
+
else
|
|
234
|
+
find_by_id(rest_parent_key, val)
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# override RestCommand method to include parent_id parameter
|
|
240
|
+
def rest_find_by_name_or_id(parent_id, val)
|
|
241
|
+
# use explicitly defined finders
|
|
242
|
+
# else default to new generic CliCommand find_by methods
|
|
243
|
+
if rest_has_name
|
|
244
|
+
if respond_to?("find_#{rest_key}_by_name_or_id", true)
|
|
245
|
+
send("find_#{rest_key}_by_name_or_id", parent_id, val)
|
|
246
|
+
else
|
|
247
|
+
find_by_name_or_id(rest_key, parent_id, val)
|
|
248
|
+
end
|
|
249
|
+
else
|
|
250
|
+
if respond_to?("find_#{rest_key}_by_id", true)
|
|
251
|
+
send("find_#{rest_key}_by_id", parent_id, val)
|
|
252
|
+
else
|
|
253
|
+
find_by_id(rest_key, parent_id, val)
|
|
254
|
+
end
|
|
255
|
+
end
|
|
184
256
|
end
|
|
185
257
|
|
|
186
258
|
def registered_interfaces
|
|
@@ -193,29 +265,23 @@ module Morpheus::Cli::SecondaryRestCommand
|
|
|
193
265
|
options = {}
|
|
194
266
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
195
267
|
opts.banner = subcommand_usage("[#{rest_parent_arg}] [search]")
|
|
196
|
-
|
|
268
|
+
build_list_options(opts, options, params)
|
|
197
269
|
opts.footer = <<-EOT
|
|
198
270
|
List #{rest_label_plural.downcase}.
|
|
199
|
-
[#{rest_parent_arg}] is required. This is the name or id of #{a_or_an(rest_parent_label)} #{rest_parent_label.downcase}.
|
|
271
|
+
[#{rest_parent_arg}] is required. This is the #{rest_parent_has_name ? 'name or id' : 'id'} of #{a_or_an(rest_parent_label)} #{rest_parent_label.downcase}.
|
|
200
272
|
[search] is optional. This is a search phrase to filter the results.
|
|
201
273
|
EOT
|
|
202
274
|
end
|
|
203
275
|
optparse.parse!(args)
|
|
204
|
-
parent_id = args[0]
|
|
205
|
-
if args[1] # && rest_has_name
|
|
206
|
-
record_name = args[1]
|
|
207
|
-
end
|
|
208
276
|
verify_args!(args:args, optparse:optparse, min:1)
|
|
209
|
-
if args.count > 1
|
|
210
|
-
options[:phrase] = args[1..-1].join(" ")
|
|
211
|
-
end
|
|
212
277
|
connect(options)
|
|
278
|
+
parent_id = args[0]
|
|
213
279
|
parent_record = rest_parent_find_by_name_or_id(parent_id)
|
|
214
280
|
if parent_record.nil?
|
|
215
|
-
|
|
281
|
+
return 1, "#{rest_parent_label} not found for '#{parent_id}"
|
|
216
282
|
end
|
|
217
283
|
parent_id = parent_record['id']
|
|
218
|
-
|
|
284
|
+
parse_list_options!(args.count > 1 ? args[1..-1] : [], options, params)
|
|
219
285
|
rest_interface.setopts(options)
|
|
220
286
|
if options[:dry_run]
|
|
221
287
|
print_dry_run rest_interface.dry.list(parent_id, params)
|
|
@@ -228,7 +294,7 @@ EOT
|
|
|
228
294
|
if records.nil? || records.empty?
|
|
229
295
|
print cyan,"No #{rest_label_plural.downcase} found.",reset,"\n"
|
|
230
296
|
else
|
|
231
|
-
print as_pretty_table(records, rest_list_column_definitions.upcase_keys!, options)
|
|
297
|
+
print as_pretty_table(records, rest_list_column_definitions(options).upcase_keys!, options)
|
|
232
298
|
print_results_pagination(json_response) if json_response['meta']
|
|
233
299
|
end
|
|
234
300
|
print reset,"\n"
|
|
@@ -241,43 +307,41 @@ EOT
|
|
|
241
307
|
options = {}
|
|
242
308
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
243
309
|
opts.banner = subcommand_usage("[#{rest_parent_arg}] [#{rest_arg}]")
|
|
244
|
-
|
|
310
|
+
build_get_options(opts, options, params)
|
|
245
311
|
opts.footer = <<-EOT
|
|
246
312
|
Get details about #{a_or_an(rest_label)} #{rest_label.downcase}.
|
|
247
|
-
[#{rest_parent_arg}] is required. This is the name or id of #{a_or_an(rest_parent_label)} #{rest_parent_label.downcase}.
|
|
248
|
-
[#{rest_arg}] is required. This is the name or id of #{a_or_an(rest_label)} #{rest_label.downcase}.
|
|
313
|
+
[#{rest_parent_arg}] is required. This is the #{rest_parent_has_name ? 'name or id' : 'id'} of #{a_or_an(rest_parent_label)} #{rest_parent_label.downcase}.
|
|
314
|
+
[#{rest_arg}] is required. This is the #{rest_has_name ? 'name or id' : 'id'} of #{a_or_an(rest_label)} #{rest_label.downcase}.
|
|
249
315
|
EOT
|
|
250
316
|
end
|
|
251
317
|
optparse.parse!(args)
|
|
252
318
|
verify_args!(args:args, optparse:optparse, min:2)
|
|
253
319
|
connect(options)
|
|
320
|
+
parse_get_options!(args.count > 1 ? args[1..-1] : [], options, params)
|
|
254
321
|
parent_id = args[0]
|
|
255
322
|
parent_record = rest_parent_find_by_name_or_id(parent_id)
|
|
256
323
|
if parent_record.nil?
|
|
257
|
-
|
|
324
|
+
return 1, "#{rest_parent_label} not found for '#{parent_id}"
|
|
258
325
|
end
|
|
259
326
|
parent_id = parent_record['id']
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
return run_command_for_each_arg(id_list) do |arg|
|
|
263
|
-
_get(parent_id, arg, params, options)
|
|
264
|
-
end
|
|
327
|
+
id = args[1..-1].join(" ")
|
|
328
|
+
_get(parent_id, id, params, options)
|
|
265
329
|
end
|
|
266
330
|
|
|
267
331
|
def _get(parent_id, id, params, options)
|
|
268
332
|
if id !~ /\A\d{1,}\Z/
|
|
269
|
-
record = rest_find_by_name_or_id(id)
|
|
333
|
+
record = rest_find_by_name_or_id(parent_id, id)
|
|
270
334
|
if record.nil?
|
|
271
|
-
|
|
335
|
+
return 1, "#{rest_label} not found for '#{id}"
|
|
272
336
|
end
|
|
273
337
|
id = record['id']
|
|
274
338
|
end
|
|
275
339
|
rest_interface.setopts(options)
|
|
276
340
|
if options[:dry_run]
|
|
277
|
-
print_dry_run rest_interface.dry.get(id, params)
|
|
341
|
+
print_dry_run rest_interface.dry.get(parent_id, id, params)
|
|
278
342
|
return
|
|
279
343
|
end
|
|
280
|
-
json_response = rest_interface.get(id, params)
|
|
344
|
+
json_response = rest_interface.get(parent_id, id, params)
|
|
281
345
|
render_response_for_get(json_response, options)
|
|
282
346
|
return 0, nil
|
|
283
347
|
end
|
|
@@ -287,7 +351,7 @@ EOT
|
|
|
287
351
|
record = json_response[rest_object_key]
|
|
288
352
|
print_h1 rest_label, [], options
|
|
289
353
|
print cyan
|
|
290
|
-
print_description_list(rest_column_definitions, record, options)
|
|
354
|
+
print_description_list(rest_column_definitions(options), record, options)
|
|
291
355
|
# show config settings...
|
|
292
356
|
if record['optionTypes'] && record['optionTypes'].size > 0
|
|
293
357
|
print_h2 "Option Types", options
|
|
@@ -301,22 +365,22 @@ EOT
|
|
|
301
365
|
parent_id, parent_record = nil, nil
|
|
302
366
|
record_type_id = nil
|
|
303
367
|
options = {}
|
|
368
|
+
option_types = respond_to?("add_#{rest_key}_option_types", true) ? send("add_#{rest_key}_option_types") : []
|
|
369
|
+
advanced_option_types = respond_to?("add_#{rest_key}_advanced_option_types", true) ? send("add_#{rest_key}_advanced_option_types") : []
|
|
370
|
+
type_option_type = option_types.find {|it| it['fieldName'] == 'type'}
|
|
304
371
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
305
|
-
|
|
372
|
+
opts.banner = subcommand_usage("[#{rest_parent_arg}] [#{rest_arg}]")
|
|
373
|
+
if rest_has_type && type_option_type.nil?
|
|
306
374
|
opts.on( '-t', "--#{rest_type_arg} TYPE", "#{rest_type_label}" ) do |val|
|
|
307
375
|
record_type_id = val
|
|
308
376
|
end
|
|
309
377
|
end
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
end
|
|
313
|
-
if self.class.method_defined?("add_#{rest_key}_advanced_option_types")
|
|
314
|
-
build_option_type_options(opts, options, self.send("add_#{rest_key}_advanced_option_types"))
|
|
315
|
-
end
|
|
378
|
+
build_option_type_options(opts, options, option_types)
|
|
379
|
+
build_option_type_options(opts, options, advanced_option_types)
|
|
316
380
|
build_standard_add_options(opts, options)
|
|
317
381
|
opts.footer = <<-EOT
|
|
318
382
|
Create a new #{rest_label.downcase}.
|
|
319
|
-
[#{rest_parent_arg}] is required. This is the name or id of #{a_or_an(rest_parent_label)} #{rest_parent_label.downcase}.
|
|
383
|
+
[#{rest_parent_arg}] is required. This is the #{rest_parent_has_name ? 'name or id' : 'id'} of #{a_or_an(rest_parent_label)} #{rest_parent_label.downcase}.
|
|
320
384
|
[#{rest_arg}] is required. This is the name of the new #{rest_label.downcase}.
|
|
321
385
|
EOT
|
|
322
386
|
end
|
|
@@ -326,31 +390,39 @@ EOT
|
|
|
326
390
|
# for now args[0] is assumed to be the 'name'
|
|
327
391
|
record_name = nil
|
|
328
392
|
parent_id = args[0]
|
|
329
|
-
if
|
|
330
|
-
|
|
393
|
+
if rest_has_name
|
|
394
|
+
if args[1]
|
|
395
|
+
record_name = args[1]
|
|
396
|
+
end
|
|
397
|
+
verify_args!(args:args, optparse:optparse, min:1, max: 2)
|
|
398
|
+
else
|
|
399
|
+
verify_args!(args:args, optparse:optparse, count: 1)
|
|
331
400
|
end
|
|
332
401
|
connect(options)
|
|
333
402
|
# load parent record
|
|
334
403
|
# todo: prompt instead of error
|
|
335
404
|
parent_record = rest_parent_find_by_name_or_id(parent_id)
|
|
336
405
|
if parent_record.nil?
|
|
337
|
-
|
|
406
|
+
return 1, "#{rest_parent_label} not found for '#{parent_id}"
|
|
338
407
|
end
|
|
339
408
|
parent_id = parent_record['id']
|
|
340
409
|
# load or prompt for type
|
|
341
|
-
if rest_has_type
|
|
410
|
+
if rest_has_type && type_option_type.nil?
|
|
342
411
|
if record_type_id.nil?
|
|
343
412
|
#raise_command_error "#{rest_type_label} is required.\n#{optparse}"
|
|
344
|
-
type_list = rest_type_interface.list({max:10000})[rest_type_list_key]
|
|
413
|
+
type_list = rest_type_interface.list({max:10000, creatable: true})[rest_type_list_key]
|
|
345
414
|
type_dropdown_options = type_list.collect {|it| {'name' => it['name'], 'value' => it['code']} }
|
|
346
415
|
record_type_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'fieldLabel' => rest_type_label, 'type' => 'select', 'selectOptions' => type_dropdown_options, 'required' => true}], options[:options], @api_client)['type']
|
|
347
416
|
end
|
|
348
417
|
record_type = rest_type_find_by_name_or_id(record_type_id)
|
|
349
418
|
if record_type.nil?
|
|
350
|
-
|
|
419
|
+
return 1, "#{rest_type_label} not found for '#{record_type_id}"
|
|
351
420
|
end
|
|
352
421
|
end
|
|
353
422
|
passed_options = parse_passed_options(options)
|
|
423
|
+
options[:params] ||= {}
|
|
424
|
+
options[:params][rest_parent_param] = parent_id
|
|
425
|
+
options[:options]['_object_key'] = rest_object_key
|
|
354
426
|
payload = {}
|
|
355
427
|
if options[:payload]
|
|
356
428
|
payload = options[:payload]
|
|
@@ -360,25 +432,41 @@ EOT
|
|
|
360
432
|
if record_name
|
|
361
433
|
record_payload['name'] = record_name
|
|
362
434
|
options[:options]['name'] = record_name # injected for prompt
|
|
435
|
+
options[:options][rest_arg] = record_name
|
|
363
436
|
end
|
|
364
437
|
if rest_has_type && record_type
|
|
365
438
|
# record_payload['type'] = {'code' => record_type['code']}
|
|
366
439
|
record_payload['type'] = record_type['code']
|
|
367
440
|
options[:options]['type'] = record_type['code'] # injected for prompt
|
|
368
441
|
# initialize params for loading optionSource data
|
|
369
|
-
options[:params] ||= {}
|
|
370
442
|
options[:params]['type'] = record_type['code']
|
|
371
443
|
end
|
|
372
444
|
record_payload.deep_merge!(passed_options)
|
|
373
|
-
if
|
|
374
|
-
|
|
375
|
-
v_prompt = Morpheus::Cli::OptionTypes.prompt(add_option_types, options[:options], @api_client, options[:params])
|
|
445
|
+
if option_types && !option_types.empty?
|
|
446
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options], @api_client, options[:params])
|
|
376
447
|
v_prompt.deep_compact!
|
|
377
448
|
v_prompt.booleanize! # 'on' => true
|
|
378
449
|
record_payload.deep_merge!(v_prompt)
|
|
379
450
|
end
|
|
380
451
|
# options by type
|
|
381
|
-
|
|
452
|
+
if rest_has_type && record_type.nil?
|
|
453
|
+
type_value = record_payload['type'].is_a?(Hash) ? record_payload['type']['id'] : record_payload['type']
|
|
454
|
+
if type_value
|
|
455
|
+
record_type = rest_type_find_by_name_or_id(type_value)
|
|
456
|
+
if record_type.nil?
|
|
457
|
+
return 1, "#{rest_type_label} not found for '#{type_value}"
|
|
458
|
+
end
|
|
459
|
+
end
|
|
460
|
+
# reload the type by id to get all the details ie. optionTypes
|
|
461
|
+
if record_type && record_type['optionTypes'].nil?
|
|
462
|
+
record_type = rest_type_find_by_name_or_id(record_type['id'])
|
|
463
|
+
end
|
|
464
|
+
end
|
|
465
|
+
if respond_to?("load_option_types_for_#{rest_key}", true)
|
|
466
|
+
my_option_types = send("load_option_types_for_#{rest_key}", record_type, parent_record)
|
|
467
|
+
else
|
|
468
|
+
my_option_types = record_type ? record_type['optionTypes'] : nil
|
|
469
|
+
end
|
|
382
470
|
if my_option_types && !my_option_types.empty?
|
|
383
471
|
# remove redundant fieldContext
|
|
384
472
|
my_option_types.each do |option_type|
|
|
@@ -386,15 +474,15 @@ EOT
|
|
|
386
474
|
option_type['fieldContext'] = nil
|
|
387
475
|
end
|
|
388
476
|
end
|
|
389
|
-
|
|
477
|
+
api_params = (options[:params] || {}).merge(record_payload)
|
|
478
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(my_option_types, options[:options], @api_client, api_params)
|
|
390
479
|
v_prompt.deep_compact!
|
|
391
480
|
v_prompt.booleanize! # 'on' => true
|
|
392
481
|
record_payload.deep_merge!(v_prompt)
|
|
393
482
|
end
|
|
394
483
|
# advanced options (uses no_prompt)
|
|
395
|
-
if
|
|
396
|
-
|
|
397
|
-
v_prompt = Morpheus::Cli::OptionTypes.no_prompt(add_advanced_option_types, options[:options], @api_client, options[:params])
|
|
484
|
+
if advanced_option_types && !advanced_option_types.empty?
|
|
485
|
+
v_prompt = Morpheus::Cli::OptionTypes.no_prompt(advanced_option_types, options[:options], @api_client, options[:params])
|
|
398
486
|
v_prompt.deep_compact!
|
|
399
487
|
v_prompt.booleanize! # 'on' => true
|
|
400
488
|
record_payload.deep_merge!(v_prompt)
|
|
@@ -421,31 +509,27 @@ EOT
|
|
|
421
509
|
record_type = nil
|
|
422
510
|
record_type_id = nil
|
|
423
511
|
options = {}
|
|
424
|
-
|
|
512
|
+
option_types = respond_to?("update_#{rest_key}_option_types", true) ? send("update_#{rest_key}_option_types") : []
|
|
513
|
+
advanced_option_types = respond_to?("update_#{rest_key}_advanced_option_types", true) ? send("update_#{rest_key}_advanced_option_types") : []
|
|
425
514
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
426
515
|
opts.banner = subcommand_usage("[#{rest_parent_arg}] [#{rest_arg}] [options]")
|
|
427
|
-
if self.class.method_defined?("update_#{rest_key}_option_types")
|
|
428
|
-
build_option_type_options(opts, options, self.send("update_#{rest_key}_option_types"))
|
|
429
|
-
end
|
|
430
|
-
if self.class.method_defined?("update_#{rest_key}_advanced_option_types")
|
|
431
|
-
build_option_type_options(opts, options, self.send("update_#{rest_key}_advanced_option_types"))
|
|
432
|
-
end
|
|
433
516
|
build_standard_update_options(opts, options)
|
|
434
517
|
opts.footer = <<-EOT
|
|
435
518
|
Update an existing #{rest_label.downcase}.
|
|
436
|
-
[#{rest_parent_arg}] is required. This is the name or id of #{a_or_an(rest_parent_label)} #{rest_parent_label.downcase}.
|
|
437
|
-
[#{rest_arg}] is required. This is the name or id of #{a_or_an(rest_label)} #{rest_label.downcase}.
|
|
519
|
+
[#{rest_parent_arg}] is required. This is the #{rest_parent_has_name ? 'name or id' : 'id'} of #{a_or_an(rest_parent_label)} #{rest_parent_label.downcase}.
|
|
520
|
+
[#{rest_arg}] is required. This is the #{rest_has_name ? 'name or id' : 'id'} of #{a_or_an(rest_label)} #{rest_label.downcase}.
|
|
438
521
|
EOT
|
|
439
522
|
end
|
|
440
523
|
optparse.parse!(args)
|
|
441
524
|
verify_args!(args:args, optparse:optparse, count:2)
|
|
525
|
+
connect(options)
|
|
442
526
|
parent_record = rest_parent_find_by_name_or_id(parent_id)
|
|
443
527
|
if parent_record.nil?
|
|
444
|
-
|
|
528
|
+
return 1, "#{rest_parent_label} not found for '#{parent_id}"
|
|
445
529
|
end
|
|
446
530
|
parent_id = parent_record['id']
|
|
447
531
|
connect(options)
|
|
448
|
-
record = rest_find_by_name_or_id(id)
|
|
532
|
+
record = rest_find_by_name_or_id(parent_id, id)
|
|
449
533
|
if record.nil?
|
|
450
534
|
return 1, "#{rest_name} not found for '#{id}'"
|
|
451
535
|
end
|
|
@@ -454,7 +538,11 @@ EOT
|
|
|
454
538
|
record_type_id = record['type']['id']
|
|
455
539
|
record_type = rest_type_find_by_name_or_id(record_type_id)
|
|
456
540
|
if record_type.nil?
|
|
457
|
-
|
|
541
|
+
return 1, "#{rest_type_label} not found for '#{record_type_id}"
|
|
542
|
+
end
|
|
543
|
+
# reload the type by id to get all the details ie. optionTypes
|
|
544
|
+
if record_type['optionTypes'].nil?
|
|
545
|
+
record_type = rest_type_find_by_name_or_id(record_type['id'])
|
|
458
546
|
end
|
|
459
547
|
end
|
|
460
548
|
passed_options = parse_passed_options(options)
|
|
@@ -473,16 +561,21 @@ EOT
|
|
|
473
561
|
options[:params]['type'] = record_type['code']
|
|
474
562
|
end
|
|
475
563
|
# update options without prompting by default
|
|
476
|
-
if
|
|
477
|
-
|
|
478
|
-
v_prompt = Morpheus::Cli::OptionTypes.no_prompt(
|
|
564
|
+
if false && option_types && !option_types.empty?
|
|
565
|
+
api_params = (options[:params] || {}).merge(record_payload) # need to merge in values from record too, ughhh
|
|
566
|
+
v_prompt = Morpheus::Cli::OptionTypes.no_prompt(option_types, options[:options], @api_client, api_params)
|
|
479
567
|
v_prompt.deep_compact!
|
|
480
568
|
v_prompt.booleanize! # 'on' => true
|
|
481
569
|
record_payload.deep_merge!(v_prompt)
|
|
482
570
|
end
|
|
483
571
|
# options by type
|
|
484
|
-
my_option_types =
|
|
485
|
-
if
|
|
572
|
+
my_option_types = nil
|
|
573
|
+
if respond_to?("load_option_types_for_#{rest_key}", true)
|
|
574
|
+
my_option_types = send("load_option_types_for_#{rest_key}", record_type, parent_record)
|
|
575
|
+
else
|
|
576
|
+
my_option_types = record_type ? record_type['optionTypes'] : nil
|
|
577
|
+
end
|
|
578
|
+
if false && my_option_types && !my_option_types.empty?
|
|
486
579
|
# remove redundant fieldContext
|
|
487
580
|
# make them optional for updates
|
|
488
581
|
# todo: use current value as default instead of just making things optioanl
|
|
@@ -500,9 +593,8 @@ EOT
|
|
|
500
593
|
record_payload.deep_merge!(v_prompt)
|
|
501
594
|
end
|
|
502
595
|
# advanced options
|
|
503
|
-
if
|
|
504
|
-
|
|
505
|
-
v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_advanced_option_types, options[:options], @api_client, options[:params])
|
|
596
|
+
if false && advanced_option_types && !advanced_option_types.empty?
|
|
597
|
+
v_prompt = Morpheus::Cli::OptionTypes.no_prompt(advanced_option_types, options[:options], @api_client, options[:params])
|
|
506
598
|
v_prompt.deep_compact!
|
|
507
599
|
v_prompt.booleanize! # 'on' => true
|
|
508
600
|
record_payload.deep_merge!(v_prompt)
|
|
@@ -540,8 +632,8 @@ EOT
|
|
|
540
632
|
build_standard_remove_options(opts, options)
|
|
541
633
|
opts.footer = <<-EOT
|
|
542
634
|
Delete an existing #{rest_label.downcase}.
|
|
543
|
-
[#{rest_parent_arg}] is required. This is the name or id of #{a_or_an(rest_parent_label)} #{rest_parent_label.downcase}.
|
|
544
|
-
[#{rest_arg}] is required. This is the name or id of #{a_or_an(rest_label)} #{rest_label.downcase}.
|
|
635
|
+
[#{rest_parent_arg}] is required. This is the #{rest_parent_has_name ? 'name or id' : 'id'} of #{a_or_an(rest_parent_label)} #{rest_parent_label.downcase}.
|
|
636
|
+
[#{rest_arg}] is required. This is the #{rest_has_name ? 'name or id' : 'id'} of #{a_or_an(rest_label)} #{rest_label.downcase}.
|
|
545
637
|
EOT
|
|
546
638
|
end
|
|
547
639
|
optparse.parse!(args)
|
|
@@ -549,9 +641,9 @@ EOT
|
|
|
549
641
|
connect(options)
|
|
550
642
|
parent_record = rest_parent_find_by_name_or_id(parent_id)
|
|
551
643
|
if parent_record.nil?
|
|
552
|
-
|
|
644
|
+
return 1, "#{rest_parent_label} not found for '#{parent_id}"
|
|
553
645
|
end
|
|
554
|
-
record = rest_find_by_name_or_id(id)
|
|
646
|
+
record = rest_find_by_name_or_id(parent_record['id'], id)
|
|
555
647
|
if record.nil?
|
|
556
648
|
return 1, "#{rest_name} not found for '#{id}'"
|
|
557
649
|
end
|
|
@@ -561,7 +653,7 @@ EOT
|
|
|
561
653
|
params.merge!(parse_query_options(options))
|
|
562
654
|
rest_interface.setopts(options)
|
|
563
655
|
if options[:dry_run]
|
|
564
|
-
print_dry_run rest_interface.dry.destroy(parent_id, record['id'])
|
|
656
|
+
print_dry_run rest_interface.dry.destroy(parent_id, record['id'], params)
|
|
565
657
|
return 0, nil
|
|
566
658
|
end
|
|
567
659
|
json_response = rest_interface.destroy(parent_id, record['id'], params)
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
require 'morpheus/cli/mixins/print_helper'
|
|
2
|
+
require 'morpheus/cli/option_types'
|
|
3
|
+
require 'morpheus/rest_client'
|
|
4
|
+
# Mixin for Morpheus::Cli command classes
|
|
5
|
+
# Provides common methods for storage server management
|
|
6
|
+
# including storage servers and storage server types
|
|
7
|
+
module Morpheus::Cli::StorageServersHelper
|
|
8
|
+
|
|
9
|
+
def self.included(klass)
|
|
10
|
+
klass.send :include, Morpheus::Cli::PrintHelper
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def storage_servers_interface
|
|
14
|
+
# @api_client.storage_servers
|
|
15
|
+
raise "#{self.class} has not defined @storage_servers_interface" if @storage_servers_interface.nil?
|
|
16
|
+
@storage_servers_interface
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def storage_server_types_interface
|
|
20
|
+
# @api_client.storage_server_types
|
|
21
|
+
raise "#{self.class} has not defined @storage_server_types_interface" if @storage_server_types_interface.nil?
|
|
22
|
+
@storage_server_types_interface
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def storage_server_object_key
|
|
26
|
+
'storageServer'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def storage_server_list_key
|
|
30
|
+
'storageServers'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def storage_server_label
|
|
34
|
+
'Storage Server'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def storage_server_label_plural
|
|
38
|
+
'Storage Server'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def storage_server_type_object_key
|
|
42
|
+
'storageServerType'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def storage_server_type_list_key
|
|
46
|
+
'storageServerTypes'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def storage_server_type_label
|
|
50
|
+
'Storage Server Type'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def storage_server_type_label_plural
|
|
54
|
+
'Storage Server Types'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def find_storage_server_by_name_or_id(val)
|
|
58
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
|
59
|
+
return find_storage_server_by_id(val)
|
|
60
|
+
else
|
|
61
|
+
return find_storage_server_by_name(val)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def find_storage_server_by_id(id)
|
|
66
|
+
begin
|
|
67
|
+
json_response = storage_servers_interface.get(id.to_i)
|
|
68
|
+
return json_response[storage_server_object_key]
|
|
69
|
+
rescue RestClient::Exception => e
|
|
70
|
+
if e.response && e.response.code == 404
|
|
71
|
+
print_red_alert "Storage Server not found by id #{id}"
|
|
72
|
+
else
|
|
73
|
+
raise e
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def find_storage_server_by_name(name)
|
|
79
|
+
lbs = storage_servers_interface.list({name: name.to_s})[storage_server_list_key]
|
|
80
|
+
if lbs.empty?
|
|
81
|
+
print_red_alert "Storage Server not found by name #{name}"
|
|
82
|
+
return nil
|
|
83
|
+
elsif lbs.size > 1
|
|
84
|
+
print_red_alert "#{lbs.size} storage servers found by name #{name}"
|
|
85
|
+
#print_lbs_table(lbs, {color: red})
|
|
86
|
+
print reset,"\n\n"
|
|
87
|
+
return nil
|
|
88
|
+
else
|
|
89
|
+
return lbs[0]
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def get_available_storage_server_types(refresh=false)
|
|
94
|
+
if !@available_storage_server_types || refresh
|
|
95
|
+
@available_storage_server_types = storage_server_types_interface.list({max:1000})[storage_server_type_list_key]
|
|
96
|
+
end
|
|
97
|
+
return @available_storage_server_types
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def storage_server_type_for_name_or_id(val)
|
|
101
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
|
102
|
+
return storage_server_type_for_id(val)
|
|
103
|
+
else
|
|
104
|
+
return storage_server_type_for_name(val)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def storage_server_type_for_id(id)
|
|
109
|
+
return get_available_storage_server_types().find { |z| z['id'].to_i == id.to_i}
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def storage_server_type_for_name(name)
|
|
113
|
+
return get_available_storage_server_types().find { |z| z['name'].downcase == name.downcase || z['code'].downcase == name.downcase}
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def find_storage_server_type_by_name_or_id(val)
|
|
117
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
|
118
|
+
return find_storage_server_type_by_id(val)
|
|
119
|
+
else
|
|
120
|
+
return find_storage_server_type_by_name(val)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def find_storage_server_type_by_id(id)
|
|
125
|
+
begin
|
|
126
|
+
json_response = storage_server_types_interface.get(id.to_i)
|
|
127
|
+
return json_response[storage_server_type_object_key]
|
|
128
|
+
rescue RestClient::Exception => e
|
|
129
|
+
if e.response && e.response.code == 404
|
|
130
|
+
print_red_alert "Storage Server Type not found by id #{id}"
|
|
131
|
+
return nil
|
|
132
|
+
else
|
|
133
|
+
raise e
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def find_storage_server_type_by_name(name)
|
|
139
|
+
json_response = storage_server_types_interface.list({name: name.to_s})
|
|
140
|
+
storage_server_types = json_response[storage_server_type_list_key]
|
|
141
|
+
if storage_server_types.empty?
|
|
142
|
+
print_red_alert "Storage Server Type not found by name #{name}"
|
|
143
|
+
return storage_server_types
|
|
144
|
+
elsif storage_server_types.size > 1
|
|
145
|
+
print_red_alert "#{storage_server_types.size} storage server types found by name #{name}"
|
|
146
|
+
rows = storage_server_types.collect do |it|
|
|
147
|
+
{id: it['id'], name: it['name']}
|
|
148
|
+
end
|
|
149
|
+
puts as_pretty_table(rows, [:id, :name], {color:red})
|
|
150
|
+
return nil
|
|
151
|
+
else
|
|
152
|
+
return storage_server_types[0]
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
end
|