morpheus-cli 6.1.0 → 6.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +8 -4
- data/lib/morpheus/api/cypher_interface.rb +11 -5
- data/lib/morpheus/api/load_balancer_pool_nodes_interface.rb +8 -0
- data/lib/morpheus/api/load_balancer_pools_interface.rb +4 -4
- data/lib/morpheus/api/load_balancer_pools_secondary_interface.rb +9 -0
- data/lib/morpheus/api/roles_interface.rb +8 -8
- data/lib/morpheus/cli/commands/instances.rb +5 -0
- data/lib/morpheus/cli/commands/load_balancer_pool_nodes.rb +87 -0
- data/lib/morpheus/cli/commands/load_balancer_pools.rb +43 -4
- data/lib/morpheus/cli/commands/roles.rb +403 -586
- data/lib/morpheus/cli/commands/security_groups.rb +58 -37
- data/lib/morpheus/cli/commands/users.rb +46 -2
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +6 -6
- data/lib/morpheus/cli/version.rb +1 -1
- metadata +5 -8
- data/lib/morpheus/api/doc_interface.rb +0 -50
- data/lib/morpheus/cli/commands/doc.rb +0 -182
- data/test/api/doc_interface_test.rb +0 -35
- data/test/cli/doc_test.rb +0 -35
@@ -210,6 +210,7 @@ class Morpheus::Cli::SecurityGroups
|
|
210
210
|
params = {}
|
211
211
|
options = {:options => {}}
|
212
212
|
cloud_id = nil
|
213
|
+
resource_pool_id = nil
|
213
214
|
tenants = nil
|
214
215
|
group_access_all = nil
|
215
216
|
group_access_list = nil
|
@@ -225,6 +226,9 @@ class Morpheus::Cli::SecurityGroups
|
|
225
226
|
opts.on( '-c', '--cloud CLOUD', "Scoped Cloud Name or ID" ) do |val|
|
226
227
|
cloud_id = val
|
227
228
|
end
|
229
|
+
opts.on( '--resource-pool ID', String, "ID of the Resource Pool for Amazon VPC and Azure Resource Group" ) do |val|
|
230
|
+
resource_pool_id = val
|
231
|
+
end
|
228
232
|
opts.on('--group-access-all [on|off]', String, "Toggle Access for all groups.") do |val|
|
229
233
|
group_access_all = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
|
230
234
|
end
|
@@ -321,17 +325,20 @@ class Morpheus::Cli::SecurityGroups
|
|
321
325
|
if !v_prompt['zoneId'].to_s.empty? && v_prompt['zoneId'].to_s != 'all' && v_prompt['zoneId'].to_s != '-1'
|
322
326
|
payload['securityGroup']['zoneId'] = v_prompt['zoneId']
|
323
327
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
328
|
+
cloud = find_cloud_by_id(payload['securityGroup']['zoneId'])
|
329
|
+
|
330
|
+
# parse --resource-pool
|
331
|
+
# if resource_pool_id
|
332
|
+
# resource_pool = find_resource_pool_by_name_or_id(cloud['id'], resource_pool_id)
|
333
|
+
# return 1 if resource_pool.nil?
|
334
|
+
# end
|
335
|
+
|
336
|
+
# prompt for zone specific settings that go under "securityGroup.customOptions" for some reason
|
337
|
+
custom_options_values = prompt_security_group_custom_options(options, cloud, resource_pool_id)
|
338
|
+
payload['securityGroup'].deep_merge!(custom_options_values)
|
333
339
|
end
|
334
340
|
rescue => ex
|
341
|
+
# raise ex
|
335
342
|
print yellow,"Failed to determine the available scoped clouds.",reset,"\n"
|
336
343
|
end
|
337
344
|
|
@@ -626,34 +633,8 @@ class Morpheus::Cli::SecurityGroups
|
|
626
633
|
# return 1 if resource_pool.nil?
|
627
634
|
# end
|
628
635
|
|
629
|
-
#
|
630
|
-
|
631
|
-
# default to the cloud type code, since it's the same...
|
632
|
-
# no optionTypes returned here, so hard coded by type
|
633
|
-
network_server_type = cloud['networkServer'] ? cloud['networkServer']['type'] : (cloud['securityServer'] ? cloud['securityServer']['type'] : cloud["zoneType"]["code"])
|
634
|
-
custom_options_values = {}
|
635
|
-
if network_server_type == 'amazon'
|
636
|
-
if cloud['config'] && !cloud['config']['vpc'].to_s.empty?
|
637
|
-
custom_options_values.deep_merge!({'customOptions' => {'vpc' => cloud['config']['vpc']} })
|
638
|
-
else
|
639
|
-
options[:options].deep_merge!({'customOptions' => {'vpc' => resource_pool_id} }) if resource_pool_id
|
640
|
-
custom_options_values = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'customOptions', 'fieldName' => 'vpc', 'fieldLabel' => 'VPC', 'type' => 'select', 'optionSource' => 'zonePools', 'required' => true, 'config' => {'valueField' => 'externalId'}}], options[:options], @api_client, {zoneId: cloud['id'], ignoreDefaultPool: true})
|
641
|
-
end
|
642
|
-
elsif network_server_type == 'azure' || network_server_type == 'azurestack'
|
643
|
-
if cloud['config'] && !cloud['config']['resourceGroup'].to_s.empty?
|
644
|
-
custom_options_values.deep_merge!({'customOptions' => {'resourceGroup' => cloud['config']['resourceGroup']} })
|
645
|
-
else
|
646
|
-
options[:options].deep_merge!({'customOptions' => {'resourceGroup' => resource_pool_id} }) if resource_pool_id
|
647
|
-
custom_options_values = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'customOptions', 'fieldName' => 'resourceGroup', 'fieldLabel' => 'Resource Group', 'type' => 'select', 'optionSource' => 'zonePools', 'required' => true, 'config' => {'valueField' => 'externalId'}}], options[:options], @api_client, {zoneId: cloud['id'], ignoreDefaultPool: true})
|
648
|
-
end
|
649
|
-
elsif network_server_type == 'openstack' || network_server_type == 'opentelekom' || network_server_type == 'huawei'
|
650
|
-
if cloud['config'] && !cloud['config']['resourcePoolId'].to_s.empty?
|
651
|
-
custom_options_values.deep_merge!({'customOptions' => {'resourcePoolId' => cloud['config']['resourcePoolId']} })
|
652
|
-
else
|
653
|
-
options[:options].deep_merge!({'customOptions' => {'resourcePoolId' => resource_pool_id} }) if resource_pool_id
|
654
|
-
custom_options_values = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'customOptions', 'fieldName' => 'resourcePoolId', 'fieldLabel' => 'Resource Pool', 'type' => 'select', 'optionSource' => 'zonePools', 'required' => true}], options[:options], @api_client, {zoneId: cloud['id'], ignoreDefaultPool: true})
|
655
|
-
end
|
656
|
-
end
|
636
|
+
# prompt for zone specific settings that go under "securityGroup.customOptions" for some reason
|
637
|
+
custom_options_values = prompt_security_group_custom_options(options, cloud, resource_pool_id)
|
657
638
|
payload['securityGroupLocation'].deep_merge!(custom_options_values)
|
658
639
|
end
|
659
640
|
@security_groups_interface.setopts(options)
|
@@ -1270,4 +1251,44 @@ class Morpheus::Cli::SecurityGroups
|
|
1270
1251
|
end
|
1271
1252
|
end
|
1272
1253
|
|
1254
|
+
def prompt_security_group_custom_options(options, cloud, resource_pool_id=nil)
|
1255
|
+
custom_options_values = {}
|
1256
|
+
# Custom Options prompt
|
1257
|
+
# securityServer is no longer used, it has been replaced by networkServer,
|
1258
|
+
# default to the cloud type code, since it's the same...
|
1259
|
+
# no optionTypes returned here, so hard coded by type
|
1260
|
+
# The API used to return securityServer which could be fetched to get its optionTypes
|
1261
|
+
if cloud['securityServer']
|
1262
|
+
sec_server = @network_security_servers.get(cloud['securityServer']['id'])['networkSecurityServer']
|
1263
|
+
if sec_server['type']
|
1264
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(sec_server['type']['optionTypes'], options[:options], @api_client, {zoneId: cloud['id']})
|
1265
|
+
custom_options_values.deep_merge!(v_prompt)
|
1266
|
+
end
|
1267
|
+
else
|
1268
|
+
network_server_type = cloud['networkServer'] ? cloud['networkServer']['type'] : (cloud['securityServer'] ? cloud['securityServer']['type'] : cloud["zoneType"]["code"])
|
1269
|
+
if network_server_type == 'amazon'
|
1270
|
+
if cloud['config'] && !cloud['config']['vpc'].to_s.empty?
|
1271
|
+
custom_options_values.deep_merge!({'customOptions' => {'vpc' => cloud['config']['vpc']} })
|
1272
|
+
else
|
1273
|
+
options[:options].deep_merge!({'customOptions' => {'vpc' => resource_pool_id} }) if resource_pool_id
|
1274
|
+
custom_options_values = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'customOptions', 'fieldName' => 'vpc', 'fieldLabel' => 'VPC', 'type' => 'select', 'optionSource' => 'zonePools', 'required' => true, 'config' => {'valueField' => 'externalId'}}], options[:options], @api_client, {zoneId: cloud['id'], ignoreDefaultPool: true})
|
1275
|
+
end
|
1276
|
+
elsif network_server_type == 'azure' || network_server_type == 'azurestack'
|
1277
|
+
if cloud['config'] && !cloud['config']['resourceGroup'].to_s.empty?
|
1278
|
+
custom_options_values.deep_merge!({'customOptions' => {'resourceGroup' => cloud['config']['resourceGroup']} })
|
1279
|
+
else
|
1280
|
+
options[:options].deep_merge!({'customOptions' => {'resourceGroup' => resource_pool_id} }) if resource_pool_id
|
1281
|
+
custom_options_values = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'customOptions', 'fieldName' => 'resourceGroup', 'fieldLabel' => 'Resource Group', 'type' => 'select', 'optionSource' => 'zonePools', 'required' => true, 'config' => {'valueField' => 'externalId'}}], options[:options], @api_client, {zoneId: cloud['id'], ignoreDefaultPool: true})
|
1282
|
+
end
|
1283
|
+
elsif network_server_type == 'openstack' || network_server_type == 'opentelekom' || network_server_type == 'huawei'
|
1284
|
+
if cloud['config'] && !cloud['config']['resourcePoolId'].to_s.empty?
|
1285
|
+
custom_options_values.deep_merge!({'customOptions' => {'resourcePoolId' => cloud['config']['resourcePoolId']} })
|
1286
|
+
else
|
1287
|
+
options[:options].deep_merge!({'customOptions' => {'resourcePoolId' => resource_pool_id} }) if resource_pool_id
|
1288
|
+
custom_options_values = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'customOptions', 'fieldName' => 'resourcePoolId', 'fieldLabel' => 'Resource Pool', 'type' => 'select', 'optionSource' => 'zonePools', 'required' => true}], options[:options], @api_client, {zoneId: cloud['id'], ignoreDefaultPool: true})
|
1289
|
+
end
|
1290
|
+
end
|
1291
|
+
end
|
1292
|
+
return custom_options_values
|
1293
|
+
end
|
1273
1294
|
end
|
@@ -297,7 +297,29 @@ EOT
|
|
297
297
|
if access.count > 0
|
298
298
|
access.each {|it| it['access'] = format_access_string(it['access'], available_access_levels)}
|
299
299
|
|
300
|
-
if ['features'
|
300
|
+
if ['features'].include?(field)
|
301
|
+
if access.find {|it| !it['subCategory'].to_s.empty? }
|
302
|
+
rows = access.collect do |it|
|
303
|
+
{
|
304
|
+
code: it['code'],
|
305
|
+
name: it['name'],
|
306
|
+
category: it['subCategory'].to_s.titleize,
|
307
|
+
access: format_access_string(it['access']),
|
308
|
+
}
|
309
|
+
end
|
310
|
+
if options[:sort]
|
311
|
+
rows.sort! {|a,b| a[options[:sort]] <=> b[options[:sort]] }
|
312
|
+
else
|
313
|
+
rows.sort! {|a,b| [a[:category],a[:name],a[:code]] <=> [b[:category],b[:name],b[:code]] }
|
314
|
+
end
|
315
|
+
if options[:direction] == 'desc'
|
316
|
+
rows.reverse!
|
317
|
+
end
|
318
|
+
print as_pretty_table(rows, [:category, :name, :code, :access], options)
|
319
|
+
else
|
320
|
+
print as_pretty_table(access, [:name, :code, :access], options)
|
321
|
+
end
|
322
|
+
elsif ['instance_types','report_types'].include?(field)
|
301
323
|
print as_pretty_table(access, [:name, :code, :access], options)
|
302
324
|
else
|
303
325
|
print as_pretty_table(access, [:name, :access], options)
|
@@ -422,7 +444,29 @@ EOT
|
|
422
444
|
if access.count > 0
|
423
445
|
access.each {|it| it['access'] = format_access_string(it['access'], available_access_levels)}
|
424
446
|
|
425
|
-
if ['features'
|
447
|
+
if ['features'].include?(field)
|
448
|
+
if access.find {|it| !it['subCategory'].to_s.empty? }
|
449
|
+
rows = access.collect do |it|
|
450
|
+
{
|
451
|
+
code: it['code'],
|
452
|
+
name: it['name'],
|
453
|
+
category: it['subCategory'].to_s.titleize,
|
454
|
+
access: format_access_string(it['access']),
|
455
|
+
}
|
456
|
+
end
|
457
|
+
if options[:sort]
|
458
|
+
rows.sort! {|a,b| a[options[:sort]] <=> b[options[:sort]] }
|
459
|
+
else
|
460
|
+
rows.sort! {|a,b| [a[:category],a[:name],a[:code]] <=> [b[:category],b[:name],b[:code]] }
|
461
|
+
end
|
462
|
+
if options[:direction] == 'desc'
|
463
|
+
rows.reverse!
|
464
|
+
end
|
465
|
+
print as_pretty_table(rows, [:category, :name, :code, :access], options)
|
466
|
+
else
|
467
|
+
print as_pretty_table(access, [:name, :code, :access], options)
|
468
|
+
end
|
469
|
+
elsif ['instance_types','report_types'].include?(field)
|
426
470
|
print as_pretty_table(access, [:name, :code, :access], options)
|
427
471
|
else
|
428
472
|
print as_pretty_table(access, [:name, :access], options)
|
@@ -719,7 +719,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
719
719
|
service_plan = nil
|
720
720
|
|
721
721
|
prompt_service_plan = -> {
|
722
|
-
service_plans_json = instances_interface.service_plans({zoneId: cloud_id, layoutId: layout['id'], siteId: group_id}.merge(resource_pool.nil? ? {} : {'resourcePoolId' => resource_pool['id']}))
|
722
|
+
service_plans_json = instances_interface.service_plans({zoneId: cloud_id, layoutId: layout['id'], siteId: group_id}.merge(resource_pool.nil? ? {} : {'poolId' => resource_pool['id'], 'resourcePoolId' => resource_pool['id']}))
|
723
723
|
service_plans = service_plans_json["plans"]
|
724
724
|
if locked_fields.include?('plan.id')
|
725
725
|
plan_id = options[:options]['plan']['id'] rescue nil
|
@@ -773,8 +773,8 @@ module Morpheus::Cli::ProvisioningHelper
|
|
773
773
|
has_zone_pools = provision_type && provision_type["id"] && provision_type["hasZonePools"]
|
774
774
|
if has_zone_pools
|
775
775
|
# pluck out the resourcePoolId option type to prompt for
|
776
|
-
resource_pool_option_type = option_type_list.find {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
|
777
|
-
option_type_list = option_type_list.reject {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
|
776
|
+
resource_pool_option_type = option_type_list.find {|opt| ['poolId','resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
|
777
|
+
option_type_list = option_type_list.reject {|opt| ['poolId','resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
|
778
778
|
|
779
779
|
resource_pool_options = options_interface.options_for_source('zonePools', {groupId: group_id, siteId: group_id, zoneId: cloud_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], layoutId: layout["id"]}.merge(service_plan.nil? ? {} : {planId: service_plan["id"]}))['data']
|
780
780
|
if options[:resource_pool]
|
@@ -836,7 +836,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
836
836
|
# add selectable datastores for resource pool
|
837
837
|
if options[:select_datastore]
|
838
838
|
begin
|
839
|
-
selectable_datastores = datastores_interface.list({'zoneId' => cloud_id, 'siteId' => group_id, 'resourcePoolId' => resource_pool['id']})
|
839
|
+
selectable_datastores = datastores_interface.list({'zoneId' => cloud_id, 'siteId' => group_id, 'poolId' => resource_pool['id'], 'resourcePoolId' => resource_pool['id']})
|
840
840
|
service_plan['datastores'] = {'clusters' => [], 'datastores' => []}
|
841
841
|
['clusters', 'datastores'].each do |type|
|
842
842
|
service_plan['datastores'][type] ||= []
|
@@ -1538,7 +1538,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
1538
1538
|
|
1539
1539
|
if datastore_options.empty? && storage_type['hasDatastore'] != false
|
1540
1540
|
begin
|
1541
|
-
datastore_res = datastores_interface.list({'resourcePoolId' => current_root_volume['resourcePoolId'], 'zoneId' => options['zoneId'], 'siteId' => options['siteId']})['datastores']
|
1541
|
+
datastore_res = datastores_interface.list({'poolId' => current_root_volume['resourcePoolId'], 'resourcePoolId' => current_root_volume['resourcePoolId'], 'zoneId' => options['zoneId'], 'siteId' => options['siteId']})['datastores']
|
1542
1542
|
datastore_res.each do |opt|
|
1543
1543
|
datastore_options << {'name' => opt['name'], 'value' => opt['id']}
|
1544
1544
|
end
|
@@ -1578,7 +1578,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
1578
1578
|
no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
|
1579
1579
|
network_interfaces = []
|
1580
1580
|
api_params = {zoneId: zone_id, provisionTypeId: provision_type_id}.merge(options[:api_params] || {})
|
1581
|
-
if pool_id
|
1581
|
+
if pool_id
|
1582
1582
|
api_params[:poolId] = pool_id
|
1583
1583
|
end
|
1584
1584
|
|
data/lib/morpheus/cli/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: morpheus-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.1.
|
4
|
+
version: 6.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Estes
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2023-
|
14
|
+
date: 2023-06-21 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -226,7 +226,6 @@ files:
|
|
226
226
|
- lib/morpheus/api/datastores_interface.rb
|
227
227
|
- lib/morpheus/api/deploy_interface.rb
|
228
228
|
- lib/morpheus/api/deployments_interface.rb
|
229
|
-
- lib/morpheus/api/doc_interface.rb
|
230
229
|
- lib/morpheus/api/environments_interface.rb
|
231
230
|
- lib/morpheus/api/execute_schedules_interface.rb
|
232
231
|
- lib/morpheus/api/execution_request_interface.rb
|
@@ -260,7 +259,9 @@ files:
|
|
260
259
|
- lib/morpheus/api/library_spec_templates_interface.rb
|
261
260
|
- lib/morpheus/api/license_interface.rb
|
262
261
|
- lib/morpheus/api/load_balancer_monitors_interface.rb
|
262
|
+
- lib/morpheus/api/load_balancer_pool_nodes_interface.rb
|
263
263
|
- lib/morpheus/api/load_balancer_pools_interface.rb
|
264
|
+
- lib/morpheus/api/load_balancer_pools_secondary_interface.rb
|
264
265
|
- lib/morpheus/api/load_balancer_profiles_interface.rb
|
265
266
|
- lib/morpheus/api/load_balancer_types_interface.rb
|
266
267
|
- lib/morpheus/api/load_balancer_virtual_servers_interface.rb
|
@@ -398,7 +399,6 @@ files:
|
|
398
399
|
- lib/morpheus/cli/commands/deploy.rb
|
399
400
|
- lib/morpheus/cli/commands/deployments.rb
|
400
401
|
- lib/morpheus/cli/commands/deploys.rb
|
401
|
-
- lib/morpheus/cli/commands/doc.rb
|
402
402
|
- lib/morpheus/cli/commands/echo_command.rb
|
403
403
|
- lib/morpheus/cli/commands/edit_profile_command.rb
|
404
404
|
- lib/morpheus/cli/commands/edit_rc_command.rb
|
@@ -434,6 +434,7 @@ files:
|
|
434
434
|
- lib/morpheus/cli/commands/library_upgrades_command.rb
|
435
435
|
- lib/morpheus/cli/commands/license.rb
|
436
436
|
- lib/morpheus/cli/commands/load_balancer_monitors.rb
|
437
|
+
- lib/morpheus/cli/commands/load_balancer_pool_nodes.rb
|
437
438
|
- lib/morpheus/cli/commands/load_balancer_pools.rb
|
438
439
|
- lib/morpheus/cli/commands/load_balancer_profiles.rb
|
439
440
|
- lib/morpheus/cli/commands/load_balancer_types.rb
|
@@ -575,14 +576,12 @@ files:
|
|
575
576
|
- lib/morpheus/util.rb
|
576
577
|
- morpheus-cli.gemspec
|
577
578
|
- test/api/containers_interface_test.rb
|
578
|
-
- test/api/doc_interface_test.rb
|
579
579
|
- test/api/instances_interface_test.rb
|
580
580
|
- test/api/whoami_interface_test.rb
|
581
581
|
- test/cli/access_token_test.rb
|
582
582
|
- test/cli/auth_test.rb
|
583
583
|
- test/cli/cli_test.rb
|
584
584
|
- test/cli/containers_test.rb
|
585
|
-
- test/cli/doc_test.rb
|
586
585
|
- test/cli/help_test.rb
|
587
586
|
- test/cli/instances_test.rb
|
588
587
|
- test/cli/man_test.rb
|
@@ -621,14 +620,12 @@ specification_version: 4
|
|
621
620
|
summary: Provides CLI Interface to the Morpheus Public/Private Cloud Appliance
|
622
621
|
test_files:
|
623
622
|
- test/api/containers_interface_test.rb
|
624
|
-
- test/api/doc_interface_test.rb
|
625
623
|
- test/api/instances_interface_test.rb
|
626
624
|
- test/api/whoami_interface_test.rb
|
627
625
|
- test/cli/access_token_test.rb
|
628
626
|
- test/cli/auth_test.rb
|
629
627
|
- test/cli/cli_test.rb
|
630
628
|
- test/cli/containers_test.rb
|
631
|
-
- test/cli/doc_test.rb
|
632
629
|
- test/cli/help_test.rb
|
633
630
|
- test/cli/instances_test.rb
|
634
631
|
- test/cli/man_test.rb
|
@@ -1,50 +0,0 @@
|
|
1
|
-
require 'morpheus/api/api_client'
|
2
|
-
|
3
|
-
class Morpheus::DocInterface < Morpheus::APIClient
|
4
|
-
|
5
|
-
def list(params={})
|
6
|
-
url = "/api/doc"
|
7
|
-
headers = {params: params}
|
8
|
-
execute(method: :get, url: url, headers: headers)
|
9
|
-
end
|
10
|
-
|
11
|
-
def openapi(params={})
|
12
|
-
url = "/api/doc/openapi"
|
13
|
-
fmt = params.delete('format')
|
14
|
-
if fmt
|
15
|
-
url = url + "." + fmt
|
16
|
-
end
|
17
|
-
is_yaml = fmt == "yml" || fmt == "yaml"
|
18
|
-
headers = {params: params}
|
19
|
-
execute(method: :get, url: url, headers: headers, timeout: 172800, parse_json: !is_yaml)
|
20
|
-
end
|
21
|
-
|
22
|
-
def download_openapi(outfile, params={})
|
23
|
-
# note that RestClient.execute still requires the full path with base_url
|
24
|
-
url = "#{@base_url}/api/doc/openapi"
|
25
|
-
fmt = params.delete('format')
|
26
|
-
if fmt
|
27
|
-
url = url + "." + fmt
|
28
|
-
end
|
29
|
-
headers = {params: params, authorization: "Bearer #{@access_token}"}
|
30
|
-
opts = {method: :get, url: url, headers: headers, timeout: 172800, parse_json: false}
|
31
|
-
|
32
|
-
if @dry_run
|
33
|
-
return opts
|
34
|
-
end
|
35
|
-
|
36
|
-
http_response = nil
|
37
|
-
File.open(File.expand_path(outfile), 'w') {|f|
|
38
|
-
block = proc { |response|
|
39
|
-
response.read_body do |chunk|
|
40
|
-
# writing to #{outfile} ..."
|
41
|
-
f.write chunk
|
42
|
-
end
|
43
|
-
}
|
44
|
-
opts[:block_response] = block
|
45
|
-
http_response = Morpheus::RestClient.execute(opts)
|
46
|
-
}
|
47
|
-
http_response
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
@@ -1,182 +0,0 @@
|
|
1
|
-
require 'morpheus/cli/cli_command'
|
2
|
-
|
3
|
-
# This provides commands for authentication
|
4
|
-
# This also includes credential management.
|
5
|
-
class Morpheus::Cli::Doc
|
6
|
-
include Morpheus::Cli::CliCommand
|
7
|
-
|
8
|
-
set_command_name :'doc'
|
9
|
-
register_subcommands :list
|
10
|
-
register_subcommands :get => :openapi
|
11
|
-
register_subcommands :download => :download_openapi
|
12
|
-
|
13
|
-
# hidden until doc complete (or close to it)
|
14
|
-
set_command_hidden
|
15
|
-
|
16
|
-
def initialize()
|
17
|
-
# @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
18
|
-
end
|
19
|
-
|
20
|
-
def handle(args)
|
21
|
-
handle_subcommand(args)
|
22
|
-
end
|
23
|
-
|
24
|
-
def connect(options)
|
25
|
-
# @api_client = establish_remote_appliance_connection(options.merge({:no_prompt => true, :skip_verify_access_token => true, :skip_login => true}))
|
26
|
-
@api_client = establish_remote_appliance_connection(options)
|
27
|
-
@doc_interface = @api_client.doc
|
28
|
-
end
|
29
|
-
|
30
|
-
def list(args)
|
31
|
-
exit_code, err = 0, nil
|
32
|
-
params, options = {}, {}
|
33
|
-
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
34
|
-
opts.banner = subcommand_usage()
|
35
|
-
build_standard_get_options(opts, options)
|
36
|
-
opts.footer = <<-EOT
|
37
|
-
List documentation links.
|
38
|
-
EOT
|
39
|
-
end
|
40
|
-
optparse.parse!(args)
|
41
|
-
verify_args!(args:args, optparse:optparse, count:0)
|
42
|
-
connect(options)
|
43
|
-
# construct the api request
|
44
|
-
params.merge!(parse_list_options(options))
|
45
|
-
# execute the api request
|
46
|
-
@doc_interface.setopts(options)
|
47
|
-
if options[:dry_run]
|
48
|
-
print_dry_run @doc_interface.dry.list(params)
|
49
|
-
return 0, nil
|
50
|
-
end
|
51
|
-
json_response = @doc_interface.list(params)
|
52
|
-
render_response(json_response, options, "links") do
|
53
|
-
title = "Morpheus Documentation"
|
54
|
-
print_h1 title, options
|
55
|
-
if json_response['links'].empty?
|
56
|
-
print yellow, "No help links found.",reset,"\n"
|
57
|
-
else
|
58
|
-
columns = {
|
59
|
-
"Link Name" => 'name',
|
60
|
-
"URL" => 'url',
|
61
|
-
"Description" => {display_method:'description', max_width: (options[:wrap] ? nil : 50)},
|
62
|
-
}
|
63
|
-
print as_pretty_table(json_response['links'], columns.upcase_keys!, options)
|
64
|
-
# print_results_pagination(json_response)
|
65
|
-
end
|
66
|
-
print reset,"\n"
|
67
|
-
end
|
68
|
-
return exit_code, err
|
69
|
-
end
|
70
|
-
|
71
|
-
def openapi(args)
|
72
|
-
exit_code, err = 0, nil
|
73
|
-
params, options = {}, {}
|
74
|
-
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
75
|
-
opts.banner = subcommand_usage()
|
76
|
-
# opts.on(nil, "--refresh", "Refresh the document. By default the openapi.yml and openapi.json are cached by the server.") do
|
77
|
-
# params['refresh'] = true
|
78
|
-
# end
|
79
|
-
# opts.on('-g', '--generate', "Alias for --refresh") do
|
80
|
-
# params['refresh'] = true
|
81
|
-
# end
|
82
|
-
build_standard_get_options(opts, options, [], [:csv])
|
83
|
-
opts.footer = <<-EOT
|
84
|
-
Print the Morpheus API OpenAPI Documentation (swagger).
|
85
|
-
The default format is JSON. Supports json or yaml.
|
86
|
-
EOT
|
87
|
-
end
|
88
|
-
optparse.parse!(args)
|
89
|
-
verify_args!(args:args, optparse:optparse, count:0)
|
90
|
-
connect(options)
|
91
|
-
# construct the api request
|
92
|
-
params.merge!(parse_list_options(options))
|
93
|
-
# for now, always use .json, and just convert to yaml for display on cli side
|
94
|
-
openapi_format = options[:yaml] ? "yaml" : "json"
|
95
|
-
# params['format'] = openapi_format
|
96
|
-
# execute the api request
|
97
|
-
@doc_interface.setopts(options)
|
98
|
-
if options[:dry_run]
|
99
|
-
params['format'] = openapi_format
|
100
|
-
print_dry_run @doc_interface.dry.openapi(params)
|
101
|
-
return 0, nil
|
102
|
-
end
|
103
|
-
json_response = @doc_interface.openapi(params)
|
104
|
-
# default format is to print header and json
|
105
|
-
render_response(json_response, options) do
|
106
|
-
title = "Morpheus API openapi.#{openapi_format}"
|
107
|
-
print_h1 title, options
|
108
|
-
print cyan
|
109
|
-
print as_json(json_response, options)
|
110
|
-
print reset,"\n"
|
111
|
-
end
|
112
|
-
return exit_code, err
|
113
|
-
end
|
114
|
-
|
115
|
-
def download_openapi(args)
|
116
|
-
exit_code, err = 0, nil
|
117
|
-
params, options = {}, {}
|
118
|
-
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
119
|
-
opts.banner = subcommand_usage("[local-file]")
|
120
|
-
# build_standard_get_options(opts, options, [], [:csv,:out])
|
121
|
-
opts.on(nil, '--yaml', "YAML Output") do
|
122
|
-
options[:yaml] = true
|
123
|
-
options[:format] = :yaml
|
124
|
-
end
|
125
|
-
# opts.on(nil, "--refresh", "Refresh the document. By default the openapi.yml and openapi.json are cached by the server.") do
|
126
|
-
# params['refresh'] = true
|
127
|
-
# end
|
128
|
-
# opts.on('-g', '--generate', "Alias for --refresh") do
|
129
|
-
# params['refresh'] = true
|
130
|
-
# end
|
131
|
-
opts.on( '-f', '--force', "Overwrite existing [local-file] if it exists." ) do
|
132
|
-
options[:overwrite] = true
|
133
|
-
end
|
134
|
-
opts.on( '-p', '--mkdir', "Create missing directories for [local-file] if they do not exist." ) do
|
135
|
-
options[:mkdir] = true
|
136
|
-
end
|
137
|
-
build_common_options(opts, options, [:dry_run, :quiet, :remote])
|
138
|
-
opts.footer = <<-EOT
|
139
|
-
Download the Morpheus API OpenAPI Documentation (swagger).
|
140
|
-
[local-file] is required. This is the full local filepath for the downloaded file.
|
141
|
-
The default format is JSON. Supports json or yaml.
|
142
|
-
EOT
|
143
|
-
end
|
144
|
-
optparse.parse!(args)
|
145
|
-
verify_args!(args:args, optparse:optparse, count:1)
|
146
|
-
connect(options)
|
147
|
-
# parse args
|
148
|
-
outfile = args[0]
|
149
|
-
if !validate_outfile(outfile, options)
|
150
|
-
return 1, "Failed to validate outfile"
|
151
|
-
end
|
152
|
-
# construct the api request
|
153
|
-
params.merge!(parse_list_options(options))
|
154
|
-
if outfile.include?(".yml") || outfile.include?(".yaml")
|
155
|
-
options[:yaml] = true
|
156
|
-
end
|
157
|
-
openapi_format = options[:yaml] ? "yaml" : "json"
|
158
|
-
params['format'] = openapi_format
|
159
|
-
# execute the api request
|
160
|
-
@doc_interface.setopts(options)
|
161
|
-
if options[:dry_run]
|
162
|
-
print_dry_run @doc_interface.dry.download_openapi(outfile, params)
|
163
|
-
return 0, nil
|
164
|
-
end
|
165
|
-
print cyan + "Downloading openapi.#{openapi_format} to #{outfile} ... " if !options[:quiet]
|
166
|
-
http_response = @doc_interface.download_openapi(outfile, params)
|
167
|
-
if http_response.code.to_i == 200
|
168
|
-
print green + "SUCCESS" + reset + "\n" if !options[:quiet]
|
169
|
-
return 0, nil
|
170
|
-
else
|
171
|
-
print red + "ERROR" + reset + " HTTP #{http_response.code}" + "\n" if !options[:quiet]
|
172
|
-
if File.exist?(outfile) && File.file?(outfile)
|
173
|
-
Morpheus::Logging::DarkPrinter.puts "Deleting bad file download: #{outfile}" if Morpheus::Logging.debug?
|
174
|
-
File.delete(outfile)
|
175
|
-
end
|
176
|
-
return 1, "HTTP #{http_response.code}"
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
protected
|
181
|
-
|
182
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'morpheus_test'
|
2
|
-
|
3
|
-
# Tests for Morpheus::DocInterface
|
4
|
-
class MorpheusTest::DocInterfaceTest < MorpheusTest::TestCase
|
5
|
-
|
6
|
-
def test_doc_list
|
7
|
-
@doc_interface = client.doc
|
8
|
-
response = @doc_interface.list()
|
9
|
-
assert_equal response['links'].class, Array
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_doc_get
|
13
|
-
@doc_interface = client.doc
|
14
|
-
response = @doc_interface.openapi()
|
15
|
-
assert_equal response['openapi'], '3.0.3'
|
16
|
-
# todo: fix this, can be cached and fail
|
17
|
-
#assert_equal response['version'], Morpheus::Cli::Remote.load_remote(@config.remote_name)[:build_version]
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_doc_get_yaml
|
21
|
-
@doc_interface = client.doc
|
22
|
-
response = @doc_interface.openapi({'format' => "yaml"})
|
23
|
-
assert response.body
|
24
|
-
assert YAML.load(response.body)
|
25
|
-
end
|
26
|
-
|
27
|
-
# def test_doc_download
|
28
|
-
# @doc_interface = client.doc
|
29
|
-
# response = @doc_interface.download_openapi('/path/to/openapi.json')
|
30
|
-
# yaml_content = response.body
|
31
|
-
# yaml_data = YAML.load(yaml_content)
|
32
|
-
# assert_not_nil yaml_data
|
33
|
-
# end
|
34
|
-
|
35
|
-
end
|
data/test/cli/doc_test.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'morpheus_test'
|
2
|
-
|
3
|
-
# Tests for Morpheus::Cli::Doc
|
4
|
-
class MorpheusTest::DocTest < MorpheusTest::TestCase
|
5
|
-
|
6
|
-
def test_doc_list
|
7
|
-
assert_execute("doc list")
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_doc_get
|
11
|
-
# using --quiet because the output is massive
|
12
|
-
assert_execute("doc get --quiet")
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_doc_get_yaml
|
16
|
-
# using --quiet because the output is massive
|
17
|
-
assert_execute("doc get --yaml --quiet")
|
18
|
-
end
|
19
|
-
|
20
|
-
# def test_doc_download
|
21
|
-
# assert_execute("doc download '/path/to/openapi.json')
|
22
|
-
# end
|
23
|
-
|
24
|
-
# def test_doc_download_yaml
|
25
|
-
# assert_execute("doc download '/path/to/openapi.yaml' --yaml")
|
26
|
-
# end
|
27
|
-
|
28
|
-
def test_doc_get_unauthorized
|
29
|
-
# authentication is NOT required for this api
|
30
|
-
without_authentication do
|
31
|
-
assert_error("doc get -q")
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|