morpheus-cli 5.4.0 → 5.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/account_users_interface.rb +68 -0
  4. data/lib/morpheus/api/api_client.rb +51 -9
  5. data/lib/morpheus/api/audit_interface.rb +9 -0
  6. data/lib/morpheus/api/instances_interface.rb +21 -0
  7. data/lib/morpheus/api/load_balancer_monitors_interface.rb +9 -0
  8. data/lib/morpheus/api/load_balancer_pools_interface.rb +4 -4
  9. data/lib/morpheus/api/load_balancer_profiles_interface.rb +4 -5
  10. data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +13 -4
  11. data/lib/morpheus/api/load_balancers_interface.rb +5 -0
  12. data/lib/morpheus/api/network_routers_interface.rb +9 -0
  13. data/lib/morpheus/api/network_static_routes_interface.rb +36 -0
  14. data/lib/morpheus/api/read_interface.rb +4 -3
  15. data/lib/morpheus/api/rest_interface.rb +3 -3
  16. data/lib/morpheus/api/secondary_read_interface.rb +1 -1
  17. data/lib/morpheus/api/secondary_rest_interface.rb +19 -19
  18. data/lib/morpheus/api/storage_server_types_interface.rb +14 -0
  19. data/lib/morpheus/api/storage_servers_interface.rb +9 -0
  20. data/lib/morpheus/api/storage_volume_types_interface.rb +9 -0
  21. data/lib/morpheus/api/storage_volumes_interface.rb +9 -0
  22. data/lib/morpheus/api/users_interface.rb +16 -63
  23. data/lib/morpheus/cli/cli_command.rb +253 -5
  24. data/lib/morpheus/cli/cli_registry.rb +1 -1
  25. data/lib/morpheus/cli/commands/alias_command.rb +1 -1
  26. data/lib/morpheus/cli/commands/apps.rb +14 -78
  27. data/lib/morpheus/cli/commands/audit.rb +188 -0
  28. data/lib/morpheus/cli/commands/blueprints_command.rb +1 -1
  29. data/lib/morpheus/cli/commands/change_password_command.rb +4 -4
  30. data/lib/morpheus/cli/commands/clusters.rb +37 -12
  31. data/lib/morpheus/cli/commands/hosts.rb +15 -15
  32. data/lib/morpheus/cli/commands/instances.rb +109 -2
  33. data/lib/morpheus/cli/commands/load_balancer_monitors.rb +71 -0
  34. data/lib/morpheus/cli/commands/load_balancer_pools.rb +30 -50
  35. data/lib/morpheus/cli/commands/load_balancer_profiles.rb +65 -0
  36. data/lib/morpheus/cli/commands/load_balancer_types.rb +9 -4
  37. data/lib/morpheus/cli/commands/load_balancer_virtual_servers.rb +77 -57
  38. data/lib/morpheus/cli/commands/load_balancers.rb +93 -6
  39. data/lib/morpheus/cli/commands/network_firewalls_command.rb +22 -5
  40. data/lib/morpheus/cli/commands/network_routers_command.rb +96 -45
  41. data/lib/morpheus/cli/commands/network_static_routes_command.rb +446 -0
  42. data/lib/morpheus/cli/commands/network_transport_zones_command.rb +4 -4
  43. data/lib/morpheus/cli/commands/open_command.rb +30 -0
  44. data/lib/morpheus/cli/commands/options.rb +98 -0
  45. data/lib/morpheus/cli/commands/policies_command.rb +1 -1
  46. data/lib/morpheus/cli/commands/prices_command.rb +7 -7
  47. data/lib/morpheus/cli/commands/remote.rb +4 -2
  48. data/lib/morpheus/cli/commands/roles.rb +1 -1
  49. data/lib/morpheus/cli/commands/shell.rb +2 -2
  50. data/lib/morpheus/cli/commands/storage_server_types.rb +50 -0
  51. data/lib/morpheus/cli/commands/storage_servers.rb +122 -0
  52. data/lib/morpheus/cli/commands/storage_volume_types.rb +50 -0
  53. data/lib/morpheus/cli/commands/storage_volumes.rb +103 -0
  54. data/lib/morpheus/cli/commands/tenants_command.rb +1 -1
  55. data/lib/morpheus/cli/commands/user_groups_command.rb +1 -1
  56. data/lib/morpheus/cli/commands/user_settings_command.rb +2 -1
  57. data/lib/morpheus/cli/commands/user_sources_command.rb +1 -1
  58. data/lib/morpheus/cli/commands/users.rb +28 -28
  59. data/lib/morpheus/cli/commands/view.rb +102 -0
  60. data/lib/morpheus/cli/mixins/accounts_helper.rb +5 -5
  61. data/lib/morpheus/cli/mixins/load_balancers_helper.rb +24 -4
  62. data/lib/morpheus/cli/mixins/print_helper.rb +50 -18
  63. data/lib/morpheus/cli/mixins/processes_helper.rb +1 -2
  64. data/lib/morpheus/cli/mixins/provisioning_helper.rb +15 -5
  65. data/lib/morpheus/cli/mixins/rest_command.rb +145 -73
  66. data/lib/morpheus/cli/mixins/secondary_rest_command.rb +174 -81
  67. data/lib/morpheus/cli/mixins/storage_servers_helper.rb +156 -0
  68. data/lib/morpheus/cli/mixins/storage_volumes_helper.rb +119 -0
  69. data/lib/morpheus/cli/option_types.rb +45 -24
  70. data/lib/morpheus/cli/version.rb +1 -1
  71. data/lib/morpheus/cli.rb +1 -0
  72. data/lib/morpheus/ext/string.rb +29 -6
  73. data/lib/morpheus/routes.rb +238 -0
  74. data/lib/morpheus/util.rb +6 -1
  75. metadata +29 -8
@@ -3,31 +3,82 @@ require 'morpheus/cli/cli_command'
3
3
  class Morpheus::Cli::LoadBalancerVirtualServers
4
4
  include Morpheus::Cli::CliCommand
5
5
  include Morpheus::Cli::RestCommand
6
- # include Morpheus::Cli::SecondaryRestCommand
6
+ include Morpheus::Cli::SecondaryRestCommand
7
7
  include Morpheus::Cli::LoadBalancersHelper
8
8
 
9
- set_command_hidden # hide until ready
9
+ set_command_hidden
10
+ set_command_description "View and manage load balancer virtual servers."
10
11
  set_command_name :'load-balancer-virtual-servers'
11
12
  register_subcommands :list, :get, :add, :update, :remove
12
13
 
13
14
  register_interfaces :load_balancer_virtual_servers,
14
15
  :load_balancers, :load_balancer_types
15
16
 
16
- # set_rest_parent_name :load_balancers
17
-
18
- # set_rest_interface_name :load_balancer_virtual_servers
19
- # set_parent_rest_interface_name :load_balancers
20
-
21
- # todo: a configurable way to load the optionTypes
22
- # option_types = loadBalancer['vipOptionTypes']
23
- # set_rest_has_type true
24
- # set_rest_type :load_balancer_virtual_server_types
25
-
17
+ set_rest_parent_name :load_balancers
26
18
  set_rest_arg 'vipName'
27
19
 
20
+ # overridden to provide global list functionality without requiring parent argument
21
+ def list(args)
22
+ parent_id, parent_record = nil, nil
23
+ params = {}
24
+ options = {}
25
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
26
+ opts.banner = subcommand_usage("[#{rest_parent_arg}] [search]")
27
+ build_list_options(opts, options, params)
28
+ opts.footer = <<-EOT
29
+ List #{rest_label_plural.downcase}.
30
+ [#{rest_parent_arg}] is optional. This is the #{rest_parent_has_name ? 'name or id' : 'id'} of #{a_or_an(rest_parent_label)} #{rest_parent_label.downcase}.
31
+ [search] is optional. This is a search phrase to filter the results.
32
+ EOT
33
+ end
34
+ optparse.parse!(args)
35
+ parent_id = args[0]
36
+ connect(options)
37
+ if parent_id
38
+ args = args[1..-1]
39
+ parent_record = rest_parent_find_by_name_or_id(parent_id)
40
+ if parent_record.nil?
41
+ return 1, "#{rest_parent_label} not found for '#{parent_id}"
42
+ end
43
+ parent_id = parent_record['id']
44
+ end
45
+ parse_list_options!(args, options, params)
46
+ rest_interface.setopts(options)
47
+ if options[:dry_run]
48
+ print_dry_run rest_interface.dry.list(parent_id, params)
49
+ return
50
+ end
51
+ json_response = rest_interface.list(parent_id, params)
52
+ render_response(json_response, options, rest_list_key) do
53
+ records = json_response[rest_list_key]
54
+ print_h1 "Morpheus #{rest_label_plural}"
55
+ if records.nil? || records.empty?
56
+ print cyan,"No #{rest_label_plural.downcase} found.",reset,"\n"
57
+ else
58
+ print as_pretty_table(records, rest_list_column_definitions(options).upcase_keys!, options)
59
+ print_results_pagination(json_response) if json_response['meta']
60
+ end
61
+ print reset,"\n"
62
+ end
63
+ return 0, nil
64
+ end
65
+
28
66
  protected
29
67
 
30
- def load_balancer_virtual_server_list_column_definitions()
68
+ def build_list_options(opts, options, params)
69
+ opts.on('--load-balancer LB', String, "Load Balancer Name or ID") do |val|
70
+ options[:load_balancer] = val
71
+ end
72
+ # build_standard_list_options(opts, options)
73
+ super
74
+ end
75
+
76
+ def parse_list_options!(args, options, params)
77
+ parse_parameter_as_resource_id!(:load_balancer, options, params)
78
+ super
79
+ end
80
+
81
+ def load_balancer_virtual_server_list_column_definitions(options)
31
82
  {
32
83
  "ID" => 'id',
33
84
  "Name" => 'vipName',
@@ -43,7 +94,7 @@ class Morpheus::Cli::LoadBalancerVirtualServers
43
94
  }
44
95
  end
45
96
 
46
- def load_balancer_virtual_server_column_definitions()
97
+ def load_balancer_virtual_server_column_definitions(options)
47
98
  {
48
99
  "ID" => 'id',
49
100
  "Name" => 'vipName',
@@ -63,11 +114,11 @@ class Morpheus::Cli::LoadBalancerVirtualServers
63
114
  end
64
115
 
65
116
  def load_balancer_virtual_server_object_key
66
- 'virtualServer'
117
+ 'loadBalancerInstance'
67
118
  end
68
119
 
69
120
  def load_balancer_virtual_server_list_key
70
- 'virtualServers'
121
+ 'loadBalancerInstances'
71
122
  end
72
123
 
73
124
  def load_balancer_virtual_server_label
@@ -78,52 +129,12 @@ class Morpheus::Cli::LoadBalancerVirtualServers
78
129
  'Virtual Servers'
79
130
  end
80
131
 
81
- def find_load_balancer_virtual_server_by_name_or_id(val)
82
- if val.to_s =~ /\A\d{1,}\Z/
83
- return find_load_balancer_virtual_server_by_id(val)
84
- else
85
- return find_load_balancer_virtual_server_by_name(val)
86
- end
87
- end
88
-
89
- def find_load_balancer_virtual_server_by_id(id)
90
- begin
91
- json_response = load_balancer_virtual_servers_interface.get(id.to_i)
92
- return json_response[load_balancer_virtual_server_object_key]
93
- rescue RestClient::Exception => e
94
- if e.response && e.response.code == 404
95
- print_red_alert "#{load_balancer_virtual_server_label} not found by id #{id}"
96
- return nil
97
- else
98
- raise e
99
- end
100
- end
101
- end
102
-
103
- def find_load_balancer_virtual_server_by_name(name)
104
- json_response = load_balancer_virtual_servers_interface.list({name: name.to_s})
105
- load_balancer_virtual_servers = json_response[load_balancer_virtual_server_list_key]
106
- if load_balancer_virtual_servers.empty?
107
- print_red_alert "#{load_balancer_virtual_server_label_plural} not found by name #{name}"
108
- return load_balancer_virtual_servers
109
- elsif load_balancer_virtual_servers.size > 1
110
- print_red_alert "#{load_balancer_virtual_servers.size} #{load_balancer_virtual_server_label_plural.downcase} found by name #{name}"
111
- rows = load_balancer_virtual_servers.collect do |it|
112
- {id: it['id'], name: it['name']}
113
- end
114
- puts as_pretty_table(rows, [:id, :name], {color:red})
115
- return nil
116
- else
117
- return load_balancer_virtual_servers[0]
118
- end
119
- end
120
-
121
132
  def format_virtual_server_status(virtual_server, return_color=cyan)
122
133
  out = ""
123
134
  status_string = virtual_server['vipStatus'] || virtual_server['status']
124
135
  if status_string.nil? || status_string.empty? || status_string == "unknown"
125
136
  out << "#{white}UNKNOWN#{return_color}"
126
- elsif status_string == 'ok'
137
+ elsif status_string == 'online'
127
138
  out << "#{green}#{status_string.upcase}#{return_color}"
128
139
  elsif status_string == 'syncing'
129
140
  out << "#{yellow}#{status_string.upcase}#{return_color}"
@@ -133,4 +144,13 @@ class Morpheus::Cli::LoadBalancerVirtualServers
133
144
  out
134
145
  end
135
146
 
147
+ def load_option_types_for_load_balancer_virtual_server(type_record, parent_record)
148
+ load_balancer = parent_record
149
+ load_balancer_type_id = load_balancer['type']['id']
150
+ load_balancer_type = find_by_id(:load_balancer_type, load_balancer_type_id)
151
+ load_balancer_type['vipOptionTypes']
152
+ end
153
+
154
+ ## using CliCommand's generic find_by methods
155
+
136
156
  end
@@ -5,8 +5,10 @@ class Morpheus::Cli::LoadBalancers
5
5
  include Morpheus::Cli::RestCommand
6
6
  include Morpheus::Cli::LoadBalancersHelper
7
7
 
8
+ set_command_hidden
9
+ set_command_description "View and manage load balancers."
8
10
  set_command_name :'load-balancers'
9
- register_subcommands :list, :get, :add, :update, :remove
11
+ register_subcommands :list, :get, :add, :update, :remove, :refresh
10
12
 
11
13
  # deprecated the `load-balancers types` command in 5.3.2, it moved to `load-balancer-types list`
12
14
  register_subcommands :types
@@ -22,7 +24,7 @@ class Morpheus::Cli::LoadBalancers
22
24
  record = json_response[rest_object_key]
23
25
  print_h1 rest_label, [], options
24
26
  print cyan
25
- print_description_list(rest_column_definitions, record, options)
27
+ print_description_list(rest_column_definitions(options), record, options)
26
28
  # show LB Ports
27
29
  ports = record['ports']
28
30
  if ports && ports.size > 0
@@ -41,6 +43,48 @@ class Morpheus::Cli::LoadBalancers
41
43
  end
42
44
  end
43
45
 
46
+ def refresh(args)
47
+ id = args[0]
48
+ record_type = nil
49
+ record_type_id = nil
50
+ options = {}
51
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
52
+ opts.banner = subcommand_usage("[#{rest_arg}] [options]")
53
+ build_standard_update_options(opts, options)
54
+ opts.footer = <<-EOT
55
+ Refresh an existing #{rest_label.downcase}.
56
+ [#{rest_arg}] is required. This is the #{rest_has_name ? 'name or id' : 'id'} of #{a_or_an(rest_label)} #{rest_label.downcase}.
57
+ EOT
58
+ end
59
+ optparse.parse!(args)
60
+ verify_args!(args:args, optparse:optparse, count:1)
61
+ connect(options)
62
+ record = rest_find_by_name_or_id(id)
63
+ if record.nil?
64
+ return 1, "#{rest_name} not found for '#{id}'"
65
+ end
66
+ passed_options = parse_passed_options(options)
67
+ payload = {}
68
+ if options[:payload]
69
+ payload = options[:payload]
70
+ payload.deep_merge!({rest_object_key => passed_options}) unless passed_options.empty?
71
+ else
72
+ record_payload = passed_options
73
+ payload[rest_object_key] = record_payload
74
+ end
75
+ rest_interface.setopts(options)
76
+ if options[:dry_run]
77
+ print_dry_run rest_interface.dry.refresh(record['id'], payload)
78
+ return
79
+ end
80
+ json_response = rest_interface.refresh(record['id'], payload)
81
+ render_response(json_response, options, rest_object_key) do
82
+ print_green_success "Refreshing #{rest_label.downcase} #{record['name'] || record['id']}"
83
+ _get(record["id"], {}, options)
84
+ end
85
+ return 0, nil
86
+ end
87
+
44
88
  # deprecated, to be removed in the future.
45
89
  def types(args)
46
90
  print_error yellow,"[DEPRECATED] The command `load-balancers types` is deprecated and replaced by `load-balancer-types list`.",reset,"\n"
@@ -49,7 +93,7 @@ class Morpheus::Cli::LoadBalancers
49
93
 
50
94
  protected
51
95
 
52
- def load_balancer_list_column_definitions()
96
+ def load_balancer_list_column_definitions(options)
53
97
  {
54
98
  "ID" => 'id',
55
99
  "Name" => 'name',
@@ -59,7 +103,7 @@ class Morpheus::Cli::LoadBalancers
59
103
  }
60
104
  end
61
105
 
62
- def load_balancer_column_definitions()
106
+ def load_balancer_column_definitions(options)
63
107
  {
64
108
  "ID" => 'id',
65
109
  "Name" => 'name',
@@ -80,10 +124,53 @@ class Morpheus::Cli::LoadBalancers
80
124
  end
81
125
 
82
126
  # overridden to work with name or code
83
- def find_load_balancer_type_by_name_or_id(name)
84
- load_balancer_type_for_name_or_id(name)
127
+ # nope, api works with name=code now too
128
+ # def find_load_balancer_type_by_name_or_id(name)
129
+ # load_balancer_type_for_name_or_id(name)
130
+ # end
131
+
132
+ # def add_load_balancer_option_types()
133
+ # [
134
+ # {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true},
135
+ # {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false},
136
+ # {'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'required' => false, 'defaultValue' => true},
137
+ # # {'fieldName' => 'type', 'fieldLabel' => 'Storage Server Type', 'type' => 'select', 'optionSource' => 'loadBalancerTypes', 'required' => true},
138
+ # ]
139
+ # end
140
+
141
+ def add_load_balancer_advanced_option_types()
142
+ [
143
+ {'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'fieldGroup' => 'Advanced', 'type' => 'select', 'selectOptions' => [{'name' => 'Private', 'value' => 'private'},{'name' => 'Public', 'value' => 'public'}], 'required' => false, 'description' => 'Visibility', 'category' => 'permissions', 'defaultValue' => 'public'},
144
+ {'fieldName' => 'tenants', 'fieldLabel' => 'Tenants', 'fieldGroup' => 'Advanced', 'type' => 'multiSelect', 'optionSource' => lambda { |api_client, api_params|
145
+ api_client.options.options_for_source("allTenants", {})['data']
146
+ }},
147
+ ]
85
148
  end
86
149
 
150
+ # def update_load_balancer_option_types()
151
+ # [
152
+ # {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text'},
153
+ # {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text'},
154
+ # {'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox'},
155
+ # ]
156
+ # end
157
+
158
+ def update_load_balancer_advanced_option_types()
159
+ add_load_balancer_advanced_option_types()
160
+ end
87
161
 
162
+ def load_option_types_for_load_balancer(type_record, parent_record)
163
+ load_balancer_type = type_record
164
+ # reload it by id to get optionTypes
165
+ option_types = load_balancer_type['optionTypes']
166
+ if option_types.nil?
167
+ load_balancer_type = find_by_id(:load_balancer_type, load_balancer_type['id'])
168
+ if load_balancer_type.nil?
169
+ raise_command_error("Load balancer type not found for id '#{id}'")
170
+ end
171
+ option_types = load_balancer_type['optionTypes']
172
+ end
173
+ return option_types
174
+ end
88
175
 
89
176
  end
@@ -4,7 +4,7 @@ class Morpheus::Cli::NetworkFirewallsCommand
4
4
  include Morpheus::Cli::CliCommand
5
5
  include Morpheus::Cli::ProvisioningHelper
6
6
  include Morpheus::Cli::WhoamiHelper
7
- set_command_hidden #hide until api ready
7
+
8
8
  set_command_name :'network-firewalls'
9
9
  register_subcommands :list_rules, :get_rule, :add_rule, :update_rule, :remove_rule
10
10
  register_subcommands :list_rule_groups, :get_rule_group, :add_rule_group, :update_rule_group, :remove_rule_group
@@ -65,7 +65,7 @@ class Morpheus::Cli::NetworkFirewallsCommand
65
65
  id: it['id'], group: it['groupName'], name: it['name'], description: it['description'],
66
66
  priority: it['priority'], enabled: format_boolean(it['enabled']), policy: it['policy'], direction: it['direction'],
67
67
  source: it['sources'].kind_of?(Array) && it['sources'].count > 0 ? it['sources'].collect {|it| it['name']}.join(', ') : (it['sources'].nil? || it['sources'].empty? ? 'any' : it['source']),
68
- destination: it['destinations'].count > 0 ? it['destinations'].collect {|it| it['name']}.join(', ') : (it['destinations'].nil? || it['destinations'].empty? ? 'any' : it['destination'])
68
+ destination: it['destinations'].kind_of?(Array) && it['destinations'].count > 0 ? it['destinations'].collect {|it| it['name']}.join(', ') : (it['destinations'].nil? || it['destinations'].empty? ? 'any' : it['destination'])
69
69
  }
70
70
 
71
71
  if it['applications'].count
@@ -78,9 +78,9 @@ class Morpheus::Cli::NetworkFirewallsCommand
78
78
 
79
79
  applied_to = []
80
80
  if server['type']['supportsFirewallRuleAppliedTarget']
81
- applied_to << 'All Edges' if row['config']['applyToAllEdges']
82
- applied_to << 'Distributed Firewall' if row['config']['applyToAllDistributed']
83
- applied_to += rule['appliedTargets'].collect {|it| it['name']}
81
+ applied_to << 'All Edges' if it['config']['applyToAllEdges']
82
+ applied_to << 'Distributed Firewall' if it['config']['applyToAllDistributed']
83
+ applied_to += it['appliedTargets'].collect {|target| target['name']}
84
84
  row[:applied_to] = applied_to.join(', ')
85
85
  end
86
86
  row
@@ -483,6 +483,11 @@ class Morpheus::Cli::NetworkFirewallsCommand
483
483
  server['type']['firewallGroupOptionTypes'].reject {|it| it['type'] == 'hidden'}.sort_by {|it| it['displayOrder']}.each do |option_type|
484
484
  description_cols[option_type['fieldLabel']] = lambda {|it| Morpheus::Cli::OptionTypes.get_option_value(it, option_type, true)}
485
485
  end
486
+
487
+ if is_master_account
488
+ description_cols["Visibility"] = lambda {|it| it['visibility']}
489
+ description_cols["Tenants"] = lambda {|it| it['tenants'].collect {|tenant| tenant['name']}.join(', ')}
490
+ end
486
491
  print_description_list(description_cols, group)
487
492
  end
488
493
  else
@@ -505,6 +510,7 @@ class Morpheus::Cli::NetworkFirewallsCommand
505
510
  opts.on('--priority VALUE', Integer, "Priority for this firewall rule group") do |val|
506
511
  options[:options]['priority'] = val
507
512
  end
513
+ add_perms_options(opts, options, ['plans', 'groups'])
508
514
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
509
515
  opts.footer = "Create a network firewall rule group." + "\n" +
510
516
  "[server] is optional. This is the name or id of a network server.\n";
@@ -537,6 +543,11 @@ class Morpheus::Cli::NetworkFirewallsCommand
537
543
 
538
544
  # prompt options
539
545
  option_result = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options].deep_merge({:context_map => {'ruleGroup' => ''}}), @api_client, {'networkServerId' => server['id']}, nil, true)
546
+
547
+ # prompt perms
548
+ if is_master_account
549
+ params.merge!(prompt_permissions_v2(options, ['plans', 'groups']))
550
+ end
540
551
  payload = {'ruleGroup' => params.deep_merge(option_result)}
541
552
  end
542
553
 
@@ -568,6 +579,7 @@ class Morpheus::Cli::NetworkFirewallsCommand
568
579
  opts.on('--priority VALUE', Integer, "Priority for this firewall rule group") do |val|
569
580
  options[:options]['priority'] = val
570
581
  end
582
+ add_perms_options(opts, options, ['plans', 'groups'])
571
583
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
572
584
  opts.footer = "Update a network firewall rule group.\n" +
573
585
  "[server] is optional. This is the name or id of an existing network server.\n" +
@@ -592,6 +604,11 @@ class Morpheus::Cli::NetworkFirewallsCommand
592
604
  group = find_rule_group(server['id'], group_id)
593
605
  return 1 if group.nil?
594
606
 
607
+ if is_master_account
608
+ params['visibility'] = options[:visibility] if !options[:visibility].nil?
609
+ params['tenants'] = options[:tenants].collect {|it| {'id' => it}} if !options[:tenants].nil?
610
+ end
611
+
595
612
  payload = parse_payload(options) || {'ruleGroup' => params}
596
613
  payload['ruleGroup'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options] && !payload['ruleGroup'].nil?
597
614
 
@@ -634,59 +634,51 @@ class Morpheus::Cli::NetworkRoutersCommand
634
634
  end
635
635
 
636
636
  def _firewall_rule_group(router_id, group_id, options)
637
- begin
638
- @network_routers_interface.setopts(options)
639
- if options[:dry_run]
640
- if args[0].to_s =~ /\A\d{1,}\Z/
641
- print_dry_run @network_routers_interface.dry.get(router_id.to_i)
637
+ @network_routers_interface.setopts(options)
638
+ if options[:dry_run]
639
+ if router_id.to_s =~ /\A\d{1,}\Z/
640
+ print_dry_run @network_routers_interface.dry.list({name:router_id})
641
+ else
642
+ if group_id.to_s =~ /\A\d{1,}\Z/
643
+ print_dry_run @network_routers_interface.dry.get_firewall_rule_group(router_id.to_i, group_id)
642
644
  else
643
- print_dry_run @network_routers_interface.dry.list({name:router_id})
645
+ print_dry_run @network_routers_interface.dry.list_firewall_rule_groups(router_id.to_i, {phrase:router_id})
644
646
  end
645
- return
646
647
  end
647
- router = find_router(router_id)
648
- if router.nil?
649
- return 1
650
- end
651
-
652
- if router['type']['hasFirewallGroups']
653
- group = (router['firewall']['ruleGroups'] || []).find {|it| it['id'].to_s == group_id.to_s || it['name'] == group_id.to_s}
648
+ return
649
+ end
650
+ router = find_router(router_id)
651
+ if router.nil?
652
+ return 1
653
+ end
654
654
 
655
- if group
656
- json_response = {'ruleGroup' => group}
655
+ if router['type']['hasFirewallGroups']
656
+ group = find_firewall_rule_group(router['id'], group_id)
657
+ return 1 if group.nil?
657
658
 
658
- if options[:json]
659
- puts as_json(json_response, options, "ruleGroup")
660
- return 0
661
- elsif options[:yaml]
662
- puts as_yaml(json_response, options, "ruleGroup")
663
- return 0
664
- elsif options[:csv]
665
- puts records_as_csv([json_response['ruleGroup']], options)
666
- return 0
667
- end
659
+ render_response({ruleGroup: group}, options, 'ruleGroup') do
660
+ print_h1 "Firewall Rule Group Details"
661
+ print cyan
662
+ description_cols = {
663
+ "ID" => lambda {|it| it['id'] },
664
+ "Name" => lambda {|it| it['name'] },
665
+ "Description" => lambda {|it| it['description']},
666
+ "Priority" => lambda {|it| it['priority']},
667
+ "Category" => lambda {|it| it['groupLayer']}
668
+ }
669
+ print_description_list(description_cols, group)
668
670
 
669
- print_h1 "Firewall Rule Group Details"
670
- print cyan
671
- description_cols = {
672
- "ID" => lambda {|it| it['id'] },
673
- "Name" => lambda {|it| it['name'] },
674
- "Description" => lambda {|it| it['description']},
675
- "Priority" => lambda {|it| it['priority']},
676
- "Category" => lambda {|it| it['groupLayer']}
677
- }
678
- print_description_list(description_cols, group)
679
- else
680
- print_red_alert "Firewall rule group #{group_id} not found for router #{router['name']}"
671
+ if is_master_account
672
+ description_cols["Visibility"] = lambda {|it| it['visibility']}
673
+ description_cols["Tenants"] = lambda {|it| it['tenants'].collect {|tenant| tenant['name']}.join(', ')}
681
674
  end
682
- else
683
- print_h1 "No Firewall Rule Groups"
675
+ print_description_list(description_cols, group)
684
676
  end
685
- println reset
686
- rescue RestClient::Exception => e
687
- print_rest_exception(e, options)
677
+ else
678
+ print_red_alert "Firewall rule groups not supported for #{router['type']['name']}"
688
679
  return 1
689
680
  end
681
+ println reset
690
682
  end
691
683
 
692
684
  def add_firewall_rule_group(args)
@@ -703,6 +695,7 @@ class Morpheus::Cli::NetworkRoutersCommand
703
695
  opts.on('--priority VALUE', Integer, "Priority for this firewall rule group (not applicable to all firewall types)") do |val|
704
696
  params['priority'] = val
705
697
  end
698
+ add_perms_options(opts, options, ['plans', 'groups'])
706
699
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
707
700
  opts.footer = "Create a network router firewall rule group."
708
701
  end
@@ -742,7 +735,14 @@ class Morpheus::Cli::NetworkRoutersCommand
742
735
 
743
736
  # prompt options
744
737
  option_result = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options].deep_merge({:context_map => {'group' => ''}}), @api_client, {}, nil, true)
745
- payload = {'ruleGroup' => params.deep_merge(option_result)}
738
+
739
+ rule_group = params.deep_merge(option_result)
740
+
741
+ # prompt perms
742
+ if is_master_account
743
+ rule_group.merge!(prompt_permissions_v2(options, ['plans', 'groups']))
744
+ end
745
+ payload = {'ruleGroup' => rule_group}
746
746
  end
747
747
 
748
748
  @network_routers_interface.setopts(options)
@@ -779,6 +779,7 @@ class Morpheus::Cli::NetworkRoutersCommand
779
779
  opts.on('--priority VALUE', Integer, "Priority for this firewall rule group (not applicable to all firewall types)") do |val|
780
780
  params['priority'] = val
781
781
  end
782
+ add_perms_options(opts, options, ['plans', 'groups'])
782
783
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
783
784
  opts.footer = "Update a network router firewall rule group.\n" +
784
785
  "[router] is required. This is the name or id of an existing network router.\n" +
@@ -810,6 +811,11 @@ class Morpheus::Cli::NetworkRoutersCommand
810
811
  exit 1
811
812
  end
812
813
 
814
+ if is_master_account
815
+ params['visibility'] = options[:visibility] if !options[:visibility].nil?
816
+ params['tenants'] = options[:tenants].collect {|it| {'id' => it}} if !options[:tenants].nil?
817
+ end
818
+
813
819
  payload = parse_payload(options) || {'ruleGroup' => params}
814
820
  payload['ruleGroup'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
815
821
 
@@ -2564,8 +2570,53 @@ class Morpheus::Cli::NetworkRoutersCommand
2564
2570
  end
2565
2571
  end
2566
2572
  else
2567
- rule = router['firewall'] && router['firewall']['rules'] ? router['firewall']['rules'].find {|it| it['name'] == args[1] || it['id'] == args[1].to_i} : nil
2573
+ rule = router['firewall'] && router['firewall']['rules'] ? router['firewall']['rules'].find {|it| it['name'] == rule_id || it['id'] == rule_id.to_i} : nil
2568
2574
  end
2569
2575
  rule
2570
2576
  end
2577
+
2578
+ def find_firewall_rule_group(router_id, val)
2579
+ if val.to_s =~ /\A\d{1,}\Z/
2580
+ return find_firewall_rule_group_by_id(router_id, val)
2581
+ else
2582
+ if group = find_firewall_rule_group_by_name(router_id, val)
2583
+ return find_firewall_rule_group_by_id(router_id, group['id'])
2584
+ end
2585
+ end
2586
+ end
2587
+
2588
+ def find_firewall_rule_group_by_id(router_id, group_id)
2589
+ begin
2590
+ json_response = @network_routers_interface.get_firewall_rule_group(router_id, group_id.to_i)
2591
+ return json_response['ruleGroup']
2592
+ rescue RestClient::Exception => e
2593
+ if e.response && e.response.code == 404
2594
+ print_red_alert "Network firewall rule group not found by id #{group_id}"
2595
+ return nil
2596
+ else
2597
+ raise e
2598
+ end
2599
+ end
2600
+ end
2601
+
2602
+ def find_firewall_rule_group_by_name(router_id, name)
2603
+ groups = search_firewall_rule_groups(router_id, name)
2604
+ if groups.empty?
2605
+ print_red_alert "Network firewall rule group not found by name #{name}"
2606
+ return nil
2607
+ elsif groups.size > 1
2608
+ print_red_alert "#{scopes.size} network firewall rule groups found by name #{name}"
2609
+ rows = groups.collect do |it|
2610
+ {id: it['id'], name: it['name']}
2611
+ end
2612
+ puts as_pretty_table(rows, [:id, :name], {color:red})
2613
+ return nil
2614
+ else
2615
+ return groups[0]
2616
+ end
2617
+ end
2618
+
2619
+ def search_firewall_rule_groups(router_id, phrase = nil)
2620
+ @network_routers_interface.list_firewall_rule_groups(router_id, phrase ? {phrase: phrase.to_s} : {})['ruleGroups']
2621
+ end
2571
2622
  end