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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +25 -0
  4. data/lib/morpheus/api/archive_buckets_interface.rb +1 -1
  5. data/lib/morpheus/api/body_io.rb +22 -0
  6. data/lib/morpheus/api/catalog_item_types_interface.rb +5 -1
  7. data/lib/morpheus/api/clients_interface.rb +41 -0
  8. data/lib/morpheus/api/clouds_interface.rb +21 -0
  9. data/lib/morpheus/api/instances_interface.rb +8 -1
  10. data/lib/morpheus/api/integrations_interface.rb +30 -0
  11. data/lib/morpheus/api/library_instance_types_interface.rb +15 -3
  12. data/lib/morpheus/api/network_pool_server_types_interface.rb +9 -0
  13. data/lib/morpheus/api/plugins_interface.rb +22 -0
  14. data/lib/morpheus/api/roles_interface.rb +20 -1
  15. data/lib/morpheus/api/security_package_types_interface.rb +9 -0
  16. data/lib/morpheus/api/security_packages_interface.rb +9 -0
  17. data/lib/morpheus/api/security_scans_interface.rb +9 -0
  18. data/lib/morpheus/api/servers_interface.rb +17 -17
  19. data/lib/morpheus/api/storage_providers_interface.rb +1 -1
  20. data/lib/morpheus/api/virtual_images_interface.rb +1 -23
  21. data/lib/morpheus/cli/cli_command.rb +81 -7
  22. data/lib/morpheus/cli/commands/apps.rb +28 -2
  23. data/lib/morpheus/cli/commands/archives_command.rb +2 -2
  24. data/lib/morpheus/cli/commands/blueprints_command.rb +16 -0
  25. data/lib/morpheus/cli/commands/catalog_item_types_command.rb +34 -2
  26. data/lib/morpheus/cli/commands/clients_command.rb +338 -0
  27. data/lib/morpheus/cli/commands/clouds.rb +127 -1
  28. data/lib/morpheus/cli/commands/clusters.rb +42 -12
  29. data/lib/morpheus/cli/commands/curl_command.rb +114 -135
  30. data/lib/morpheus/cli/commands/hosts.rb +108 -11
  31. data/lib/morpheus/cli/commands/instances.rb +115 -14
  32. data/lib/morpheus/cli/commands/integrations_command.rb +215 -4
  33. data/lib/morpheus/cli/commands/invoices_command.rb +20 -11
  34. data/lib/morpheus/cli/commands/jobs_command.rb +299 -190
  35. data/lib/morpheus/cli/commands/library_cluster_layouts_command.rb +16 -2
  36. data/lib/morpheus/cli/commands/library_container_scripts_command.rb +14 -0
  37. data/lib/morpheus/cli/commands/library_container_templates_command.rb +131 -48
  38. data/lib/morpheus/cli/commands/library_container_types_command.rb +17 -4
  39. data/lib/morpheus/cli/commands/library_instance_types_command.rb +85 -7
  40. data/lib/morpheus/cli/commands/library_layouts_command.rb +32 -1
  41. data/lib/morpheus/cli/commands/library_option_lists_command.rb +30 -18
  42. data/lib/morpheus/cli/commands/library_option_types_command.rb +31 -14
  43. data/lib/morpheus/cli/commands/library_spec_templates_command.rb +14 -0
  44. data/lib/morpheus/cli/commands/library_upgrades_command.rb +2 -2
  45. data/lib/morpheus/cli/commands/network_pool_server_types.rb +20 -0
  46. data/lib/morpheus/cli/commands/network_pool_servers_command.rb +55 -158
  47. data/lib/morpheus/cli/commands/network_pools_command.rb +49 -23
  48. data/lib/morpheus/cli/commands/networks_command.rb +262 -45
  49. data/lib/morpheus/cli/commands/plugins.rb +213 -0
  50. data/lib/morpheus/cli/commands/price_sets_command.rb +40 -10
  51. data/lib/morpheus/cli/commands/prices_command.rb +17 -5
  52. data/lib/morpheus/cli/commands/processes_command.rb +2 -1
  53. data/lib/morpheus/cli/commands/remote.rb +7 -10
  54. data/lib/morpheus/cli/commands/roles.rb +924 -335
  55. data/lib/morpheus/cli/commands/search_command.rb +2 -0
  56. data/lib/morpheus/cli/commands/security_groups.rb +72 -84
  57. data/lib/morpheus/cli/commands/security_package_types.rb +32 -0
  58. data/lib/morpheus/cli/commands/security_packages.rb +84 -0
  59. data/lib/morpheus/cli/commands/security_scans.rb +107 -0
  60. data/lib/morpheus/cli/commands/service_plans_command.rb +16 -14
  61. data/lib/morpheus/cli/commands/subnets_command.rb +15 -1
  62. data/lib/morpheus/cli/commands/tasks.rb +34 -1
  63. data/lib/morpheus/cli/commands/tenants_command.rb +1 -1
  64. data/lib/morpheus/cli/commands/user_settings_command.rb +11 -2
  65. data/lib/morpheus/cli/commands/users.rb +50 -9
  66. data/lib/morpheus/cli/commands/virtual_images.rb +14 -0
  67. data/lib/morpheus/cli/commands/workflows.rb +14 -0
  68. data/lib/morpheus/cli/mixins/accounts_helper.rb +6 -5
  69. data/lib/morpheus/cli/mixins/infrastructure_helper.rb +79 -0
  70. data/lib/morpheus/cli/mixins/jobs_helper.rb +4 -5
  71. data/lib/morpheus/cli/mixins/library_helper.rb +2 -0
  72. data/lib/morpheus/cli/mixins/logs_helper.rb +3 -0
  73. data/lib/morpheus/cli/mixins/monitoring_helper.rb +1 -1
  74. data/lib/morpheus/cli/mixins/print_helper.rb +29 -4
  75. data/lib/morpheus/cli/mixins/provisioning_helper.rb +38 -9
  76. data/lib/morpheus/cli/mixins/rest_command.rb +106 -8
  77. data/lib/morpheus/cli/mixins/secondary_rest_command.rb +6 -2
  78. data/lib/morpheus/cli/option_types.rb +94 -25
  79. data/lib/morpheus/cli/version.rb +1 -1
  80. data/lib/morpheus/formatters.rb +10 -1
  81. metadata +15 -2
@@ -173,6 +173,8 @@ EOT
173
173
  Morpheus::Cli::Roles
174
174
  when "wikipage","wiki"
175
175
  Morpheus::Cli::WikiCommand
176
+ when "clients"
177
+ Morpheus::Cli::ClientsCommand
176
178
  else
177
179
  nil
178
180
  end
@@ -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
- build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
34
+ build_standard_list_options(opts, options)
33
35
  opts.footer = "List security groups."
34
36
  end
35
37
  optparse.parse!(args)
36
- if args.count != 0
37
- raise_command_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
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
- begin
41
- params = {}
42
- params.merge!(parse_list_options(options))
43
- @security_groups_interface.setopts(options)
44
- if options[:dry_run]
45
- print_dry_run @security_groups_interface.dry.list(params)
46
- return
47
- end
48
- json_response = @security_groups_interface.list(params)
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
- print reset
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
- if args.count != 1
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
- if cloud
651
- payload['securityGroupLocation']['zoneId'] = cloud['id']
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
- if cloud['securityServer']
655
- if cloud['securityServer']['type'] == 'amazon'
656
- if resource_pool
657
- payload['securityGroupLocation']['customOptions'] = {'vpc' => resource_pool['externalId']}
658
- elsif cloud['config'] && cloud['config']['vpc']
659
- payload['securityGroupLocation']['customOptions'] = {'vpc' => cloud['config']['vpc']}
660
- end
661
- elsif cloud['securityServer']['type'] == 'azure'
662
- if resource_pool
663
- payload['securityGroupLocation']['customOptions'] = {'resourceGroup' => resource_pool['externalId']}
664
- elsif cloud['config'] && cloud['config']['resourceGroup']
665
- payload['securityGroupLocation']['customOptions'] = {'resourceGroup' => cloud['config']['resourceGroup']}
666
- end
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
- raise_command_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args}\n#{optparse}"
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