morpheus-cli 5.5.1.4 → 5.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +25 -0
  4. data/lib/morpheus/api/archive_buckets_interface.rb +1 -1
  5. data/lib/morpheus/api/body_io.rb +22 -0
  6. data/lib/morpheus/api/catalog_item_types_interface.rb +5 -1
  7. data/lib/morpheus/api/clients_interface.rb +41 -0
  8. data/lib/morpheus/api/clouds_interface.rb +21 -0
  9. data/lib/morpheus/api/instances_interface.rb +8 -1
  10. data/lib/morpheus/api/integrations_interface.rb +30 -0
  11. data/lib/morpheus/api/library_instance_types_interface.rb +15 -3
  12. data/lib/morpheus/api/network_pool_server_types_interface.rb +9 -0
  13. data/lib/morpheus/api/plugins_interface.rb +22 -0
  14. data/lib/morpheus/api/roles_interface.rb +20 -1
  15. data/lib/morpheus/api/security_package_types_interface.rb +9 -0
  16. data/lib/morpheus/api/security_packages_interface.rb +9 -0
  17. data/lib/morpheus/api/security_scans_interface.rb +9 -0
  18. data/lib/morpheus/api/servers_interface.rb +17 -17
  19. data/lib/morpheus/api/storage_providers_interface.rb +1 -1
  20. data/lib/morpheus/api/virtual_images_interface.rb +1 -23
  21. data/lib/morpheus/cli/cli_command.rb +81 -7
  22. data/lib/morpheus/cli/commands/apps.rb +28 -2
  23. data/lib/morpheus/cli/commands/archives_command.rb +2 -2
  24. data/lib/morpheus/cli/commands/blueprints_command.rb +16 -0
  25. data/lib/morpheus/cli/commands/catalog_item_types_command.rb +34 -2
  26. data/lib/morpheus/cli/commands/clients_command.rb +338 -0
  27. data/lib/morpheus/cli/commands/clouds.rb +127 -1
  28. data/lib/morpheus/cli/commands/clusters.rb +42 -12
  29. data/lib/morpheus/cli/commands/curl_command.rb +114 -135
  30. data/lib/morpheus/cli/commands/hosts.rb +108 -11
  31. data/lib/morpheus/cli/commands/instances.rb +115 -14
  32. data/lib/morpheus/cli/commands/integrations_command.rb +215 -4
  33. data/lib/morpheus/cli/commands/invoices_command.rb +20 -11
  34. data/lib/morpheus/cli/commands/jobs_command.rb +299 -190
  35. data/lib/morpheus/cli/commands/library_cluster_layouts_command.rb +16 -2
  36. data/lib/morpheus/cli/commands/library_container_scripts_command.rb +14 -0
  37. data/lib/morpheus/cli/commands/library_container_templates_command.rb +131 -48
  38. data/lib/morpheus/cli/commands/library_container_types_command.rb +17 -4
  39. data/lib/morpheus/cli/commands/library_instance_types_command.rb +85 -7
  40. data/lib/morpheus/cli/commands/library_layouts_command.rb +32 -1
  41. data/lib/morpheus/cli/commands/library_option_lists_command.rb +30 -18
  42. data/lib/morpheus/cli/commands/library_option_types_command.rb +31 -14
  43. data/lib/morpheus/cli/commands/library_spec_templates_command.rb +14 -0
  44. data/lib/morpheus/cli/commands/library_upgrades_command.rb +2 -2
  45. data/lib/morpheus/cli/commands/network_pool_server_types.rb +20 -0
  46. data/lib/morpheus/cli/commands/network_pool_servers_command.rb +55 -158
  47. data/lib/morpheus/cli/commands/network_pools_command.rb +49 -23
  48. data/lib/morpheus/cli/commands/networks_command.rb +262 -45
  49. data/lib/morpheus/cli/commands/plugins.rb +213 -0
  50. data/lib/morpheus/cli/commands/price_sets_command.rb +40 -10
  51. data/lib/morpheus/cli/commands/prices_command.rb +17 -5
  52. data/lib/morpheus/cli/commands/processes_command.rb +2 -1
  53. data/lib/morpheus/cli/commands/remote.rb +7 -10
  54. data/lib/morpheus/cli/commands/roles.rb +924 -335
  55. data/lib/morpheus/cli/commands/search_command.rb +2 -0
  56. data/lib/morpheus/cli/commands/security_groups.rb +72 -84
  57. data/lib/morpheus/cli/commands/security_package_types.rb +32 -0
  58. data/lib/morpheus/cli/commands/security_packages.rb +84 -0
  59. data/lib/morpheus/cli/commands/security_scans.rb +107 -0
  60. data/lib/morpheus/cli/commands/service_plans_command.rb +16 -14
  61. data/lib/morpheus/cli/commands/subnets_command.rb +15 -1
  62. data/lib/morpheus/cli/commands/tasks.rb +34 -1
  63. data/lib/morpheus/cli/commands/tenants_command.rb +1 -1
  64. data/lib/morpheus/cli/commands/user_settings_command.rb +11 -2
  65. data/lib/morpheus/cli/commands/users.rb +50 -9
  66. data/lib/morpheus/cli/commands/virtual_images.rb +14 -0
  67. data/lib/morpheus/cli/commands/workflows.rb +14 -0
  68. data/lib/morpheus/cli/mixins/accounts_helper.rb +6 -5
  69. data/lib/morpheus/cli/mixins/infrastructure_helper.rb +79 -0
  70. data/lib/morpheus/cli/mixins/jobs_helper.rb +4 -5
  71. data/lib/morpheus/cli/mixins/library_helper.rb +2 -0
  72. data/lib/morpheus/cli/mixins/logs_helper.rb +3 -0
  73. data/lib/morpheus/cli/mixins/monitoring_helper.rb +1 -1
  74. data/lib/morpheus/cli/mixins/print_helper.rb +29 -4
  75. data/lib/morpheus/cli/mixins/provisioning_helper.rb +38 -9
  76. data/lib/morpheus/cli/mixins/rest_command.rb +106 -8
  77. data/lib/morpheus/cli/mixins/secondary_rest_command.rb +6 -2
  78. data/lib/morpheus/cli/option_types.rb +94 -25
  79. data/lib/morpheus/cli/version.rb +1 -1
  80. data/lib/morpheus/formatters.rb +10 -1
  81. metadata +15 -2
@@ -6,14 +6,21 @@ class Morpheus::Cli::Roles
6
6
  include Morpheus::Cli::ProvisioningHelper
7
7
  include Morpheus::Cli::WhoamiHelper
8
8
  register_subcommands :list, :get, :add, :update, :remove,
9
- :'list-permissions', :'update-feature-access', :'update-global-group-access',
10
- :'update-group-access', :'update-global-cloud-access', :'update-cloud-access',
11
- :'update-global-instance-type-access', :'update-instance-type-access',
12
- :'update-global-blueprint-access', :'update-blueprint-access',
13
- :'update-global-catalog-item-type-access', :'update-catalog-item-type-access',
14
- :'update-persona-access',
15
- :'update-global-vdi-pool-access', :'update-vdi-pool-access',
16
- :'update-global-report-type-access', :'update-report-type-access'
9
+ :'list-permissions', :'update-feature-access', :'update-default-feature-access',
10
+ :'update-group-access', :'update-global-group-access', :'update-default-group-access',
11
+ :'update-global-cloud-access', :'update-cloud-access', :'update-default-cloud-access',
12
+ :'update-global-instance-type-access', :'update-instance-type-access', :'update-default-instance-type-access',
13
+ :'update-global-blueprint-access', :'update-blueprint-access', :'update-default-blueprint-access',
14
+ :'update-global-catalog-item-type-access', :'update-catalog-item-type-access', :'update-default-catalog-item-type-access',
15
+ :'update-persona-access', :'update-default-persona-access',
16
+ :'update-global-vdi-pool-access', :'update-vdi-pool-access', :'update-default-vdi-pool-access',
17
+ :'update-global-report-type-access', :'update-report-type-access', :'update-default-report-type-access',
18
+ :'update-global-task-access', :'update-task-access', :'update-default-task-access',
19
+ :'update-global-workflow-access', :'update-workflow-access', :'update-default-workflow-access'
20
+ set_subcommands_hidden(
21
+ subcommands.keys.select{|c|
22
+ c.include?('update-global')
23
+ })
17
24
  alias_subcommand :details, :get
18
25
  set_default_subcommand :list
19
26
 
@@ -39,6 +46,9 @@ class Morpheus::Cli::Roles
39
46
  options = {}
40
47
  optparse = Morpheus::Cli::OptionParser.new do |opts|
41
48
  opts.banner = subcommand_usage("[search phrase]")
49
+ opts.on( '--tenant TENANT', "Tenant Filter for list of Roles." ) do |val|
50
+ options[:tenant] = val
51
+ end
42
52
  build_standard_list_options(opts, options)
43
53
  opts.footer = "List roles."
44
54
  end
@@ -57,6 +67,9 @@ class Morpheus::Cli::Roles
57
67
  return 0, nil
58
68
  end
59
69
  load_whoami()
70
+ if options[:tenant]
71
+ params[:tenant] = options[:tenant]
72
+ end
60
73
  json_response = @roles_interface.list(account_id, params)
61
74
 
62
75
  render_response(json_response, options, "roles") do
@@ -82,13 +95,13 @@ class Morpheus::Cli::Roles
82
95
  options = {}
83
96
  optparse = Morpheus::Cli::OptionParser.new do |opts|
84
97
  opts.banner = subcommand_usage("[role]")
85
- opts.on('-p','--permissions', "Display Permissions") do |val|
98
+ opts.on('-p','--permissions', "Display Permissions [deprecated]") do |val|
86
99
  options[:include_feature_access] = true
87
100
  end
88
- opts.on('-f','--feature-access', "Display Permissions [deprecated]") do |val|
101
+ opts.add_hidden_option('-p,')
102
+ opts.on('-f','--feature-access', "Display Feature Access") do |val|
89
103
  options[:include_feature_access] = true
90
104
  end
91
- opts.add_hidden_option('--feature-access')
92
105
  opts.on('-g','--group-access', "Display Group Access") do
93
106
  options[:include_group_access] = true
94
107
  end
@@ -105,7 +118,11 @@ class Morpheus::Cli::Roles
105
118
  options[:include_catalog_item_type_access] = true
106
119
  end
107
120
  opts.on(nil,'--personas', "Display Persona Access") do
108
- options[:include_personas_access] = true
121
+ options[:include_persona_access] = true
122
+ end
123
+ opts.add_hidden_option('--personas')
124
+ opts.on(nil,'--persona-access', "Display Persona Access") do
125
+ options[:include_persona_access] = true
109
126
  end
110
127
  opts.on(nil,'--vdi-pool-access', "Display VDI Pool Access") do
111
128
  options[:include_vdi_pool_access] = true
@@ -113,16 +130,19 @@ class Morpheus::Cli::Roles
113
130
  opts.on(nil,'--report-type-access', "Display Report Type Access") do
114
131
  options[:include_report_type_access] = true
115
132
  end
133
+ opts.on(nil,'--workflow-access', "Display Workflow Access") do
134
+ options[:include_workflow_access] = true
135
+ end
136
+ opts.on(nil,'--task-access', "Display Task Access") do
137
+ options[:include_task_access] = true
138
+ end
116
139
  opts.on('-a','--all', "Display All Access Lists") do
117
- options[:include_feature_access] = true
118
- options[:include_group_access] = true
119
- options[:include_cloud_access] = true
120
- options[:include_instance_type_access] = true
121
- options[:include_blueprint_access] = true
122
- options[:include_catalog_item_type_access] = true
123
- options[:include_personas_access] = true
124
- options[:include_vdi_pool_access] = true
125
- options[:include_report_type_access] = true
140
+ options[:include_all_access] = true
141
+ end
142
+ opts.on('--account-id ID', String, "Clarify Owner of Role") do |val|
143
+ if has_complete_access
144
+ options[:account_id] = val.to_s
145
+ end
126
146
  end
127
147
  build_standard_get_options(opts, options)
128
148
  opts.footer = <<-EOT
@@ -142,65 +162,51 @@ EOT
142
162
  def _get(id, options={})
143
163
  args = [id] # heh
144
164
  params = {}
165
+ account = find_account_from_options(options)
166
+ account_id = account ? account['id'] : nil
145
167
 
146
-
147
- account = find_account_from_options(options)
148
- account_id = account ? account['id'] : nil
149
-
150
- params.merge!(parse_query_options(options))
151
-
152
- @roles_interface.setopts(options)
153
- if options[:dry_run]
154
- if args[0].to_s =~ /\A\d{1,}\Z/
155
- print_dry_run @roles_interface.dry.get(account_id, args[0].to_i)
156
- else
157
- print_dry_run @roles_interface.dry.list(account_id, {name: args[0]})
158
- end
159
- return
160
- end
168
+ params.merge!(parse_query_options(options))
161
169
 
162
- # role = find_role_by_name_or_id(account_id, args[0])
163
- # exit 1 if role.nil?
164
- # refetch from show action, argh
165
- # json_response = @roles_interface.get(account_id, role['id'])
166
- # role = json_response['role']
167
- load_whoami()
168
- json_response = nil
169
- role = nil
170
+ @roles_interface.setopts(options)
171
+ if options[:dry_run]
170
172
  if args[0].to_s =~ /\A\d{1,}\Z/
171
- json_response = @roles_interface.get(account_id, args[0].to_i)
172
- role = json_response['role']
173
+ print_dry_run @roles_interface.dry.get(account_id, args[0].to_i)
173
174
  else
174
- role = find_role_by_name_or_id(account_id, args[0])
175
- exit 1 if role.nil?
176
- # refetch from show action, argh
177
- json_response = @roles_interface.get(account_id, role['id'])
178
- role = json_response['role']
175
+ print_dry_run @roles_interface.dry.list(account_id, {name: args[0]})
179
176
  end
177
+ return
178
+ end
179
+
180
+ load_whoami()
181
+ json_response = nil
182
+ role = nil
183
+ if args[0].to_s =~ /\A\d{1,}\Z/
184
+ json_response = @roles_interface.get(account_id, args[0].to_i)
185
+ role = json_response['role']
186
+ else
187
+ role = find_role_by_name_or_id(account_id, args[0])
188
+ exit 1 if role.nil?
189
+ # refetch from show action, argh
190
+ json_response = @roles_interface.get(account_id, role['id'])
191
+ role = json_response['role']
192
+ end
193
+
194
+ render_response(json_response, options, 'role') do
180
195
 
181
- render_response(json_response, options, 'role') do
182
-
183
196
  print cyan
184
197
  print_h1 "Role Details", options
185
198
  print cyan
186
199
  columns = @is_master_account ? role_column_definitions : subtenant_role_column_definitions
187
200
  print_description_list(columns, role, options)
188
201
 
189
- # print_h2 "Role Instance Limits", options
190
- # print cyan
191
- # print_description_list({
192
- # "Max Storage" => lambda {|it| (it && it['maxStorage'].to_i != 0) ? Filesize.from("#{it['maxStorage']} B").pretty : "no limit" },
193
- # "Max Memory" => lambda {|it| (it && it['maxMemory'].to_i != 0) ? Filesize.from("#{it['maxMemory']} B").pretty : "no limit" },
194
- # "CPU Count" => lambda {|it| (it && it['maxCpu'].to_i != 0) ? it['maxCpu'] : "no limit" }
195
- # }, role['instanceLimits'])
196
-
197
202
  print_h2 "Permissions", options
198
203
  print cyan
199
- if options[:include_feature_access]
204
+ if options[:include_feature_access] || options[:include_all_access]
200
205
  rows = json_response['featurePermissions'].collect do |it|
201
206
  {
202
207
  code: it['code'],
203
208
  name: it['name'],
209
+ subCategory: it['subCategory'],
204
210
  access: format_access_string(it['access']),
205
211
  }
206
212
  end
@@ -214,24 +220,28 @@ EOT
214
220
  phrase_regexp = /#{Regexp.escape(options[:phrase])}/i
215
221
  rows = rows.select {|row| row[:code].to_s =~ phrase_regexp || row[:name].to_s =~ phrase_regexp }
216
222
  end
217
- print as_pretty_table(rows, [:code, :name, :access], options)
223
+ print as_pretty_table(rows, [:code, :name, :subCategory, :access], options)
218
224
  # print reset,"\n"
219
225
  else
220
- print cyan,"Use --permissions to list feature permissions","\n"
226
+ print cyan,"Use --feature-access to list feature access","\n"
221
227
  end
222
228
 
223
229
  has_group_access = true
224
230
  has_cloud_access = true
225
- print_h2 "Global Access", options
231
+ print_h2 "Default Access", options
226
232
  global_access_columns = {
227
233
  "Groups" => lambda {|it| get_access_string(it['globalSiteAccess']) },
228
234
  "Clouds" => lambda {|it| get_access_string(it['globalZoneAccess']) },
229
235
  "Instance Types" => lambda {|it| get_access_string(it['globalInstanceTypeAccess']) },
230
236
  "Blueprints" => lambda {|it| get_access_string(it['globalAppTemplateAccess'] || it['globalBlueprintAccess']) },
237
+ "Personas" => lambda {|it| get_access_string(it['globalPersonaAccess']) },
238
+ "Report Types" => lambda {|it| get_access_string(it['globalReportTypeAccess']) },
231
239
  "Catalog Item Types" => lambda {|it| get_access_string(it['globalCatalogItemTypeAccess']) },
232
240
  "VDI Pools" => lambda {|it| get_access_string(it['globalVdiPoolAccess']) },
233
- "Report Types" => lambda {|it| get_access_string(it['globalReportTypeAccess']) },
241
+ "Workflows" => lambda {|it| get_access_string(it['globalTaskSetAccess']) },
242
+ "Tasks" => lambda {|it| get_access_string(it['globalTaskAccess']) },
234
243
  }
244
+
235
245
  if role['roleType'].to_s.downcase == 'account'
236
246
  global_access_columns.delete("Groups")
237
247
  has_group_access = false
@@ -239,15 +249,16 @@ EOT
239
249
  global_access_columns.delete("Clouds")
240
250
  has_cloud_access = false
241
251
  end
252
+
242
253
  print as_pretty_table([json_response], global_access_columns, options)
243
254
 
244
255
  if has_group_access
245
256
  #print_h2 "Group Access: #{get_access_string(json_response['globalSiteAccess'])}", options
246
257
  print cyan
247
- if json_response['globalSiteAccess'] == 'custom'
258
+ if json_response['sites'].find {|it| !it['access'].nil?}
248
259
  print_h2 "Group Access", options
249
- if options[:include_group_access]
250
- rows = json_response['sites'].collect do |it|
260
+ if options[:include_group_access] || options[:include_all_access]
261
+ rows = json_response['sites'].select {|it| !it['access'].nil?}.collect do |it|
251
262
  {
252
263
  name: it['name'],
253
264
  access: format_access_string(it['access'], ["none","read","full"]),
@@ -263,15 +274,15 @@ EOT
263
274
  # print cyan,bold,"Group Access: #{get_access_string(json_response['globalSiteAccess'])}",reset,"\n"
264
275
  end
265
276
  end
266
-
277
+
267
278
  if has_cloud_access
268
279
  print cyan
269
280
  #puts "Cloud Access: #{get_access_string(json_response['globalZoneAccess'])}"
270
281
  #print "\n"
271
- if json_response['globalZoneAccess'] == 'custom'
282
+ if json_response['sites'].find{|it| !it['access'].nil?}
272
283
  print_h2 "Cloud Access", options
273
- if options[:include_cloud_access]
274
- rows = json_response['zones'].collect do |it|
284
+ if options[:include_cloud_access] || options[:include_all_access]
285
+ rows = json_response['zones'].select {|it| !it['access'].nil?}.collect do |it|
275
286
  {
276
287
  name: it['name'],
277
288
  access: format_access_string(it['access'], ["none","read","full"]),
@@ -293,195 +304,226 @@ EOT
293
304
  # print "\n"
294
305
  instance_type_global_access = json_response['globalInstanceTypeAccess']
295
306
  instance_type_permissions = role['instanceTypes'] ? role['instanceTypes'] : (json_response['instanceTypePermissions'] || [])
296
- if instance_type_global_access == 'custom'
307
+
308
+ # if have any custom, then we want to show the flag indicator
309
+ # if including, show
310
+
311
+ if options[:include_instance_type_access] || options[:include_all_access]
297
312
  print_h2 "Instance Type Access", options
298
- if options[:include_instance_type_access]
299
- rows = instance_type_permissions.collect do |it|
300
- {
301
- name: it['name'],
302
- access: format_access_string(it['access'], ["none","read","full"]),
303
- }
304
- end
305
- print as_pretty_table(rows, [:name, :access], options)
306
- else
307
- print cyan,"Use -i, --instance-type-access to list custom access","\n"
313
+ rows = instance_type_permissions.collect do |it|
314
+ {
315
+ name: it['name'],
316
+ access: format_access_string(it['access'], ["none","read","full"]),
317
+ }
308
318
  end
309
- # print reset,"\n"
310
- else
311
- # print "\n"
312
- # print cyan,bold,"Instance Type Access: #{get_access_string(json_response['globalInstanceTypeAccess'])}",reset,"\n"
319
+ print as_pretty_table(rows, [:name, :access], options)
320
+ elsif instance_type_permissions.find {|it| !it['access'].nil?}
321
+ print_h2 "Instance Type Access", options
322
+ print cyan,"Use -i, --instance-type-access to list custom access","\n"
313
323
  end
314
324
 
315
325
  blueprint_global_access = json_response['globalAppTemplateAccess'] || json_response['globalBlueprintAccess']
316
326
  blueprint_permissions = (role['appTemplates'] || role['blueprints']) ? (role['appTemplates'] || role['blueprints']) : (json_response['appTemplatePermissions'] || json_response['blueprintPermissions'] || [])
317
327
  print cyan
318
- # print_h2 "Blueprint Access: #{get_access_string(json_response['globalAppTemplateAccess'])}", options
319
- # print "\n"
320
- if blueprint_global_access == 'custom'
328
+ if options[:include_blueprint_access] || options[:include_all_access]
321
329
  print_h2 "Blueprint Access", options
322
- if options[:include_blueprint_access]
323
- rows = blueprint_permissions.collect do |it|
324
- {
325
- name: it['name'],
326
- access: format_access_string(it['access'], ["none","read","full"]),
327
- }
328
- end
329
- print as_pretty_table(rows, [:name, :access], options)
330
- else
331
- print cyan,"Use -b, --blueprint-access to list custom access","\n"
330
+ rows = blueprint_permissions.select {|it| !it['access'].nil?}.collect do |it|
331
+ {
332
+ name: it['name'],
333
+ access: format_access_string(it['access'], ["none","read","full"]),
334
+ }
332
335
  end
333
- # print reset,"\n"
334
- else
335
- # print "\n"
336
- # print cyan,bold,"Blueprint Access: #{get_access_string(json_response['globalAppTemplateAccess'])}",reset,"\n"
336
+ print as_pretty_table(rows, [:name, :access], options)
337
+ elsif blueprint_permissions.find {|it| !it['access'].nil?}
338
+ print_h2 "Blueprint Access", options
339
+ print cyan,"Use -b, --blueprint-access to list custom access","\n"
337
340
  end
338
-
341
+
339
342
  catalog_item_type_global_access = json_response['globalCatalogItemTypeAccess']
340
343
  catalog_item_type_permissions = role['catalogItemTypes'] ? role['catalogItemTypes'] : (json_response['catalogItemTypePermissions'] || [])
341
344
  print cyan
342
- # print_h2 "catalog_item_type Access: #{get_access_string(json_response['globalCatalogItemTypeAccess'])}", options
343
- # print "\n"
344
- if catalog_item_type_global_access == 'custom'
345
+ if options[:include_catalog_item_type_access] || options[:include_all_access]
345
346
  print_h2 "Catalog Item Type Access", options
346
- if options[:include_catalog_item_type_access]
347
- rows = catalog_item_type_permissions.collect do |it|
348
- {
349
- name: it['name'],
350
- access: format_access_string(it['access'], ["none","read","full"]),
351
- }
352
- end
353
- print as_pretty_table(rows, [:name, :access], options)
354
- else
355
- print cyan,"Use --catalog-item-type-access to list custom access","\n"
347
+ rows = catalog_item_type_permissions.select {|it| !it['access'].nil?}.collect do |it|
348
+ {
349
+ name: it['name'],
350
+ access: format_access_string(it['access'], ["none","read","full"]),
351
+ }
356
352
  end
357
- else
358
- # print "\n"
359
- # print cyan,bold,"Catalog Item Type Access: #{get_access_string(json_response['globalCatalogItemTypeAccess'])}",reset,"\n"
353
+ print as_pretty_table(rows, [:name, :access], options)
354
+ elsif catalog_item_type_permissions.find {|it| !it['access'].nil?}
355
+ print_h2 "Catalog Item Type Access", options
356
+ print cyan,"Use --catalog-item-type-access to list access","\n"
360
357
  end
361
-
358
+
359
+ persona_global_access = json_response['globalPersonaAccess']
362
360
  persona_permissions = role['personas'] ? role['personas'] : (json_response['personaPermissions'] || [])
363
- # if options[:include_personas_access]
364
361
  print cyan
365
- if persona_permissions
362
+ if options[:include_persona_access] || options[:include_all_access]
366
363
  print_h2 "Persona Access", options
367
364
  rows = persona_permissions.collect do |it|
368
365
  {
369
366
  name: it['name'],
370
- access: format_access_string(it['access'], ["none","read","full"]),
367
+ access: format_access_string(it['access'], ["none","full"]),
371
368
  }
372
369
  end
373
- print as_pretty_table(rows, [:name, :access], options)
370
+ print as_pretty_table(rows, [:name, :access], options)
371
+ elsif persona_permissions.find {|it| !it['access'].nil?}
372
+ print_h2 "Persona Access", options
373
+ print cyan,"Use --persona-access to list access","\n"
374
374
  end
375
375
 
376
- # print reset,"\n"
377
-
378
376
  vdi_pool_global_access = json_response['globalVdiPoolAccess']
379
377
  vdi_pool_permissions = role['vdiPools'] ? role['vdiPools'] : (json_response['vdiPoolPermissions'] || [])
380
378
  print cyan
381
- if vdi_pool_global_access == 'custom'
379
+ if options[:include_vdi_pool_access] || options[:include_all_access]
382
380
  print_h2 "VDI Pool Access", options
383
- if options[:include_vdi_pool_access]
384
- rows = vdi_pool_permissions.collect do |it|
385
- {
386
- name: it['name'],
387
- access: format_access_string(it['access'], ["none","full"]),
388
- }
389
- end
390
- print as_pretty_table(rows, [:name, :access], options)
391
- else
392
- print cyan,"Use --vdi-pool-access to list custom access","\n"
381
+ rows = vdi_pool_permissions.select {|it| !it['access'].nil?}.collect do |it|
382
+ {
383
+ name: it['name'],
384
+ access: format_access_string(it['access'], ["none","full"]),
385
+ }
393
386
  end
394
- else
395
- # print "\n"
396
- # print cyan,bold,"VDI Pool Access: #{get_access_string(json_response['globalVdiPoolAccess'])}",reset,"\n"
387
+ print as_pretty_table(rows, [:name, :access], options)
388
+ elsif vdi_pool_permissions.find {|it| !it['access'].nil?}
389
+ print_h2 "VDI Pool Access", options
390
+ print cyan,"Use --vdi-pool-access to list custom access","\n"
397
391
  end
398
392
 
399
393
  report_type_global_access = json_response['globalReportTypeAccess']
400
394
  report_type_permissions = role['reportTypes'] ? role['reportTypes'] : (json_response['reportTypePermissions'] || [])
401
395
  print cyan
402
- if report_type_global_access == 'custom'
396
+ if options[:include_report_type_access] || options[:include_all_access]
403
397
  print_h2 "Report Type Access", options
404
- if options[:include_report_type_access]
405
- rows = report_type_permissions.collect do |it|
406
- {
407
- name: it['name'],
408
- access: format_access_string(it['access'], ["none","full"]),
409
- }
410
- end
411
- print as_pretty_table(rows, [:name, :access], options)
412
- else
413
- print cyan,"Use --report-type-access to list custom access","\n"
398
+ rows = report_type_permissions.select {|it| !it['access'].nil?}.collect do |it|
399
+ {
400
+ name: it['name'],
401
+ access: format_access_string(it['access'], ["none","full"]),
402
+ }
414
403
  end
415
- else
416
- # print "\n"
417
- # print cyan,bold,"Report Type Access: #{get_access_string(json_response['globalReportTypeAccess'])}",reset,"\n"
404
+ print as_pretty_table(rows, [:name, :access], options)
405
+ elsif report_type_permissions.find {|it| !it['access'].nil?}
406
+ print_h2 "Report Type Access", options
407
+ print cyan,"Use --report-type-access to list custom access","\n"
418
408
  end
419
409
 
420
- end
421
- print reset,"\n"
410
+ task_global_access = json_response['globalTaskAccess']
411
+ task_permissions = role['tasks'] ? role['tasks'] : (json_response['taskPermissions'] || [])
412
+ print cyan
413
+ if options[:include_task_access] || options[:include_all_access]
414
+ print_h2 "Task Access", options
415
+ rows = task_permissions.collect do |it|
416
+ {
417
+ name: it['name'],
418
+ access: format_access_string(it['access'], ["none","full"]),
419
+ }
420
+ end
421
+ print as_pretty_table(rows, [:name, :access], options)
422
+ elsif task_permissions.find {|it| !it['access'].nil?}
423
+ print_h2 "Task Access", options
424
+ print cyan,"Use --task-access to list custom access","\n"
425
+ end
422
426
 
423
- return 0, nil
427
+ workflow_global_access = json_response['globalTaskSetAccess']
428
+ workflow_permissions = role['taskSets'] ? role['taskSets'] : (json_response['taskSetPermissions'] || [])
429
+ print cyan
430
+ if options[:include_workflow_access] || options[:include_all_access]
431
+ print_h2 "Workflow", options
432
+ rows = workflow_permissions.select {|it| !it['access'].nil?}.collect do |it|
433
+ {
434
+ name: it['name'],
435
+ access: format_access_string(it['access'], ["none","full"]),
436
+ }
437
+ end
438
+ print as_pretty_table(rows, [:name, :access], options)
439
+ elsif workflow_permissions.find {|it| !it['access'].nil?}
440
+ print_h2 "Workflow", options
441
+ print cyan,"Use --workflow-access to list custom access","\n"
442
+ end
443
+ print reset,"\n"
444
+ return 0, nil
445
+ end
424
446
  end
425
447
 
426
448
  def list_permissions(args)
427
449
  options = {}
450
+ available_categories = ['feature', 'group', 'cloud', 'instance-type', 'blueprint', 'report-type', 'persona', 'catalog-item-type', 'vdi-pool', 'workflow', 'task']
428
451
  optparse = Morpheus::Cli::OptionParser.new do |opts|
429
- opts.banner = subcommand_usage("[role]")
452
+ opts.banner = subcommand_usage("[role] [category]")
430
453
  build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :dry_run, :remote])
431
- opts.footer = "List the permissions for a role.\n" +
432
- "[role] is required. This is the name or id of a role."
454
+ opts.footer = "List the access for a role.\n" +
455
+ "[role] is required. This is the name or id of a role.\n" +
456
+ "[category] is optional. Available categories: #{ored_list(available_categories)}"
433
457
  end
458
+
434
459
  optparse.parse!(args)
435
- verify_args!(args:args, optparse:optparse, count:1)
460
+ verify_args!(args:args, optparse:optparse, min: 1, max:2)
436
461
  connect(options)
437
-
438
- account = find_account_from_options(options)
439
- account_id = account ? account['id'] : nil
440
462
 
441
- # role = find_role_by_name_or_id(account_id, args[0])
442
- # exit 1 if role.nil?
463
+ category = args[1].to_s.downcase if args[1]
443
464
 
444
- @roles_interface.setopts(options)
445
- if options[:dry_run]
446
- if args[0].to_s =~ /\A\d{1,}\Z/
447
- print_dry_run @roles_interface.dry.get(account_id, args[0].to_i)
448
- else
449
- print_dry_run @roles_interface.dry.list(account_id, {name: args[0]})
450
- end
451
- return
452
- end
465
+ if !category.nil? && !available_categories.include?(category)
466
+ raise_command_error("invalid category: #{category}", args, optparse)
467
+ end
468
+
469
+ account = find_account_from_options(options)
470
+ account_id = account ? account['id'] : nil
453
471
 
454
- json_response = nil
472
+ @roles_interface.setopts(options)
473
+ if options[:dry_run]
455
474
  if args[0].to_s =~ /\A\d{1,}\Z/
456
- json_response = @roles_interface.get(account_id, args[0].to_i)
457
- role = json_response['role']
475
+ print_dry_run @roles_interface.dry.get(account_id, args[0].to_i)
458
476
  else
459
- role = find_role_by_name_or_id(account_id, args[0])
460
- exit 1 if role.nil?
461
- # refetch from show action, argh
462
- json_response = @roles_interface.get(account_id, role['id'])
463
- role = json_response['role']
477
+ print_dry_run @roles_interface.dry.list(account_id, {name: args[0]})
464
478
  end
479
+ return
480
+ end
481
+
482
+ if args[0].to_s =~ /\A\d{1,}\Z/
483
+ role = @roles_interface.get(account_id, args[0].to_i)
484
+ else
485
+ role = find_role_by_name_or_id(account_id, args[0])
486
+ exit 1 if role.nil?
487
+ role = @roles_interface.get(account_id, role['id'])
488
+ end
465
489
 
466
- role_permissions = json_response['featurePermissions']
490
+ available_categories.reject! {|category| category == 'cloud'} if role['role']['roleType'] == 'user'
491
+ available_categories.reject! {|category| category == 'group'} if role['role']['roleType'] == 'account'
467
492
 
468
- if options[:json]
469
- puts as_json(role_permissions, options)
470
- return 0
471
- elsif options[:yaml]
472
- puts as_yaml(role_permissions, options)
473
- return 0
474
- elsif options[:csv]
475
- puts records_as_csv(role_permissions)
476
- return 0
477
- end
493
+ permission_name = -> (s) {
494
+ return 'sites' if s == 'group'
495
+ return 'zones' if s == 'cloud'
496
+ s = 'task-set' if s == 'workflow'
497
+ s = 'app-template' if s == 'blueprint'
498
+ s.split('-').map.with_index{|s,i| i == 0 ? s : s.capitalize}.join + 'Permissions'
499
+ }
500
+ permission_label = -> (s) {s.split('-').collect{|s| s.capitalize}.join(' ') + ' Permissions'}
478
501
 
479
- print cyan
480
- print_h1 "Role Permissions: [#{role['id']}] #{role['authority']}", options
502
+ if category.nil?
503
+ permissions = available_categories.collect{|category| role[permission_name.call(category)].map{|perm| perm.merge({'category' => permission_label.call(category)})}}.flatten
504
+ else
505
+ permissions = role[permission_name.call(category)]
506
+ end
481
507
 
482
- print cyan
483
- if role_permissions && role_permissions.size > 0
484
- rows = role_permissions.collect do |it|
508
+ if options[:json]
509
+ puts as_json(permissions, options)
510
+ return 0
511
+ elsif options[:yaml]
512
+ puts as_yaml(permissions, options)
513
+ return 0
514
+ elsif options[:csv]
515
+ puts records_as_csv(permissions, :include_fields => ['category', 'id', 'code', 'name', 'access', 'sub category'])
516
+ return 0
517
+ end
518
+
519
+ print cyan
520
+ print_h1 "Role: [#{role['role']['id']},#{role['role']['owner']['name']}] #{role['role']['authority']}", options
521
+
522
+ (category.nil? ? available_categories : [category]).each do |category|
523
+ print_h2 "#{permission_label.call(category)}", options
524
+ permissions = role[permission_name.call(category)]
525
+ if permissions.size > 0
526
+ rows = permissions.collect do |it|
485
527
  {
486
528
  code: it['code'],
487
529
  name: it['name'],
@@ -502,10 +544,8 @@ EOT
502
544
  else
503
545
  puts "No permissions found"
504
546
  end
505
-
506
- print reset,"\n"
507
- return 0
508
-
547
+ end
548
+ print reset,"\n"
509
549
  end
510
550
 
511
551
  def add(args)
@@ -518,74 +558,139 @@ EOT
518
558
  options[:permissions] ||= {}
519
559
  parse_access_csv(options[:permissions], val, args, optparse)
520
560
  end
521
- opts.on('--global-group-access ACCESS', String, "Update the global group (site) access: [none|read|custom|full]" ) do |val|
561
+ opts.add_hidden_option('--permissions')
562
+ opts.on('--feature-access CODE=ACCESS', String, "Set feature permission access by permission code. Example: dashboard=read,operations-wiki=full" ) do |val|
563
+ options[:permissions] ||= {}
564
+ parse_access_csv(options[:permissions], val, args, optparse)
565
+ end
566
+ opts.on('--global-group-access ACCESS', String, "Update the global group (site) access: [none|read|full]" ) do |val|
567
+ params['globalSiteAccess'] = val.to_s.downcase
568
+ end
569
+ opts.add_hidden_option('--global-group-access')
570
+ opts.on('--default-group-access ACCESS', String, "Update the default group (site) access: [none|read|full]" ) do |val|
522
571
  params['globalSiteAccess'] = val.to_s.downcase
523
572
  end
524
573
  opts.on('--groups ID=ACCESS', String, "Set group (site) to a custom access by group id. Example: 1=none,2=full,3=read" ) do |val|
525
574
  options[:group_permissions] ||= {}
526
575
  parse_access_csv(options[:group_permissions], val, args, optparse)
527
576
  end
528
- opts.on('--global-cloud-access ACCESS', String, "Update the global cloud (zone) access: [none|custom|full]" ) do |val|
577
+ opts.on('--global-cloud-access ACCESS', String, "Update the global cloud (zone) access: [none|read|full]" ) do |val|
578
+ params['globalZoneAccess'] = val.to_s.downcase
579
+ end
580
+ opts.add_hidden_option('--global-cloud-access')
581
+ opts.on('--default-cloud-access ACCESS', String, "Update the default cloud (zone) access: [none|read|full]" ) do |val|
529
582
  params['globalZoneAccess'] = val.to_s.downcase
530
583
  end
531
584
  opts.on('--clouds ID=ACCESS', String, "Set cloud (zone) to a custom access by cloud id. Example: 1=none,2=full,3=read" ) do |val|
532
585
  options[:cloud_permissions] ||= {}
533
586
  parse_access_csv(options[:cloud_permissions], val, args, optparse)
534
587
  end
535
- opts.on('--global-instance-type-access ACCESS', String, "Update the global instance type access: [none|custom|full]" ) do |val|
588
+ opts.on('--global-instance-type-access ACCESS', String, "Update the global instance type access: [none|full]" ) do |val|
589
+ params['globalInstanceTypeAccess'] = val.to_s.downcase
590
+ end
591
+ opts.add_hidden_option('--global-instance-type-access')
592
+ opts.on('--default-instance-type-access ACCESS', String, "Update the default instance type access: [none|full]" ) do |val|
536
593
  params['globalInstanceTypeAccess'] = val.to_s.downcase
537
594
  end
538
595
  opts.on('--instance-types CODE=ACCESS', String, "Set instance type to a custom access instance type code. Example: nginx=full,apache=none" ) do |val|
539
596
  options[:instance_type_permissions] ||= {}
540
597
  parse_access_csv(options[:instance_type_permissions], val, args, optparse)
541
598
  end
542
- opts.on('--global-blueprint-access ACCESS', String, "Update the global blueprint access: [none|custom|full]" ) do |val|
599
+ opts.on('--global-blueprint-access ACCESS', String, "Update the global blueprint access: [none|full]" ) do |val|
600
+ params['globalAppTemplateAccess'] = val.to_s.downcase
601
+ end
602
+ opts.add_hidden_option('--global-blueprint-access')
603
+ opts.on('--default-blueprint-access ACCESS', String, "Update the default blueprint access: [none|full]" ) do |val|
543
604
  params['globalAppTemplateAccess'] = val.to_s.downcase
544
605
  end
545
606
  opts.on('--blueprints ID=ACCESS', String, "Set blueprint to a custom access by blueprint id. Example: 1=full,2=none" ) do |val|
546
607
  options[:blueprint_permissions] ||= {}
547
608
  parse_access_csv(options[:blueprint_permissions], val, args, optparse)
548
609
  end
549
- opts.on('--global-catalog-item-type-access ACCESS', String, "Update the global catalog item type access: [none|custom|full]" ) do |val|
610
+ opts.on('--global-catalog-item-type-access ACCESS', String, "Update the global catalog item type access: [none|full]" ) do |val|
611
+ params['globalCatalogItemTypeAccess'] = val.to_s.downcase
612
+ end
613
+ opts.add_hidden_option('--global-catalog-item-type-access')
614
+ opts.on('--default-catalog-item-type-access ACCESS', String, "Update the default catalog item type access: [none|full]" ) do |val|
550
615
  params['globalCatalogItemTypeAccess'] = val.to_s.downcase
551
616
  end
552
617
  opts.on('--catalog-item-types CODE=ACCESS', String, "Set catalog item type to a custom access by catalog item type id. Example: 1=full,2=none" ) do |val|
553
618
  options[:catalog_item_type_permissions] ||= {}
554
619
  parse_access_csv(options[:catalog_item_type_permissions], val, args, optparse)
555
620
  end
621
+ opts.on('--default-persona-access ACCESS', String, "Update the default persona access: [none|full]" ) do |val|
622
+ params['globalPersonaAccess'] = val.to_s.downcase
623
+ end
556
624
  opts.on('--personas CODE=ACCESS', String, "Set persona to a custom access by persona code. Example: standard=full,serviceCatalog=full,vdi=full" ) do |val|
557
625
  options[:persona_permissions] ||= {}
558
626
  parse_access_csv(options[:persona_permissions], val, args, optparse)
559
627
  end
560
- opts.on('--global-vdi-pool-access-access ACCESS', String, "Update the global VDI pool access: [none|custom|full]" ) do |val|
628
+ opts.on('--global-vdi-pool-access-access ACCESS', String, "Update the global VDI pool access: [none|full]" ) do |val|
629
+ params['globalVdiPoolAccess'] = val.to_s.downcase
630
+ end
631
+ opts.add_hidden_option('--global-vdi-pool-access-access')
632
+ opts.on('--default-vdi-pool-access-access ACCESS', String, "Update the default VDI pool access: [none|full]" ) do |val|
561
633
  params['globalVdiPoolAccess'] = val.to_s.downcase
562
634
  end
563
635
  opts.on('--vdi-pools ID=ACCESS', String, "Set VDI pool to a custom access by VDI pool id. Example: 1=full,2=none" ) do |val|
564
636
  options[:vdi_pool_permissions] ||= {}
565
637
  parse_access_csv(options[:vdi_pool_permissions], val, args, optparse)
566
638
  end
567
- opts.on('--global-report-type-access ACCESS', String, "Update the global report type access: [none|custom|full]" ) do |val|
639
+ opts.on('--global-report-type-access ACCESS', String, "Update the global report type access: [none|full]" ) do |val|
640
+ params['globalReportTypeAccess'] = val.to_s.downcase
641
+ end
642
+ opts.on('--default-report-type-access ACCESS', String, "Update the default report type access: [none|full]" ) do |val|
568
643
  params['globalReportTypeAccess'] = val.to_s.downcase
569
644
  end
645
+ opts.add_hidden_option('--default-report-type-access')
570
646
  opts.on('--report-types CODE=ACCESS', String, "Set report type to a custom access by report type code. Example: appCost=none,guidance=full" ) do |val|
571
647
  options[:report_type_permissions] ||= {}
572
648
  parse_access_csv(options[:report_type_permissions], val, args, optparse)
573
649
  end
650
+ opts.on('--global-task-access ACCESS', String, "Set the global task access: [none|full]" ) do |val|
651
+ params['globalTaskAccess'] = val.to_s.downcase
652
+ end
653
+ opts.add_hidden_option('--global-task-access')
654
+ opts.on('--default-task-access ACCESS', String, "Set the default task access: [none|full]" ) do |val|
655
+ params['globalTaskAccess'] = val.to_s.downcase
656
+ end
657
+ opts.on('--tasks ID=ACCESS', String, "Set task to a custom access by task id. Example: 1=none,2=full" ) do |val|
658
+ options[:task_permissions] ||= {}
659
+ parse_access_csv(options[:task_permissions], val, args, optparse)
660
+ end
661
+ opts.on('--global-workflow-access ACCESS', String, "Set the default workflow access: [none|full]" ) do |val|
662
+ params['globalTaskSetAccess'] = val.to_s.downcase
663
+ end
664
+ opts.add_hidden_option('--global-workflow-access')
665
+ opts.on('--default-workflow-access ACCESS', String, "Set the default workflow access: [none|full]" ) do |val|
666
+ params['globalTaskSetAccess'] = val.to_s.downcase
667
+ end
668
+ opts.on('--workflows ID=ACCESS', String, "Set workflow to a custom access by workflow id. Example: 1=none,2=full" ) do |val|
669
+ options[:workflow_permissions] ||= {}
670
+ parse_access_csv(options[:workflow_permissions], val, args, optparse)
671
+ end
574
672
  opts.on('--reset-permissions', "Reset all feature permission access to none. This can be used in conjunction with --permissions to recreate the feature permission access for the role." ) do
575
673
  options[:reset_permissions] = true
576
674
  end
577
- opts.on('--reset-all-access', "Reset all access to none including permissions, global groups, instance types, etc. This can be used in conjunction with --permissions to recreate the feature permission access for the role." ) do
675
+ opts.add_hidden_option('--reset-permissions')
676
+ opts.on('--reset-feature-access', "Reset all feature permission access to none. This can be used in conjunction with --feature-access to recreate the feature permission access for the role." ) do
677
+ options[:reset_permissions] = true
678
+ end
679
+ opts.on('--reset-all-access', "Reset all access to none including permissions, global groups, instance types, etc. This can be used in conjunction with --feature-access to recreate the feature permission access for the role." ) do
578
680
  options[:reset_all_access] = true
681
+ end
682
+ opts.on('--owner ID', String, "Set the owner/tenant/account for the role by account id. Only master tenants with full permission for Tenant and Role may use this option." ) do |val|
683
+ params['owner'] = val
579
684
  end
580
685
  opts.footer = <<-EOT
581
686
  Create a new role.
582
687
  [name] is required. This is a unique name (authority) for the new role.
583
688
  All the role permissions and access values can be configured.
584
- Use --permissions "CODE=ACCESS,CODE=ACCESS" to update access levels for specific feature permissions identified by code.
585
- Use --global-instance-type-access custom --instance-types "CODE=ACCESS,CODE=ACCESS" to customize instance type access.
689
+ Use --feature-access "CODE=ACCESS,CODE=ACCESS" to update access levels for specific feature permissions identified by code.
690
+ Use --default-instance-type-access custom --instance-types "CODE=ACCESS,CODE=ACCESS" to customize instance type access.
586
691
  Only the specified permissions,instance types, etc. are updated.
587
- Use --reset-permissions to set access to "none" for all unspecified feature permissions.
588
- Use --reset-all-access to set access to "none" for all unspecified feature permissions and global access values for groups, instance types, etc.
692
+ Use --reset-feature-access to set access to "none" for all unspecified feature permissions.
693
+ Use --reset-all-access to set access to "none" for all unspecified feature permissions and default access values for groups, instance types, etc.
589
694
  EOT
590
695
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
591
696
  end
@@ -619,21 +724,35 @@ EOT
619
724
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 2}], options[:options])
620
725
  role_payload['description'] = v_prompt['description']
621
726
 
622
- if @is_master_account
623
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'roleType', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => role_type_options, 'defaultValue' => 'user', 'displayOrder' => 3}], options[:options])
727
+ if params['owner']
728
+ if @is_master_account && has_complete_access
729
+ role_payload['owner'] = params['owner']
730
+ else
731
+ print_red_alert "You do not have the necessary authority to use owner option"
732
+ return
733
+ end
734
+ elsif @is_master_account && has_complete_access
735
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'owner', 'fieldLabel' => 'Owner', 'type' => 'select', 'selectOptions' => role_owner_options, 'defaultValue' => current_account['id'], 'displayOrder' => 3}], options[:options])
736
+ role_payload['owner'] = v_prompt['owner']
737
+ else
738
+ role_payload['owner'] = current_account['id']
739
+ end
740
+
741
+ if @is_master_account && role_payload['owner'] == current_account['id']
742
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'roleType', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => role_type_options, 'defaultValue' => 'user', 'displayOrder' => 4}], options[:options])
624
743
  role_payload['roleType'] = v_prompt['roleType']
625
744
  else
626
745
  role_payload['roleType'] = 'user'
627
746
  end
628
747
 
629
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'baseRole', 'fieldLabel' => 'Copy From Role', 'type' => 'text', 'displayOrder' => 4}], options[:options])
748
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'baseRole', 'fieldLabel' => 'Copy From Role', 'type' => 'select', 'selectOptions' => base_role_options(role_payload), 'displayOrder' => 5}], options[:options])
630
749
  if v_prompt['baseRole'].to_s != ''
631
750
  base_role = find_role_by_name_or_id(account_id, v_prompt['baseRole'])
632
751
  exit 1 if base_role.nil?
633
752
  role_payload['baseRoleId'] = base_role['id']
634
753
  end
635
754
 
636
- if @is_master_account
755
+ if @is_master_account && role_payload['owner'] == current_account['id']
637
756
  if role_payload['roleType'] == 'user'
638
757
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'multitenant', 'fieldLabel' => 'Multitenant', 'type' => 'checkbox', 'defaultValue' => 'off', 'description' => 'A Multitenant role is automatically copied into all existing subaccounts as well as placed into a subaccount when created. Useful for providing a set of predefined roles a Customer can use', 'displayOrder' => 5}], options[:options])
639
758
  role_payload['multitenant'] = ['on','true'].include?(v_prompt['multitenant'].to_s)
@@ -752,6 +871,32 @@ EOT
752
871
  end
753
872
  params['reportTypes'] = perms_array
754
873
  end
874
+ if options[:task_permissions]
875
+ perms_array = []
876
+ options[:task_permissions].each do |k,v|
877
+ task_id = k
878
+ access_value = v.to_s.empty? ? "none" : v.to_s
879
+ if task_id =~ /\A\d{1,}\Z/
880
+ perms_array << {"id" => task_id.to_i, "access" => access_value}
881
+ else
882
+ perms_array << {"name" => task_id, "access" => access_value}
883
+ end
884
+ end
885
+ params['tasks'] = perms_array
886
+ end
887
+ if options[:workflow_permissions]
888
+ perms_array = []
889
+ options[:workflow_permissions].each do |k,v|
890
+ workflow_id = k
891
+ access_value = v.to_s.empty? ? "none" : v.to_s
892
+ if workflow_id =~ /\A\d{1,}\Z/
893
+ perms_array << {"id" => workflow_id.to_i, "access" => access_value}
894
+ else
895
+ perms_array << {"name" => workflow_id, "access" => access_value}
896
+ end
897
+ end
898
+ params['workflows'] = perms_array
899
+ end
755
900
  if options[:reset_permissions]
756
901
  params["resetPermissions"] = true
757
902
  end
@@ -790,6 +935,10 @@ EOT
790
935
  if account
791
936
  details_options.push "--account-id", account['id'].to_s
792
937
  end
938
+
939
+ if role_payload['owner']
940
+ details_options.push "--account-id", role_payload['owner'].to_s
941
+ end
793
942
  get(details_options)
794
943
 
795
944
  rescue RestClient::Exception => e
@@ -808,35 +957,60 @@ EOT
808
957
  options[:permissions] ||= {}
809
958
  parse_access_csv(options[:permissions], val, args, optparse)
810
959
  end
811
- opts.on('--global-group-access ACCESS', String, "Update the global group (site) access: [none|read|custom|full]" ) do |val|
960
+ opts.add_hidden_option('--permissions')
961
+ opts.on('--feature-access CODE=ACCESS', String, "Set feature permission access by permission code. Example: dashboard=read,operations-wiki=full" ) do |val|
962
+ options[:permissions] ||= {}
963
+ parse_access_csv(options[:permissions], val, args, optparse)
964
+ end
965
+ opts.on('--global-group-access ACCESS', String, "Update the global group (site) access: [none|read|full]" ) do |val|
966
+ params['globalSiteAccess'] = val.to_s.downcase
967
+ end
968
+ opts.add_hidden_option('--global-group-access')
969
+ opts.on('--default-group-access ACCESS', String, "Update the default group (site) access: [none|read|full]" ) do |val|
812
970
  params['globalSiteAccess'] = val.to_s.downcase
813
971
  end
814
972
  opts.on('--groups ID=ACCESS', String, "Set group (site) to a custom access by group id. Example: 1=none,2=full,3=read" ) do |val|
815
973
  options[:group_permissions] ||= {}
816
974
  parse_access_csv(options[:group_permissions], val, args, optparse)
817
975
  end
818
- opts.on('--global-cloud-access ACCESS', String, "Update the global cloud (zone) access: [none|custom|full]" ) do |val|
976
+ opts.on('--global-cloud-access ACCESS', String, "Update the global cloud (zone) access: [none|read|full]" ) do |val|
977
+ params['globalZoneAccess'] = val.to_s.downcase
978
+ end
979
+ opts.add_hidden_option('--global-cloud-access')
980
+ opts.on('--default-cloud-access ACCESS', String, "Update the default cloud (zone) access: [none|read|full]" ) do |val|
819
981
  params['globalZoneAccess'] = val.to_s.downcase
820
982
  end
821
983
  opts.on('--clouds ID=ACCESS', String, "Set cloud (zone) to a custom access by cloud id. Example: 1=none,2=full,3=read" ) do |val|
822
984
  options[:cloud_permissions] ||= {}
823
985
  parse_access_csv(options[:cloud_permissions], val, args, optparse)
824
986
  end
825
- opts.on('--global-instance-type-access ACCESS', String, "Update the global instance type access: [none|custom|full]" ) do |val|
987
+ opts.on('--global-instance-type-access ACCESS', String, "Update the global instance type access: [none|full]" ) do |val|
988
+ params['globalInstanceTypeAccess'] = val.to_s.downcase
989
+ end
990
+ opts.add_hidden_option('--global-instance-type-access')
991
+ opts.on('--default-instance-type-access ACCESS', String, "Update the default instance type access: [none|full]" ) do |val|
826
992
  params['globalInstanceTypeAccess'] = val.to_s.downcase
827
993
  end
828
994
  opts.on('--instance-types CODE=ACCESS', String, "Set instance type to a custom access instance type code. Example: nginx=full,apache=none" ) do |val|
829
995
  options[:instance_type_permissions] ||= {}
830
996
  parse_access_csv(options[:instance_type_permissions], val, args, optparse)
831
997
  end
832
- opts.on('--global-blueprint-access ACCESS', String, "Update the global blueprint access: [none|custom|full]" ) do |val|
998
+ opts.on('--global-blueprint-access ACCESS', String, "Update the global blueprint access: [none|full]" ) do |val|
999
+ params['globalAppTemplateAccess'] = val.to_s.downcase
1000
+ end
1001
+ opts.add_hidden_option('--global-blueprint-access')
1002
+ opts.on('--default-blueprint-access ACCESS', String, "Update the default blueprint access: [none|full]" ) do |val|
833
1003
  params['globalAppTemplateAccess'] = val.to_s.downcase
834
1004
  end
835
1005
  opts.on('--blueprints ID=ACCESS', String, "Set blueprint to a custom access by blueprint id. Example: 1=full,2=none" ) do |val|
836
1006
  options[:blueprint_permissions] ||= {}
837
1007
  parse_access_csv(options[:blueprint_permissions], val, args, optparse)
838
1008
  end
839
- opts.on('--global-catalog-item-type-access ACCESS', String, "Update the global catalog item type access: [none|custom|full]" ) do |val|
1009
+ opts.on('--global-catalog-item-type-access ACCESS', String, "Update the global catalog item type access: [none|full]" ) do |val|
1010
+ params['globalCatalogItemTypeAccess'] = val.to_s.downcase
1011
+ end
1012
+ opts.add_hidden_option('--global-catalog-item-type-access')
1013
+ opts.on('--default-catalog-item-type-access ACCESS', String, "Update the default catalog item type access: [none|full]" ) do |val|
840
1014
  params['globalCatalogItemTypeAccess'] = val.to_s.downcase
841
1015
  end
842
1016
  opts.on('--catalog-item-types CODE=ACCESS', String, "Set catalog item type to a custom access by catalog item type id. Example: 1=full,2=none" ) do |val|
@@ -847,24 +1021,58 @@ EOT
847
1021
  options[:persona_permissions] ||= {}
848
1022
  parse_access_csv(options[:persona_permissions], val, args, optparse)
849
1023
  end
850
- opts.on('--global-vdi-pool-access-access ACCESS', String, "Update the global VDI pool access: [none|custom|full]" ) do |val|
1024
+ opts.on('--global-vdi-pool-access ACCESS', String, "Update the global VDI pool access: [none|full]" ) do |val|
1025
+ params['globalVdiPoolAccess'] = val.to_s.downcase
1026
+ end
1027
+ opts.add_hidden_option('--global-vdi-pool-access')
1028
+ opts.on('--default-vdi-pool-access ACCESS', String, "Update the default VDI pool access: [none|full]" ) do |val|
851
1029
  params['globalVdiPoolAccess'] = val.to_s.downcase
852
1030
  end
853
1031
  opts.on('--vdi-pools ID=ACCESS', String, "Set VDI pool to a custom access by VDI pool id. Example: 1=full,2=none" ) do |val|
854
1032
  options[:vdi_pool_permissions] ||= {}
855
1033
  parse_access_csv(options[:vdi_pool_permissions], val, args, optparse)
856
1034
  end
857
- opts.on('--global-report-type-access ACCESS', String, "Update the global report type access: [none|custom|full]" ) do |val|
1035
+ opts.on('--global-report-type-access ACCESS', String, "Update the global report type access: [none|full]" ) do |val|
1036
+ params['globalReportTypeAccess'] = val.to_s.downcase
1037
+ end
1038
+ opts.add_hidden_option('--global-report-type-access')
1039
+ opts.on('--default-report-type-access ACCESS', String, "Update the default report type access: [none|full]" ) do |val|
858
1040
  params['globalReportTypeAccess'] = val.to_s.downcase
859
1041
  end
860
1042
  opts.on('--report-types CODE=ACCESS', String, "Set report type to a custom access by report type code. Example: appCost=none,guidance=full" ) do |val|
861
1043
  options[:report_type_permissions] ||= {}
862
1044
  parse_access_csv(options[:report_type_permissions], val, args, optparse)
863
1045
  end
1046
+ opts.on('--global-task-access ACCESS', String, "Update the global task access: [none|full]" ) do |val|
1047
+ params['globalTaskAccess'] = val.to_s.downcase
1048
+ end
1049
+ opts.add_hidden_option('--global-task-access')
1050
+ opts.on('--default-task-access ACCESS', String, "Update the default task access: [none|full]" ) do |val|
1051
+ params['globalTaskAccess'] = val.to_s.downcase
1052
+ end
1053
+ opts.on('--tasks ID=ACCESS', String, "Set task to a custom access by task id. Example: 1=none,2=full" ) do |val|
1054
+ options[:task_permissions] ||= {}
1055
+ parse_access_csv(options[:task_permissions], val, args, optparse)
1056
+ end
1057
+ opts.on('--global-workflow-access ACCESS', String, "Update the global workflow access: [none|full]" ) do |val|
1058
+ params['globalTaskSetAccess'] = val.to_s.downcase
1059
+ end
1060
+ opts.add_hidden_option('--global-workflow-access')
1061
+ opts.on('--default-workflow-access ACCESS', String, "Update the default workflow access: [none|full]" ) do |val|
1062
+ params['globalTaskSetAccess'] = val.to_s.downcase
1063
+ end
1064
+ opts.on('--workflows ID=ACCESS', String, "Set workflow to a custom access by workflow id. Example: 1=none,2=full" ) do |val|
1065
+ options[:workflow_permissions] ||= {}
1066
+ parse_access_csv(options[:workflow_permissions], val, args, optparse)
1067
+ end
864
1068
  opts.on('--reset-permissions', "Reset all feature permission access to none. This can be used in conjunction with --permissions to recreate the feature permission access for the role." ) do
865
1069
  options[:reset_permissions] = true
866
1070
  end
867
- opts.on('--reset-all-access', "Reset all access to none including permissions, global groups, instance types, etc. This can be used in conjunction with --permissions to recreate the feature permission access for the role." ) do
1071
+ opts.add_hidden_option('--reset-permissions')
1072
+ opts.on('--reset-feature-access', "Reset all feature permission access to none. This can be used in conjunction with --feature-access to recreate the feature permission access for the role." ) do
1073
+ options[:reset_permissions] = true
1074
+ end
1075
+ opts.on('--reset-all-access', "Reset all access to none including permissions, global groups, instance types, etc. This can be used in conjunction with --feature-access to recreate the feature permission access for the role." ) do
868
1076
  options[:reset_all_access] = true
869
1077
  end
870
1078
  build_standard_update_options(opts, options)
@@ -872,10 +1080,10 @@ EOT
872
1080
  Update a role.
873
1081
  [role] is required. This is the name (authority) or id of a role.
874
1082
  All the role permissions and access values can be configured.
875
- Use --permissions "CODE=ACCESS,CODE=ACCESS" to update access levels for specific feature permissions identified by code.
876
- Use --global-instance-type-access custom --instance-types "CODE=ACCESS,CODE=ACCESS" to customize instance type access.
1083
+ Use --feature-access "CODE=ACCESS,CODE=ACCESS" to update access levels for specific feature permissions identified by code.
1084
+ Use --default-instance-type-access custom --instance-types "CODE=ACCESS,CODE=ACCESS" to customize instance type access.
877
1085
  Only the specified permissions,instance types, etc. are updated.
878
- Use --reset-permissions to set access to "none" for all unspecified feature permissions.
1086
+ Use --reset-feature-access to set access to "none" for all unspecified feature permissions.
879
1087
  Use --reset-all-access to set access to "none" for all unspecified feature permissions and global access values for groups, instance types, etc.
880
1088
  EOT
881
1089
  end
@@ -1016,6 +1224,32 @@ EOT
1016
1224
  end
1017
1225
  params['reportTypes'] = perms_array
1018
1226
  end
1227
+ if options[:task_permissions]
1228
+ perms_array = []
1229
+ options[:task_permissions].each do |k,v|
1230
+ task_id = k
1231
+ access_value = v.to_s.empty? ? "none" : v.to_s
1232
+ if task_id =~ /\A\d{1,}\Z/
1233
+ perms_array << {"id" => task_id.to_i, "access" => access_value}
1234
+ else
1235
+ perms_array << {"name" => task_id, "access" => access_value}
1236
+ end
1237
+ end
1238
+ params['tasks'] = perms_array
1239
+ end
1240
+ if options[:workflow_permissions]
1241
+ perms_array = []
1242
+ options[:workflow_permissions].each do |k,v|
1243
+ workflow_id = k
1244
+ access_value = v.to_s.empty? ? "none" : v.to_s
1245
+ if workflow_id =~ /\A\d{1,}\Z/
1246
+ perms_array << {"id" => workflow_id.to_i, "access" => access_value}
1247
+ else
1248
+ perms_array << {"name" => workflow_id, "access" => access_value}
1249
+ end
1250
+ end
1251
+ params['taskSets'] = perms_array
1252
+ end
1019
1253
  if options[:reset_permissions]
1020
1254
  params["resetPermissions"] = true
1021
1255
  end
@@ -1099,7 +1333,7 @@ EOT
1099
1333
 
1100
1334
  def update_feature_access(args)
1101
1335
  options = {}
1102
- allowed_access_values = ['full', 'user', 'read', 'none'] # just for display , veries per permission
1336
+ allowed_access_values = ["full", "full_decrypted", "group", "listfiles", "managerules", "no", "none", "provision", "read", "rolemappings", "user", "view", "yes"]
1103
1337
  permission_code = nil
1104
1338
  access_value = nil
1105
1339
  optparse = Morpheus::Cli::OptionParser.new do |opts|
@@ -1168,15 +1402,19 @@ EOT
1168
1402
  end
1169
1403
 
1170
1404
  def update_global_group_access(args)
1171
- usage = "Usage: morpheus roles update-global-group-access [role] [full|read|custom|none]"
1405
+ puts "#{yellow}DEPRECATED#{reset}"
1406
+ update_default_group_access(args)
1407
+ end
1408
+
1409
+ def update_default_group_access(args)
1172
1410
  options = {}
1173
1411
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1174
- opts.banner = subcommand_usage("[role] [full|read|custom|none]")
1412
+ opts.banner = subcommand_usage("[role] [access]")
1175
1413
  build_common_options(opts, options, [:json, :dry_run, :remote])
1176
1414
  opts.footer = <<-EOT
1177
- Update global group access for a role.
1415
+ Update default group access for a role.
1178
1416
  [role] is required. This is the name (authority) or id of a role.
1179
- [access] is required. This is the access level to assign: full, read, custom or none.
1417
+ [access] is required. This is the access level to assign: full, read, or none.
1180
1418
  Only applicable to User roles.
1181
1419
  EOT
1182
1420
  end
@@ -1188,7 +1426,7 @@ EOT
1188
1426
  end
1189
1427
  name = args[0]
1190
1428
  access_value = args[1].to_s.downcase
1191
- if !['full', 'read', 'custom', 'none'].include?(access_value)
1429
+ if !['full', 'read', 'none'].include?(access_value)
1192
1430
  puts optparse
1193
1431
  exit 1
1194
1432
  end
@@ -1212,7 +1450,7 @@ EOT
1212
1450
  print JSON.pretty_generate(json_response)
1213
1451
  print "\n"
1214
1452
  else
1215
- print_green_success "Role #{role['authority']} global group access updated"
1453
+ print_green_success "Role #{role['authority']} default group access updated"
1216
1454
  end
1217
1455
  rescue RestClient::Exception => e
1218
1456
  print_rest_exception(e, options)
@@ -1226,7 +1464,7 @@ EOT
1226
1464
  group_id = nil
1227
1465
  access_value = nil
1228
1466
  do_all = false
1229
- allowed_access_values = ['full', 'read', 'none']
1467
+ allowed_access_values = ['full', 'read', 'none', 'default']
1230
1468
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1231
1469
  opts.banner = subcommand_usage("[role] [group] [access]")
1232
1470
  opts.on( '-g', '--group GROUP', "Group name or id" ) do |val|
@@ -1244,7 +1482,6 @@ Update role access for a group or all groups.
1244
1482
  [role] is required. This is the name or id of a role.
1245
1483
  --group or --all is required. This is the name or id of a group.
1246
1484
  --access is required. This is the new access value: #{ored_list(allowed_access_values)}
1247
- Only applicable to User roles and when global group access is set to "custom".
1248
1485
  EOT
1249
1486
 
1250
1487
  end
@@ -1279,14 +1516,6 @@ EOT
1279
1516
  role = find_role_by_name_or_id(account_id, name)
1280
1517
  return 1 if role.nil?
1281
1518
 
1282
- role_json = @roles_interface.get(account_id, role['id'])
1283
- if role_json['globalSiteAccess'] != 'custom'
1284
- print "\n", red, "Global Group Access is currently: #{role_json['globalSiteAccess'].capitalize}"
1285
- print "\n", "You must first set it to Custom via `morpheus roles update-global-group-access \"#{name}\" custom`"
1286
- print "\n\n", reset
1287
- exit 1
1288
- end
1289
-
1290
1519
  group = nil
1291
1520
  if !do_all
1292
1521
  group = find_group_by_name_or_id_for_provisioning(group_id)
@@ -1326,15 +1555,19 @@ EOT
1326
1555
  end
1327
1556
 
1328
1557
  def update_global_cloud_access(args)
1329
- usage = "Usage: morpheus roles update-global-cloud-access [role] [full|custom|none]"
1558
+ puts "#{yellow}DEPRECATED#{reset}"
1559
+ update_default_cloud_access(args)
1560
+ end
1561
+
1562
+ def update_default_cloud_access(args)
1330
1563
  options = {}
1331
1564
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1332
- opts.banner = subcommand_usage("[role] [full|custom|none]")
1565
+ opts.banner = subcommand_usage("[role] [access]")
1333
1566
  build_common_options(opts, options, [:json, :dry_run, :remote])
1334
- opts.footer = <<-EOT
1335
- Update global cloud access for a role.
1567
+ opts.footer = <<-EOT
1568
+ Update default cloud access for a role.
1336
1569
  [role] is required. This is the name (authority) or id of a role.
1337
- [access] is required. This is the access level to assign: full, custom or none.
1570
+ [access] is required. This is the access level to assign: full, read or none.
1338
1571
  Only applicable to Tenant roles.
1339
1572
  EOT
1340
1573
  end
@@ -1346,7 +1579,7 @@ EOT
1346
1579
  end
1347
1580
  name = args[0]
1348
1581
  access_value = args[1].to_s.downcase
1349
- if !['full', 'custom', 'none'].include?(access_value)
1582
+ if !['full', 'read', 'none'].include?(access_value)
1350
1583
  puts optparse
1351
1584
  exit 1
1352
1585
  end
@@ -1370,7 +1603,7 @@ EOT
1370
1603
  print JSON.pretty_generate(json_response)
1371
1604
  print "\n"
1372
1605
  else
1373
- print_green_success "Role #{role['authority']} global cloud access updated"
1606
+ print_green_success "Role #{role['authority']} default cloud access updated"
1374
1607
  end
1375
1608
  rescue RestClient::Exception => e
1376
1609
  print_rest_exception(e, options)
@@ -1383,7 +1616,7 @@ EOT
1383
1616
  cloud_id = nil
1384
1617
  access_value = nil
1385
1618
  do_all = false
1386
- allowed_access_values = ['full', 'read', 'none']
1619
+ allowed_access_values = ['full', 'read', 'none', 'default']
1387
1620
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1388
1621
  opts.banner = subcommand_usage("[role]")
1389
1622
  opts.on( '-c', '--cloud CLOUD', "Cloud name or id" ) do |val|
@@ -1401,7 +1634,6 @@ Update role access for a cloud or all clouds.
1401
1634
  [role] is required. This is the name or id of a role.
1402
1635
  --cloud or --all is required. This is the name or id of a cloud.
1403
1636
  --access is required. This is the new access value: #{ored_list(allowed_access_values)}
1404
- Only applicable to Tenant roles and when global cloud access is set to "custom".
1405
1637
  EOT
1406
1638
  end
1407
1639
  optparse.parse!(args)
@@ -1436,12 +1668,6 @@ EOT
1436
1668
  exit 1 if role.nil?
1437
1669
 
1438
1670
  role_json = @roles_interface.get(account_id, role['id'])
1439
- if role_json['globalZoneAccess'] != 'custom'
1440
- print "\n", red, "Global Cloud Access is currently: #{role_json['globalZoneAccess'].capitalize}"
1441
- print "\n", "You must first set it to Custom via `morpheus roles update-global-cloud-access \"#{name}\" custom`"
1442
- print "\n\n", reset
1443
- exit 1
1444
- end
1445
1671
 
1446
1672
  cloud = nil
1447
1673
  if !do_all
@@ -1481,15 +1707,19 @@ EOT
1481
1707
  end
1482
1708
 
1483
1709
  def update_global_instance_type_access(args)
1484
- usage = "Usage: morpheus roles update-global-instance-type-access [role] [full|custom|none]"
1710
+ puts "#{yellow}DEPRECATED#{reset}"
1711
+ update_default_instance_type_access(args)
1712
+ end
1713
+
1714
+ def update_default_instance_type_access(args)
1485
1715
  options = {}
1486
1716
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1487
- opts.banner = subcommand_usage("[role] [full|custom|none]")
1717
+ opts.banner = subcommand_usage("[role] [access]")
1488
1718
  build_common_options(opts, options, [:json, :dry_run, :remote])
1489
1719
  opts.footer = <<-EOT
1490
- Update global instance type access for a role.
1720
+ Update default instance type access for a role.
1491
1721
  [role] is required. This is the name (authority) or id of a role.
1492
- [access] is required. This is the access level to assign: full, custom or none.
1722
+ [access] is required. This is the access level to assign: full or none.
1493
1723
  EOT
1494
1724
  end
1495
1725
  optparse.parse!(args)
@@ -1500,7 +1730,7 @@ EOT
1500
1730
  end
1501
1731
  name = args[0]
1502
1732
  access_value = args[1].to_s.downcase
1503
- if !['full', 'custom', 'none'].include?(access_value)
1733
+ if !['full', 'none'].include?(access_value)
1504
1734
  puts optparse
1505
1735
  exit 1
1506
1736
  end
@@ -1525,7 +1755,7 @@ EOT
1525
1755
  print JSON.pretty_generate(json_response)
1526
1756
  print "\n"
1527
1757
  else
1528
- print_green_success "Role #{role['authority']} global instance type access updated"
1758
+ print_green_success "Role #{role['authority']} default instance type access updated"
1529
1759
  end
1530
1760
  rescue RestClient::Exception => e
1531
1761
  print_rest_exception(e, options)
@@ -1538,7 +1768,7 @@ EOT
1538
1768
  instance_type_name = nil
1539
1769
  access_value = nil
1540
1770
  do_all = false
1541
- allowed_access_values = ['full', 'none']
1771
+ allowed_access_values = ['full', 'none', 'default']
1542
1772
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1543
1773
  opts.banner = subcommand_usage("[role] [type] [access]")
1544
1774
  opts.on( '--instance-type INSTANCE_TYPE', String, "Instance Type name" ) do |val|
@@ -1587,13 +1817,6 @@ EOT
1587
1817
  return 1 if role.nil?
1588
1818
 
1589
1819
  role_json = @roles_interface.get(account_id, role['id'])
1590
- if role_json['globalInstanceTypeAccess'] != 'custom'
1591
- print "\n", red, "Global Instance Type Access is currently: #{role_json['globalInstanceTypeAccess'].capitalize}"
1592
- print "\n", "You must first set it to Custom via `morpheus roles update-global-instance-type-access \"#{name}\" custom`"
1593
- print "\n\n", reset
1594
- return 1
1595
- end
1596
-
1597
1820
  instance_type = nil
1598
1821
  if !do_all
1599
1822
  instance_type = find_instance_type_by_name(instance_type_name)
@@ -1632,15 +1855,19 @@ EOT
1632
1855
  end
1633
1856
 
1634
1857
  def update_global_blueprint_access(args)
1635
- usage = "Usage: morpheus roles update-global-blueprint-access [role] [full|custom|none]"
1858
+ puts "#{yellow}DEPRECATED#{reset}"
1859
+ update_default_blueprint_access(args)
1860
+ end
1861
+
1862
+ def update_default_blueprint_access(args)
1636
1863
  options = {}
1637
1864
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1638
- opts.banner = subcommand_usage("[role] [full|custom|none]")
1865
+ opts.banner = subcommand_usage("[role] [access]")
1639
1866
  build_common_options(opts, options, [:json, :dry_run, :remote])
1640
1867
  opts.footer = <<-EOT
1641
- Update global blueprint access for a role.
1868
+ Update default blueprint access for a role.
1642
1869
  [role] is required. This is the name (authority) or id of a role.
1643
- [access] is required. This is the access level to assign: full, custom or none.
1870
+ [access] is required. This is the access level to assign: full or none.
1644
1871
  EOT
1645
1872
  end
1646
1873
  optparse.parse!(args)
@@ -1651,7 +1878,7 @@ EOT
1651
1878
  end
1652
1879
  name = args[0]
1653
1880
  access_value = args[1].to_s.downcase
1654
- if !['full', 'custom', 'none'].include?(access_value)
1881
+ if !['full', 'none'].include?(access_value)
1655
1882
  puts optparse
1656
1883
  exit 1
1657
1884
  end
@@ -1676,7 +1903,7 @@ EOT
1676
1903
  print JSON.pretty_generate(json_response)
1677
1904
  print "\n"
1678
1905
  else
1679
- print_green_success "Role #{role['authority']} global blueprint access updated"
1906
+ print_green_success "Role #{role['authority']} default blueprint access updated"
1680
1907
  end
1681
1908
  rescue RestClient::Exception => e
1682
1909
  print_rest_exception(e, options)
@@ -1689,7 +1916,7 @@ EOT
1689
1916
  blueprint_id = nil
1690
1917
  access_value = nil
1691
1918
  do_all = false
1692
- allowed_access_values = ['full', 'none']
1919
+ allowed_access_values = ['full', 'none', 'default']
1693
1920
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1694
1921
  opts.banner = subcommand_usage("[role] [blueprint] [access]")
1695
1922
  opts.on( '--blueprint ID', String, "Blueprint ID or Name" ) do |val|
@@ -1741,12 +1968,6 @@ EOT
1741
1968
  role_json = @roles_interface.get(account_id, role['id'])
1742
1969
  blueprint_global_access = role_json['globalAppTemplateAccess'] || role_json['globalBlueprintAccess']
1743
1970
  blueprint_permissions = role_json['appTemplatePermissions'] || role_json['blueprintPermissions'] || []
1744
- if blueprint_global_access != 'custom'
1745
- print "\n", red, "Global Blueprint Access is currently: #{blueprint_global_access.to_s.capitalize}"
1746
- print "\n", "You must first set it to Custom via `morpheus roles update-global-blueprint-access \"#{name}\" custom`"
1747
- print "\n\n", reset
1748
- return 1
1749
- end
1750
1971
 
1751
1972
  # hacky, but support name or code lookup via the list returned in the show payload
1752
1973
  blueprint = nil
@@ -1796,15 +2017,19 @@ EOT
1796
2017
  end
1797
2018
 
1798
2019
  def update_global_catalog_item_type_access(args)
1799
- usage = "Usage: morpheus roles update-global-catalog-item-type-access [role] [full|custom|none]"
2020
+ puts "#{yellow}DEPRECATED#{reset}"
2021
+ update_default_catalog_item_type_access(args)
2022
+ end
2023
+
2024
+ def update_default_catalog_item_type_access(args)
1800
2025
  options = {}
1801
2026
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1802
- opts.banner = subcommand_usage("[role] [full|custom|none]")
2027
+ opts.banner = subcommand_usage("[role] [access]")
1803
2028
  build_common_options(opts, options, [:json, :dry_run, :remote])
1804
2029
  opts.footer = <<-EOT
1805
- Update global catalog item type access for a role.
2030
+ Update default catalog item type access for a role.
1806
2031
  [role] is required. This is the name (authority) or id of a role.
1807
- [access] is required. This is the access level to assign: full, custom or none.
2032
+ [access] is required. This is the access level to assign: full or none.
1808
2033
  EOT
1809
2034
  end
1810
2035
  optparse.parse!(args)
@@ -1815,7 +2040,7 @@ EOT
1815
2040
  end
1816
2041
  name = args[0]
1817
2042
  access_value = args[1].to_s.downcase
1818
- if !['full', 'custom', 'none'].include?(access_value)
2043
+ if !['full', 'none'].include?(access_value)
1819
2044
  puts optparse
1820
2045
  exit 1
1821
2046
  end
@@ -1840,7 +2065,7 @@ EOT
1840
2065
  print JSON.pretty_generate(json_response)
1841
2066
  print "\n"
1842
2067
  else
1843
- print_green_success "Role #{role['authority']} global catalog item type access updated"
2068
+ print_green_success "Role #{role['authority']} default catalog item type access updated"
1844
2069
  end
1845
2070
  rescue RestClient::Exception => e
1846
2071
  print_rest_exception(e, options)
@@ -1853,7 +2078,7 @@ EOT
1853
2078
  catalog_item_type_id = nil
1854
2079
  access_value = nil
1855
2080
  do_all = false
1856
- allowed_access_values = ['full', 'none']
2081
+ allowed_access_values = ['full', 'none', 'default']
1857
2082
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1858
2083
  opts.banner = subcommand_usage("[role] [catalog-item-type] [access]")
1859
2084
  opts.on( '--catalog-item-type ID', String, "Catalog Item Type ID or Name" ) do |val|
@@ -1905,12 +2130,6 @@ EOT
1905
2130
  role_json = @roles_interface.get(account_id, role['id'])
1906
2131
  catalog_item_type_global_access = role_json['globalCatalogItemTypeAccess']
1907
2132
  catalog_item_type_permissions = role_json['catalogItemTypePermissions'] || role_json['catalogItemTypes'] []
1908
- if catalog_item_type_global_access != 'custom'
1909
- print "\n", red, "Global Catalog Item Type Access is currently: #{catalog_item_type_global_access.to_s.capitalize}"
1910
- print "\n", "You must first set it to Custom via `morpheus roles update-global-catalog-item-type-access \"#{name}\" custom`"
1911
- print "\n\n", reset
1912
- return 1
1913
- end
1914
2133
 
1915
2134
  # hacky, but support name or code lookup via the list returned in the show payload
1916
2135
  catalog_item_type = nil
@@ -1957,13 +2176,64 @@ EOT
1957
2176
  end
1958
2177
  end
1959
2178
 
2179
+ def update_default_persona_access(args)
2180
+ options = {}
2181
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
2182
+ opts.banner = subcommand_usage("[role] [access]")
2183
+ build_common_options(opts, options, [:json, :dry_run, :remote])
2184
+ opts.footer = <<-EOT
2185
+ Update default persona access for a role.
2186
+ [role] is required. This is the name (authority) or id of a role.
2187
+ [access] is required. This is the access level to assign: full or none.
2188
+ EOT
2189
+ end
2190
+ optparse.parse!(args)
2191
+
2192
+ if args.count < 2
2193
+ puts optparse
2194
+ exit 1
2195
+ end
2196
+ name = args[0]
2197
+ access_value = args[1].to_s.downcase
2198
+ if !['full', 'none'].include?(access_value)
2199
+ puts optparse
2200
+ exit 1
2201
+ end
2202
+
2203
+ connect(options)
2204
+ begin
2205
+ account = find_account_from_options(options)
2206
+ account_id = account ? account['id'] : nil
2207
+ role = find_role_by_name_or_id(account_id, name)
2208
+ exit 1 if role.nil?
2209
+
2210
+ params = {permissionCode: 'Persona', access: access_value}
2211
+ @roles_interface.setopts(options)
2212
+ if options[:dry_run]
2213
+ print_dry_run @roles_interface.dry.update_permission(account_id, role['id'], params)
2214
+ return
2215
+ end
2216
+ json_response = @roles_interface.update_permission(account_id, role['id'], params)
2217
+
2218
+ if options[:json]
2219
+ print JSON.pretty_generate(json_response)
2220
+ print "\n"
2221
+ else
2222
+ print_green_success "Role #{role['authority']} default persona access updated"
2223
+ end
2224
+ rescue RestClient::Exception => e
2225
+ print_rest_exception(e, options)
2226
+ exit 1
2227
+ end
2228
+ end
2229
+
1960
2230
  def update_persona_access(args)
1961
2231
  options = {}
1962
2232
  persona_id = nil
1963
2233
  name = nil
1964
2234
  access_value = nil
1965
2235
  do_all = false
1966
- allowed_access_values = ['full', 'none']
2236
+ allowed_access_values = ['full', 'none', 'default']
1967
2237
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1968
2238
  opts.banner = subcommand_usage("[role] [persona] [access]")
1969
2239
  opts.on( '--persona CODE', String, "Persona Code" ) do |val|
@@ -2049,22 +2319,26 @@ EOT
2049
2319
  end
2050
2320
 
2051
2321
  def update_global_vdi_pool_access(args)
2052
- usage = "Usage: morpheus roles update-global-vdi-pool-access [role] [full|custom|none]"
2322
+ puts "#{yellow}DEPRECATED#{reset}"
2323
+ update_default_vdi_pool_access(args)
2324
+ end
2325
+
2326
+ def update_default_vdi_pool_access(args)
2053
2327
  options = {}
2054
2328
  optparse = Morpheus::Cli::OptionParser.new do |opts|
2055
- opts.banner = subcommand_usage("[role] [full|custom|none]")
2329
+ opts.banner = subcommand_usage("[role] [access]")
2056
2330
  build_common_options(opts, options, [:json, :dry_run, :remote])
2057
2331
  opts.footer = <<-EOT
2058
- Update global VDI pool access for a role.
2332
+ Update default VDI pool access for a role.
2059
2333
  [role] is required. This is the name (authority) or id of a role.
2060
- [access] is required. This is the access level to assign: full, custom or none.
2334
+ [access] is required. This is the access level to assign: full or none.
2061
2335
  EOT
2062
2336
  end
2063
2337
  optparse.parse!(args)
2064
2338
  verify_args!(args:args, optparse:optparse, count: 2)
2065
2339
  name = args[0]
2066
2340
  access_value = args[1].to_s.downcase
2067
- if !['full', 'custom', 'none'].include?(access_value)
2341
+ if !['full', 'none'].include?(access_value)
2068
2342
  raise_command_error("invalid access value: #{args[1]}", args, optparse)
2069
2343
  end
2070
2344
 
@@ -2088,7 +2362,7 @@ EOT
2088
2362
  print JSON.pretty_generate(json_response)
2089
2363
  print "\n"
2090
2364
  else
2091
- print_green_success "Role #{role['authority']} global vdi pool access updated"
2365
+ print_green_success "Role #{role['authority']} default vdi pool access updated"
2092
2366
  end
2093
2367
  rescue RestClient::Exception => e
2094
2368
  print_rest_exception(e, options)
@@ -2101,7 +2375,7 @@ EOT
2101
2375
  vdi_pool_id = nil
2102
2376
  access_value = nil
2103
2377
  do_all = false
2104
- allowed_access_values = ['full', 'none']
2378
+ allowed_access_values = ['full', 'none', 'default']
2105
2379
  optparse = Morpheus::Cli::OptionParser.new do |opts|
2106
2380
  opts.banner = subcommand_usage("[role] [vdi-pool] [access]")
2107
2381
  opts.on( '--vdi-pool ID', String, "VDI Pool ID or Name" ) do |val|
@@ -2121,8 +2395,6 @@ EOT
2121
2395
  end
2122
2396
  optparse.parse!(args)
2123
2397
 
2124
- # usage: update-vdi-pool-access [role] [access] --all
2125
- # update-vdi-pool-access [role] [vdi-pool] [access]
2126
2398
  name = args[0]
2127
2399
  if do_all
2128
2400
  verify_args!(args:args, optparse:optparse, min:1, max:2)
@@ -2155,12 +2427,6 @@ EOT
2155
2427
  role_json = @roles_interface.get(account_id, role['id'])
2156
2428
  vdi_pool_global_access = role_json['globalVdiPoolAccess']
2157
2429
  vdi_pool_permissions = role_json['vdiPoolPermissions'] || role_json['vdiPools'] || []
2158
- if vdi_pool_global_access != 'custom'
2159
- print "\n", red, "Global VDI Pool Access is currently: #{vdi_pool_global_access.to_s.capitalize}"
2160
- print "\n", "You must first set it to Custom via `morpheus roles update-global-vdi-pool-access \"#{name}\" custom`"
2161
- print "\n\n", reset
2162
- return 1
2163
- end
2164
2430
 
2165
2431
  # hacky, but support name or code lookup via the list returned in the show payload
2166
2432
  vdi_pool = nil
@@ -2208,26 +2474,29 @@ EOT
2208
2474
  end
2209
2475
 
2210
2476
  def update_global_report_type_access(args)
2211
- usage = "Usage: morpheus roles update-global-report-type-access [role] [full|custom|none]"
2477
+ puts "#{yellow}DEPRECATED#{reset}"
2478
+ update_default_report_type_access(args)
2479
+ end
2480
+
2481
+ def update_default_report_type_access(args)
2212
2482
  options = {}
2213
2483
  optparse = Morpheus::Cli::OptionParser.new do |opts|
2214
- opts.banner = subcommand_usage("[role] [full|custom|none]")
2484
+ opts.banner = subcommand_usage("[role] [access]")
2215
2485
  build_common_options(opts, options, [:json, :dry_run, :remote])
2216
2486
  opts.footer = <<-EOT
2217
- Update global report type access for a role.
2487
+ Update default report type access for a role.
2218
2488
  [role] is required. This is the name (authority) or id of a role.
2219
- [access] is required. This is the access level to assign: full, custom or none.
2489
+ [access] is required. This is the access level to assign: full or none.
2220
2490
  EOT
2221
2491
  end
2222
2492
  optparse.parse!(args)
2223
2493
  verify_args!(args:args, optparse:optparse, count: 2)
2224
2494
  name = args[0]
2225
2495
  access_value = args[1].to_s.downcase
2226
- if !['full', 'custom', 'none'].include?(access_value)
2496
+ if !['full', 'none'].include?(access_value)
2227
2497
  raise_command_error("invalid access value: #{args[1]}", args, optparse)
2228
2498
  end
2229
2499
 
2230
-
2231
2500
  connect(options)
2232
2501
  begin
2233
2502
  account = find_account_from_options(options)
@@ -2247,7 +2516,7 @@ EOT
2247
2516
  print JSON.pretty_generate(json_response)
2248
2517
  print "\n"
2249
2518
  else
2250
- print_green_success "Role #{role['authority']} global report type access updated"
2519
+ print_green_success "Role #{role['authority']} default report type access updated"
2251
2520
  end
2252
2521
  rescue RestClient::Exception => e
2253
2522
  print_rest_exception(e, options)
@@ -2260,7 +2529,7 @@ EOT
2260
2529
  report_type_id = nil
2261
2530
  access_value = nil
2262
2531
  do_all = false
2263
- allowed_access_values = ['full', 'none']
2532
+ allowed_access_values = ['full', 'none', 'default']
2264
2533
  optparse = Morpheus::Cli::OptionParser.new do |opts|
2265
2534
  opts.banner = subcommand_usage("[role] [report-type] [access]")
2266
2535
  opts.on( '--report-type ID', String, "Report Type ID or Name" ) do |val|
@@ -2314,12 +2583,6 @@ EOT
2314
2583
  role_json = @roles_interface.get(account_id, role['id'])
2315
2584
  report_type_global_access = role_json['globalReportTypeAccess']
2316
2585
  report_type_permissions = role_json['reportTypePermissions'] || role_json['reportTypes'] || []
2317
- if report_type_global_access != 'custom'
2318
- print "\n", red, "Global Report Type Access is currently: #{report_type_global_access.to_s.capitalize}"
2319
- print "\n", "You must first set it to Custom via `morpheus roles update-global-report-type-access \"#{name}\" custom`"
2320
- print "\n\n", reset
2321
- return 1
2322
- end
2323
2586
 
2324
2587
  # hacky, but support name or code lookup via the list returned in the show payload
2325
2588
  report_type = nil
@@ -2366,6 +2629,311 @@ EOT
2366
2629
  end
2367
2630
  end
2368
2631
 
2632
+ def update_global_task_access(args)
2633
+ puts "#{yellow}DEPRECATED#{reset}"
2634
+ update_default_task_access(args)
2635
+ end
2636
+
2637
+ def update_default_task_access(args)
2638
+ options = {}
2639
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
2640
+ opts.banner = subcommand_usage("[role] [access]")
2641
+ build_common_options(opts, options, [:json, :dry_run, :remote])
2642
+ opts.footer = <<-EOT
2643
+ Update default task access for a role.
2644
+ [role] is required. This is the id of a role.
2645
+ [access] is required. This is the access level to assign: full or none.
2646
+ EOT
2647
+ end
2648
+ optparse.parse!(args)
2649
+ verify_args!(args:args, optparse:optparse, count: 2)
2650
+ name = args[0]
2651
+ access_value = args[1].to_s.downcase
2652
+ if !['full', 'none'].include?(access_value)
2653
+ raise_command_error("invalid access value: #{args[1]}", args, optparse)
2654
+ end
2655
+
2656
+ connect(options)
2657
+ begin
2658
+ account = find_account_from_options(options)
2659
+ account_id = account ? account['id'] : nil
2660
+ role = find_role_by_name_or_id(account_id, name)
2661
+ exit 1 if role.nil?
2662
+ # note: ReportTypes being plural is odd, the others are singular
2663
+ params = {permissionCode: 'Task', access: access_value}
2664
+ @roles_interface.setopts(options)
2665
+ if options[:dry_run]
2666
+ print_dry_run @roles_interface.dry.update_permission(account_id, role['id'], params)
2667
+ return
2668
+ end
2669
+ json_response = @roles_interface.update_permission(account_id, role['id'], params)
2670
+
2671
+ if options[:json]
2672
+ print JSON.pretty_generate(json_response)
2673
+ print "\n"
2674
+ else
2675
+ print_green_success "Role #{role['authority']} default task access updated"
2676
+ end
2677
+ rescue RestClient::Exception => e
2678
+ print_rest_exception(e, options)
2679
+ exit 1
2680
+ end
2681
+ end
2682
+
2683
+ def update_task_access(args)
2684
+ options = {}
2685
+ task_id = nil
2686
+ access_value = nil
2687
+ do_all = false
2688
+ allowed_access_values = ['full', 'none', 'default']
2689
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
2690
+ opts.banner = subcommand_usage("[role] [task] [access]")
2691
+ opts.on( '--task ID', String, "Task ID, code or name" ) do |val|
2692
+ report_type_id = val
2693
+ end
2694
+ opts.on( nil, '--all', "Update all tasks at once." ) do
2695
+ do_all = true
2696
+ end
2697
+ opts.on( '--access VALUE', String, "Access value [#{allowed_access_values.join('|')}]" ) do |val|
2698
+ access_value = val
2699
+ end
2700
+ build_common_options(opts, options, [:json, :dry_run, :remote])
2701
+ opts.footer = "Update role access for a task or all tasks.\n" +
2702
+ "[role] is required. This is the name, code or id of a task.\n" +
2703
+ "--task or --all is required. This is the name, code or id of a task.\n" +
2704
+ "--access is required. This is the new access value: #{ored_list(allowed_access_values)}"
2705
+ end
2706
+ optparse.parse!(args)
2707
+
2708
+ name = args[0]
2709
+ if do_all
2710
+ verify_args!(args:args, optparse:optparse, min:1, max:2)
2711
+ access_value = args[1] if args[1]
2712
+ else
2713
+ verify_args!(args:args, optparse:optparse, min:1, max:3)
2714
+ task_id = args[1] if args[1]
2715
+ access_value = args[2] if args[2]
2716
+ end
2717
+ if !task_id && !do_all
2718
+ raise_command_error("missing required argument: [task] or --all", args, optparse)
2719
+ end
2720
+ if !access_value
2721
+ raise_command_error("missing required argument: [access]", args, optparse)
2722
+ end
2723
+ access_value = access_value.to_s.downcase
2724
+ if !allowed_access_values.include?(access_value)
2725
+ raise_command_error("invalid access value: #{access_value}", args, optparse)
2726
+ puts optparse
2727
+ return 1
2728
+ end
2729
+
2730
+ connect(options)
2731
+ begin
2732
+ account = find_account_from_options(options)
2733
+ account_id = account ? account['id'] : nil
2734
+ role = find_role_by_name_or_id(account_id, name)
2735
+ return 1 if role.nil?
2736
+
2737
+ role_json = @roles_interface.get(account_id, role['id'])
2738
+ task_permissions = role_json['taskPermissions'] || role_json['tasks'] || []
2739
+
2740
+ # hacky, but support name or code lookup via the list returned in the show payload
2741
+ task = nil
2742
+ if !do_all
2743
+ if task_id.to_s =~ /\A\d{1,}\Z/
2744
+ task = task_permissions.find {|b| b['id'] == task_id.to_i }
2745
+ else
2746
+ task = task_permissions.find {|b| b['name'] == task_id || b['code'] == task_id }
2747
+ end
2748
+ if task.nil?
2749
+ print_red_alert "Task not found: '#{task_id}'"
2750
+ return 1
2751
+ end
2752
+ end
2753
+
2754
+ params = {}
2755
+ if do_all
2756
+ params['allTasks'] = true
2757
+ else
2758
+ params['taskId'] = task['id']
2759
+ end
2760
+ params['access'] = access_value == 'default' ? nil : access_value
2761
+ @roles_interface.setopts(options)
2762
+ if options[:dry_run]
2763
+ print_dry_run @roles_interface.dry.update_task(account_id, role['id'], params)
2764
+ return
2765
+ end
2766
+ json_response = @roles_interface.update_task(account_id, role['id'], params)
2767
+
2768
+ if options[:json]
2769
+ print JSON.pretty_generate(json_response)
2770
+ print "\n"
2771
+ else
2772
+ if do_all
2773
+ print_green_success "Role #{role['authority']} access updated for all tasks"
2774
+ else
2775
+ print_green_success "Role #{role['authority']} access updated for task #{task['name']}"
2776
+ end
2777
+ end
2778
+ return 0
2779
+ rescue RestClient::Exception => e
2780
+ print_rest_exception(e, options)
2781
+ exit 1
2782
+ end
2783
+ end
2784
+
2785
+ def update_global_workflow_access(args)
2786
+ puts "#{yellow}DEPRECATED#{reset}"
2787
+ update_default_workflow_access(args)
2788
+ end
2789
+
2790
+ def update_default_workflow_access(args)
2791
+ options = {}
2792
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
2793
+ opts.banner = subcommand_usage("[role] [access]")
2794
+ build_common_options(opts, options, [:json, :dry_run, :remote])
2795
+ opts.footer = <<-EOT
2796
+ Update default workflow access for a role.
2797
+ [role] is required. This is the id of a role.
2798
+ [access] is required. This is the access level to assign: full or none.
2799
+ EOT
2800
+ end
2801
+ optparse.parse!(args)
2802
+ verify_args!(args:args, optparse:optparse, count: 2)
2803
+ name = args[0]
2804
+ access_value = args[1].to_s.downcase
2805
+ if !['full', 'none'].include?(access_value)
2806
+ raise_command_error("invalid access value: #{args[1]}", args, optparse)
2807
+ end
2808
+
2809
+ connect(options)
2810
+ begin
2811
+ account = find_account_from_options(options)
2812
+ account_id = account ? account['id'] : nil
2813
+ role = find_role_by_name_or_id(account_id, name)
2814
+ exit 1 if role.nil?
2815
+ params = {permissionCode: 'TaskSet', access: access_value}
2816
+ @roles_interface.setopts(options)
2817
+ if options[:dry_run]
2818
+ print_dry_run @roles_interface.dry.update_permission(account_id, role['id'], params)
2819
+ return
2820
+ end
2821
+ json_response = @roles_interface.update_permission(account_id, role['id'], params)
2822
+
2823
+ if options[:json]
2824
+ print JSON.pretty_generate(json_response)
2825
+ print "\n"
2826
+ else
2827
+ print_green_success "Role #{role['authority']} default workflow access updated"
2828
+ end
2829
+ rescue RestClient::Exception => e
2830
+ print_rest_exception(e, options)
2831
+ exit 1
2832
+ end
2833
+ end
2834
+
2835
+ def update_workflow_access(args)
2836
+ options = {}
2837
+ workflow_id = nil
2838
+ access_value = nil
2839
+ do_all = false
2840
+ allowed_access_values = ['full', 'none', 'default']
2841
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
2842
+ opts.banner = subcommand_usage("[role] [workflow] [access]")
2843
+ opts.on( '--workflow ID', String, "Workflow ID, code or Name" ) do |val|
2844
+ workflow_id = val
2845
+ end
2846
+ opts.on( nil, '--all', "Update all workflows at once." ) do
2847
+ do_all = true
2848
+ end
2849
+ opts.on( '--access VALUE', String, "Access value [#{allowed_access_values.join('|')}]" ) do |val|
2850
+ access_value = val
2851
+ end
2852
+ build_common_options(opts, options, [:json, :dry_run, :remote])
2853
+ opts.footer = "Update role access for a workflow or all workflows.\n" +
2854
+ "[role] is required. This is the name or id of a role.\n" +
2855
+ "--workflow or --all is required. This is the name, code or id of a workflow.\n" +
2856
+ "--access is required. This is the new access value: #{ored_list(allowed_access_values)}"
2857
+ end
2858
+ optparse.parse!(args)
2859
+
2860
+ name = args[0]
2861
+ if do_all
2862
+ verify_args!(args:args, optparse:optparse, min:1, max:2)
2863
+ access_value = args[1] if args[1]
2864
+ else
2865
+ verify_args!(args:args, optparse:optparse, min:1, max:3)
2866
+ workflow_id = args[1] if args[1]
2867
+ access_value = args[2] if args[2]
2868
+ end
2869
+ if !workflow_id && !do_all
2870
+ raise_command_error("missing required argument: [workflow] or --all", args, optparse)
2871
+ end
2872
+ if !access_value
2873
+ raise_command_error("missing required argument: [access]", args, optparse)
2874
+ end
2875
+ access_value = access_value.to_s.downcase
2876
+ if !allowed_access_values.include?(access_value)
2877
+ raise_command_error("invalid access value: #{access_value}", args, optparse)
2878
+ puts optparse
2879
+ return 1
2880
+ end
2881
+
2882
+ connect(options)
2883
+ begin
2884
+ account = find_account_from_options(options)
2885
+ account_id = account ? account['id'] : nil
2886
+ role = find_role_by_name_or_id(account_id, name)
2887
+ return 1 if role.nil?
2888
+
2889
+ role_json = @roles_interface.get(account_id, role['id'])
2890
+ workflow_permissions = role_json['taskSetPermissions'] || role_json['taskSets'] || []
2891
+
2892
+ # hacky, but support name or code lookup via the list returned in the show payload
2893
+ workflow = nil
2894
+ if !do_all
2895
+ if workflow_id.to_s =~ /\A\d{1,}\Z/
2896
+ workflow = workflow_permissions.find {|b| b['id'] == workflow_id.to_i }
2897
+ else
2898
+ workflow = workflow_permissions.find {|b| b['name'] == workflow_id }
2899
+ end
2900
+ if workflow.nil?
2901
+ print_red_alert "Workflow not found: '#{workflow_id}'"
2902
+ return 1
2903
+ end
2904
+ end
2905
+
2906
+ params = {}
2907
+ if do_all
2908
+ params['allTaskSets'] = true
2909
+ else
2910
+ params['taskSetId'] = workflow['id']
2911
+ end
2912
+ params['access'] = access_value == 'default' ? nil : access_value
2913
+ @roles_interface.setopts(options)
2914
+ if options[:dry_run]
2915
+ print_dry_run @roles_interface.dry.update_task_set(account_id, role['id'], params)
2916
+ return
2917
+ end
2918
+ json_response = @roles_interface.update_task_set(account_id, role['id'], params)
2919
+
2920
+ if options[:json]
2921
+ print JSON.pretty_generate(json_response)
2922
+ print "\n"
2923
+ else
2924
+ if do_all
2925
+ print_green_success "Role #{role['authority']} access updated for all workflows"
2926
+ else
2927
+ print_green_success "Role #{role['authority']} access updated for workflow #{workflow['name']}"
2928
+ end
2929
+ end
2930
+ return 0
2931
+ rescue RestClient::Exception => e
2932
+ print_rest_exception(e, options)
2933
+ exit 1
2934
+ end
2935
+ end
2936
+
2369
2937
  private
2370
2938
 
2371
2939
  def add_role_option_types
@@ -2396,6 +2964,27 @@ EOT
2396
2964
  ]
2397
2965
  end
2398
2966
 
2967
+ def role_owner_options
2968
+ @options_interface.options_for_source("tenants", {})['data']
2969
+ end
2970
+
2971
+ def base_role_options(role_payload)
2972
+ params = {"tenantId" => role_payload['owner'], "userId" => current_user['id'], "roleType" => role_payload['roleType'] }
2973
+ @options_interface.options_for_source("copyFromRole", params)['data']
2974
+ end
2975
+
2976
+ def has_complete_access
2977
+ has_access = false
2978
+ if @is_master_account
2979
+ admin_accounts = @user_permissions.select { |it| it['code'] == 'admin-accounts' && it['access'] == 'full'}
2980
+ admin_roles = @user_permissions.select { |it| it['code'] == 'admin-roles' && it['access'] == 'full' }
2981
+ if admin_accounts != nil && admin_roles != nil
2982
+ has_access = true
2983
+ end
2984
+ end
2985
+ has_access
2986
+ end
2987
+
2399
2988
  def parse_access_csv(output, val, args, optparse)
2400
2989
  output ||= {}
2401
2990
  val.split(",").each do |value_pair|