morpheus-cli 5.3.2 → 5.3.2.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.
@@ -6,11 +6,12 @@ class Morpheus::Cli::LogSettingsCommand
6
6
 
7
7
  set_command_name :'log-settings'
8
8
 
9
- register_subcommands :get, :update
10
- register_subcommands :enable_integration, :disable_integration, :remove_integration
9
+ register_subcommands :get, :update
11
10
  register_subcommands :add_syslog_rule, :remove_syslog_rule
12
11
 
13
- set_default_subcommand :get
12
+ # these command are deprecated in 5.3.3 and can be removed
13
+ register_subcommands :enable_integration, :disable_integration, :remove_integration
14
+ set_subcommands_hidden :enable_integration, :disable_integration, :remove_integration
14
15
 
15
16
  def connect(opts)
16
17
  @api_client = establish_remote_appliance_connection(opts)
@@ -186,6 +187,7 @@ class Morpheus::Cli::LogSettingsCommand
186
187
  end
187
188
 
188
189
  def enable_integration(args)
190
+ print_error yellow,"[DEPRECATED] The command `#{command_name} enable-integration` is deprecated.",reset,"\n"
189
191
  options = {}
190
192
 
191
193
  optparse = Morpheus::Cli::OptionParser.new do |opts|
@@ -240,6 +242,7 @@ class Morpheus::Cli::LogSettingsCommand
240
242
  end
241
243
 
242
244
  def disable_integration(args)
245
+ print_error yellow,"[DEPRECATED] The command `#{command_name} disable-integration` is deprecated.",reset,"\n"
243
246
  options = {}
244
247
 
245
248
  optparse = Morpheus::Cli::OptionParser.new do |opts|
@@ -285,6 +288,7 @@ class Morpheus::Cli::LogSettingsCommand
285
288
  end
286
289
 
287
290
  def remove_integration(args)
291
+ print_error yellow,"[DEPRECATED] The command `#{command_name } remove-integration` is deprecated.",reset,"\n"
288
292
  options = {}
289
293
 
290
294
  optparse = Morpheus::Cli::OptionParser.new do |opts|
@@ -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 load balancer management
6
+ # including load balancers, load balancer types, virtual servers, etc.
7
+ module Morpheus::Cli::LoadBalancersHelper
8
+
9
+ def self.included(klass)
10
+ klass.send :include, Morpheus::Cli::PrintHelper
11
+ end
12
+
13
+ def load_balancers_interface
14
+ # @api_client.load_balancers
15
+ raise "#{self.class} has not defined @load_balancers_interface" if @load_balancers_interface.nil?
16
+ @load_balancers_interface
17
+ end
18
+
19
+ def load_balancer_types_interface
20
+ # @api_client.load_balancer_types
21
+ raise "#{self.class} has not defined @load_balancer_types_interface" if @load_balancer_types_interface.nil?
22
+ @load_balancer_types_interface
23
+ end
24
+
25
+ def load_balancer_object_key
26
+ 'loadBalancer'
27
+ end
28
+
29
+ def load_balancer_list_key
30
+ 'loadBalancers'
31
+ end
32
+
33
+ def load_balancer_label
34
+ 'Load Balancer'
35
+ end
36
+
37
+ def load_balancer_plural_label
38
+ 'Load Balancers'
39
+ end
40
+
41
+ def load_balancer_type_object_key
42
+ 'loadBalancerType'
43
+ end
44
+
45
+ def load_balancer_type_list_key
46
+ 'loadBalancerTypes'
47
+ end
48
+
49
+ def load_balancer_type_label
50
+ 'Load Balancer Type'
51
+ end
52
+
53
+ def load_balancer_type_plural_label
54
+ 'Load Balancer Types'
55
+ end
56
+
57
+ def find_load_balancer_by_name_or_id(val)
58
+ if val.to_s =~ /\A\d{1,}\Z/
59
+ return find_load_balancer_by_id(val)
60
+ else
61
+ return find_load_balancer_by_name(val)
62
+ end
63
+ end
64
+
65
+ def find_load_balancer_by_id(id)
66
+ begin
67
+ json_response = load_balancers_interface.get(id.to_i)
68
+ return json_response[load_balancer_object_key]
69
+ rescue RestClient::Exception => e
70
+ if e.response && e.response.code == 404
71
+ print_red_alert "Load Balancer not found by id #{id}"
72
+ else
73
+ raise e
74
+ end
75
+ end
76
+ end
77
+
78
+ def find_load_balancer_by_name(name)
79
+ lbs = load_balancers_interface.list({name: name.to_s})[load_balancer_list_key]
80
+ if lbs.empty?
81
+ print_red_alert "Load Balancer not found by name #{name}"
82
+ return nil
83
+ elsif lbs.size > 1
84
+ print_red_alert "#{lbs.size} load balancers 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_load_balancer_types(refresh=false)
94
+ if !@available_load_balancer_types || refresh
95
+ @available_load_balancer_types = load_balancer_types_interface.list({max:1000})[load_balancer_type_list_key]
96
+ end
97
+ return @available_load_balancer_types
98
+ end
99
+
100
+ def load_balancer_type_for_name_or_id(val)
101
+ if val.to_s =~ /\A\d{1,}\Z/
102
+ return load_balancer_type_for_id(val)
103
+ else
104
+ return load_balancer_type_for_name(val)
105
+ end
106
+ end
107
+
108
+ def load_balancer_type_for_id(id)
109
+ return get_available_load_balancer_types().find { |z| z['id'].to_i == id.to_i}
110
+ end
111
+
112
+ def load_balancer_type_for_name(name)
113
+ return get_available_load_balancer_types().find { |z| z['name'].downcase == name.downcase || z['code'].downcase == name.downcase}
114
+ end
115
+
116
+ def find_load_balancer_type_by_name_or_id(val)
117
+ if val.to_s =~ /\A\d{1,}\Z/
118
+ return find_load_balancer_type_by_id(val)
119
+ else
120
+ return find_load_balancer_type_by_name(val)
121
+ end
122
+ end
123
+
124
+ def find_load_balancer_type_by_id(id)
125
+ begin
126
+ json_response = load_balancer_types_interface.get(id.to_i)
127
+ return json_response[load_balancer_type_object_key]
128
+ rescue RestClient::Exception => e
129
+ if e.response && e.response.code == 404
130
+ print_red_alert "Load Balancer Type not found by id #{id}"
131
+ return nil
132
+ else
133
+ raise e
134
+ end
135
+ end
136
+ end
137
+
138
+ def find_load_balancer_type_by_name(name)
139
+ json_response = load_balancer_types_interface.list({name: name.to_s})
140
+ load_balancer_types = json_response[load_balancer_type_list_key]
141
+ if load_balancer_types.empty?
142
+ print_red_alert "Load Balancer Type not found by name #{name}"
143
+ return load_balancer_types
144
+ elsif load_balancer_types.size > 1
145
+ print_red_alert "#{load_balancer_types.size} load balancer types found by name #{name}"
146
+ rows = load_balancer_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 load_balancer_types[0]
153
+ end
154
+ end
155
+
156
+ end
@@ -1335,4 +1335,15 @@ module Morpheus::Cli::PrintHelper
1335
1335
  parse_json_or_yaml(config, parsers)
1336
1336
  end
1337
1337
 
1338
+ def format_option_types_table(option_types, options={}, domain_name=nil)
1339
+ columns = [
1340
+ {"FIELD LABEL" => lambda {|it| it['fieldLabel'] } },
1341
+ {"FIELD NAME" => lambda {|it| [it['fieldContext'] == domain_name ? nil : it['fieldContext'], it['fieldName']].select {|it| !it.to_s.empty? }.join('.') } },
1342
+ {"TYPE" => lambda {|it| it['type'] } },
1343
+ {"DEFAULT" => lambda {|it| it['defaultValue'] } },
1344
+ {"REQUIRED" => lambda {|it| format_boolean it['required'] } },
1345
+ ]
1346
+ as_pretty_table(option_types, columns, options)
1347
+ end
1348
+
1338
1349
  end
@@ -0,0 +1,657 @@
1
+ # RestCommand is a mixin for Morpheus::Cli command classes.
2
+ # Provides basic CRUD commands: list, get, add, update, remove
3
+ # Currently the command class must also include Morpheus::Cli::CliCommand
4
+ # The command class can define a few variables to dictate what the resource
5
+ # is called and the the api interface used to fetch the records. The command class
6
+ # or helper must also provide several methods to provide the default behavior.
7
+ # In the example below, the command (helper) defines the following methods:
8
+ # * load_balancer_object_key() - Key name of object returned by the "get" api endpoint.
9
+ # * load_balancer_list_key() - Key name of array of records returned by the "list" api endpoint.
10
+ # * load_balancer_column_definitions() - Column definitions for the "get" command display output.
11
+ # * load_balancer_list_column_definitions() - Column definitions for the "list" command display output.
12
+ #
13
+ # # An example of a RestCommand for `morpheus load-balancers`.
14
+ # class Morpheus::Cli::LoadBalancers
15
+ #
16
+ # include Morpheus::Cli::CliCommand
17
+ # include Morpheus::Cli::RestCommand
18
+ # include Morpheus::Cli::LoadBalancersHelper
19
+ #
20
+ # # All of the example settings below are redundant
21
+ # # and would be the default values if not set.
22
+ # set_rest_name :load_balancers
23
+ # set_rest_label "Load Balancer"
24
+ # set_rest_plural_label "Load Balancers"
25
+ # set_rest_object_key "load_balancer"
26
+ # set_rest_has_type true
27
+ # set_rest_type "load_balancer_types"
28
+ # register_interfaces :load_balancers, :load_balancer_types
29
+ #
30
+ # end
31
+ #
32
+ module Morpheus::Cli::RestCommand
33
+ def self.included(base)
34
+ #puts "including RestCommand for #{base}"
35
+ #base.send :include, Morpheus::Cli::CliCommand
36
+ base.extend ClassMethods
37
+ end
38
+
39
+ module ClassMethods
40
+
41
+ # rest_name is the plural name of the rest command resource eg. NeatThingsCommand would be "neat_things"
42
+ # It is used to derive all other default rest settings key, label, etc.
43
+ # The default name the command name with underscores `_` instead of dashes `-`.
44
+ def rest_name
45
+ @rest_name || default_rest_name
46
+ end
47
+
48
+ def default_rest_name
49
+ self.command_name.to_s.gsub("-", "_")
50
+ end
51
+
52
+ def rest_name=(v)
53
+ @rest_name = v
54
+ end
55
+
56
+ alias :set_rest_name :rest_name=
57
+
58
+ # rest_key is the singular name of the resource eg. "neat_thing"
59
+ def rest_key
60
+ @rest_key || default_rest_key
61
+ end
62
+
63
+ def default_rest_key
64
+ rest_name.chomp("s")
65
+ end
66
+
67
+ def rest_key=(v)
68
+ @rest_key = v
69
+ end
70
+
71
+ alias :set_rest_key :rest_key=
72
+
73
+ # rest_arg is a label for the arg in the command usage eg. "thing" gets displayed as [thing]
74
+ def rest_arg
75
+ @rest_arg || default_rest_arg
76
+ end
77
+
78
+ def default_rest_arg
79
+ rest_key.gsub("_", " ") # "[" + rest_key.gsub("_", " ") + "]"
80
+ end
81
+
82
+ def rest_arg=(v)
83
+ @rest_arg = v
84
+ end
85
+
86
+ alias :set_rest_arg :rest_arg=
87
+
88
+ # rest_label is the capitalized resource label eg. "Neat Thing"
89
+ def rest_label
90
+ @rest_label || default_rest_label
91
+ end
92
+
93
+ def default_rest_label
94
+ rest_key.to_s.split("_").collect {|it| it.to_s.capitalize }.join(" ")
95
+ end
96
+
97
+ def rest_label=(v)
98
+ @rest_label = v
99
+ end
100
+
101
+ alias :set_rest_label :rest_label=
102
+
103
+ # the plural version of the label eg. "Neat Things"
104
+ def rest_plural_label
105
+ @rest_plural_label || default_rest_plural_label
106
+ end
107
+
108
+ def default_rest_plural_label
109
+ #rest_name.to_s.split("_").collect {|it| it.to_s.capitalize }.join(" ")
110
+ rest_label.to_s.pluralize
111
+ end
112
+
113
+ def rest_plural_label=(v)
114
+ @rest_plural_label = v
115
+ end
116
+
117
+ alias :set_rest_plural_label :rest_plural_label=
118
+
119
+ # rest_interface_name is the interface name for the resource. eg. "neat_things"
120
+ def rest_interface_name
121
+ @rest_interface_name || default_rest_interface_name
122
+ end
123
+
124
+ def default_rest_interface_name
125
+ rest_name
126
+ end
127
+
128
+ def rest_interface_name=(v)
129
+ @rest_interface_name = v
130
+ end
131
+
132
+ alias :set_rest_interface_name :rest_interface_name=
133
+
134
+ # rest_has_type indicates a resource has a type. default is false
135
+ def rest_has_type
136
+ @rest_has_type == true
137
+ end
138
+
139
+ def default_rest_has_type
140
+ false
141
+ end
142
+
143
+ def rest_has_type=(v)
144
+ @rest_has_type = !!v
145
+ end
146
+
147
+ alias :set_rest_has_type :rest_has_type=
148
+
149
+ ## duplicated the rest_* settings with rest_type, for the types resource
150
+
151
+ # rest_type_name is the rest_name for the type, only applicable if rest_has_type
152
+ def rest_type_name
153
+ @rest_type_name || default_rest_type_name
154
+ end
155
+
156
+ def default_rest_type_name
157
+ rest_key + "_types"
158
+ end
159
+
160
+ def rest_type_name=(v)
161
+ @rest_type_name = v
162
+ end
163
+
164
+ alias :set_rest_type_name :rest_type_name=
165
+ alias :set_rest_type :rest_type_name=
166
+ #alias :rest_type= :rest_type_name=
167
+
168
+ # rest_type_key is the singular name of the resource eg. "neat_thing"
169
+ def rest_type_key
170
+ @rest_type_key || default_rest_type_key
171
+ end
172
+
173
+ def default_rest_type_key
174
+ rest_type_name.chomp("s")
175
+ end
176
+
177
+ def rest_type_key=(v)
178
+ @rest_type_key = v
179
+ end
180
+
181
+ alias :set_rest_type_key :rest_type_key=
182
+
183
+ def rest_type_arg
184
+ @rest_type_arg || default_rest_type_arg
185
+ end
186
+
187
+ def default_rest_type_arg
188
+ # rest_type_key.gsub("_", " ") # "[" + rest_key.gsub("_", " ") + "]"
189
+ "type" # [type]
190
+ end
191
+
192
+ def rest_type_arg=(v)
193
+ @rest_type_arg = v
194
+ end
195
+
196
+ alias :set_rest_type_arg :rest_type_arg=
197
+
198
+ # rest_type_label is the capitalized resource label eg. "Neat Thing"
199
+ def rest_type_label
200
+ @rest_type_label || default_rest_type_label
201
+ end
202
+
203
+ def default_rest_type_label
204
+ rest_type_key.to_s.split("_").collect {|it| it.to_s.capitalize }.join(" ")
205
+ end
206
+
207
+ def rest_type_label=(v)
208
+ @rest_type_label = v
209
+ end
210
+
211
+ alias :set_rest_type_label :rest_type_label=
212
+
213
+ # the plural version of the label eg. "Neat Things"
214
+ def rest_type_plural_label
215
+ @rest_type_plural_label || default_rest_type_plural_label
216
+ end
217
+
218
+ def default_rest_type_plural_label
219
+ #rest_type_name.to_s.split("_").collect {|it| it.to_s.capitalize }.join(" ")
220
+ rest_type_label.to_s.pluralize
221
+ end
222
+
223
+ def rest_type_plural_label=(v)
224
+ @rest_type_plural_label = v
225
+ end
226
+
227
+ alias :set_rest_type_plural_label :rest_type_plural_label=
228
+
229
+ # the name of the default interface, matches the rest name eg. "neat_things"
230
+ def rest_type_interface_name
231
+ @rest_type_interface_name || default_rest_type_interface_name
232
+ end
233
+
234
+ def default_rest_type_interface_name
235
+ rest_type_name
236
+ end
237
+
238
+ def rest_type_interface_name=(v)
239
+ @rest_type_interface_name = v
240
+ end
241
+
242
+ alias :set_rest_type_interface_name :rest_type_interface_name=
243
+
244
+ # set or append to the list of interface names to register for this command
245
+ # The registered interfaces will be pre-loaded into instance variables
246
+ # eg. [:neat_things, :neat_thing_types] will instantiate @neat_things_interface and @neat_thing_types_interface
247
+ def register_interfaces(*interfaces)
248
+ @registered_interfaces ||= []
249
+ interfaces.flatten.each do |it|
250
+ @registered_interfaces << it.to_sym
251
+ end
252
+ # put the default rest_interface first
253
+ if rest_interface_name && !@registered_interfaces.include?(rest_interface_name)
254
+ @registered_interfaces.unshift(rest_interface_name)
255
+ end
256
+ # and also the rest_type_interface
257
+ if rest_has_type && !@registered_interfaces.include?(rest_type_interface_name)
258
+ @registered_interfaces.unshift(rest_type_interface_name)
259
+ end
260
+ end
261
+
262
+ alias :register_interface :register_interfaces
263
+
264
+ # get list of interface names that are registered for this command
265
+ # automatically includes the interface for the rest_name and rest_type_name if has_type
266
+ def registered_interfaces
267
+ @registered_interfaces ||= []
268
+ # put the default rest_interface first
269
+ if @registered_interfaces.empty?
270
+ if rest_interface_name
271
+ @registered_interfaces.unshift(rest_interface_name)
272
+ end
273
+ if rest_has_type
274
+ @registered_interfaces.unshift(rest_type_interface_name)
275
+ end
276
+ end
277
+ @registered_interfaces
278
+ end
279
+
280
+ # clear the list of registered interfaces, perhaps useful in a command subclass
281
+ def clear_registered_interfaces()
282
+ @registered_interfaces = []
283
+ end
284
+
285
+ end
286
+
287
+ def rest_name
288
+ self.class.rest_name
289
+ end
290
+
291
+ def rest_key
292
+ self.class.rest_key
293
+ end
294
+
295
+ def rest_arg
296
+ self.class.rest_arg
297
+ end
298
+
299
+ def rest_label
300
+ self.class.rest_label
301
+ end
302
+
303
+ def rest_plural_label
304
+ self.class.rest_plural_label
305
+ end
306
+
307
+ def rest_interface_name
308
+ self.class.rest_interface_name
309
+ end
310
+
311
+ # returns the default rest interface, allows using rest_interface_name = "your"
312
+ # or override this method to return @your_interface if needed
313
+ def rest_interface
314
+ instance_variable_get("@#{rest_interface_name}_interface")
315
+ end
316
+
317
+ def rest_object_key
318
+ self.send("#{rest_key}_object_key")
319
+ end
320
+
321
+ def rest_list_key
322
+ self.send("#{rest_key}_list_key")
323
+ end
324
+
325
+ def rest_column_definitions
326
+ self.send("#{rest_key}_column_definitions")
327
+ end
328
+
329
+ def rest_list_column_definitions
330
+ self.send("#{rest_key}_list_column_definitions")
331
+ end
332
+
333
+ def rest_find_by_name_or_id(name)
334
+ return self.send("find_#{rest_key}_by_name_or_id", name)
335
+ end
336
+
337
+ def rest_has_type
338
+ self.class.rest_has_type
339
+ end
340
+
341
+ ## duplicated the rest_* settings with rest_type, for the types resource
342
+
343
+ def rest_type_name
344
+ self.class.rest_type_name
345
+ end
346
+
347
+ def rest_type_key
348
+ self.class.rest_type_key
349
+ end
350
+
351
+ def rest_type_arg
352
+ self.class.rest_type_arg
353
+ end
354
+
355
+ def rest_type_label
356
+ self.class.rest_type_label
357
+ end
358
+
359
+ def rest_type_plural_label
360
+ self.class.rest_type_plural_label
361
+ end
362
+
363
+ def rest_type_interface_name
364
+ self.class.rest_type_interface_name # || "@#{rest_type_name}_interface"
365
+ end
366
+
367
+ def rest_type_interface
368
+ instance_variable_get("@#{rest_type_interface_name}_interface")
369
+ end
370
+
371
+ def rest_type_object_key
372
+ self.send("#{rest_type_key}_object_key")
373
+ end
374
+
375
+ def rest_type_list_key
376
+ self.send("#{rest_type_key}_list_key")
377
+ end
378
+
379
+ def rest_type_column_definitions
380
+ self.send("#{rest_type_key}_column_definitions")
381
+ end
382
+
383
+ def rest_type_list_column_definitions
384
+ self.send("#{rest_type_key}_list_column_definitions")
385
+ end
386
+
387
+ def rest_type_find_by_name_or_id(name)
388
+ return self.send("find_#{rest_type_key}_by_name_or_id", name)
389
+ end
390
+
391
+ def registered_interfaces
392
+ self.class.registered_interfaces
393
+ end
394
+
395
+ # standard connect method to establish @api_client
396
+ # and @{name}_interface variables for each registered interface.
397
+ def connect(options)
398
+ @api_client = establish_remote_appliance_connection(options)
399
+ self.class.registered_interfaces.each do |interface_name|
400
+ if interface_name.is_a?(String) || interface_name.is_a?(Symbol)
401
+ instance_variable_set("@#{interface_name}_interface", @api_client.send(interface_name))
402
+ elsif interface_name.is_a?(Hash)
403
+ interface_name.each do |k,v|
404
+ instance_variable_set("#{k}_interface", @api_client.send(v))
405
+ end
406
+ end
407
+ end
408
+ end
409
+
410
+ def handle(args)
411
+ handle_subcommand(args)
412
+ end
413
+
414
+ def list(args)
415
+ params = {}
416
+ options = {}
417
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
418
+ opts.banner = subcommand_usage()
419
+ build_standard_list_options(opts, options)
420
+ opts.footer = "List #{rest_plural_label.downcase}."
421
+ end
422
+ optparse.parse!(args)
423
+ connect(options)
424
+ if args.count > 0
425
+ options[:phrase] = args.join(" ")
426
+ end
427
+ params.merge!(parse_list_options(options))
428
+ rest_interface.setopts(options)
429
+ if options[:dry_run]
430
+ print_dry_run rest_interface.dry.list(params)
431
+ return
432
+ end
433
+ json_response = rest_interface.list(params)
434
+ render_response(json_response, options, rest_list_key) do
435
+ records = json_response[rest_list_key]
436
+ print_h1 "Morpheus #{rest_plural_label}"
437
+ if records.nil? || records.empty?
438
+ print cyan,"No #{rest_plural_label.downcase} found.",reset,"\n"
439
+ else
440
+ print as_pretty_table(records, rest_list_column_definitions.upcase_keys!, options)
441
+ print_results_pagination(json_response) if json_response['meta']
442
+ end
443
+ print reset,"\n"
444
+ end
445
+ return 0, nil
446
+ end
447
+
448
+ def get(args)
449
+ params = {}
450
+ options = {}
451
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
452
+ opts.banner = subcommand_usage("[type]")
453
+ build_standard_get_options(opts, options)
454
+ opts.footer = <<-EOT
455
+ Get details about #{a_or_an(rest_label)} #{rest_label.downcase}.
456
+ [#{rest_arg}] is required. This is the name or id of #{a_or_an(rest_label)} #{rest_label.downcase}.
457
+ EOT
458
+ end
459
+ optparse.parse!(args)
460
+ verify_args!(args:args, optparse:optparse, min:1)
461
+ connect(options)
462
+ params.merge!(parse_query_options(options))
463
+ id_list = parse_id_list(args)
464
+ return run_command_for_each_arg(id_list) do |arg|
465
+ _get(arg, params, options)
466
+ end
467
+ end
468
+
469
+ def _get(id, params, options)
470
+ if id !~ /\A\d{1,}\Z/
471
+ record = rest_find_by_name_or_id(id)
472
+ if record.nil?
473
+ raise_command_error "#{rest_label} not found for name '#{id}'"
474
+ end
475
+ id = record['id']
476
+ end
477
+ rest_interface.setopts(options)
478
+ if options[:dry_run]
479
+ print_dry_run rest_interface.dry.get(id, params)
480
+ return
481
+ end
482
+ json_response = rest_interface.get(id, params)
483
+ render_response_for_get(json_response, options)
484
+ return 0, nil
485
+ end
486
+
487
+ def render_response_for_get(json_response, options)
488
+ render_response(json_response, options, rest_object_key) do
489
+ record = json_response[rest_object_key]
490
+ print_h1 rest_label, [], options
491
+ print cyan
492
+ print_description_list(rest_column_definitions, record, options)
493
+ # show config settings...
494
+ if record['optionTypes'] && record['optionTypes'].size > 0
495
+ print_h2 "Option Types", options
496
+ print format_option_types_table(record['optionTypes'], options, rest_object_key)
497
+ end
498
+ print reset,"\n"
499
+ end
500
+ end
501
+
502
+ def add(args)
503
+ record_type_id = nil
504
+ options = {}
505
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
506
+ if rest_has_type
507
+ opts.banner = subcommand_usage("[name] -t TYPE")
508
+ opts.on( '-t', "--#{rest_type_arg} TYPE", "#{rest_type_label}" ) do |val|
509
+ record_type_id = val
510
+ end
511
+ else
512
+ opts.banner = subcommand_usage("[name]")
513
+ end
514
+ # if defined?(add_#{rest_key}_option_types)
515
+ # build_option_type_options(opts, options, add_#{rest_key}_option_types)
516
+ # end
517
+ build_standard_add_options(opts, options)
518
+ end
519
+ optparse.parse!(args)
520
+ # todo: make supporting args[0] optional and more flexible
521
+ # for now args[0] is assumed to be the 'name'
522
+ record_name = nil
523
+ if args[0] # && rest_has_name
524
+ record_name = args[0]
525
+ end
526
+ verify_args!(args:args, optparse:optparse, min:0, max: 1)
527
+ # todo: maybe need a flag to make this required, it could be an option type too, so
528
+ if rest_has_type
529
+ if record_type_id.nil?
530
+ raise_command_error "#{rest_type_label} is required.\n#{optparse}"
531
+ end
532
+ end
533
+ connect(options)
534
+ if rest_has_type
535
+ record_type = rest_type_find_by_name_or_id(record_type_id)
536
+ if record_type.nil?
537
+ raise_command_error "#{rest_type_label} not found for '#{record_type_id}'.\n#{optparse}"
538
+ end
539
+ end
540
+ passed_options = parse_passed_options(options)
541
+ payload = {}
542
+ if options[:payload]
543
+ payload = options[:payload]
544
+ payload.deep_merge!({rest_object_key => passed_options})
545
+ else
546
+ record_payload = {}
547
+ if record_name
548
+ record_payload['name'] = record_name
549
+ options[:options]['name'] = record_name # injected for prompt
550
+ end
551
+ if rest_has_type && record_type
552
+ # record_payload['type'] = {'code' => record_type['code']}
553
+ record_payload['type'] = record_type['code']
554
+ options[:options]['type'] = record_type['code'] # injected for prompt
555
+ end
556
+ record_payload.deep_merge!(passed_options)
557
+ # options by type
558
+ my_option_types = record_type ? record_type['optionTypes'] : nil
559
+ if my_option_types && !my_option_types.empty?
560
+ # remove redundant fieldContext
561
+ my_option_types.each do |option_type|
562
+ if option_type['fieldContext'] == rest_object_key
563
+ option_type['fieldContext'] = nil
564
+ end
565
+ end
566
+ v_prompt = Morpheus::Cli::OptionTypes.prompt(my_option_types, options[:options], @api_client, options[:params])
567
+ v_prompt.deep_compact!
568
+ v_prompt.booleanize! # 'on' => true
569
+ record_payload.deep_merge!(v_prompt)
570
+ end
571
+ payload[rest_object_key] = record_payload
572
+ end
573
+ rest_interface.setopts(options)
574
+ if options[:dry_run]
575
+ print_dry_run rest_interface.dry.create(payload)
576
+ return
577
+ end
578
+ json_response = rest_interface.create(payload)
579
+ render_response(json_response, options, rest_object_key) do
580
+ record = json_response[rest_object_key]
581
+ print_green_success "Added #{rest_label.downcase} #{record['name'] || record['id']}"
582
+ return _get(record["id"], {}, options)
583
+ end
584
+ return 0, nil
585
+ end
586
+
587
+ def update(args)
588
+ id = args[0]
589
+ options = {}
590
+ params = {}
591
+ account_name = nil
592
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
593
+ opts.banner = subcommand_usage("[#{rest_arg}] [options]")
594
+ build_standard_update_options(opts, options)
595
+ end
596
+ optparse.parse!(args)
597
+ verify_args!(args:args, optparse:optparse, count:1)
598
+ connect(options)
599
+ record = rest_find_by_name_or_id(id)
600
+ passed_options = parse_passed_options(options)
601
+ payload = nil
602
+ if options[:payload]
603
+ payload = options[:payload]
604
+ payload.deep_merge!({rest_object_key => passed_options}) unless passed_options.empty?
605
+ else
606
+ record_payload = passed_options
607
+ if record_payload.empty?
608
+ raise_command_error "Specify at least one option to update.\n#{optparse}"
609
+ end
610
+ payload[rest_object_key] = record_payload
611
+ end
612
+ rest_interface.setopts(options)
613
+ if options[:dry_run]
614
+ print_dry_run rest_interface.dry.update(record['id'], payload)
615
+ return
616
+ end
617
+ json_response = rest_interface.update(record['id'], payload)
618
+ render_response(json_response, options, rest_object_key) do
619
+ print_green_success "Updated #{rest_label.downcase} #{record['name'] || record['id']}"
620
+ _get(record["id"], {}, options)
621
+ end
622
+ return 0, nil
623
+ end
624
+
625
+ def remove(args)
626
+ id = args[0]
627
+ params = {}
628
+ options = {}
629
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
630
+ opts.banner = subcommand_usage("[#{rest_arg}]")
631
+ build_standard_remove_options(opts, options)
632
+ end
633
+ optparse.parse!(args)
634
+ verify_args!(args:args, optparse:optparse, count:1)
635
+ connect(options)
636
+ params.merge!(parse_query_options(options))
637
+ record = rest_find_by_name_or_id(id)
638
+ if record.nil?
639
+ return 1, "#{rest_name} not found for '#{id}'"
640
+ end
641
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the #{rest_label.downcase} #{record['name'] || record['id']}?")
642
+ return 9, "aborted"
643
+ end
644
+ rest_interface.setopts(options)
645
+ if options[:dry_run]
646
+ print_dry_run rest_interface.dry.destroy(record['id'])
647
+ return 0, nil
648
+ end
649
+ json_response = rest_interface.destroy(record['id'], params)
650
+ render_response(json_response, options) do
651
+ print_green_success "Removed #{rest_label.downcase} #{record['name'] || record['id']}"
652
+ end
653
+ return 0, nil
654
+ end
655
+
656
+ end
657
+