Module: Morpheus::Cli::SecondaryRestCommand

Defined in:
lib/morpheus/cli/mixins/secondary_rest_command.rb

Overview

SecondaryRestCommand is a mixin for Morpheus::Cli command classes. for resources that are secondary to some parent resource. Provides basic CRUD commands: list, get, add, update, remove The parent resource is specified as the first argument for all the comments.

Example of a SecondaryRestCommand for ‘morpheus load-balancer-virtual-servers`.

class Morpheus::Cli::LoadBalancerVirtualServers

include Morpheus::Cli::CliCommand
include Morpheus::Cli::RestCommand
include Morpheus::Cli::SecondaryRestCommand
include Morpheus::Cli::LoadBalancersHelper

set_command_name :'load-balancer-virtual-servers'
register_subcommands :list, :get, :add, :update, :remove

register_interfaces :load_balancer_virtual_servers,
                    :load_balancers, :load_balancer_types

set_rest_parent_name :load_balancers

end

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



26
27
28
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 26

def self.included(base)
  base.extend ClassMethods
end

Instance Method Details

#_get(parent_id, id, params, options) ⇒ Object



267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 267

def _get(parent_id, id, params, options)
  if id !~ /\A\d{1,}\Z/
    record = rest_find_by_name_or_id(id)
    if record.nil?
      raise_command_error "#{rest_label} not found for name '#{id}'"
    end
    id = record['id']
  end
  rest_interface.setopts(options)
  if options[:dry_run]
    print_dry_run rest_interface.dry.get(id, params)
    return
  end
  json_response = rest_interface.get(id, params)
  render_response_for_get(json_response, options)
  return 0, nil
end

#add(args) ⇒ Object



300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 300

def add(args)
  parent_id, parent_record = nil, nil
  record_type_id = nil
  options = {}
  optparse = Morpheus::Cli::OptionParser.new do |opts|
    if rest_has_type
      opts.banner = subcommand_usage("[#{rest_parent_arg}] [#{rest_arg}] -t TYPE")
      opts.on( '-t', "--#{rest_type_arg} TYPE", "#{rest_type_label}" ) do |val|
        record_type_id = val
      end
    else
      opts.banner = subcommand_usage("[#{rest_parent_arg}] [#{rest_arg}]")
    end
    # if defined?(add_#{rest_key}_option_types)
    #   build_option_type_options(opts, options, add_#{rest_key}_option_types)
    # end
    build_standard_add_options(opts, options)
    opts.footer = "Create a new \#{rest_label.downcase}.\n[\#{rest_parent_arg}] is required. This is the name or id of \#{a_or_an(rest_parent_label)} \#{rest_parent_label.downcase}.\n[\#{rest_arg}] is required. This is the name of the new \#{rest_label.downcase}.\n"
  end
  optparse.parse!(args)
  verify_args!(args:args, optparse:optparse, min:1, max: 2)
  # todo: make supporting args[0] optional and more flexible
  # for now args[0] is assumed to be the 'name'
  record_name = nil
  parent_id = args[0]
  if args[1] # && rest_has_name
    record_name = args[1]
  end
  # todo: maybe need a flag to make this required, it could be an option type too, so
  if rest_has_type
    if record_type_id.nil?
      raise_command_error "#{rest_type_label} is required.\n#{optparse}"
    end
  end
  connect(options)
  if rest_has_type
    record_type = rest_type_find_by_name_or_id(record_type_id)
    if record_type.nil?
      raise_command_error "#{rest_type_label} not found for '#{record_type_id}'.\n#{optparse}"
    end
  end
  parent_record = rest_parent_find_by_name_or_id(parent_id)
  if parent_record.nil?
    raise_command_error "#{rest_parent_label} not found for '#{parent_id}'.\n#{optparse}"
  end
  parent_id = parent_record['id']
  passed_options = parse_passed_options(options)
  payload = {}
  if options[:payload]
    payload = options[:payload]
    payload.deep_merge!({rest_object_key => passed_options})
  else
    record_payload = {}
    if record_name
      record_payload['name'] = record_name
      options[:options]['name'] = record_name # injected for prompt
    end
    if rest_has_type && record_type
      # record_payload['type'] = {'code' => record_type['code']}
      record_payload['type'] = record_type['code']
      options[:options]['type'] = record_type['code'] # injected for prompt
    end
    record_payload.deep_merge!(passed_options)
    # options by type
    my_option_types = record_type ? record_type['optionTypes'] : nil
    if my_option_types && !my_option_types.empty?
      # remove redundant fieldContext
      my_option_types.each do |option_type| 
        if option_type['fieldContext'] == rest_object_key
          option_type['fieldContext'] = nil
        end
      end
      v_prompt = Morpheus::Cli::OptionTypes.prompt(my_option_types, options[:options], @api_client, options[:params])
      v_prompt.deep_compact!
      v_prompt.booleanize! # 'on' => true
      record_payload.deep_merge!(v_prompt)
    end
    payload[rest_object_key] = record_payload
  end
  rest_interface.setopts(options)
  if options[:dry_run]
    print_dry_run rest_interface.dry.create(parent_id, payload)
    return
  end
  json_response = rest_interface.create(parent_id, payload)
  render_response(json_response, options, rest_object_key) do
    record = json_response[rest_object_key]
    print_green_success "Added #{rest_label.downcase} #{record['name'] || record['id']}"
    return _get(parent_id, record["id"], {}, options)
  end
  return 0, nil
end

#get(args) ⇒ Object



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 239

def get(args)
  params = {}
  options = {}
  optparse = Morpheus::Cli::OptionParser.new do |opts|
    opts.banner = subcommand_usage("[#{rest_parent_arg}] [#{rest_arg}]")
    build_standard_get_options(opts, options)
    opts.footer = "Get details about \#{a_or_an(rest_label)} \#{rest_label.downcase}.\n[\#{rest_parent_arg}] is required. This is the name or id of \#{a_or_an(rest_parent_label)} \#{rest_parent_label.downcase}.\n[\#{rest_arg}] is required. This is the name or id of \#{a_or_an(rest_label)} \#{rest_label.downcase}.\n"
  end
  optparse.parse!(args)
  verify_args!(args:args, optparse:optparse, min:2)
  connect(options)
  parent_id = args[0]
  parent_record = rest_parent_find_by_name_or_id(parent_id)
  if parent_record.nil?
    raise_command_error "#{rest_parent_label} not found for '#{parent_id}'.\n#{optparse}"
  end
  parent_id = parent_record['id']
  params.merge!(parse_query_options(options))
  id_list = parse_id_list(args[1..-1])
  return run_command_for_each_arg(id_list) do |arg|
    _get(parent_id, arg, params, options)
  end
end

#list(args) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 190

def list(args)
  parent_id, parent_record = nil, nil
  params = {}
  options = {}
  optparse = Morpheus::Cli::OptionParser.new do |opts|
    opts.banner = subcommand_usage("[#{rest_parent_arg}] [search]")
    build_standard_list_options(opts, options)
    opts.footer = "List \#{rest_label_plural.downcase}.\n[\#{rest_parent_arg}] is required. This is the name or id of \#{a_or_an(rest_parent_label)} \#{rest_parent_label.downcase}.\n[search] is optional. This is a search phrase to filter the results.\n"
  end
  optparse.parse!(args)
  parent_id = args[0]
  if args[1] # && rest_has_name
    record_name = args[1]
  end
  verify_args!(args:args, optparse:optparse, min:1)
  if args.count > 1
    options[:phrase] = args[1..-1].join(" ")
  end
  connect(options)
  parent_record = rest_parent_find_by_name_or_id(parent_id)
  if parent_record.nil?
    raise_command_error "#{rest_parent_label} not found for '#{parent_id}'.\n#{optparse}"
  end
  parent_id = parent_record['id']
  params.merge!(parse_list_options(options))
  rest_interface.setopts(options)
  if options[:dry_run]
    print_dry_run rest_interface.dry.list(parent_id, params)
    return
  end
  json_response = rest_interface.list(parent_id, params)
  render_response(json_response, options, rest_list_key) do
    records = json_response[rest_list_key]
    print_h1 "Morpheus #{rest_label_plural}"
    if records.nil? || records.empty?
      print cyan,"No #{rest_label_plural.downcase} found.",reset,"\n"
    else
      print as_pretty_table(records, rest_list_column_definitions.upcase_keys!, options)
      print_results_pagination(json_response) if json_response['meta']
    end
    print reset,"\n"
  end
  return 0, nil
end

#registered_interfacesObject



186
187
188
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 186

def registered_interfaces
  self.class.registered_interfaces
end

#remove(args) ⇒ Object



446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 446

def remove(args)
  parent_id = args[0]
  id = args[1]
  params = {}
  options = {}
  optparse = Morpheus::Cli::OptionParser.new do |opts|
    opts.banner = subcommand_usage("[#{rest_parent_arg}] [#{rest_arg}]")
    build_standard_remove_options(opts, options)
    opts.footer = "Delete an existing \#{rest_label.downcase}.\n[\#{rest_parent_arg}] is required. This is the name or id of \#{a_or_an(rest_parent_label)} \#{rest_parent_label.downcase}.\n[\#{rest_arg}] is required. This is the name or id of \#{a_or_an(rest_label)} \#{rest_label.downcase}.\n"
  end
  optparse.parse!(args)
  verify_args!(args:args, optparse:optparse, count:2)
  connect(options)
  parent_record = rest_parent_find_by_name_or_id(parent_id)
  if parent_record.nil?
    raise_command_error "#{rest_parent_label} not found for '#{parent_id}'.\n#{optparse}"
  end
  record = rest_find_by_name_or_id(id)
  if record.nil?
    return 1, "#{rest_name} not found for '#{id}'"
  end
  unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the #{rest_label.downcase} #{record['name'] || record['id']}?")
    return 9, "aborted"
  end
  params.merge!(parse_query_options(options))
  rest_interface.setopts(options)
  if options[:dry_run]
    print_dry_run rest_interface.dry.destroy(parent_id, record['id'])
    return 0, nil
  end
  json_response = rest_interface.destroy(parent_id, record['id'], params)
  render_response(json_response, options) do
    print_green_success "Removed #{rest_label.downcase} #{record['name'] || record['id']}"
  end
  return 0, nil
end

#render_response_for_get(json_response, options) ⇒ Object



285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 285

def render_response_for_get(json_response, options)
  render_response(json_response, options, rest_object_key) do
    record = json_response[rest_object_key]
    print_h1 rest_label, [], options
    print cyan
    print_description_list(rest_column_definitions, record, options)
    # show config settings...
    if record['optionTypes'] && record['optionTypes'].size > 0
      print_h2 "Option Types", options
      print format_option_types_table(record['optionTypes'], options, rest_object_key)
    end
    print reset,"\n"
  end
end

#rest_parent_argObject



146
147
148
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 146

def rest_parent_arg
  self.class.rest_parent_arg
end

#rest_parent_column_definitionsObject



174
175
176
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 174

def rest_parent_column_definitions
  self.send("#{rest_parent_key}_column_definitions")
end

#rest_parent_find_by_name_or_id(name) ⇒ Object



182
183
184
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 182

def rest_parent_find_by_name_or_id(name)
  return self.send("find_#{rest_parent_key}_by_name_or_id", name)
end

#rest_parent_interfaceObject



162
163
164
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 162

def rest_parent_interface
  instance_variable_get("@#{rest_parent_interface_name}_interface")
end

#rest_parent_interface_nameObject



158
159
160
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 158

def rest_parent_interface_name
  self.class.rest_parent_interface_name # || "@#{rest_parent_name}_interface"
end

#rest_parent_keyObject



142
143
144
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 142

def rest_parent_key
  self.class.rest_parent_key
end

#rest_parent_labelObject



150
151
152
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 150

def rest_parent_label
  self.class.rest_parent_label
end

#rest_parent_label_pluralObject



154
155
156
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 154

def rest_parent_label_plural
  self.class.rest_parent_label_plural
end

#rest_parent_list_column_definitionsObject



178
179
180
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 178

def rest_parent_list_column_definitions
  self.send("#{rest_parent_key}_list_column_definitions")
end

#rest_parent_list_keyObject



170
171
172
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 170

def rest_parent_list_key
  self.send("#{rest_parent_key}_list_key")
end

#rest_parent_nameObject

duplicated the rest_* settings with rest_parent, for the parents resource



138
139
140
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 138

def rest_parent_name
  self.class.rest_parent_name
end

#rest_parent_object_keyObject



166
167
168
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 166

def rest_parent_object_key
  self.send("#{rest_parent_key}_object_key")
end

#update(args) ⇒ Object



397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
# File 'lib/morpheus/cli/mixins/secondary_rest_command.rb', line 397

def update(args)
  parent_id = args[0]
  id = args[1]
  options = {}
  params = {}
   = nil
  optparse = Morpheus::Cli::OptionParser.new do |opts|
    opts.banner = subcommand_usage("[#{rest_parent_arg}] [#{rest_arg}] [options]")
    build_standard_update_options(opts, options)
    opts.footer = "Update an existing \#{rest_label.downcase}.\n[\#{rest_parent_arg}] is required. This is the name or id of \#{a_or_an(rest_parent_label)} \#{rest_parent_label.downcase}.\n[\#{rest_arg}] is required. This is the name or id of \#{a_or_an(rest_label)} \#{rest_label.downcase}.\n"
  end
  optparse.parse!(args)
  verify_args!(args:args, optparse:optparse, count:2)
  parent_record = rest_parent_find_by_name_or_id(parent_id)
  if parent_record.nil?
    raise_command_error "#{rest_parent_label} not found for '#{parent_id}'.\n#{optparse}"
  end
  parent_id = parent_record['id']
  connect(options)
  record = rest_find_by_name_or_id(id)
  passed_options = parse_passed_options(options)
  payload = nil
  if options[:payload]
    payload = options[:payload]
    payload.deep_merge!({rest_object_key => passed_options}) unless passed_options.empty?
  else
    record_payload = passed_options
    if record_payload.empty?
      raise_command_error "Specify at least one option to update.\n#{optparse}"
    end
    payload[rest_object_key] = record_payload
  end
  rest_interface.setopts(options)
  if options[:dry_run]
    print_dry_run rest_interface.dry.update(parent_id, record['id'], payload)
    return
  end
  json_response = rest_interface.update(parent_id, record['id'], payload)
  render_response(json_response, options, rest_object_key) do
    print_green_success "Updated #{rest_label.downcase} #{record['name'] || record['id']}"
    _get(parent_id, record["id"], {}, options)
  end
  return 0, nil
end