morpheus-cli 5.4.0 → 5.4.1

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 (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