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.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/README.md +1 -3
- data/lib/morpheus/api/api_client.rb +48 -14
- data/lib/morpheus/api/certificate_types_interface.rb +14 -0
- data/lib/morpheus/api/certificates_interface.rb +9 -0
- data/lib/morpheus/api/integration_types_interface.rb +14 -0
- data/lib/morpheus/api/integrations_interface.rb +7 -22
- data/lib/morpheus/api/network_services_interface.rb +14 -0
- data/lib/morpheus/api/read_interface.rb +23 -0
- data/lib/morpheus/api/rest_interface.rb +12 -10
- data/lib/morpheus/api/roles_interface.rb +7 -0
- data/lib/morpheus/api/servers_interface.rb +7 -0
- data/lib/morpheus/api/user_settings_interface.rb +38 -18
- data/lib/morpheus/api/vdi_allocations_interface.rb +9 -0
- data/lib/morpheus/api/vdi_apps_interface.rb +9 -0
- data/lib/morpheus/api/vdi_gateways_interface.rb +9 -0
- data/lib/morpheus/api/vdi_interface.rb +28 -0
- data/lib/morpheus/api/vdi_pools_interface.rb +19 -0
- data/lib/morpheus/cli.rb +9 -2
- data/lib/morpheus/cli/activity_command.rb +7 -4
- data/lib/morpheus/cli/apps.rb +59 -75
- data/lib/morpheus/cli/catalog_item_types_command.rb +13 -13
- data/lib/morpheus/cli/certificates_command.rb +575 -0
- data/lib/morpheus/cli/cli_command.rb +61 -6
- data/lib/morpheus/cli/clouds.rb +1 -0
- data/lib/morpheus/cli/clusters.rb +5 -2
- data/lib/morpheus/cli/commands/standard/history_command.rb +4 -5
- data/lib/morpheus/cli/commands/standard/man_command.rb +4 -5
- data/lib/morpheus/cli/dashboard_command.rb +3 -3
- data/lib/morpheus/cli/execution_request_command.rb +15 -5
- data/lib/morpheus/cli/hosts.rb +245 -224
- data/lib/morpheus/cli/instances.rb +150 -167
- data/lib/morpheus/cli/integrations_command.rb +588 -41
- data/lib/morpheus/cli/invoices_command.rb +23 -46
- data/lib/morpheus/cli/login.rb +7 -0
- data/lib/morpheus/cli/mixins/option_source_helper.rb +15 -16
- data/lib/morpheus/cli/mixins/print_helper.rb +36 -18
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +3 -3
- data/lib/morpheus/cli/mixins/vdi_helper.rb +246 -0
- data/lib/morpheus/cli/network_domains_command.rb +2 -2
- data/lib/morpheus/cli/network_routers_command.rb +22 -9
- data/lib/morpheus/cli/networks_command.rb +2 -2
- data/lib/morpheus/cli/option_types.rb +34 -33
- data/lib/morpheus/cli/remote.rb +3 -2
- data/lib/morpheus/cli/reports_command.rb +5 -2
- data/lib/morpheus/cli/roles.rb +215 -55
- data/lib/morpheus/cli/service_plans_command.rb +4 -1
- data/lib/morpheus/cli/subnets_command.rb +11 -2
- data/lib/morpheus/cli/user_settings_command.rb +268 -57
- data/lib/morpheus/cli/vdi_allocations_command.rb +159 -0
- data/lib/morpheus/cli/vdi_apps_command.rb +317 -0
- data/lib/morpheus/cli/vdi_command.rb +359 -0
- data/lib/morpheus/cli/vdi_gateways_command.rb +290 -0
- data/lib/morpheus/cli/vdi_pools_command.rb +571 -0
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/rest_client.rb +30 -0
- data/lib/morpheus/terminal.rb +15 -7
- 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
|
-
|
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
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
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
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
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
|
-
|
153
|
-
|
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
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
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
|
-
|
163
|
-
|
164
|
-
params
|
165
|
-
|
166
|
-
|
167
|
-
|
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
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
201
|
+
title = "Morpheus Instances"
|
202
|
+
subtitles = []
|
203
|
+
if group
|
204
|
+
subtitles << "Group: #{group['name']}".strip
|
175
205
|
end
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
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
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
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
|
-
|
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
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
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
|
279
|
+
print cyan
|
280
|
+
print as_pretty_table(rows, columns, options)
|
281
|
+
print reset
|
282
|
+
print_results_pagination(json_response)
|
281
283
|
end
|
282
|
-
|
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
|
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
|
-
|
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
|
-
|
1254
|
-
|
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
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
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
|
-
|
46
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
56
|
-
|
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
|
-
|
59
|
-
|
60
|
-
|
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
|
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
|