morpheus-cli 5.5.1.4 → 5.5.2
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/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
|