morpheus-cli 5.2.4.1 → 5.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/README.md +1 -3
  4. data/lib/morpheus/api/api_client.rb +48 -14
  5. data/lib/morpheus/api/certificate_types_interface.rb +14 -0
  6. data/lib/morpheus/api/certificates_interface.rb +9 -0
  7. data/lib/morpheus/api/integration_types_interface.rb +14 -0
  8. data/lib/morpheus/api/integrations_interface.rb +7 -22
  9. data/lib/morpheus/api/network_services_interface.rb +14 -0
  10. data/lib/morpheus/api/read_interface.rb +23 -0
  11. data/lib/morpheus/api/rest_interface.rb +12 -10
  12. data/lib/morpheus/api/roles_interface.rb +7 -0
  13. data/lib/morpheus/api/servers_interface.rb +7 -0
  14. data/lib/morpheus/api/user_settings_interface.rb +38 -18
  15. data/lib/morpheus/api/vdi_allocations_interface.rb +9 -0
  16. data/lib/morpheus/api/vdi_apps_interface.rb +9 -0
  17. data/lib/morpheus/api/vdi_gateways_interface.rb +9 -0
  18. data/lib/morpheus/api/vdi_interface.rb +28 -0
  19. data/lib/morpheus/api/vdi_pools_interface.rb +19 -0
  20. data/lib/morpheus/cli.rb +9 -2
  21. data/lib/morpheus/cli/activity_command.rb +7 -4
  22. data/lib/morpheus/cli/apps.rb +59 -75
  23. data/lib/morpheus/cli/catalog_item_types_command.rb +13 -13
  24. data/lib/morpheus/cli/certificates_command.rb +575 -0
  25. data/lib/morpheus/cli/cli_command.rb +61 -6
  26. data/lib/morpheus/cli/clouds.rb +1 -0
  27. data/lib/morpheus/cli/clusters.rb +5 -2
  28. data/lib/morpheus/cli/commands/standard/history_command.rb +4 -5
  29. data/lib/morpheus/cli/commands/standard/man_command.rb +4 -5
  30. data/lib/morpheus/cli/dashboard_command.rb +3 -3
  31. data/lib/morpheus/cli/execution_request_command.rb +15 -5
  32. data/lib/morpheus/cli/hosts.rb +245 -224
  33. data/lib/morpheus/cli/instances.rb +150 -167
  34. data/lib/morpheus/cli/integrations_command.rb +588 -41
  35. data/lib/morpheus/cli/invoices_command.rb +23 -46
  36. data/lib/morpheus/cli/login.rb +7 -0
  37. data/lib/morpheus/cli/mixins/option_source_helper.rb +15 -16
  38. data/lib/morpheus/cli/mixins/print_helper.rb +36 -18
  39. data/lib/morpheus/cli/mixins/provisioning_helper.rb +3 -3
  40. data/lib/morpheus/cli/mixins/vdi_helper.rb +246 -0
  41. data/lib/morpheus/cli/network_domains_command.rb +2 -2
  42. data/lib/morpheus/cli/network_routers_command.rb +22 -9
  43. data/lib/morpheus/cli/networks_command.rb +2 -2
  44. data/lib/morpheus/cli/option_types.rb +34 -33
  45. data/lib/morpheus/cli/remote.rb +3 -2
  46. data/lib/morpheus/cli/reports_command.rb +5 -2
  47. data/lib/morpheus/cli/roles.rb +215 -55
  48. data/lib/morpheus/cli/service_plans_command.rb +4 -1
  49. data/lib/morpheus/cli/subnets_command.rb +11 -2
  50. data/lib/morpheus/cli/user_settings_command.rb +268 -57
  51. data/lib/morpheus/cli/vdi_allocations_command.rb +159 -0
  52. data/lib/morpheus/cli/vdi_apps_command.rb +317 -0
  53. data/lib/morpheus/cli/vdi_command.rb +359 -0
  54. data/lib/morpheus/cli/vdi_gateways_command.rb +290 -0
  55. data/lib/morpheus/cli/vdi_pools_command.rb +571 -0
  56. data/lib/morpheus/cli/version.rb +1 -1
  57. data/lib/morpheus/rest_client.rb +30 -0
  58. data/lib/morpheus/terminal.rb +15 -7
  59. metadata +18 -2
@@ -84,6 +84,16 @@ class Morpheus::Cli::Instances
84
84
  opts.on('--status STATUS', "Filter by status i.e. provisioning,running,starting,stopping") do |val|
85
85
  params['status'] = (params['status'] || []) + val.to_s.split(',').collect {|s| s.strip }.select {|s| s != "" }
86
86
  end
87
+ opts.on( '--type CODE', String, "Filter by Instance Type code" ) do |val|
88
+ # commas used in names a lot so use --plan one --plan two
89
+ params['instanceType'] ||= []
90
+ params['instanceType'] << val
91
+ end
92
+ opts.on( '--environment CODE', String, "Filter by Environment code(s)" ) do |val|
93
+ # commas used in names a lot so use --plan one --plan two
94
+ params['environment'] ||= []
95
+ params['environment'] << val
96
+ end
87
97
  opts.on('--pending-removal', "Include instances pending removal.") do
88
98
  options[:showDeleted] = true
89
99
  end
@@ -121,7 +131,7 @@ class Morpheus::Cli::Instances
121
131
  opts.on('-a', '--details', "Display all details: plan, stats, etc" ) do
122
132
  options[:details] = true
123
133
  end
124
- build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
134
+ build_standard_list_options(opts, options)
125
135
  opts.footer = "List instances."
126
136
  end
127
137
  optparse.parse!(args)
@@ -130,159 +140,150 @@ class Morpheus::Cli::Instances
130
140
  options[:phrase] = args.join(" ")
131
141
  end
132
142
  connect(options)
133
- begin
134
- params.merge!(parse_list_options(options))
135
- group = options[:group] ? find_group_by_name_or_id_for_provisioning(options[:group]) : nil
136
- if group
137
- params['siteId'] = group['id']
138
- end
139
143
 
140
- # argh, this doesn't work because group_id is required for options/clouds
141
- # cloud = options[:cloud] ? find_cloud_by_name_or_id_for_provisioning(group_id, options[:cloud]) : nil
142
- cloud = options[:cloud] ? find_zone_by_name_or_id(nil, options[:cloud]) : nil
143
- if cloud
144
- params['zoneId'] = cloud['id']
145
- end
144
+ params.merge!(parse_list_options(options))
145
+ group = options[:group] ? find_group_by_name_or_id_for_provisioning(options[:group]) : nil
146
+ if group
147
+ params['siteId'] = group['id']
148
+ end
146
149
 
147
- host = options[:host] ? find_host_by_name_or_id(options[:host]) : options[:host]
148
- if host
149
- params['serverId'] = host['id']
150
- end
150
+ # argh, this doesn't work because group_id is required for options/clouds
151
+ # cloud = options[:cloud] ? find_cloud_by_name_or_id_for_provisioning(group_id, options[:cloud]) : nil
152
+ cloud = options[:cloud] ? find_zone_by_name_or_id(nil, options[:cloud]) : nil
153
+ if cloud
154
+ params['zoneId'] = cloud['id']
155
+ end
151
156
 
152
- account = nil
153
- #todo: user = find_available_user_option(owner_id)
157
+ host = options[:host] ? find_host_by_name_or_id(options[:host]) : options[:host]
158
+ if host
159
+ params['serverId'] = host['id']
160
+ end
154
161
 
155
- if options[:owner]
156
- created_by_ids = find_all_user_ids(account ? account['id'] : nil, options[:owner])
157
- return if created_by_ids.nil?
158
- params['createdBy'] = created_by_ids
159
- params['ownerId'] = created_by_ids # 4.2.1+
162
+ account = nil
163
+ #todo: user = find_available_user_option(owner_id)
164
+
165
+ if options[:owner]
166
+ created_by_ids = find_all_user_ids(account ? account['id'] : nil, options[:owner])
167
+ return if created_by_ids.nil?
168
+ params['createdBy'] = created_by_ids
169
+ params['ownerId'] = created_by_ids # 4.2.1+
170
+ end
171
+
172
+ params['showDeleted'] = true if options[:showDeleted]
173
+ params['deleted'] = true if options[:deleted]
174
+ params['labels'] = options[:labels] if options[:labels]
175
+ if options[:tags]
176
+ options[:tags].each do |k,v|
177
+ params['tags.' + k] = v
160
178
  end
179
+ end
161
180
 
162
- params['showDeleted'] = true if options[:showDeleted]
163
- params['deleted'] = true if options[:deleted]
164
- params['labels'] = options[:labels] if options[:labels]
165
- if options[:tags]
166
- options[:tags].each do |k,v|
167
- params['tags.' + k] = v
181
+ @instances_interface.setopts(options)
182
+ if options[:dry_run]
183
+ print_dry_run @instances_interface.dry.list(params)
184
+ return 0
185
+ end
186
+ json_response = @instances_interface.list(params)
187
+ all_stats = json_response['stats'] || {}
188
+ # merge stats into each record just to be nice...
189
+ if options[:include_fields] || options[:all_fields]
190
+ if json_response['instances']
191
+ if all_stats
192
+ json_response['instances'].each do |it|
193
+ it['stats'] ||= all_stats[it['id'].to_s] || all_stats[it['id']]
194
+ end
168
195
  end
169
196
  end
197
+ end
198
+ render_response(json_response, options, "instances") do
199
+ instances = json_response['instances']
170
200
 
171
- @instances_interface.setopts(options)
172
- if options[:dry_run]
173
- print_dry_run @instances_interface.dry.list(params)
174
- return 0
201
+ title = "Morpheus Instances"
202
+ subtitles = []
203
+ if group
204
+ subtitles << "Group: #{group['name']}".strip
175
205
  end
176
- json_response = @instances_interface.list(params)
177
- if options[:json]
178
- puts as_json(json_response, options, "instances")
179
- return 0
180
- elsif options[:yaml]
181
- puts as_yaml(json_response, options, "instances")
182
- return 0
183
- elsif options[:csv]
184
- # merge stats to be nice here..
185
- if json_response['instances']
186
- all_stats = json_response['stats'] || {}
187
- if all_stats
188
- json_response['instances'].each do |it|
189
- it['stats'] ||= all_stats[it['id'].to_s] || all_stats[it['id']]
206
+ if cloud
207
+ subtitles << "Cloud: #{cloud['name']}".strip
208
+ end
209
+ if host
210
+ subtitles << "Host: #{host['name']}".strip
211
+ end
212
+ if options[:owner]
213
+ subtitles << "Created By: #{options[:owner]}"
214
+ end
215
+ subtitles += parse_list_subtitles(options)
216
+ print_h1 title, subtitles, options
217
+ if instances.empty?
218
+ print cyan,"No instances found.",reset,"\n"
219
+ else
220
+ # print_instances_table(instances)
221
+ # server returns stats in a separate key stats => {"id" => {} }
222
+ # the id is a string right now..for some reason..
223
+ all_stats = json_response['stats'] || {}
224
+ if all_stats
225
+ instances.each do |it|
226
+ if !it['stats']
227
+ found_stats = all_stats[it['id'].to_s] || all_stats[it['id']]
228
+ it['stats'] = found_stats # || {}
190
229
  end
191
230
  end
192
231
  end
193
- puts records_as_csv(json_response['instances'], options)
194
- else
195
- instances = json_response['instances']
196
232
 
197
- title = "Morpheus Instances"
198
- subtitles = []
199
- if group
200
- subtitles << "Group: #{group['name']}".strip
201
- end
202
- if cloud
203
- subtitles << "Cloud: #{cloud['name']}".strip
204
- end
205
- if host
206
- subtitles << "Host: #{host['name']}".strip
207
- end
208
- if options[:owner]
209
- subtitles << "Created By: #{options[:owner]}"
210
- end
211
- subtitles += parse_list_subtitles(options)
212
- print_h1 title, subtitles, options
213
- if instances.empty?
214
- print cyan,"No instances found.",reset,"\n"
215
- else
216
- # print_instances_table(instances)
217
- # server returns stats in a separate key stats => {"id" => {} }
218
- # the id is a string right now..for some reason..
219
- all_stats = json_response['stats'] || {}
220
- if all_stats
221
- instances.each do |it|
222
- if !it['stats']
223
- found_stats = all_stats[it['id'].to_s] || all_stats[it['id']]
224
- it['stats'] = found_stats # || {}
225
- end
233
+ rows = instances.collect {|instance|
234
+ stats = instance['stats']
235
+ cpu_usage_str = !stats ? "" : generate_usage_bar((stats['usedCpu'] || stats['cpuUsage']).to_f, 100, {max_bars: 10})
236
+ memory_usage_str = !stats ? "" : generate_usage_bar(stats['usedMemory'], stats['maxMemory'], {max_bars: 10})
237
+ storage_usage_str = !stats ? "" : generate_usage_bar(stats['usedStorage'], stats['maxStorage'], {max_bars: 10})
238
+ if options[:details] || options[:stats]
239
+ if stats['maxMemory'] && stats['maxMemory'].to_i != 0
240
+ memory_usage_str = memory_usage_str + cyan + format_bytes_short(stats['usedMemory']).strip.rjust(8, ' ') + " / " + format_bytes_short(stats['maxMemory']).strip
226
241
  end
227
- end
228
-
229
- rows = instances.collect {|instance|
230
- stats = instance['stats']
231
- cpu_usage_str = !stats ? "" : generate_usage_bar((stats['usedCpu'] || stats['cpuUsage']).to_f, 100, {max_bars: 10})
232
- memory_usage_str = !stats ? "" : generate_usage_bar(stats['usedMemory'], stats['maxMemory'], {max_bars: 10})
233
- storage_usage_str = !stats ? "" : generate_usage_bar(stats['usedStorage'], stats['maxStorage'], {max_bars: 10})
234
- if options[:details] || options[:stats]
235
- if stats['maxMemory'] && stats['maxMemory'].to_i != 0
236
- memory_usage_str = memory_usage_str + cyan + format_bytes_short(stats['usedMemory']).strip.rjust(8, ' ') + " / " + format_bytes_short(stats['maxMemory']).strip
237
- end
238
- if stats['maxStorage'] && stats['maxStorage'].to_i != 0
239
- storage_usage_str = storage_usage_str + cyan + format_bytes_short(stats['usedStorage']).strip.rjust(8, ' ') + " / " + format_bytes_short(stats['maxStorage']).strip
240
- end
242
+ if stats['maxStorage'] && stats['maxStorage'].to_i != 0
243
+ storage_usage_str = storage_usage_str + cyan + format_bytes_short(stats['usedStorage']).strip.rjust(8, ' ') + " / " + format_bytes_short(stats['maxStorage']).strip
241
244
  end
242
- row = {
243
- id: instance['id'],
244
- name: instance['name'],
245
- connection: format_instance_connection_string(instance),
246
- environment: instance['instanceContext'],
247
- user: (instance['owner'] ? (instance['owner']['username'] || instance['owner']['id']) : (instance['createdBy'].is_a?(Hash) ? instance['createdBy']['username'] : instance['createdBy'])),
248
- tenant: (instance['owner'] ? (instance['owner']['username'] || instance['owner']['id']) : (instance['createdBy'].is_a?(Hash) ? instance['createdBy']['username'] : instance['createdBy'])),
249
- nodes: instance['containers'].count,
250
- status: format_instance_status(instance, cyan),
251
- type: instance['instanceType']['name'],
252
- group: instance['group'] ? instance['group']['name'] : nil,
253
- cloud: instance['cloud'] ? instance['cloud']['name'] : nil,
254
- plan: instance['plan'] ? instance['plan']['name'] : '',
255
- version: instance['instanceVersion'] ? instance['instanceVersion'] : '',
256
- created: format_local_dt(instance['dateCreated']),
257
- cpu: cpu_usage_str + cyan,
258
- memory: memory_usage_str + cyan,
259
- storage: storage_usage_str + cyan
260
- }
261
- row
262
- }
263
- columns = [:id, {:name => {:max_width => 50}}, :group, :cloud,
264
- :type, :version, :environment,
265
- {:created => {:display_name => "CREATED"}},
266
- # {:tenant => {:display_name => "TENANT"}},
267
- {:user => {:display_name => "OWNER", :max_width => 20}},
268
- :plan,
269
- :nodes, {:connection => {:max_width => 30}}, :status, :cpu, :memory, :storage]
270
- # custom pretty table columns ... this is handled in as_pretty_table now(),
271
- # todo: remove all these.. and try to always pass rows as the json data itself..
272
- if options[:details] != true
273
- columns.delete(:plan)
274
245
  end
275
- print cyan
276
- print as_pretty_table(rows, columns, options)
277
- print reset
278
- print_results_pagination(json_response)
246
+ row = {
247
+ id: instance['id'],
248
+ name: instance['name'],
249
+ connection: format_instance_connection_string(instance),
250
+ environment: instance['instanceContext'],
251
+ user: (instance['owner'] ? (instance['owner']['username'] || instance['owner']['id']) : (instance['createdBy'].is_a?(Hash) ? instance['createdBy']['username'] : instance['createdBy'])),
252
+ tenant: (instance['owner'] ? (instance['owner']['username'] || instance['owner']['id']) : (instance['createdBy'].is_a?(Hash) ? instance['createdBy']['username'] : instance['createdBy'])),
253
+ nodes: instance['containers'].count,
254
+ status: format_instance_status(instance, cyan),
255
+ type: instance['instanceType']['name'],
256
+ group: instance['group'] ? instance['group']['name'] : nil,
257
+ cloud: instance['cloud'] ? instance['cloud']['name'] : nil,
258
+ plan: instance['plan'] ? instance['plan']['name'] : '',
259
+ version: instance['instanceVersion'] ? instance['instanceVersion'] : '',
260
+ created: format_local_dt(instance['dateCreated']),
261
+ cpu: cpu_usage_str + cyan,
262
+ memory: memory_usage_str + cyan,
263
+ storage: storage_usage_str + cyan
264
+ }
265
+ row
266
+ }
267
+ columns = [:id, {:name => {:max_width => 50}}, :group, :cloud,
268
+ :type, :version, :environment,
269
+ {:created => {:display_name => "CREATED"}},
270
+ # {:tenant => {:display_name => "TENANT"}},
271
+ {:user => {:display_name => "OWNER", :max_width => 20}},
272
+ :plan,
273
+ :nodes, {:connection => {:max_width => 30}}, :status, :cpu, :memory, :storage]
274
+ # custom pretty table columns ... this is handled in as_pretty_table now(),
275
+ # todo: remove all these.. and try to always pass rows as the json data itself..
276
+ if options[:details] != true
277
+ columns.delete(:plan)
279
278
  end
280
- print reset,"\n"
279
+ print cyan
280
+ print as_pretty_table(rows, columns, options)
281
+ print reset
282
+ print_results_pagination(json_response)
281
283
  end
282
- rescue RestClient::Exception => e
283
- print_rest_exception(e, options)
284
- exit 1
284
+ print reset,"\n"
285
285
  end
286
+ return 0, nil
286
287
  end
287
288
 
288
289
  def count(args)
@@ -436,7 +437,7 @@ class Morpheus::Cli::Instances
436
437
  opts.on("--create-backup [on|off]", String, "Automation: Create Backups.") do |val|
437
438
  options[:create_backup] = ['on','true','1',''].include?(val.to_s.downcase) ? 'on' : 'off'
438
439
  end
439
- opts.on("--security-groups LIST", String, "Security Groups, comma sepearated list of security group IDs") do |val|
440
+ opts.on("--security-groups LIST", String, "Security Groups, comma separated list of security group IDs") do |val|
440
441
  options[:security_groups] = val.split(",").collect {|s| s.strip }.select {|s| !s.to_s.empty? }
441
442
  end
442
443
  opts.on('--refresh [SECONDS]', String, "Refresh until status is running,failed. Default interval is #{default_refresh_interval} seconds.") do |val|
@@ -1233,7 +1234,7 @@ class Morpheus::Cli::Instances
1233
1234
  # opts.on( nil, '--lb', "Display Load Balancer Details" ) do
1234
1235
  # options[:include_lb] = true
1235
1236
  # end
1236
- build_common_options(opts, options, [:query, :json, :yaml, :csv, :fields, :dry_run, :remote])
1237
+ build_standard_get_options(opts, options)
1237
1238
  opts.footer = "Get details about an instance.\n" +
1238
1239
  "[instance] is required. This is the name or id of an instance. Supports 1-N [instance] arguments."
1239
1240
  end
@@ -1250,34 +1251,20 @@ class Morpheus::Cli::Instances
1250
1251
  end
1251
1252
 
1252
1253
  def _get(arg, options={})
1253
- begin
1254
- if options[:dry_run]
1255
- @instances_interface.setopts(options)
1256
- if arg.to_s =~ /\A\d{1,}\Z/
1257
- print_dry_run @instances_interface.dry.get(arg.to_i)
1258
- else
1259
- print_dry_run @instances_interface.dry.get({name:arg})
1260
- end
1261
- return
1262
- end
1263
- instance = find_instance_by_name_or_id(arg =~ /\A\d{1,}\Z/ ? arg.to_i : arg)
1254
+
1255
+ if options[:dry_run]
1264
1256
  @instances_interface.setopts(options)
1265
- json_response = @instances_interface.get(instance['id'])
1266
- if options[:quiet]
1267
- return 0
1268
- end
1269
- if options[:json]
1270
- puts as_json(json_response, options, "instance")
1271
- return 0
1272
- elsif options[:yaml]
1273
- puts as_yaml(json_response, options, "instance")
1274
- return 0
1275
- end
1276
-
1277
- if options[:csv]
1278
- puts records_as_csv([json_response['instance']], options)
1279
- return 0
1257
+ if arg.to_s =~ /\A\d{1,}\Z/
1258
+ print_dry_run @instances_interface.dry.get(arg.to_i)
1259
+ else
1260
+ print_dry_run @instances_interface.dry.get({name:arg})
1280
1261
  end
1262
+ return
1263
+ end
1264
+ instance = find_instance_by_name_or_id(arg =~ /\A\d{1,}\Z/ ? arg.to_i : arg)
1265
+ @instances_interface.setopts(options)
1266
+ json_response = @instances_interface.get(instance['id'])
1267
+ render_response(json_response, options, "instance") do
1281
1268
  instance = json_response['instance']
1282
1269
  stats = instance['stats'] || json_response['stats'] || {}
1283
1270
  # load_balancers = json_response['loadBalancers'] || {}
@@ -1494,12 +1481,8 @@ class Morpheus::Cli::Instances
1494
1481
  _get(arg, options)
1495
1482
  end
1496
1483
  end
1497
-
1498
- return 0
1499
- rescue RestClient::Exception => e
1500
- print_rest_exception(e, options)
1501
- exit 1
1502
1484
  end
1485
+ return 0, nil
1503
1486
  end
1504
1487
 
1505
1488
  def list_containers(args)
@@ -5,13 +5,15 @@ class Morpheus::Cli::IntegrationsCommand
5
5
  include Morpheus::Cli::AccountsHelper
6
6
 
7
7
  set_command_name :'integrations'
8
+ set_command_description "Integrations: View and manage integrations"
8
9
 
9
- register_subcommands :list
10
- set_default_subcommand :list
10
+ register_subcommands :list, :get, :add, :update, :remove, :refresh
11
+ register_subcommands :list_types, :get_type
11
12
 
12
13
  def connect(opts)
13
14
  @api_client = establish_remote_appliance_connection(opts)
14
15
  @integrations_interface = @api_client.integrations
16
+ @integration_types_interface = @api_client.integration_types
15
17
  end
16
18
 
17
19
  def handle(args)
@@ -22,68 +24,535 @@ class Morpheus::Cli::IntegrationsCommand
22
24
  options = {}
23
25
  params = {}
24
26
  optparse = Morpheus::Cli::OptionParser.new do |opts|
25
- opts.banner = subcommand_usage()
26
- build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
27
+ opts.banner = subcommand_usage("[search]")
28
+ opts.on('-t', '--type CODE', "Filter by type code(s), see `list-types` for available type codes") do |val|
29
+ params['type'] = val
30
+ end
31
+ opts.on('--url URL', String, "Filter by url") do |val|
32
+ params['url'] = val
33
+ end
34
+ build_standard_list_options(opts, options)
27
35
  opts.footer = "List integrations."
28
36
  end
29
37
  optparse.parse!(args)
38
+ # verify_args!(args:args, optparse:optparse, count:0)
39
+ if args.count > 0
40
+ options[:phrase] = args.join(" ")
41
+ end
30
42
  connect(options)
31
- if args.count != 0
32
- raise_command_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args}\n#{optparse}"
33
- return 1
43
+ params.merge!(parse_list_options(options))
44
+ @integrations_interface.setopts(options)
45
+ if options[:dry_run]
46
+ print_dry_run @integrations_interface.dry.list(params)
47
+ return
34
48
  end
49
+ json_response = @integrations_interface.list(params)
50
+ render_response(json_response, options, integration_list_key) do
51
+ integrations = json_response[integration_list_key]
52
+ print_h1 "Morpheus Integrations", parse_list_subtitles(options), options
53
+ if integrations.empty?
54
+ print cyan,"No integrations found.",reset,"\n"
55
+ else
56
+ list_columns = {
57
+ "ID" => 'id',
58
+ "Name" => 'name',
59
+ "Type" => lambda {|it| format_integration_type(it) },
60
+ "URL" => lambda {|it| it['url'] },
61
+ "Username" => lambda {|it| it['username'] },
62
+ "Enabled" => lambda {|it| format_boolean(it['enabled']) },
63
+ "Status Date" => lambda {|it| format_local_dt(it['statusDate']) },
64
+ "Status" => lambda {|it| format_integration_status(it) },
65
+ # "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
66
+ # "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
67
+ }.upcase_keys!
68
+ print as_pretty_table(integrations, list_columns, options)
69
+ print_results_pagination(json_response)
70
+ end
71
+ print reset,"\n"
72
+ end
73
+ return 0, nil
74
+ end
35
75
 
36
- begin
37
- params.merge!(parse_list_options(options))
38
- @integrations_interface.setopts(options)
39
- if options[:dry_run]
40
- print_dry_run @integrations_interface.dry.list(params)
41
- return
76
+ def get(args)
77
+ params = {}
78
+ options = {}
79
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
80
+ opts.banner = subcommand_usage("[integration]")
81
+ build_standard_get_options(opts, options)
82
+ opts.footer = <<-EOT
83
+ Get details about a specific integration.
84
+ [integration] is required. This is the name or id of an integration.
85
+ EOT
86
+ end
87
+ optparse.parse!(args)
88
+ verify_args!(args:args, optparse:optparse, min:1)
89
+ connect(options)
90
+ params.merge!(parse_query_options(options))
91
+ id_list = parse_id_list(args)
92
+ return run_command_for_each_arg(id_list) do |arg|
93
+ _get(arg, params, options)
94
+ end
95
+ end
96
+
97
+ def _get(id, params, options)
98
+ integration = nil
99
+ if id.to_s !~ /\A\d{1,}\Z/
100
+ integration = find_integration_by_name_or_id(id)
101
+ return 1, "integration not found for #{id}" if integration.nil?
102
+ id = integration['id']
103
+ end
104
+ @integrations_interface.setopts(options)
105
+ if options[:dry_run]
106
+ print_dry_run @integrations_interface.dry.get(id, params)
107
+ return
108
+ end
109
+ json_response = @integrations_interface.get(id, params)
110
+ integration = json_response[integration_object_key]
111
+ render_response(json_response, options, integration_object_key) do
112
+ print_h1 "Integration Details", [], options
113
+ print cyan
114
+ show_columns = {
115
+ "ID" => 'id',
116
+ "Name" => 'name',
117
+ "Type" => lambda {|it| format_integration_type(it) },
118
+ "URL" => lambda {|it| it['url'] },
119
+ "Host" => lambda {|it| it['host'] },
120
+ "Port" => lambda {|it| it['port'] },
121
+ "Username" => lambda {|it| it['username'] },
122
+ "Password" => lambda {|it| it['password'] },
123
+ "Token" => lambda {|it| it['token'] },
124
+ "Service Key" => lambda {|it| it['serviceKey'] ? it['serviceKey']['name'] : nil },
125
+ "Auth Key" => lambda {|it| it['authKey'] ? it['authKey']['name'] : nil },
126
+ "Enabled" => lambda {|it| format_boolean(it['enabled']) },
127
+ "Status Date" => lambda {|it| format_local_dt(it['statusDate']) },
128
+ "Status" => lambda {|it| format_integration_status(it) },
129
+ # "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
130
+ # "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
131
+ }
132
+ show_columns.delete("URL") if integration['url'].nil?
133
+ show_columns.delete("Host") if integration['host'].nil?
134
+ show_columns.delete("Port") if integration['port'].nil?
135
+ show_columns.delete("Password") if integration['password'].nil?
136
+ show_columns.delete("Token") if integration['token'].nil?
137
+ show_columns.delete("Service Key") if integration['serviceKey'].nil?
138
+ show_columns.delete("Auth Key") if integration['authKey'].nil?
139
+ print_description_list(show_columns, integration, options)
140
+ print reset,"\n"
141
+ end
142
+ return 0, nil
143
+ end
144
+
145
+ def add(args)
146
+ options = {}
147
+ params = {}
148
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
149
+ opts.banner = subcommand_usage("[name] -t CODE [options]")
150
+ # opts.on('-t', '--type CODE', "Integration Type code, see `#{command_name} list-types` for available type codes") do |val|
151
+ # options[:options]['type'] = val
152
+ # end
153
+ build_option_type_options(opts, options, add_integration_option_types)
154
+ build_option_type_options(opts, options, add_integration_advanced_option_types)
155
+ build_standard_add_options(opts, options)
156
+ opts.footer = <<-EOT
157
+ Create a new integration.
158
+ [name] is required. This is the name of the new integration
159
+ Configuration options vary by integration type.
160
+ EOT
161
+ end
162
+ optparse.parse!(args)
163
+ verify_args!(args:args, optparse:optparse, min:0, max:1)
164
+ options[:options]['name'] = args[0] if args[0]
165
+ connect(options)
166
+ payload = {}
167
+ if options[:payload]
168
+ payload = options[:payload]
169
+ payload.deep_merge!({integration_object_key => parse_passed_options(options)})
170
+ else
171
+ payload.deep_merge!({integration_object_key => parse_passed_options(options)})
172
+ # Type prompt first
173
+ #params['type'] = Morpheus::Cli::OptionTypes.no_prompt([{'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => [{'name' => 'Instance', 'value' => 'instance'}, {'name' => 'Blueprint', 'value' => 'blueprint'}, {'name' => 'Workflow', 'value' => 'workflow'}], 'defaultValue' => 'instance', 'required' => true}], options[:options], @api_client, options[:params])['type']
174
+ v_prompt = Morpheus::Cli::OptionTypes.prompt(add_integration_option_types(), options[:options], @api_client, options[:params])
175
+ params.deep_merge!(v_prompt)
176
+ advanced_config = Morpheus::Cli::OptionTypes.no_prompt(add_integration_advanced_option_types, options[:options], @api_client, options[:params])
177
+ advanced_config.deep_compact!
178
+ params.deep_merge!(advanced_config)
179
+
180
+ # lookup type by name or code to validate it exists and to prompt for its optionTypes
181
+ # set integration.type=code because the api expects it that way.
182
+ if params['type'].to_s.empty?
183
+ raise_command_error "missing required option: --type TYPE", args, optparse
184
+ end
185
+ integration_type = find_integration_type_by_name_or_code_id(params['type'])
186
+ if integration_type.nil?
187
+ return 1, "integration type not found for #{params['type']}"
188
+ end
189
+ params['type'] = integration_type['code']
190
+ config_option_types = integration_type['optionTypes']
191
+ if config_option_types.nil?
192
+ config_option_types = @integration_types_interface.option_types(integration_type['id'])['optionTypes']
193
+ end
194
+ if config_option_types.nil?
195
+ print yellow,"No option types found for integration type: #{integration_type['name']} (#{integration_type['code']})", reset, "\n"
196
+ end
197
+ if config_option_types && config_option_types.size > 0
198
+ # optionTypes do not need fieldContext: 'integration'
199
+ config_option_types.each do |opt|
200
+ if opt['fieldContext'] == 'integration' || opt['fieldContext'] == 'domain'
201
+ opt['fieldContext'] = nil
202
+ end
203
+ end
204
+ config_prompt = Morpheus::Cli::OptionTypes.prompt(config_option_types, options[:options], @api_client, options[:params])
205
+ config_prompt.deep_compact!
206
+ params.deep_merge!(config_prompt)
42
207
  end
43
- json_response = @integrations_interface.list(params)
208
+ # convert checkbox "on" and "off" to true and false
209
+ params.booleanize!
210
+ payload[integration_object_key].deep_merge!(params)
211
+ end
212
+ @integrations_interface.setopts(options)
213
+ if options[:dry_run]
214
+ print_dry_run @integrations_interface.dry.create(payload)
215
+ return 0, nil
216
+ end
217
+ json_response = @integrations_interface.create(payload)
218
+ integration = json_response[integration_object_key]
219
+ render_response(json_response, options, integration_object_key) do
220
+ print_green_success "Added integration #{integration['name']}"
221
+ return _get(integration["id"], {}, options)
222
+ end
223
+ return 0, nil
224
+ end
44
225
 
45
- render_result = render_with_format(json_response, options, 'integrations')
46
- return 0 if render_result
226
+ def update(args)
227
+ options = {}
228
+ params = {}
229
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
230
+ opts.banner = subcommand_usage("[integration] [options]")
231
+ build_option_type_options(opts, options, update_integration_option_types)
232
+ build_option_type_options(opts, options, update_integration_advanced_option_types)
233
+ opts.on(nil, '--no-refresh', "Skip refresh on update.") do
234
+ params['refresh'] = 'false'
235
+ end
236
+ build_standard_update_options(opts, options)
237
+ opts.footer = <<-EOT
238
+ Update an integration.
239
+ [integration] is required. This is the name or id of an integration.
240
+ EOT
241
+ end
242
+ optparse.parse!(args)
243
+ verify_args!(args:args, optparse:optparse, count:1)
244
+ connect(options)
245
+ integration = find_integration_by_name_or_id(args[0])
246
+ return 1 if integration.nil?
247
+ payload = {}
248
+ if options[:payload]
249
+ payload = options[:payload]
250
+ payload.deep_merge!({integration_object_key => parse_passed_options(options)})
251
+ else
252
+ payload.deep_merge!({integration_object_key => parse_passed_options(options)})
253
+ # do not prompt on update
254
+ v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_integration_option_types, options[:options], @api_client, options[:params])
255
+ v_prompt.deep_compact!
256
+ params.deep_merge!(v_prompt)
257
+ advanced_config = Morpheus::Cli::OptionTypes.no_prompt(update_integration_advanced_option_types, options[:options], @api_client, options[:params])
258
+ advanced_config.deep_compact!
259
+ params.deep_merge!(advanced_config)
260
+ # convert checkbox "on" and "off" to true and false
261
+ params.booleanize!
262
+ # massage association params a bit
263
+
264
+ payload.deep_merge!({integration_object_key => params})
265
+ if payload[integration_object_key].empty? # || options[:no_prompt]
266
+ raise_command_error "Specify at least one option to update.\n#{optparse}"
267
+ end
268
+ end
269
+ @integrations_interface.setopts(options)
270
+ if options[:dry_run]
271
+ print_dry_run @integrations_interface.dry.update(integration['id'], payload)
272
+ return
273
+ end
274
+ json_response = @integrations_interface.update(integration['id'], payload)
275
+ integration = json_response[integration_object_key]
276
+ render_response(json_response, options, integration_object_key) do
277
+ print_green_success "Updated integration #{integration['name']}"
278
+ return _get(integration["id"], {}, options)
279
+ end
280
+ return 0, nil
281
+ end
282
+
283
+ def refresh(args)
284
+ options = {}
285
+ query_params = {}
286
+ params = {}
287
+ payload = {}
288
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
289
+ opts.banner = subcommand_usage("[integration] [options]")
290
+ build_option_type_options(opts, options, update_integration_option_types)
291
+ build_option_type_options(opts, options, update_integration_advanced_option_types)
292
+ build_standard_update_options(opts, options)
293
+ opts.footer = <<-EOT
294
+ Refresh an integration.
295
+ [integration] is required. This is the name or id of an integration.
296
+ EOT
297
+ end
298
+ optparse.parse!(args)
299
+ verify_args!(args:args, optparse:optparse, count:1)
300
+ connect(options)
301
+ query_params.merge!(parse_query_options(options))
302
+ integration = find_integration_by_name_or_id(args[0])
303
+ return 1 if integration.nil?
304
+ payload = {}
305
+ if options[:payload]
306
+ payload = options[:payload]
307
+ payload.deep_merge!({integration_object_key => parse_passed_options(options)})
308
+ else
309
+ payload.deep_merge!({integration_object_key => parse_passed_options(options)})
310
+ end
311
+ @integrations_interface.setopts(options)
312
+ if options[:dry_run]
313
+ print_dry_run @integrations_interface.dry.refresh(integration['id'], query_params, payload)
314
+ return
315
+ end
316
+ json_response = @integrations_interface.refresh(integration['id'], query_params, payload)
317
+ integration = json_response[integration_object_key]
318
+ render_response(json_response, options, integration_object_key) do
319
+ print_green_success "Refreshed integration #{integration['name']}"
320
+ return _get(integration["id"], {}, options)
321
+ end
322
+ return 0, nil
323
+ end
47
324
 
48
- title = "Morpheus Integrations"
49
- subtitles = []
50
- subtitles += parse_list_subtitles(options)
51
- print_h1 title, subtitles
325
+ def remove(args)
326
+ options = {}
327
+ params = {}
328
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
329
+ opts.banner = subcommand_usage("[integration] [options]")
330
+ build_standard_remove_options(opts, options)
331
+ opts.footer = <<-EOT
332
+ Delete an integration.
333
+ [integration] is required. This is the name or id of an integration.
334
+ EOT
335
+ end
336
+ optparse.parse!(args)
337
+ verify_args!(args:args, optparse:optparse, count:1)
338
+ connect(options)
339
+ integration = find_integration_by_name_or_id(args[0])
340
+ return 1 if integration.nil?
341
+ @integrations_interface.setopts(options)
342
+ if options[:dry_run]
343
+ print_dry_run @integrations_interface.dry.destroy(integration['id'], params)
344
+ return
345
+ end
346
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the integration #{integration['name']}?")
347
+ return 9, "aborted command"
348
+ end
349
+ json_response = @integrations_interface.destroy(integration['id'], params)
350
+ render_response(json_response, options) do
351
+ print_green_success "Removed integration #{integration['name']}"
352
+ end
353
+ return 0, nil
354
+ end
52
355
 
53
- integrations = json_response['integrations']
54
356
 
55
- if integrations.empty?
56
- print cyan,"No integrations found.",reset,"\n"
357
+ def list_types(args)
358
+ options = {}
359
+ params = {}
360
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
361
+ opts.banner = subcommand_usage("[search]")
362
+ opts.on('--optionTypes [true|false]', String, "Include optionTypes in the response. Default is false.") do |val|
363
+ params['optionTypes'] = (val.to_s == '' || val.to_s == 'on' || val.to_s == 'true')
364
+ end
365
+ build_standard_list_options(opts, options)
366
+ opts.footer = "List integration types."
367
+ end
368
+ optparse.parse!(args)
369
+ connect(options)
370
+ # verify_args!(args:args, optparse:optparse, count:0)
371
+ if args.count > 0
372
+ options[:phrase] = args.join(" ")
373
+ end
374
+ params.merge!(parse_list_options(options))
375
+ @integration_types_interface.setopts(options)
376
+ if options[:dry_run]
377
+ print_dry_run @integration_types_interface.dry.list(params)
378
+ return
379
+ end
380
+ json_response = @integration_types_interface.list(params)
381
+ render_response(json_response, options, integration_type_list_key) do
382
+ integration_types = json_response[integration_type_list_key]
383
+ print_h1 "Morpheus Integration Types", parse_list_subtitles(options), options
384
+ if integration_types.empty?
385
+ print cyan,"No integration types found.",reset,"\n"
57
386
  else
58
- rows = integrations.collect do |it|
59
- {
60
- id: it['id'],
61
- name: it['name'],
62
- status: format_integration_status(it),
63
- last_updated: format_local_dt(it['statusDate']),
64
- type: it['integrationType'] ? it['integrationType']['name'] : ''
65
- }
66
- end
67
- columns = [ :id, :name, :status, :last_updated, :type]
68
- print as_pretty_table(rows, columns)
387
+ list_columns = integration_type_column_definitions.upcase_keys!
388
+ print as_pretty_table(integration_types, list_columns, options)
389
+ print_results_pagination(json_response)
69
390
  end
70
391
  print reset,"\n"
71
- return 0
72
- rescue RestClient::Exception => e
73
- print_rest_exception(e, options)
74
- exit 1
75
392
  end
393
+ return 0, nil
394
+ end
395
+
396
+ def get_type(args)
397
+ params = {'optionTypes' => true}
398
+ options = {}
399
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
400
+ opts.banner = subcommand_usage("[type]")
401
+ build_standard_get_options(opts, options)
402
+ opts.on('--optionTypes [true|false]', String, "Include optionTypes in the response. Default is true.") do |val|
403
+ params['optionTypes'] = (val.to_s == '' || val.to_s == 'on' || val.to_s == 'true')
404
+ end
405
+ opts.footer = <<-EOT
406
+ Get details about a specific integration type.
407
+ [type] is required. This is the name or id of an integration type.
408
+ EOT
409
+ end
410
+ optparse.parse!(args)
411
+ verify_args!(args:args, optparse:optparse, min:1)
412
+ connect(options)
413
+ params.merge!(parse_query_options(options))
414
+ id_list = parse_id_list(args)
415
+ return run_command_for_each_arg(id_list) do |arg|
416
+ _get_type(arg, params, options)
417
+ end
418
+ end
419
+
420
+ def _get_type(id, params, options)
421
+ integration_type = nil
422
+ if id.to_s !~ /\A\d{1,}\Z/
423
+ integration_type = find_integration_type_by_name_or_code(id)
424
+ return 1, "integration type not found for name or code '#{id}'" if integration_type.nil?
425
+ id = integration_type['id']
426
+ end
427
+ # /api/integration-types does not return optionTypes by default, use ?optionTypes=true
428
+ @integration_types_interface.setopts(options)
429
+ if options[:dry_run]
430
+ print_dry_run @integration_types_interface.dry.get(id, params)
431
+ return
432
+ end
433
+ json_response = @integration_types_interface.get(id, params)
434
+ integration_type = json_response[integration_type_object_key]
435
+ render_response(json_response, options, integration_type_object_key) do
436
+ print_h1 "Integration Type Details", [], options
437
+ print cyan
438
+ show_columns = integration_type_column_definitions
439
+ print_description_list(show_columns, integration_type)
440
+
441
+ if integration_type['optionTypes'] && integration_type['optionTypes'].size > 0
442
+ print_h2 "Option Types"
443
+ opt_columns = [
444
+ # {"ID" => lambda {|it| it['id'] } },
445
+ {"FIELD NAME" => lambda {|it| (it['fieldContext'] && it['fieldContext'] != 'integration') ? [it['fieldContext'], it['fieldName']].join('.') : it['fieldName'] } },
446
+ {"FIELD LABEL" => lambda {|it| it['fieldLabel'] } },
447
+ {"TYPE" => lambda {|it| it['type'] } },
448
+ {"DEFAULT" => lambda {|it| it['defaultValue'] } },
449
+ {"REQUIRED" => lambda {|it| format_boolean it['required'] } },
450
+ # {"DESCRIPTION" => lambda {|it| it['description'] }, # do it!
451
+ ]
452
+ print as_pretty_table(integration_type['optionTypes'], opt_columns)
453
+ else
454
+ # print cyan,"No option types found for this integration type.","\n",reset
455
+ end
456
+
457
+ print reset,"\n"
458
+ end
459
+ return 0, nil
76
460
  end
77
461
 
78
462
  private
79
463
 
464
+ def format_integration_type(integration)
465
+ (integration['integrationType']['name'] || integration['integrationType']['code']) rescue integration['integrationType'].to_s
466
+ end
467
+
468
+ def add_integration_option_types
469
+ [
470
+ {'code' => 'integration.type', 'shorthand' => '-t', 'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
471
+ # @integration_types_interface.list(max:-1)[integration_list_key].collect {|it|
472
+ get_available_integration_types().collect {|it|
473
+ {'name' => it['name'], 'value' => it['code']}
474
+ } }, 'required' => true, 'description' => "Integration Type code, see `#{command_name} list-types` for available type codes"},
475
+ {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Name of the integration'},
476
+ # {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text'},
477
+ {'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'defaultValue' => true, 'description' => 'Can be used to disable an integration'}
478
+ ]
479
+ end
480
+
481
+ def add_integration_advanced_option_types
482
+ []
483
+ end
484
+
485
+ def update_integration_option_types
486
+ list = add_integration_option_types.collect {|it|
487
+ it.delete('required')
488
+ it.delete('defaultValue')
489
+ it
490
+ }
491
+ list = list.reject {|it| ["type"].include? it['fieldName'] }
492
+ list
493
+ end
494
+
495
+ def update_integration_advanced_option_types
496
+ add_integration_advanced_option_types.collect {|it|
497
+ it.delete('required')
498
+ it.delete('defaultValue')
499
+ it
500
+ }
501
+ end
502
+
503
+ def integration_object_key
504
+ 'integration'
505
+ end
506
+
507
+ def integration_list_key
508
+ 'integrations'
509
+ end
510
+
511
+ def find_integration_by_name_or_id(val)
512
+ if val.to_s =~ /\A\d{1,}\Z/
513
+ return find_integration_by_id(val)
514
+ else
515
+ return find_integration_by_name(val)
516
+ end
517
+ end
518
+
519
+ def find_integration_by_id(id)
520
+ begin
521
+ json_response = @integrations_interface.get(id.to_i)
522
+ return json_response[integration_object_key]
523
+ rescue RestClient::Exception => e
524
+ if e.response && e.response.code == 404
525
+ print_red_alert "integration not found by id '#{id}'"
526
+ else
527
+ raise e
528
+ end
529
+ end
530
+ end
531
+
532
+ def find_integration_by_name(name)
533
+ json_response = @integrations_interface.list({name: name.to_s})
534
+ integrations = json_response[integration_list_key]
535
+ if integrations.empty?
536
+ print_red_alert "integration not found by name '#{name}'"
537
+ return nil
538
+ elsif integrations.size > 1
539
+ print_red_alert "#{integrations.size} integrations found by name '#{name}'"
540
+ puts_error as_pretty_table(integrations, [:id, :name], {color:red})
541
+ print_red_alert "Try using ID instead"
542
+ print reset,"\n"
543
+ return nil
544
+ else
545
+ return integrations[0]
546
+ end
547
+ end
548
+
80
549
  def format_integration_status(integration, return_color=cyan)
81
550
  out = ""
82
551
  status_string = integration['status']
83
- if integration['enabled'] == false
84
- out << "#{red}DISABLED#{integration['statusMessage'] ? "#{return_color} - #{integration['statusMessage']}" : ''}#{return_color}"
85
- elsif status_string.nil? || status_string.empty? || status_string == "unknown"
552
+ if status_string.nil? || status_string.empty? || status_string == "unknown"
86
553
  out << "#{white}UNKNOWN#{integration['statusMessage'] ? "#{return_color} - #{integration['statusMessage']}" : ''}#{return_color}"
554
+ # elsif integration['enabled'] == false
555
+ # out << "#{red}DISABLED#{integration['statusMessage'] ? "#{return_color} - #{integration['statusMessage']}" : ''}#{return_color}"
87
556
  elsif status_string == 'ok'
88
557
  out << "#{green}#{status_string.upcase}#{return_color}"
89
558
  elsif status_string == 'error' || status_string == 'offline'
@@ -94,4 +563,82 @@ class Morpheus::Cli::IntegrationsCommand
94
563
  out
95
564
  end
96
565
 
566
+
567
+ def integration_type_column_definitions()
568
+ {
569
+ "ID" => 'id',
570
+ "Code" => 'code',
571
+ "Name" => 'name',
572
+ # "Description" => 'description',
573
+ "Category" => 'category',
574
+ # "Enabled" => lambda {|it| format_boolean(it['enabled']) },
575
+ "Creatable" => lambda {|it| format_boolean(it['creatable']) },
576
+ }
577
+ end
578
+
579
+ def integration_type_object_key
580
+ 'integrationType'
581
+ end
582
+
583
+ def integration_type_list_key
584
+ 'integrationTypes'
585
+ end
586
+
587
+ def find_integration_type_by_name_or_code_id(val, params={})
588
+ if val.to_s =~ /\A\d{1,}\Z/
589
+ return find_integration_type_by_id(val, params)
590
+ else
591
+ return find_integration_type_by_name_or_code(val)
592
+ end
593
+ end
594
+
595
+ def find_integration_type_by_id(id, params={})
596
+ begin
597
+ json_response = @integration_types_interface.get(id.to_i, params)
598
+ return json_response[integration_object_key]
599
+ rescue RestClient::Exception => e
600
+ if e.response && e.response.code == 404
601
+ print_red_alert "integration not found by id '#{id}'"
602
+ else
603
+ raise e
604
+ end
605
+ end
606
+ end
607
+
608
+ def find_integration_type_by_name(name, params={})
609
+ json_response = @integration_types_interface.list(params.merge({name: name.to_s}))
610
+ integration_types = json_response[integration_type_list_key]
611
+ if integration_types.empty?
612
+ print_red_alert "integration type not found by name '#{name}'"
613
+ return nil
614
+ elsif integration_types.size > 1
615
+ print_red_alert "#{integration_types.size} integration types found by name '#{name}'"
616
+ puts_error as_pretty_table(integration_types, [:id, :code, :name], {color:red})
617
+ print_red_alert "Try using ID instead"
618
+ print reset,"\n"
619
+ return nil
620
+ else
621
+ return integration_types[0]
622
+ end
623
+ end
624
+
625
+ def get_available_integration_types(refresh=false)
626
+ if !@available_integration_types || refresh
627
+ @available_integration_types = @integration_types_interface.list(max:10000)[integration_type_list_key]
628
+ end
629
+ return @available_integration_types
630
+ end
631
+
632
+ def find_integration_type_by_name_or_code(name)
633
+ records = get_available_integration_types()
634
+ record = records.find { |z| z['name'].downcase == name.downcase || z['code'].downcase == name.downcase}
635
+ record = record ? record : records.find { |z| z['id'].to_s == name.to_s }
636
+ if record
637
+ return record
638
+ else
639
+ print_red_alert "integration type not found by '#{name}'"
640
+ return nil
641
+ end
642
+ end
643
+
97
644
  end