morpheus-cli 5.5.1.4 → 5.5.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 +25 -0
- data/lib/morpheus/api/archive_buckets_interface.rb +1 -1
- data/lib/morpheus/api/body_io.rb +22 -0
- data/lib/morpheus/api/catalog_item_types_interface.rb +5 -1
- data/lib/morpheus/api/clients_interface.rb +41 -0
- data/lib/morpheus/api/clouds_interface.rb +21 -0
- data/lib/morpheus/api/instances_interface.rb +8 -1
- data/lib/morpheus/api/integrations_interface.rb +30 -0
- data/lib/morpheus/api/library_instance_types_interface.rb +15 -3
- data/lib/morpheus/api/network_pool_server_types_interface.rb +9 -0
- data/lib/morpheus/api/plugins_interface.rb +22 -0
- data/lib/morpheus/api/roles_interface.rb +20 -1
- data/lib/morpheus/api/security_package_types_interface.rb +9 -0
- data/lib/morpheus/api/security_packages_interface.rb +9 -0
- data/lib/morpheus/api/security_scans_interface.rb +9 -0
- data/lib/morpheus/api/servers_interface.rb +17 -17
- data/lib/morpheus/api/storage_providers_interface.rb +1 -1
- data/lib/morpheus/api/virtual_images_interface.rb +1 -23
- data/lib/morpheus/cli/cli_command.rb +81 -7
- data/lib/morpheus/cli/commands/apps.rb +28 -2
- data/lib/morpheus/cli/commands/archives_command.rb +2 -2
- data/lib/morpheus/cli/commands/blueprints_command.rb +16 -0
- data/lib/morpheus/cli/commands/catalog_item_types_command.rb +34 -2
- data/lib/morpheus/cli/commands/clients_command.rb +338 -0
- data/lib/morpheus/cli/commands/clouds.rb +127 -1
- data/lib/morpheus/cli/commands/clusters.rb +42 -12
- data/lib/morpheus/cli/commands/curl_command.rb +114 -135
- data/lib/morpheus/cli/commands/hosts.rb +108 -11
- data/lib/morpheus/cli/commands/instances.rb +115 -14
- data/lib/morpheus/cli/commands/integrations_command.rb +215 -4
- data/lib/morpheus/cli/commands/invoices_command.rb +20 -11
- data/lib/morpheus/cli/commands/jobs_command.rb +299 -190
- data/lib/morpheus/cli/commands/library_cluster_layouts_command.rb +16 -2
- data/lib/morpheus/cli/commands/library_container_scripts_command.rb +14 -0
- data/lib/morpheus/cli/commands/library_container_templates_command.rb +131 -48
- data/lib/morpheus/cli/commands/library_container_types_command.rb +17 -4
- data/lib/morpheus/cli/commands/library_instance_types_command.rb +85 -7
- data/lib/morpheus/cli/commands/library_layouts_command.rb +32 -1
- data/lib/morpheus/cli/commands/library_option_lists_command.rb +30 -18
- data/lib/morpheus/cli/commands/library_option_types_command.rb +31 -14
- data/lib/morpheus/cli/commands/library_spec_templates_command.rb +14 -0
- data/lib/morpheus/cli/commands/library_upgrades_command.rb +2 -2
- data/lib/morpheus/cli/commands/network_pool_server_types.rb +20 -0
- data/lib/morpheus/cli/commands/network_pool_servers_command.rb +55 -158
- data/lib/morpheus/cli/commands/network_pools_command.rb +49 -23
- data/lib/morpheus/cli/commands/networks_command.rb +262 -45
- data/lib/morpheus/cli/commands/plugins.rb +213 -0
- data/lib/morpheus/cli/commands/price_sets_command.rb +40 -10
- data/lib/morpheus/cli/commands/prices_command.rb +17 -5
- data/lib/morpheus/cli/commands/processes_command.rb +2 -1
- data/lib/morpheus/cli/commands/remote.rb +7 -10
- data/lib/morpheus/cli/commands/roles.rb +924 -335
- data/lib/morpheus/cli/commands/search_command.rb +2 -0
- data/lib/morpheus/cli/commands/security_groups.rb +72 -84
- data/lib/morpheus/cli/commands/security_package_types.rb +32 -0
- data/lib/morpheus/cli/commands/security_packages.rb +84 -0
- data/lib/morpheus/cli/commands/security_scans.rb +107 -0
- data/lib/morpheus/cli/commands/service_plans_command.rb +16 -14
- data/lib/morpheus/cli/commands/subnets_command.rb +15 -1
- data/lib/morpheus/cli/commands/tasks.rb +34 -1
- data/lib/morpheus/cli/commands/tenants_command.rb +1 -1
- data/lib/morpheus/cli/commands/user_settings_command.rb +11 -2
- data/lib/morpheus/cli/commands/users.rb +50 -9
- data/lib/morpheus/cli/commands/virtual_images.rb +14 -0
- data/lib/morpheus/cli/commands/workflows.rb +14 -0
- data/lib/morpheus/cli/mixins/accounts_helper.rb +6 -5
- data/lib/morpheus/cli/mixins/infrastructure_helper.rb +79 -0
- data/lib/morpheus/cli/mixins/jobs_helper.rb +4 -5
- data/lib/morpheus/cli/mixins/library_helper.rb +2 -0
- data/lib/morpheus/cli/mixins/logs_helper.rb +3 -0
- data/lib/morpheus/cli/mixins/monitoring_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/print_helper.rb +29 -4
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +38 -9
- data/lib/morpheus/cli/mixins/rest_command.rb +106 -8
- data/lib/morpheus/cli/mixins/secondary_rest_command.rb +6 -2
- data/lib/morpheus/cli/option_types.rb +94 -25
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/formatters.rb +10 -1
- metadata +15 -2
|
@@ -18,6 +18,7 @@ class Morpheus::Cli::SecurityGroups
|
|
|
18
18
|
@options_interface = @api_client.options
|
|
19
19
|
@active_security_group = ::Morpheus::Cli::SecurityGroups.load_security_group_file
|
|
20
20
|
@network_security_servers = @api_client.network_security_servers
|
|
21
|
+
@network_servers = @api_client.network_servers
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
def handle(args)
|
|
@@ -26,57 +27,35 @@ class Morpheus::Cli::SecurityGroups
|
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
def list(args)
|
|
30
|
+
params = {}
|
|
29
31
|
options = {}
|
|
30
32
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
31
33
|
opts.banner = subcommand_usage()
|
|
32
|
-
|
|
34
|
+
build_standard_list_options(opts, options)
|
|
33
35
|
opts.footer = "List security groups."
|
|
34
36
|
end
|
|
35
37
|
optparse.parse!(args)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
# verify_args!(args:args, optparse:optparse, count:0)
|
|
39
|
+
if args.count > 0
|
|
40
|
+
options[:phrase] = args.join(" ")
|
|
38
41
|
end
|
|
39
42
|
connect(options)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
@security_groups_interface.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
render_result = render_with_format(json_response, options, 'securityGroups')
|
|
51
|
-
return 0 if render_result
|
|
52
|
-
|
|
43
|
+
params.merge!(parse_list_options(options))
|
|
44
|
+
@security_groups_interface.setopts(options)
|
|
45
|
+
if options[:dry_run]
|
|
46
|
+
print_dry_run @security_groups_interface.dry.list(params)
|
|
47
|
+
return
|
|
48
|
+
end
|
|
49
|
+
json_response = @security_groups_interface.list(params)
|
|
50
|
+
render_response(json_response, options, "securityGroups") do
|
|
51
|
+
security_groups = json_response['securityGroups']
|
|
53
52
|
title = "Morpheus Security Groups"
|
|
54
53
|
subtitles = []
|
|
55
54
|
subtitles += parse_list_subtitles(options)
|
|
56
|
-
print_h1 title, subtitles
|
|
57
|
-
|
|
58
|
-
security_groups = json_response['securityGroups']
|
|
59
|
-
|
|
55
|
+
print_h1 title, subtitles, options
|
|
60
56
|
if security_groups.empty?
|
|
61
57
|
print cyan,"No security groups found.",reset,"\n"
|
|
62
58
|
else
|
|
63
|
-
active_id = @active_security_group[@appliance_name.to_sym]
|
|
64
|
-
# table_color = options[:color] || cyan
|
|
65
|
-
# rows = security_groups.collect do |security_group|
|
|
66
|
-
# {
|
|
67
|
-
# id: security_group['id'].to_s + ((security_group['id'] == active_id.to_i) ? " (active)" : ""),
|
|
68
|
-
# name: security_group['name'],
|
|
69
|
-
# description: security_group['description']
|
|
70
|
-
# }
|
|
71
|
-
# end
|
|
72
|
-
|
|
73
|
-
# columns = [
|
|
74
|
-
# :id,
|
|
75
|
-
# :name,
|
|
76
|
-
# :description,
|
|
77
|
-
# # :ports,
|
|
78
|
-
# # :status,
|
|
79
|
-
# ]
|
|
80
59
|
columns = {
|
|
81
60
|
"ID" => 'id',
|
|
82
61
|
"NAME" => 'name',
|
|
@@ -86,25 +65,12 @@ class Morpheus::Cli::SecurityGroups
|
|
|
86
65
|
"SCOPED CLOUD" => lambda {|it| it['zone'] ? it['zone']['name'] : 'All' },
|
|
87
66
|
"SOURCE" => lambda {|it| it['syncSource'] == 'external' ? 'SYNCED' : 'CREATED' }
|
|
88
67
|
}
|
|
89
|
-
# custom pretty table columns ...
|
|
90
|
-
if options[:include_fields]
|
|
91
|
-
columns = options[:include_fields]
|
|
92
|
-
end
|
|
93
68
|
print as_pretty_table(security_groups, columns, options)
|
|
94
|
-
|
|
95
|
-
if json_response['meta']
|
|
96
|
-
print_results_pagination(json_response)
|
|
97
|
-
else
|
|
98
|
-
print_results_pagination({'meta'=>{'total'=>(json_response['securityGroupCount'] ? json_response['securityGroupCount'] : security_groups.size),'size'=>security_groups.size,'max'=>(params['max']||25),'offset'=>(params['offset']||0)}})
|
|
99
|
-
end
|
|
100
|
-
# print reset
|
|
69
|
+
print_results_pagination(json_response)
|
|
101
70
|
end
|
|
102
71
|
print reset,"\n"
|
|
103
|
-
return 0
|
|
104
|
-
rescue RestClient::Exception => e
|
|
105
|
-
print_rest_exception(e, options)
|
|
106
|
-
exit 1
|
|
107
72
|
end
|
|
73
|
+
return 0, nil
|
|
108
74
|
end
|
|
109
75
|
|
|
110
76
|
def get(args)
|
|
@@ -356,6 +322,7 @@ class Morpheus::Cli::SecurityGroups
|
|
|
356
322
|
payload['securityGroup']['zoneId'] = v_prompt['zoneId']
|
|
357
323
|
|
|
358
324
|
zone = find_cloud_by_id(payload['securityGroup']['zoneId'])
|
|
325
|
+
# networkServer needed here too? err
|
|
359
326
|
if zone['securityServer']
|
|
360
327
|
sec_server = @network_security_servers.get(zone['securityServer']['id'])['networkSecurityServer']
|
|
361
328
|
|
|
@@ -613,27 +580,12 @@ class Morpheus::Cli::SecurityGroups
|
|
|
613
580
|
"[security-group] is required. This is the name or id of the security group."
|
|
614
581
|
end
|
|
615
582
|
optparse.parse!(args)
|
|
616
|
-
|
|
617
|
-
raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
|
|
618
|
-
end
|
|
583
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
619
584
|
connect(options)
|
|
620
585
|
begin
|
|
621
586
|
security_group = find_security_group_by_name_or_id(args[0])
|
|
622
587
|
return 1 if security_group.nil?
|
|
623
588
|
|
|
624
|
-
# load cloud
|
|
625
|
-
if cloud_id.nil?
|
|
626
|
-
puts_error "#{Morpheus::Terminal.angry_prompt}missing required option: [cloud]\n#{optparse}"
|
|
627
|
-
return 1
|
|
628
|
-
end
|
|
629
|
-
cloud = find_cloud_by_name_or_id(cloud_id)
|
|
630
|
-
return 1 if cloud.nil?
|
|
631
|
-
|
|
632
|
-
if resource_pool_id
|
|
633
|
-
resource_pool = find_resource_pool_by_name_or_id(cloud['id'], resource_pool_id)
|
|
634
|
-
return 1 if resource_pool.nil?
|
|
635
|
-
end
|
|
636
|
-
|
|
637
589
|
# construct payload
|
|
638
590
|
passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
|
|
639
591
|
payload = nil
|
|
@@ -647,27 +599,63 @@ class Morpheus::Cli::SecurityGroups
|
|
|
647
599
|
}
|
|
648
600
|
}
|
|
649
601
|
payload.deep_merge!({'securityGroupLocation' => passed_options}) unless passed_options.empty?
|
|
650
|
-
|
|
651
|
-
|
|
602
|
+
|
|
603
|
+
cloud = nil
|
|
604
|
+
if cloud_id
|
|
605
|
+
options[:options]['zoneId'] = cloud_id
|
|
606
|
+
end
|
|
607
|
+
# Cloud prompt
|
|
608
|
+
scoped_clouds = []
|
|
609
|
+
clouds_response = @options_interface.options_for_source('cloudsForSecurityGroup',{securityGroupId: security_group['id']})
|
|
610
|
+
if clouds_response['data']
|
|
611
|
+
clouds_response['data'].each do |it|
|
|
612
|
+
scoped_clouds << {"name" => it['name'], "value" => it['value']}
|
|
613
|
+
end
|
|
652
614
|
end
|
|
615
|
+
if scoped_clouds.empty?
|
|
616
|
+
raise_command_error("Security group has 0 available clouds for adding a location", args, optparse)
|
|
617
|
+
end
|
|
618
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'zoneId', 'fieldLabel' => 'Cloud', 'type' => 'select', 'selectOptions' => scoped_clouds, 'required' => true}], options[:options], @api_client)
|
|
619
|
+
payload['securityGroupLocation']['zoneId'] = v_prompt['zoneId']
|
|
620
|
+
cloud = find_cloud_by_id(payload['securityGroupLocation']['zoneId'])
|
|
621
|
+
return 1 if cloud.nil?
|
|
653
622
|
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
623
|
+
# parse --resource-pool
|
|
624
|
+
# if resource_pool_id
|
|
625
|
+
# resource_pool = find_resource_pool_by_name_or_id(cloud['id'], resource_pool_id)
|
|
626
|
+
# return 1 if resource_pool.nil?
|
|
627
|
+
# end
|
|
628
|
+
|
|
629
|
+
# Custom Options prompt
|
|
630
|
+
# securityServer is no longer used, it has been replaced by networkServer,
|
|
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})
|
|
667
655
|
end
|
|
668
656
|
end
|
|
657
|
+
payload['securityGroupLocation'].deep_merge!(custom_options_values)
|
|
669
658
|
end
|
|
670
|
-
|
|
671
659
|
@security_groups_interface.setopts(options)
|
|
672
660
|
if options[:dry_run]
|
|
673
661
|
print_dry_run @security_groups_interface.dry.create_location(security_group['id'], payload)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
|
2
|
+
|
|
3
|
+
class Morpheus::Cli::SecurityPackageTypesCommand
|
|
4
|
+
include Morpheus::Cli::CliCommand
|
|
5
|
+
include Morpheus::Cli::RestCommand
|
|
6
|
+
|
|
7
|
+
set_command_description "View security_package types"
|
|
8
|
+
set_command_name :'security-package-types'
|
|
9
|
+
register_subcommands :list, :get
|
|
10
|
+
|
|
11
|
+
# register_interfaces :security_package_types
|
|
12
|
+
|
|
13
|
+
protected
|
|
14
|
+
|
|
15
|
+
def security_package_type_list_column_definitions(options)
|
|
16
|
+
{
|
|
17
|
+
"ID" => 'id',
|
|
18
|
+
"Name" => 'name',
|
|
19
|
+
"Code" => 'code',
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def security_package_type_column_definitions(options)
|
|
24
|
+
{
|
|
25
|
+
"ID" => 'id',
|
|
26
|
+
"Name" => 'name',
|
|
27
|
+
"Code" => 'code',
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
|
2
|
+
|
|
3
|
+
class Morpheus::Cli::SecurityPackagesCommand
|
|
4
|
+
include Morpheus::Cli::CliCommand
|
|
5
|
+
include Morpheus::Cli::RestCommand
|
|
6
|
+
|
|
7
|
+
set_command_name :'security-packages'
|
|
8
|
+
set_command_description "View and manage security packages."
|
|
9
|
+
register_subcommands :list, :get, :add, :update, :remove
|
|
10
|
+
|
|
11
|
+
# RestCommand settings
|
|
12
|
+
register_interfaces :security_packages, :security_package_types
|
|
13
|
+
set_rest_has_type true
|
|
14
|
+
# set_rest_type :security_package_types
|
|
15
|
+
|
|
16
|
+
protected
|
|
17
|
+
|
|
18
|
+
def build_list_options(opts, options, params)
|
|
19
|
+
opts.on('-l', '--labels LABEL', String, "Filter by labels, can match any of the values") do |val|
|
|
20
|
+
add_query_parameter(params, 'labels', parse_labels(val))
|
|
21
|
+
end
|
|
22
|
+
opts.on('--all-labels LABEL', String, "Filter by labels, must match all of the values") do |val|
|
|
23
|
+
add_query_parameter(params, 'allLabels', parse_labels(val))
|
|
24
|
+
end
|
|
25
|
+
# build_standard_list_options(opts, options)
|
|
26
|
+
super
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def security_package_list_column_definitions(options)
|
|
30
|
+
{
|
|
31
|
+
"ID" => 'id',
|
|
32
|
+
"Name" => 'name',
|
|
33
|
+
"Labels" => lambda {|it| format_list(it['labels'], '', 3) rescue '' },
|
|
34
|
+
"Type" => lambda {|it| it['type'] ? it['type']['name'] : '' },
|
|
35
|
+
"Description" => 'description',
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def security_package_column_definitions(options)
|
|
40
|
+
{
|
|
41
|
+
"ID" => 'id',
|
|
42
|
+
"Name" => 'name',
|
|
43
|
+
"Labels" => lambda {|it| format_list(it['labels'], '', 3) rescue '' },
|
|
44
|
+
"Type" => lambda {|it| it['type'] ? it['type']['name'] : '' },
|
|
45
|
+
"Description" => 'description',
|
|
46
|
+
"Enabled" => lambda {|it| format_boolean(it['enabled']) },
|
|
47
|
+
# "Source" => 'sourceType',
|
|
48
|
+
"URL" => 'url',
|
|
49
|
+
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
|
50
|
+
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
|
|
51
|
+
}
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def add_security_package_option_types()
|
|
55
|
+
[
|
|
56
|
+
{'shorthand' => '-t', 'fieldName' => 'type', 'fieldLabel' => 'Security Package Type', 'type' => 'select', 'optionSource' => lambda {|api_client, api_params|
|
|
57
|
+
api_client.security_package_types.list({max:10000})['securityPackageTypes'].collect { |it| {"name" => it["name"], "value" => it["code"]} }
|
|
58
|
+
}, 'required' => true, 'defaultValue' => 'SCAP Package'},
|
|
59
|
+
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true},
|
|
60
|
+
{'shorthand' => '-l', 'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text', 'required' => false, 'noPrompt' => true, 'processValue' => lambda {|val| parse_labels(val) }},
|
|
61
|
+
{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false},
|
|
62
|
+
{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'required' => false, 'defaultValue' => true},
|
|
63
|
+
# {'code' => 'securityPackage.sourceType', 'fieldName' => 'sourceType', 'fieldLabel' => 'Source', 'type' => 'select', 'selectOptions' => [{'name'=>'url','value'=>'url'}], 'defaultValue' => 'url', 'required' => true},
|
|
64
|
+
# {'code' => 'securityPackage.sourceType', 'fieldContext' => 'file', 'fieldName' => 'sourceType', 'fieldLabel' => 'Source', 'type' => 'hidden', 'defaultValue' => 'url', 'required' => true},
|
|
65
|
+
{'fieldName' => 'url', 'fieldLabel' => 'URL', 'type' => 'text', 'required' => true, 'description' => "URL to download the security package zip file from"},
|
|
66
|
+
# {'fieldName' => 'file', 'fieldLabel' => 'File Content', 'type' => 'file-content', 'required' => true},
|
|
67
|
+
]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def add_security_package_advanced_option_types()
|
|
71
|
+
[]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def update_security_package_option_types()
|
|
75
|
+
option_types = add_security_package_option_types.collect {|it| it.delete('required'); it.delete('defaultValue'); it.delete('dependsOnCode'); it }
|
|
76
|
+
option_types.reject! {|it| it['fieldName'] == 'type' }
|
|
77
|
+
option_types
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def update_security_package_advanced_option_types()
|
|
81
|
+
add_security_package_advanced_option_types().collect {|it| it.delete('required'); it.delete('defaultValue'); it.delete('dependsOnCode'); it }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
|
2
|
+
|
|
3
|
+
class Morpheus::Cli::SecurityScansCommand
|
|
4
|
+
include Morpheus::Cli::CliCommand
|
|
5
|
+
include Morpheus::Cli::RestCommand
|
|
6
|
+
|
|
7
|
+
set_command_name :'security-scans'
|
|
8
|
+
set_command_description "View and manage security scans."
|
|
9
|
+
register_subcommands :list, :get, :remove
|
|
10
|
+
|
|
11
|
+
# RestCommand settings
|
|
12
|
+
register_interfaces :security_scans,
|
|
13
|
+
:security_packages, :servers
|
|
14
|
+
|
|
15
|
+
# display argument as [id] since name is not supported
|
|
16
|
+
set_rest_has_name false
|
|
17
|
+
set_rest_arg "id"
|
|
18
|
+
|
|
19
|
+
protected
|
|
20
|
+
|
|
21
|
+
def build_list_options(opts, options, params)
|
|
22
|
+
opts.on('--security-package PACKAGE', String, "Filter by security package name or id") do |val|
|
|
23
|
+
options[:security_package] ||= []
|
|
24
|
+
options[:security_package] << val
|
|
25
|
+
end
|
|
26
|
+
opts.on('--server SERVER', String, "Filter by server name or id") do |val|
|
|
27
|
+
options[:server] ||= []
|
|
28
|
+
options[:server] << val
|
|
29
|
+
end
|
|
30
|
+
opts.on('--results', "Include the results object in the response under each security scan. This is a potentially very large object containing the raw results of the scan. Use with --json to see this data.") do
|
|
31
|
+
params['results'] = true
|
|
32
|
+
end
|
|
33
|
+
super
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def parse_list_options!(args, options, params)
|
|
37
|
+
# parse --security-package
|
|
38
|
+
# todo: one liner with find_by_name_or_id!
|
|
39
|
+
if options[:security_package]
|
|
40
|
+
params['securityPackageId'] = options[:security_package].collect do |val|
|
|
41
|
+
record = find_by_name_or_id(:security_package, val)
|
|
42
|
+
if record.nil?
|
|
43
|
+
exit 1 #return 1, "Security Package not found by '#{val}'"
|
|
44
|
+
else
|
|
45
|
+
record['id']
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
# parse --server
|
|
50
|
+
if options[:server]
|
|
51
|
+
params['serverId'] = options[:server].collect do |val|
|
|
52
|
+
record = find_by_name_or_id(:server, val)
|
|
53
|
+
if record.nil?
|
|
54
|
+
exit 1 # return 1, "Server not found by '#{val}'"
|
|
55
|
+
else
|
|
56
|
+
record['id']
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
super
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def build_get_options(opts, options, params)
|
|
64
|
+
opts.on('--results', "Include the results object in the response under the security scan. This is a potentially very large object containing the raw results of the scan. Use with --json to see this data.") do
|
|
65
|
+
params['results'] = true
|
|
66
|
+
end
|
|
67
|
+
super
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def security_scan_list_column_definitions(options)
|
|
71
|
+
{
|
|
72
|
+
"ID" => 'id',
|
|
73
|
+
"Security Package" => lambda {|it| it['securityPackage']['name'] rescue '' },
|
|
74
|
+
"Type" => lambda {|it| it['securityPackage']['type']['name'] rescue '' },
|
|
75
|
+
"Server" => lambda {|it| it['server']['name'] rescue '' },
|
|
76
|
+
"Scan Date" => lambda {|it| format_local_dt(it['scanDate']) },
|
|
77
|
+
"Status" => lambda {|it| it['status'] },
|
|
78
|
+
"Score" => lambda {|it| it['scanScore'] },
|
|
79
|
+
"Results" => lambda {|it| format_security_scan_results_summary(it) },
|
|
80
|
+
|
|
81
|
+
}
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def security_scan_column_definitions(options)
|
|
85
|
+
{
|
|
86
|
+
"ID" => 'id',
|
|
87
|
+
"Security Package" => lambda {|it| it['securityPackage']['name'] rescue '' },
|
|
88
|
+
"Type" => lambda {|it| it['securityPackage']['type']['name'] rescue '' },
|
|
89
|
+
"Server" => lambda {|it| it['server']['name'] rescue '' },
|
|
90
|
+
"Scan Date" => lambda {|it| format_local_dt(it['scanDate']) },
|
|
91
|
+
"Status" => lambda {|it| it['status'] },
|
|
92
|
+
"Score" => lambda {|it| it['scanScore'] },
|
|
93
|
+
"Results" => lambda {|it| format_security_scan_results_summary(it) },
|
|
94
|
+
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
|
95
|
+
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
|
|
96
|
+
}
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def format_security_scan_results_summary(security_scan)
|
|
100
|
+
totals = []
|
|
101
|
+
totals << "Run: #{security_scan['runCount']}" # if security_scan['runCount'].to_i > 0
|
|
102
|
+
totals << "Pass: #{security_scan['passCount']}" if security_scan['passCount'].to_i > 0
|
|
103
|
+
totals << "Fail: #{security_scan['failCount']}" if security_scan['failCount'].to_i > 0
|
|
104
|
+
totals << "Warn: #{security_scan['runCount']}" if security_scan['otherCount'].to_i > 0
|
|
105
|
+
totals.join(", ")
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -249,12 +249,12 @@ class Morpheus::Cli::ServicePlanCommand
|
|
|
249
249
|
params['editable'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
|
|
250
250
|
end
|
|
251
251
|
opts.on('--storage [AMOUNT]', String, "Storage size is required. Assumes GB unless optional modifier specified, ex: 512MB" ) do |val|
|
|
252
|
-
bytes = parse_bytes_param(val, '--storage', 'GB')
|
|
252
|
+
bytes = parse_bytes_param(val, '--storage', 'GB', true)
|
|
253
253
|
params['maxStorage'] = bytes[:bytes]
|
|
254
254
|
(params['config'] ||= {})['storageSizeType'] = bytes[:unit].downcase
|
|
255
255
|
end
|
|
256
256
|
opts.on('--memory [AMOUNT]', String, "Memory size is required. Assumes MB unless optional modifier specified, ex: 1GB" ) do |val|
|
|
257
|
-
bytes = parse_bytes_param(val, '--memory', 'MB')
|
|
257
|
+
bytes = parse_bytes_param(val, '--memory', 'MB', true)
|
|
258
258
|
params['maxMemory'] = bytes[:bytes]
|
|
259
259
|
(params['config'] ||= {})['memorySizeType'] = bytes[:unit].downcase
|
|
260
260
|
end
|
|
@@ -287,25 +287,25 @@ class Morpheus::Cli::ServicePlanCommand
|
|
|
287
287
|
end
|
|
288
288
|
opts.on('--min-storage NUMBER', String, "Min storage. Assumes GB unless optional modifier specified, ex: 512MB") do |val|
|
|
289
289
|
# Storage doesn't get converted to bytes
|
|
290
|
-
bytes = parse_bytes_param(val, '--min-storage', 'GB')
|
|
290
|
+
bytes = parse_bytes_param(val, '--min-storage', 'GB', true)
|
|
291
291
|
((params['config'] ||= {})['ranges'] ||= {})['minStorage'] = bytes[:number]
|
|
292
292
|
(params['config'] ||= {})['storageSizeType'] = bytes[:unit].downcase
|
|
293
293
|
end
|
|
294
294
|
opts.on('--max-storage NUMBER', String, "Max storage. Assumes GB unless optional modifier specified, ex: 512MB") do |val|
|
|
295
295
|
# Storage doesn't get converted to bytes
|
|
296
|
-
bytes = parse_bytes_param(val, '--max-storage', 'GB')
|
|
296
|
+
bytes = parse_bytes_param(val.to_s, '--max-storage', 'GB', true)
|
|
297
297
|
((params['config'] ||= {})['ranges'] ||= {})['maxStorage'] = bytes[:number]
|
|
298
298
|
(params['config'] ||= {})['storageSizeType'] = bytes[:unit].downcase
|
|
299
299
|
end
|
|
300
300
|
opts.on('--min-memory NUMBER', String, "Min memory. Assumes MB unless optional modifier specified, ex: 1GB") do |val|
|
|
301
301
|
# Memory does get converted to bytes
|
|
302
|
-
bytes = parse_bytes_param(val, '--min-memory', 'MB')
|
|
302
|
+
bytes = parse_bytes_param(val, '--min-memory', 'MB', true)
|
|
303
303
|
((params['config'] ||= {})['ranges'] ||= {})['minMemory'] = bytes[:bytes]
|
|
304
304
|
(params['config'] ||= {})['memorySizeType'] = bytes[:unit].downcase
|
|
305
305
|
end
|
|
306
306
|
opts.on('--max-memory NUMBER', String, "Max memory. Assumes MB unless optional modifier specified, ex: 1GB") do |val|
|
|
307
307
|
# Memory does get converted to bytes
|
|
308
|
-
bytes = parse_bytes_param(val, '--max-memory', 'MB')
|
|
308
|
+
bytes = parse_bytes_param(val, '--max-memory', 'MB', true)
|
|
309
309
|
((params['config'] ||= {})['ranges'] ||= {})['maxMemory'] = bytes[:bytes]
|
|
310
310
|
(params['config'] ||= {})['memorySizeType'] = bytes[:unit].downcase
|
|
311
311
|
end
|
|
@@ -368,9 +368,10 @@ class Morpheus::Cli::ServicePlanCommand
|
|
|
368
368
|
while params['maxStorage'].nil? do
|
|
369
369
|
begin
|
|
370
370
|
bytes = parse_bytes_param(
|
|
371
|
-
Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'storage', 'type' => 'text', 'fieldLabel' => 'Storage (GB) [can use MB modifier]', 'required' => true, 'description' => 'Storage (GB)'}],options[:options],@api_client,{}, options[:no_prompt])['storage'],
|
|
371
|
+
Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'storage', 'type' => 'text', 'fieldLabel' => 'Storage (GB) [can use MB modifier]', 'required' => true, 'description' => 'Storage (GB)', 'defaultValue' => '0'}],options[:options],@api_client,{}, options[:no_prompt])['storage'],
|
|
372
372
|
'storage',
|
|
373
|
-
'GB'
|
|
373
|
+
'GB',
|
|
374
|
+
true
|
|
374
375
|
)
|
|
375
376
|
params['maxStorage'] = bytes[:bytes]
|
|
376
377
|
# (params['config'] ||= {})['storageSizeType'] = bytes[:unit].downcase
|
|
@@ -389,9 +390,10 @@ class Morpheus::Cli::ServicePlanCommand
|
|
|
389
390
|
while params['maxMemory'].nil? do
|
|
390
391
|
begin
|
|
391
392
|
bytes = parse_bytes_param(
|
|
392
|
-
Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'memory', 'type' => 'text', 'fieldLabel' => 'Memory (MB) [can use GB modifier]', 'required' => true, 'description' => 'Memory (MB)'}],options[:options],@api_client,{}, options[:no_prompt])['memory'],
|
|
393
|
+
Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'memory', 'type' => 'text', 'fieldLabel' => 'Memory (MB) [can use GB modifier]', 'required' => true, 'description' => 'Memory (MB)', 'defaultValue' => '0'}],options[:options],@api_client,{}, options[:no_prompt])['memory'],
|
|
393
394
|
'memory',
|
|
394
|
-
'MB'
|
|
395
|
+
'MB',
|
|
396
|
+
true
|
|
395
397
|
)
|
|
396
398
|
params['maxMemory'] = bytes[:bytes]
|
|
397
399
|
# (params['config'] ||= {})['memorySizeType'] = bytes[:unit].downcase
|
|
@@ -479,12 +481,12 @@ class Morpheus::Cli::ServicePlanCommand
|
|
|
479
481
|
params['active'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
|
|
480
482
|
end
|
|
481
483
|
opts.on('--storage [AMOUNT]', String, "Storage size is required. Assumes GB unless optional modifier specified, ex: 512MB" ) do |val|
|
|
482
|
-
bytes = parse_bytes_param(val, '--storage', 'GB')
|
|
484
|
+
bytes = parse_bytes_param(val, '--storage', 'GB', true)
|
|
483
485
|
params['maxStorage'] = bytes[:bytes]
|
|
484
486
|
(params['config'] ||= {})['storageSizeType'] = bytes[:unit].downcase
|
|
485
487
|
end
|
|
486
488
|
opts.on('--memory [AMOUNT]', String, "Memory size is required. Assumes MB unless optional modifier specified, ex: 1GB" ) do |val|
|
|
487
|
-
bytes = parse_bytes_param(val, '--memory', 'MB')
|
|
489
|
+
bytes = parse_bytes_param(val, '--memory', 'MB', true)
|
|
488
490
|
params['maxMemory'] = bytes[:bytes]
|
|
489
491
|
(params['config'] ||= {})['memorySizeType'] = bytes[:unit].downcase
|
|
490
492
|
end
|
|
@@ -523,7 +525,7 @@ class Morpheus::Cli::ServicePlanCommand
|
|
|
523
525
|
end
|
|
524
526
|
opts.on('--max-storage NUMBER', String, "Max storage. Assumes GB unless optional modifier specified, ex: 512MB") do |val|
|
|
525
527
|
# Storage doesn't get converted to bytes
|
|
526
|
-
bytes = parse_bytes_param(val, '--max-storage', 'GB')
|
|
528
|
+
bytes = parse_bytes_param(val, '--max-storage', 'GB', true)
|
|
527
529
|
((params['config'] ||= {})['ranges'] ||= {})['maxStorage'] = bytes[:number]
|
|
528
530
|
(params['config'] ||= {})['storageSizeType'] = bytes[:unit].downcase
|
|
529
531
|
end
|
|
@@ -535,7 +537,7 @@ class Morpheus::Cli::ServicePlanCommand
|
|
|
535
537
|
end
|
|
536
538
|
opts.on('--max-memory NUMBER', String, "Max memory. Assumes MB unless optional modifier specified, ex: 1GB") do |val|
|
|
537
539
|
# Memory does get converted to bytes
|
|
538
|
-
bytes = parse_bytes_param(val, '--max-memory', 'MB')
|
|
540
|
+
bytes = parse_bytes_param(val, '--max-memory', 'MB', true)
|
|
539
541
|
((params['config'] ||= {})['ranges'] ||= {})['maxMemory'] = bytes[:bytes]
|
|
540
542
|
(params['config'] ||= {})['memorySizeType'] = bytes[:unit].downcase
|
|
541
543
|
end
|
|
@@ -44,11 +44,17 @@ class Morpheus::Cli::SubnetsCommand
|
|
|
44
44
|
opts.on( '--network NETWORK', '--network NETWORK', "Filter by Network" ) do |val|
|
|
45
45
|
options[:network] = val
|
|
46
46
|
end
|
|
47
|
+
opts.on('-l', '--labels LABEL', String, "Filter by labels, can match any of the values") do |val|
|
|
48
|
+
add_query_parameter(params, 'labels', parse_labels(val))
|
|
49
|
+
end
|
|
50
|
+
opts.on('--all-labels LABEL', String, "Filter by labels, must match all of the values") do |val|
|
|
51
|
+
add_query_parameter(params, 'allLabels', parse_labels(val))
|
|
52
|
+
end
|
|
47
53
|
opts.footer = "List subnets."
|
|
48
54
|
end
|
|
49
55
|
optparse.parse!(args)
|
|
50
56
|
if args.count > 0
|
|
51
|
-
|
|
57
|
+
options[:phrase] = args.join(" ")
|
|
52
58
|
end
|
|
53
59
|
connect(options)
|
|
54
60
|
|
|
@@ -103,6 +109,7 @@ class Morpheus::Cli::SubnetsCommand
|
|
|
103
109
|
subnet_columns = {
|
|
104
110
|
"ID" => 'id',
|
|
105
111
|
"Name" => 'name',
|
|
112
|
+
"Labels" => lambda {|it| format_list(it['labels'], '', 3) },
|
|
106
113
|
#"Description" => 'description',
|
|
107
114
|
"Network" => lambda {|it| it['network']['name'] rescue it['network'] },
|
|
108
115
|
"Type" => lambda {|it| it['type']['name'] rescue it['type'] },
|
|
@@ -170,6 +177,7 @@ class Morpheus::Cli::SubnetsCommand
|
|
|
170
177
|
description_cols = {
|
|
171
178
|
"ID" => 'id',
|
|
172
179
|
"Name" => 'name',
|
|
180
|
+
"Labels" => lambda {|it| format_list(it['labels']) },
|
|
173
181
|
"Description" => 'description',
|
|
174
182
|
"Type" => lambda {|it| it['type'] ? it['type']['name'] : '' },
|
|
175
183
|
"Network" => lambda {|it| subnet['network']['name'] rescue subnet['network'] },
|
|
@@ -239,6 +247,9 @@ class Morpheus::Cli::SubnetsCommand
|
|
|
239
247
|
# fill in silly names that vary by type
|
|
240
248
|
options[:options].deep_merge!({'config' => {'subnetName' => val}})
|
|
241
249
|
end
|
|
250
|
+
opts.on('-l', '--labels [LIST]', String, "Labels") do |val|
|
|
251
|
+
options[:options]['labels'] = parse_labels(val)
|
|
252
|
+
end
|
|
242
253
|
opts.on('--cidr VALUE', String, "Name for this subnet") do |val|
|
|
243
254
|
options[:options]['cidr'] = val
|
|
244
255
|
# fill in silly names that vary by type
|
|
@@ -466,6 +477,9 @@ class Morpheus::Cli::SubnetsCommand
|
|
|
466
477
|
group_defaults_list = nil
|
|
467
478
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
468
479
|
opts.banner = subcommand_usage("[subnet]")
|
|
480
|
+
opts.on('-l', '--labels [LIST]', String, "Labels") do |val|
|
|
481
|
+
options[:options]['labels'] = parse_labels(val)
|
|
482
|
+
end
|
|
469
483
|
opts.on('--group-access-all [on|off]', String, "Toggle Access for all groups.") do |val|
|
|
470
484
|
group_access_all = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
|
|
471
485
|
end
|