morpheus-cli 5.5.1.5 → 5.5.2

Sign up to get free protection for your applications and to get access to all the features.
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 +27 -8
  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