morpheus-cli 5.3.0.1 → 5.3.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 (190) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/README.md +1 -3
  4. data/lib/morpheus/api/account_groups_interface.rb +0 -6
  5. data/lib/morpheus/api/accounts_interface.rb +1 -7
  6. data/lib/morpheus/api/api_client.rb +155 -119
  7. data/lib/morpheus/api/appliance_settings_interface.rb +6 -9
  8. data/lib/morpheus/api/approvals_interface.rb +5 -8
  9. data/lib/morpheus/api/apps_interface.rb +0 -7
  10. data/lib/morpheus/api/archive_buckets_interface.rb +9 -16
  11. data/lib/morpheus/api/archive_files_interface.rb +0 -6
  12. data/lib/morpheus/api/auth_interface.rb +4 -4
  13. data/lib/morpheus/api/backup_settings_interface.rb +5 -8
  14. data/lib/morpheus/api/blueprints_interface.rb +1 -7
  15. data/lib/morpheus/api/budgets_interface.rb +0 -6
  16. data/lib/morpheus/api/certificate_types_interface.rb +14 -0
  17. data/lib/morpheus/api/certificates_interface.rb +9 -0
  18. data/lib/morpheus/api/cloud_datastores_interface.rb +0 -6
  19. data/lib/morpheus/api/cloud_folders_interface.rb +1 -7
  20. data/lib/morpheus/api/cloud_policies_interface.rb +0 -6
  21. data/lib/morpheus/api/cloud_resource_pools_interface.rb +0 -6
  22. data/lib/morpheus/api/clouds_interface.rb +0 -6
  23. data/lib/morpheus/api/clusters_interface.rb +39 -42
  24. data/lib/morpheus/api/containers_interface.rb +0 -6
  25. data/lib/morpheus/api/custom_instance_types_interface.rb +0 -6
  26. data/lib/morpheus/api/cypher_interface.rb +0 -6
  27. data/lib/morpheus/api/datastores_interface.rb +4 -7
  28. data/lib/morpheus/api/deploy_interface.rb +1 -6
  29. data/lib/morpheus/api/environments_interface.rb +0 -6
  30. data/lib/morpheus/api/execute_schedules_interface.rb +0 -6
  31. data/lib/morpheus/api/execution_request_interface.rb +0 -6
  32. data/lib/morpheus/api/file_copy_request_interface.rb +2 -9
  33. data/lib/morpheus/api/group_policies_interface.rb +0 -6
  34. data/lib/morpheus/api/groups_interface.rb +0 -7
  35. data/lib/morpheus/api/guidance_interface.rb +9 -12
  36. data/lib/morpheus/api/health_interface.rb +0 -6
  37. data/lib/morpheus/api/image_builder_boot_scripts_interface.rb +0 -6
  38. data/lib/morpheus/api/image_builder_image_builds_interface.rb +0 -6
  39. data/lib/morpheus/api/image_builder_interface.rb +3 -9
  40. data/lib/morpheus/api/image_builder_preseed_scripts_interface.rb +0 -6
  41. data/lib/morpheus/api/instance_types_interface.rb +0 -7
  42. data/lib/morpheus/api/instances_interface.rb +8 -19
  43. data/lib/morpheus/api/integration_types_interface.rb +14 -0
  44. data/lib/morpheus/api/integrations_interface.rb +36 -21
  45. data/lib/morpheus/api/invoice_line_items_interface.rb +4 -9
  46. data/lib/morpheus/api/jobs_interface.rb +11 -14
  47. data/lib/morpheus/api/key_pairs_interface.rb +0 -6
  48. data/lib/morpheus/api/library_cluster_layouts_interface.rb +0 -6
  49. data/lib/morpheus/api/library_container_scripts_interface.rb +0 -6
  50. data/lib/morpheus/api/library_container_templates_interface.rb +0 -6
  51. data/lib/morpheus/api/library_container_types_interface.rb +0 -6
  52. data/lib/morpheus/api/library_container_upgrades_interface.rb +0 -6
  53. data/lib/morpheus/api/library_instance_types_interface.rb +0 -6
  54. data/lib/morpheus/api/library_layouts_interface.rb +0 -6
  55. data/lib/morpheus/api/library_spec_template_types_interface.rb +0 -6
  56. data/lib/morpheus/api/library_spec_templates_interface.rb +0 -6
  57. data/lib/morpheus/api/license_interface.rb +0 -6
  58. data/lib/morpheus/api/load_balancers_interface.rb +0 -6
  59. data/lib/morpheus/api/log_settings_interface.rb +9 -12
  60. data/lib/morpheus/api/logs_interface.rb +0 -6
  61. data/lib/morpheus/api/monitoring_alerts_interface.rb +0 -6
  62. data/lib/morpheus/api/monitoring_apps_interface.rb +0 -6
  63. data/lib/morpheus/api/monitoring_checks_interface.rb +0 -6
  64. data/lib/morpheus/api/monitoring_contacts_interface.rb +0 -6
  65. data/lib/morpheus/api/monitoring_groups_interface.rb +0 -6
  66. data/lib/morpheus/api/monitoring_incidents_interface.rb +0 -6
  67. data/lib/morpheus/api/monitoring_interface.rb +6 -12
  68. data/lib/morpheus/api/network_domain_records_interface.rb +0 -6
  69. data/lib/morpheus/api/network_domains_interface.rb +0 -6
  70. data/lib/morpheus/api/network_groups_interface.rb +0 -6
  71. data/lib/morpheus/api/network_pool_ips_interface.rb +0 -6
  72. data/lib/morpheus/api/network_pool_servers_interface.rb +0 -6
  73. data/lib/morpheus/api/network_pools_interface.rb +0 -6
  74. data/lib/morpheus/api/network_proxies_interface.rb +0 -6
  75. data/lib/morpheus/api/network_routers_interface.rb +0 -6
  76. data/lib/morpheus/api/network_security_servers_interface.rb +6 -9
  77. data/lib/morpheus/api/network_services_interface.rb +14 -14
  78. data/lib/morpheus/api/network_subnets_interface.rb +0 -6
  79. data/lib/morpheus/api/network_types_interface.rb +1 -7
  80. data/lib/morpheus/api/networks_interface.rb +0 -6
  81. data/lib/morpheus/api/option_type_lists_interface.rb +18 -12
  82. data/lib/morpheus/api/option_types_interface.rb +0 -6
  83. data/lib/morpheus/api/options_interface.rb +0 -6
  84. data/lib/morpheus/api/packages_interface.rb +0 -6
  85. data/lib/morpheus/api/policies_interface.rb +1 -8
  86. data/lib/morpheus/api/power_schedules_interface.rb +0 -6
  87. data/lib/morpheus/api/price_sets_interface.rb +8 -11
  88. data/lib/morpheus/api/prices_interface.rb +12 -15
  89. data/lib/morpheus/api/processes_interface.rb +0 -6
  90. data/lib/morpheus/api/provision_types_interface.rb +0 -6
  91. data/lib/morpheus/api/provisioning_license_types_interface.rb +0 -6
  92. data/lib/morpheus/api/provisioning_licenses_interface.rb +0 -6
  93. data/lib/morpheus/api/provisioning_settings_interface.rb +6 -9
  94. data/lib/morpheus/api/read_interface.rb +23 -0
  95. data/lib/morpheus/api/reports_interface.rb +0 -6
  96. data/lib/morpheus/api/rest_interface.rb +12 -10
  97. data/lib/morpheus/api/roles_interface.rb +7 -6
  98. data/lib/morpheus/api/security_group_rules_interface.rb +0 -7
  99. data/lib/morpheus/api/security_groups_interface.rb +0 -6
  100. data/lib/morpheus/api/server_types_interface.rb +0 -6
  101. data/lib/morpheus/api/servers_interface.rb +7 -6
  102. data/lib/morpheus/api/service_plans_interface.rb +11 -14
  103. data/lib/morpheus/api/storage_providers_interface.rb +9 -16
  104. data/lib/morpheus/api/subnet_types_interface.rb +1 -7
  105. data/lib/morpheus/api/subnets_interface.rb +0 -6
  106. data/lib/morpheus/api/task_sets_interface.rb +0 -6
  107. data/lib/morpheus/api/tasks_interface.rb +0 -6
  108. data/lib/morpheus/api/user_groups_interface.rb +0 -6
  109. data/lib/morpheus/api/user_settings_interface.rb +38 -18
  110. data/lib/morpheus/api/user_sources_interface.rb +0 -6
  111. data/lib/morpheus/api/users_interface.rb +0 -6
  112. data/lib/morpheus/api/vdi_allocations_interface.rb +9 -0
  113. data/lib/morpheus/api/vdi_apps_interface.rb +9 -0
  114. data/lib/morpheus/api/vdi_gateways_interface.rb +9 -0
  115. data/lib/morpheus/api/vdi_interface.rb +28 -0
  116. data/lib/morpheus/api/vdi_pools_interface.rb +19 -0
  117. data/lib/morpheus/api/virtual_images_interface.rb +0 -6
  118. data/lib/morpheus/api/whitelabel_settings_interface.rb +8 -11
  119. data/lib/morpheus/api/wiki_interface.rb +0 -6
  120. data/lib/morpheus/cli.rb +9 -2
  121. data/lib/morpheus/cli/access_token_command.rb +1 -1
  122. data/lib/morpheus/cli/account_groups_command.rb +4 -4
  123. data/lib/morpheus/cli/apps.rb +68 -84
  124. data/lib/morpheus/cli/archives_command.rb +5 -5
  125. data/lib/morpheus/cli/blueprints_command.rb +5 -5
  126. data/lib/morpheus/cli/boot_scripts_command.rb +1 -1
  127. data/lib/morpheus/cli/catalog_item_types_command.rb +13 -13
  128. data/lib/morpheus/cli/certificates_command.rb +575 -0
  129. data/lib/morpheus/cli/change_password_command.rb +4 -4
  130. data/lib/morpheus/cli/cli_command.rb +63 -7
  131. data/lib/morpheus/cli/clouds.rb +3 -2
  132. data/lib/morpheus/cli/clusters.rb +3 -3
  133. data/lib/morpheus/cli/commands/standard/man_command.rb +4 -5
  134. data/lib/morpheus/cli/credentials.rb +4 -11
  135. data/lib/morpheus/cli/environments_command.rb +1 -1
  136. data/lib/morpheus/cli/execute_schedules_command.rb +3 -3
  137. data/lib/morpheus/cli/hosts.rb +253 -232
  138. data/lib/morpheus/cli/image_builder_command.rb +6 -6
  139. data/lib/morpheus/cli/instance_types.rb +1 -1
  140. data/lib/morpheus/cli/instances.rb +196 -186
  141. data/lib/morpheus/cli/integrations_command.rb +1155 -42
  142. data/lib/morpheus/cli/invoices_command.rb +75 -67
  143. data/lib/morpheus/cli/key_pairs.rb +2 -2
  144. data/lib/morpheus/cli/library_cluster_layouts_command.rb +2 -3
  145. data/lib/morpheus/cli/library_container_scripts_command.rb +4 -5
  146. data/lib/morpheus/cli/library_container_templates_command.rb +5 -1
  147. data/lib/morpheus/cli/library_container_types_command.rb +8 -9
  148. data/lib/morpheus/cli/library_instance_types_command.rb +6 -7
  149. data/lib/morpheus/cli/library_layouts_command.rb +9 -5
  150. data/lib/morpheus/cli/library_option_lists_command.rb +72 -20
  151. data/lib/morpheus/cli/library_option_types_command.rb +8 -4
  152. data/lib/morpheus/cli/library_spec_templates_command.rb +3 -4
  153. data/lib/morpheus/cli/library_upgrades_command.rb +6 -6
  154. data/lib/morpheus/cli/license.rb +2 -2
  155. data/lib/morpheus/cli/load_balancers.rb +1 -1
  156. data/lib/morpheus/cli/login.rb +10 -1
  157. data/lib/morpheus/cli/mixins/option_source_helper.rb +15 -16
  158. data/lib/morpheus/cli/mixins/print_helper.rb +33 -18
  159. data/lib/morpheus/cli/mixins/provisioning_helper.rb +4 -4
  160. data/lib/morpheus/cli/mixins/vdi_helper.rb +246 -0
  161. data/lib/morpheus/cli/network_domains_command.rb +2 -2
  162. data/lib/morpheus/cli/network_routers_command.rb +22 -9
  163. data/lib/morpheus/cli/networks_command.rb +2 -2
  164. data/lib/morpheus/cli/option_types.rb +39 -34
  165. data/lib/morpheus/cli/policies_command.rb +0 -1
  166. data/lib/morpheus/cli/power_schedules_command.rb +3 -3
  167. data/lib/morpheus/cli/preseed_scripts_command.rb +1 -1
  168. data/lib/morpheus/cli/remote.rb +2 -2
  169. data/lib/morpheus/cli/reports_command.rb +5 -2
  170. data/lib/morpheus/cli/roles.rb +224 -64
  171. data/lib/morpheus/cli/security_group_rules.rb +1 -1
  172. data/lib/morpheus/cli/setup.rb +0 -1
  173. data/lib/morpheus/cli/subnets_command.rb +11 -2
  174. data/lib/morpheus/cli/tenants_command.rb +3 -3
  175. data/lib/morpheus/cli/user_groups_command.rb +3 -3
  176. data/lib/morpheus/cli/user_settings_command.rb +268 -57
  177. data/lib/morpheus/cli/user_sources_command.rb +3 -3
  178. data/lib/morpheus/cli/users.rb +3 -3
  179. data/lib/morpheus/cli/vdi_allocations_command.rb +159 -0
  180. data/lib/morpheus/cli/vdi_apps_command.rb +317 -0
  181. data/lib/morpheus/cli/vdi_command.rb +359 -0
  182. data/lib/morpheus/cli/vdi_gateways_command.rb +290 -0
  183. data/lib/morpheus/cli/vdi_pools_command.rb +571 -0
  184. data/lib/morpheus/cli/version.rb +1 -1
  185. data/lib/morpheus/cli/virtual_images.rb +1 -1
  186. data/lib/morpheus/cli/whoami.rb +0 -15
  187. data/lib/morpheus/cli/wiki_command.rb +1 -1
  188. data/lib/morpheus/rest_client.rb +30 -0
  189. data/lib/morpheus/terminal.rb +15 -7
  190. metadata +18 -2
@@ -181,7 +181,7 @@ class Morpheus::Cli::NetworkDomainsCommand
181
181
  options['name'] = val
182
182
  end
183
183
  opts.on('--description VALUE', String, "Description for this network domain") do |val|
184
- options['type'] = val
184
+ options['description'] = val
185
185
  end
186
186
  opts.on('--public-zone [on|off]', String, "Public Zone") do |val|
187
187
  options['publicZone'] = val.to_s == 'on' || val.to_s == 'true'
@@ -722,7 +722,7 @@ class Morpheus::Cli::NetworkDomainsCommand
722
722
  payload['networkDomainRecord']['name'] = v_prompt['name'] unless v_prompt['name'].to_s.empty?
723
723
 
724
724
  # Type
725
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'content', 'fieldLabel' => 'Type', 'type' => 'select', 'required' => true, 'optionSource' => 'dnsRecordType', 'description' => 'Type for this domain record.', 'defaultValue' => 'A'}], options[:options], @api_client)
725
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'required' => true, 'optionSource' => 'dnsRecordType', 'description' => 'Type for this domain record.', 'defaultValue' => 'A'}], options[:options], @api_client)
726
726
  payload['networkDomainRecord']['type'] = v_prompt['type'] unless v_prompt['type'].to_s.empty?
727
727
 
728
728
  # Content
@@ -22,6 +22,7 @@ class Morpheus::Cli::NetworkRoutersCommand
22
22
  def connect(opts)
23
23
  @api_client = establish_remote_appliance_connection(opts)
24
24
  @network_routers_interface = @api_client.network_routers
25
+ @network_services_interface = @api_client.network_services
25
26
  @clouds_interface = @api_client.clouds
26
27
  @options_interface = @api_client.options
27
28
  @accounts_interface = @api_client.accounts
@@ -249,6 +250,9 @@ class Morpheus::Cli::NetworkRoutersCommand
249
250
  opts.on('--enabled [on|off]', String, "Can be used to enable / disable the network router. Default is on") do |val|
250
251
  options[:enabled] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
251
252
  end
253
+ opts.on('--hostname VALUE', String, "Hostname for this network pool IP") do |val|
254
+ options[:options]['hostname'] = val
255
+ end
252
256
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
253
257
  opts.footer = "Create a network router."
254
258
  end
@@ -275,7 +279,7 @@ class Morpheus::Cli::NetworkRoutersCommand
275
279
  group_options = available_groups
276
280
 
277
281
  if options[:group]
278
- group = avail_groups.find {|it| it['name'] == options[:group] || "#{it['value']}" == "#{options[:group]}".downcase}
282
+ group = available_groups.find {|it| it['name'] == options[:group] || "#{it['value']}" == "#{options[:group]}".downcase}
279
283
 
280
284
  if group.nil?
281
285
  print_red_alert "Group #{options[:group]} not found"
@@ -292,10 +296,10 @@ class Morpheus::Cli::NetworkRoutersCommand
292
296
  params = {'router' => {'site' => router['site']}, 'routerType' => {'id' => router_type['id']}}
293
297
 
294
298
  if router_type['hasNetworkServer']
295
- if options[:server]
296
- server = find_network_server(options[:server])
299
+ if options[:network_server]
300
+ server = find_network_server(options[:network_server])
297
301
  if server.nil?
298
- print_red_alert "Network server #{options[:server]} not found"
302
+ print_red_alert "Network server #{options[:network_server]} not found"
299
303
  exit 1
300
304
  end
301
305
  else
@@ -322,7 +326,7 @@ class Morpheus::Cli::NetworkRoutersCommand
322
326
  # prompt for enabled
323
327
  router['enabled'] = options[:enabled].nil? ? Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'description' => 'Enable Router.', 'defaultValue' => true, 'required' => false}], options, @api_client, {})['enabled'] == 'on' : options[:enabled]
324
328
 
325
- option_types = router_type['optionTypes'].reject {|it| ['enabled'].include?(it['fieldName'])}.sort {|it| it['displayOrder']}
329
+ option_types = router_type['optionTypes'].reject {|it| ['enabled'].include?(it['fieldName']) || it['showOnCreate'] === false}.sort {|it| it['displayOrder']}
326
330
 
327
331
  # prompt options
328
332
  option_opts = options[:options].deep_merge!({'config' => options[:options].clone})
@@ -570,7 +574,7 @@ class Morpheus::Cli::NetworkRoutersCommand
570
574
  api_params = {}
571
575
  api_params['networkServerId'] = router['networkServer']['id'] if router['networkServer']
572
576
  api_params['zoneId'] = router['zone']['id'] if router['networkServer'].nil?
573
- option_result = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options].deep_merge({:context_map => {'networkRouter' => ''}}), @api_client, api_params, nil, true)
577
+ option_result = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options].deep_merge({:context_map => {'rule' => ''}}), @api_client, api_params, nil, true)
574
578
  payload = {'rule' => params.deep_merge(option_result)}
575
579
  end
576
580
 
@@ -792,6 +796,9 @@ class Morpheus::Cli::NetworkRoutersCommand
792
796
  opts.on('--mtu VALUE', String, "MTU for this route") do |val|
793
797
  params['networkMtu'] = val
794
798
  end
799
+ opts.on('--priority VALUE', Integer, "Priority for this route") do |val|
800
+ params['priority'] = val
801
+ end
795
802
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
796
803
  opts.footer = "Create a network router route."
797
804
  end
@@ -821,17 +828,18 @@ class Morpheus::Cli::NetworkRoutersCommand
821
828
  payload = options[:payload]
822
829
  else
823
830
  params['name'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Name', 'required' => true}], options[:options], @api_client, params)['name']
824
- params['description'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'type' => 'text', 'fieldLabel' => 'Description', 'required' => true}], options[:options], @api_client, params)['description']
831
+ params['description'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'type' => 'text', 'fieldLabel' => 'Description', 'required' => false}], options[:options], @api_client, params)['description']
825
832
 
826
833
  # prompt for enabled if not set
827
834
  params['enabled'] = options[:enabled].nil? ? Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'description' => 'Enabling Route.', 'defaultValue' => true, 'required' => false}], options, @api_client, {})['enabled'] == 'on' : options[:enabled]
828
835
 
829
- # default ruote
836
+ # default route
830
837
  params['defaultRoute'] = options[:defaultRoute].nil? ? Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultRoute', 'fieldLabel' => 'Default Route', 'type' => 'checkbox', 'description' => 'Default Route.', 'defaultValue' => false, 'required' => false}], options, @api_client, {})['defaultRoute'] == 'on' : options[:defaultRoute]
831
838
 
832
839
  params['source'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'source', 'type' => 'text', 'fieldLabel' => 'Network', 'required' => true}], options[:options], @api_client, params)['source']
833
840
  params['destination'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'destination', 'type' => 'text', 'fieldLabel' => 'Next Hop', 'required' => true}], options[:options], @api_client, params)['destination']
834
- params['networkMtu'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'networkMtu', 'type' => 'text', 'fieldLabel' => 'MTU', 'required' => true}], options[:options], @api_client, params)['networkMtu']
841
+ params['networkMtu'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'networkMtu', 'type' => 'text', 'fieldLabel' => 'MTU', 'required' => false}], options[:options], @api_client, params)['networkMtu']
842
+ params['priority'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'priority', 'type' => 'number', 'fieldLabel' => 'Priority', 'required' => false}], options[:options], @api_client, params)['priority']
835
843
 
836
844
  payload = {'route' => params}
837
845
  end
@@ -1278,4 +1286,9 @@ class Morpheus::Cli::NetworkRoutersCommand
1278
1286
  def available_groups()
1279
1287
  @network_routers_interface.groups
1280
1288
  end
1289
+
1290
+ def find_network_server(val)
1291
+ services = @network_services_interface.list()['networkServices']
1292
+ (val.to_s =~ /\A\d{1,}\Z/) ? services.find {|it| it['id'].to_i == val.to_i} : services.find {|it| it['name'] == val}
1293
+ end
1281
1294
  end
@@ -521,10 +521,10 @@ class Morpheus::Cli::NetworksCommand
521
521
  if options['cidr']
522
522
  payload['network']['cidr'] = options['cidr']
523
523
  else
524
- #if network_type['cidrEditable']
524
+ if network_type['cidrEditable']
525
525
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cidr', 'fieldLabel' => 'CIDR', 'type' => 'text', 'required' => network_type['cidrRequired'], 'description' => ''}], options)
526
526
  payload['network']['cidr'] = v_prompt['cidr']
527
- #end
527
+ end
528
528
  end
529
529
 
530
530
  # Gateway
@@ -46,15 +46,29 @@ module Morpheus
46
46
  if options[:help_field_prefix]
47
47
  option_type[:help_field_prefix] = options[:help_field_prefix]
48
48
  end
49
+ # a lot of optionTypes have fieldGroup:'Options' instead of 'default'
50
+ if option_type['fieldGroup'].to_s.downcase == 'options'
51
+ option_type['fieldGroup'] = 'default'
52
+ end
49
53
  end
50
54
  # puts "Options Prompt #{options}"
51
- # only sort if displayOrder is set
52
- sorted_option_types = (option_types[0] && option_types[0]['displayOrder']) ? option_types.sort { |x,y| x['displayOrder'].to_i <=> y['displayOrder'].to_i } : option_types
53
- sorted_option_types.each do |option_type|
55
+ # Sort options by default, group, advanced
56
+ cur_field_group = 'default'
57
+ (
58
+ option_types.reject {|it| (it['fieldGroup'] || 'default') != 'default'}.sort {|a,b| a['displayOrder'].to_i <=> b['displayOrder'].to_i} +
59
+ option_types.reject {|it| ['default', 'advanced'].include?(it['fieldGroup'] || 'default')}.sort{|a,b| a['displayOrder'] <=> b['displayOrder']}.group_by{|it| it['fieldGroup']}.values.collect { |it| it.sort{|a,b| a['displayOrder'].to_i <=> b['displayOrder'].to_i}}.flatten +
60
+ option_types.reject {|it| it['fieldGroup'] != 'advanced'}.sort {|a,b| a['displayOrder'].to_i <=> b['displayOrder'].to_i}
61
+ ).each do |option_type|
54
62
  context_map = results
55
63
  value = nil
56
64
  value_found=false
57
65
 
66
+ if cur_field_group != (option_type['fieldGroup'] || 'default')
67
+ cur_field_group = option_type['fieldGroup']
68
+ cur_field_group = cur_field_group.to_s.sub(/options\Z/i, "").strip # avoid "ADVANCED OPTION OPTIONS"
69
+ print "\n#{cur_field_group.upcase} OPTIONS\n#{"=" * ("#{cur_field_group} OPTIONS".length)}\n\n"
70
+ end
71
+
58
72
  # How about this instead?
59
73
  # option_type = option_type.clone
60
74
  # field_key = [option_type['fieldContext'], option_type['fieldName']].select {|it| it && it != '' }.join('.')
@@ -78,6 +92,7 @@ module Morpheus
78
92
  if !option_type['visibleOnCode'].to_s.empty?
79
93
  visible_option_check_value = option_type['visibleOnCode']
80
94
  end
95
+
81
96
  if !visible_option_check_value.to_s.empty?
82
97
  # support formats code=value or code:value OR code:(value|value2|value3)
83
98
  # OR fieldContext.fieldName=value
@@ -101,8 +116,9 @@ module Morpheus
101
116
  end
102
117
  if depends_on_option_type
103
118
  # dependent option type has a different value
104
- depends_on_field_key = depends_on_option_type['fieldContext'] ? "#{depends_on_option_type['fieldContext']}.#{depends_on_option_type['fieldName']}" : "#{depends_on_option_type['fieldName']}"
119
+ depends_on_field_key = depends_on_option_type['fieldContext'].nil? || depends_on_option_type['fieldContext'].empty? ? "#{depends_on_option_type['fieldName']}" : "#{depends_on_option_type['fieldContext']}.#{depends_on_option_type['fieldName']}"
105
120
  found_dep_value = get_object_value(results, depends_on_field_key) || get_object_value(options, depends_on_field_key)
121
+
106
122
  if depends_on_values.size > 0
107
123
  # must be in the specified values
108
124
  # todo: uhh this actually needs to change to parse regex
@@ -139,7 +155,9 @@ module Morpheus
139
155
  value = cur_namespace[field_name]
140
156
  input_value = ['select', 'multiSelect','typeahead', 'multiTypeahead'].include?(option_type['type']) && option_type['fieldInput'] ? cur_namespace[option_type['fieldInput']] : nil
141
157
  if option_type['type'] == 'number'
142
- value = value.to_s.include?('.') ? value.to_f : value.to_i
158
+ if !value.to_s.empty?
159
+ value = value.to_s.include?('.') ? value.to_f : value.to_i
160
+ end
143
161
  # these select prompts should just fall down through below, with the extra params no_prompt, use_value
144
162
  elsif option_type['type'] == 'select'
145
163
  value = select_prompt(option_type.merge({'defaultValue' => value, 'defaultInputValue' => input_value}), api_client, (option_type['noParams'] ? {} : (api_params || {}).merge(results)), true)
@@ -273,22 +291,6 @@ module Morpheus
273
291
  results
274
292
  end
275
293
 
276
- def self.grails_params(data, context=nil)
277
- params = {}
278
- data.each do |k,v|
279
- if v.is_a?(Hash)
280
- params.merge!(grails_params(v, context ? "#{context}.#{k.to_s}" : k))
281
- else
282
- if context
283
- params["#{context}.#{k.to_s}"] = v
284
- else
285
- params[k.to_s] = v
286
- end
287
- end
288
- end
289
- return params
290
- end
291
-
292
294
  def self.radio_prompt(option_type)
293
295
  value_found = false
294
296
  value = nil
@@ -330,7 +332,9 @@ module Morpheus
330
332
  print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}#{!option_type['defaultValue'].to_s.empty? ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
331
333
  input = $stdin.gets.chomp!
332
334
  value = input.empty? ? option_type['defaultValue'] : input
333
- value = value.to_s.include?('.') ? value.to_f : value.to_i
335
+ if !value.to_s.empty?
336
+ value = value.to_s.include?('.') ? value.to_f : value.to_i
337
+ end
334
338
  if input == '?'
335
339
  help_prompt(option_type)
336
340
  elsif !value.nil? || option_type['required'] != true
@@ -363,7 +367,7 @@ module Morpheus
363
367
  if option_type['selectOptions']
364
368
  # calculate from inline lambda
365
369
  if option_type['selectOptions'].is_a?(Proc)
366
- select_options = option_type['selectOptions'].call(api_client, grails_params(api_params || {}))
370
+ select_options = option_type['selectOptions'].call(api_client, api_params || {})
367
371
  else
368
372
  # todo: better type validation
369
373
  select_options = option_type['selectOptions']
@@ -371,13 +375,13 @@ module Morpheus
371
375
  elsif option_type['optionSource']
372
376
  # calculate from inline lambda
373
377
  if option_type['optionSource'].is_a?(Proc)
374
- select_options = option_type['optionSource'].call(api_client, grails_params(api_params || {}))
378
+ select_options = option_type['optionSource'].call(api_client, api_params || {})
375
379
  elsif option_type['optionSource'] == 'list'
376
380
  # /api/options/list is a special action for custom OptionTypeLists, just need to pass the optionTypeId parameter
377
- select_options = load_source_options(option_type['optionSource'], api_client, grails_params(api_params || {}).merge({'optionTypeId' => option_type['id']}))
381
+ select_options = load_source_options(option_type['optionSource'], option_type['optionSourceType'], api_client, api_params || {}.merge({'optionTypeId' => option_type['id']}))
378
382
  else
379
383
  # remote optionSource aka /api/options/$optionSource?
380
- select_options = load_source_options(option_type['optionSource'], api_client, grails_params(api_params || {}))
384
+ select_options = load_source_options(option_type['optionSource'], option_type['optionSourceType'], api_client, api_params || {})
381
385
  end
382
386
  else
383
387
  raise "option '#{field_key}' is type: 'select' and missing selectOptions or optionSource!"
@@ -571,6 +575,7 @@ module Morpheus
571
575
  # looking for help with this input
572
576
  if input == '?'
573
577
  help_prompt(option_type)
578
+ select_options = load_options(option_type, api_client, api_params)
574
579
  display_select_options(option_type, select_options) unless select_options.empty?
575
580
  next
576
581
  end
@@ -597,7 +602,7 @@ module Morpheus
597
602
  # actually that is redundant, it should already be filtered to matches
598
603
  # and can just do this:
599
604
  # select_option = select_options.size == 1 ? select_options[0] : nil
600
- select_option = select_options.find{|b| (b[value_field] && (b[value_field].to_s == input.to_s)) || ((b[value_field].nil? || b[value_field].empty?) && (input == "")) }
605
+ select_option = select_options.find{|b| (b[value_field] && (b[value_field].to_s == input.to_s)) || ((b[value_field].nil? || b[value_field] == "") && (input == "")) }
601
606
  if select_option.nil?
602
607
  select_option = select_options.find{|b| b['name'] && b['name'] == input }
603
608
  end
@@ -888,7 +893,7 @@ module Morpheus
888
893
  if option_type['selectOptions']
889
894
  # calculate from inline lambda
890
895
  if option_type['selectOptions'].is_a?(Proc)
891
- select_options = option_type['selectOptions'].call(api_client, grails_params(api_params || {}))
896
+ select_options = option_type['selectOptions'].call(api_client, api_params || {})
892
897
  else
893
898
  select_options = option_type['selectOptions']
894
899
  end
@@ -903,13 +908,13 @@ module Morpheus
903
908
  elsif option_type['optionSource']
904
909
  # calculate from inline lambda
905
910
  if option_type['optionSource'].is_a?(Proc)
906
- select_options = option_type['optionSource'].call(api_client, grails_params(api_params || {}))
911
+ select_options = option_type['optionSource'].call(api_client, api_params || {})
907
912
  elsif option_type['optionSource'] == 'list'
908
913
  # /api/options/list is a special action for custom OptionTypeLists, just need to pass the optionTypeId parameter
909
- select_options = load_source_options(option_type['optionSource'], api_client, grails_params(api_params || {}).merge({'optionTypeId' => option_type['id']}))
914
+ select_options = load_source_options(option_type['optionSource'], option_type['optionSourceType'], api_client, api_params || {}.merge({'optionTypeId' => option_type['id']}))
910
915
  else
911
916
  # remote optionSource aka /api/options/$optionSource?
912
- select_options = load_source_options(option_type['optionSource'], api_client, grails_params(api_params || {}))
917
+ select_options = load_source_options(option_type['optionSource'], option_type['optionSourceType'], api_client, api_params || {})
913
918
  end
914
919
  else
915
920
  raise "option '#{field_key}' is type: 'typeahead' and missing selectOptions or optionSource!"
@@ -935,8 +940,8 @@ module Morpheus
935
940
  end
936
941
 
937
942
 
938
- def self.load_source_options(source,api_client,params)
939
- api_client.options.options_for_source(source,params)['data']
943
+ def self.load_source_options(source,sourceType,api_client,params)
944
+ api_client.options.options_for_source("#{sourceType ? "#{sourceType}/" : ''}#{source}",params)['data']
940
945
  end
941
946
 
942
947
  def self.format_select_options_help(opt, select_options = [], paging = nil)
@@ -951,7 +956,7 @@ module Morpheus
951
956
  out = ""
952
957
  out << "\n"
953
958
  out << "#{header}\n"
954
- out << "===============\n"
959
+ out << "#{'=' * header.length}\n"
955
960
  select_options.each do |option|
956
961
  out << " * #{option['name']} [#{option['value']}]\n"
957
962
  end
@@ -26,7 +26,6 @@ class Morpheus::Cli::PoliciesCommand
26
26
 
27
27
  def connect(opts)
28
28
  @api_client = establish_remote_appliance_connection(opts)
29
- # @policies_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).policies
30
29
  @policies_interface = @api_client.policies
31
30
  @group_policies_interface = @api_client.group_policies
32
31
  @cloud_policies_interface = @api_client.cloud_policies
@@ -13,9 +13,9 @@ class Morpheus::Cli::PowerSchedulesCommand
13
13
 
14
14
  def connect(opts)
15
15
  @api_client = establish_remote_appliance_connection(opts)
16
- @power_schedules_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).power_schedules
17
- @instances_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).instances
18
- @servers_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).servers
16
+ @power_schedules_interface = @api_client.power_schedules
17
+ @instances_interface = @api_client.instances
18
+ @servers_interface = @api_client.servers
19
19
  end
20
20
 
21
21
  def handle(args)
@@ -23,7 +23,7 @@ class Morpheus::Cli::PreseedScriptsCommand
23
23
 
24
24
  def connect(opts)
25
25
  @api_client = establish_remote_appliance_connection(opts)
26
- @image_builder_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).image_builder
26
+ @image_builder_interface = @api_client.image_builder
27
27
  @preseed_scripts_interface = @image_builder_interface.preseed_scripts
28
28
  end
29
29
 
@@ -1337,7 +1337,7 @@ EOT
1337
1337
  include Term::ANSIColor
1338
1338
 
1339
1339
  # for caching the the contents of YAML file $home/appliances
1340
- # it is structured like :appliance_name => {:host => "htt[://api.gomorpheus.com", :active => true}
1340
+ # it is structured like :appliance_name => {:host => "https://api.gomorpheus.com", :active => true}
1341
1341
  # not named @@appliances to avoid confusion with the instance variable . This is also a command class...
1342
1342
  @@appliance_config = nil
1343
1343
 
@@ -1700,7 +1700,7 @@ EOT
1700
1700
  # wtf, no url...
1701
1701
  return appliance, json_response
1702
1702
  else
1703
- setup_interface = Morpheus::SetupInterface.new({url:appliance_url, verify_ssl: (appliance[:insecure] != true), timeout: timeout})
1703
+ setup_interface = Morpheus::SetupInterface.new({url:appliance_url, verify_ssl: !appliance[:insecure], timeout: timeout})
1704
1704
  start_time = Time.now
1705
1705
  begin
1706
1706
  json_response = setup_interface.check(params)
@@ -346,7 +346,7 @@ class Morpheus::Cli::ReportsCommand
346
346
  report_result = find_report_result_by_id(args[0])
347
347
  return 1 if report_result.nil?
348
348
 
349
- link = "#{@appliance_url}/login/oauth-redirect?access_token=#{@access_token}\\&redirectUri=/operations/reports/#{report_result['type']['code']}/reportResults/#{report_result['id']}"
349
+ link = "#{@appliance_url}/login/oauth-redirect?access_token=#{@access_token}\\&redirectUri=/operations/reports/#{report_result['type']['code']}/results/#{report_result['id']}%3Fcontext=results"
350
350
 
351
351
  if options[:dry_run]
352
352
  puts Morpheus::Util.open_url_command(link)
@@ -368,7 +368,6 @@ class Morpheus::Cli::ReportsCommand
368
368
  do_mkdir = false
369
369
  optparse = Morpheus::Cli::OptionParser.new do |opts|
370
370
  opts.banner = subcommand_usage("[id] [file]")
371
- build_common_options(opts, options, [:dry_run, :remote])
372
371
  opts.on( '--format VALUE', String, "Report Format for exported file, json or csv. Default is json." ) do |val|
373
372
  report_format = val
374
373
  end
@@ -379,6 +378,7 @@ class Morpheus::Cli::ReportsCommand
379
378
  opts.on( '-p', '--mkdir', "Create missing directories for [local-file] if they do not exist." ) do
380
379
  do_mkdir = true
381
380
  end
381
+ build_common_options(opts, options, [:dry_run, :remote])
382
382
  opts.footer = "Export a report result as json or csv." + "\n" +
383
383
  "[id] is required. This is id of the report result." + "\n" +
384
384
  "[file] is required. This is local destination for the downloaded file."
@@ -394,6 +394,9 @@ class Morpheus::Cli::ReportsCommand
394
394
 
395
395
  outfile = args[1]
396
396
  outfile = File.expand_path(outfile)
397
+ if outfile =~ /\.csv\Z/i
398
+ report_format = "csv"
399
+ end
397
400
 
398
401
  if Dir.exists?(outfile)
399
402
  print_red_alert "[file] is invalid. It is the name of an existing directory: #{outfile}"
@@ -13,21 +13,21 @@ class Morpheus::Cli::Roles
13
13
  include Morpheus::Cli::AccountsHelper
14
14
  include Morpheus::Cli::ProvisioningHelper
15
15
  include Morpheus::Cli::WhoamiHelper
16
- register_subcommands :list, :get, :add, :update, :remove, :'list-permissions', :'update-feature-access', :'update-global-group-access', :'update-group-access', :'update-global-cloud-access', :'update-cloud-access', :'update-global-instance-type-access', :'update-instance-type-access', :'update-global-blueprint-access', :'update-blueprint-access', :'update-global-catalog-item-type-access', :'update-catalog-item-type-access', :'update-persona-access'
16
+ register_subcommands :list, :get, :add, :update, :remove, :'list-permissions', :'update-feature-access', :'update-global-group-access', :'update-group-access', :'update-global-cloud-access', :'update-cloud-access', :'update-global-instance-type-access', :'update-instance-type-access', :'update-global-blueprint-access', :'update-blueprint-access', :'update-global-catalog-item-type-access', :'update-catalog-item-type-access', :'update-persona-access', :'update-global-vdi-pool-access', :'update-vdi-pool-access'
17
17
  alias_subcommand :details, :get
18
18
  set_default_subcommand :list
19
19
 
20
20
  def connect(opts)
21
21
  @api_client = establish_remote_appliance_connection(opts)
22
- @whoami_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).whoami
23
- @users_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).users
24
- @accounts_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).accounts
25
- @roles_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).roles
26
- @groups_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).groups
27
- @options_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).options
28
- @instances_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).instances
29
- @instance_types_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).instance_types
30
- @blueprints_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).blueprints
22
+ @whoami_interface = @api_client.whoami
23
+ @users_interface = @api_client.users
24
+ @accounts_interface = @api_client.accounts
25
+ @roles_interface = @api_client.roles
26
+ @groups_interface = @api_client.groups
27
+ @options_interface = @api_client.options
28
+ @instances_interface = @api_client.instances
29
+ @instance_types_interface = @api_client.instance_types
30
+ @blueprints_interface = @api_client.blueprints
31
31
  @active_group_id = Morpheus::Cli::Groups.active_groups[@appliance_name]
32
32
  end
33
33
 
@@ -102,19 +102,23 @@ class Morpheus::Cli::Roles
102
102
  options[:include_blueprint_access] = true
103
103
  end
104
104
  opts.on(nil,'--catalog-item-type-access', "Display Catalog Item Type Access") do
105
- options[:include_catalog_item_types_access] = true
105
+ options[:include_catalog_item_type_access] = true
106
106
  end
107
107
  opts.on(nil,'--personas', "Display Persona Access") do
108
108
  options[:include_personas_access] = true
109
109
  end
110
+ opts.on(nil,'--vdi-pool-access', "Display VDI Pool Access") do
111
+ options[:include_vdi_pool_access] = true
112
+ end
110
113
  opts.on('-a','--all', "Display All Access Lists") do
111
114
  options[:include_feature_access] = true
112
115
  options[:include_group_access] = true
113
116
  options[:include_cloud_access] = true
114
117
  options[:include_instance_type_access] = true
115
118
  options[:include_blueprint_access] = true
116
- options[:include_catalog_item_types_access] = true
119
+ options[:include_catalog_item_type_access] = true
117
120
  options[:include_personas_access] = true
121
+ options[:include_vdi_pool_access] = true
118
122
  end
119
123
  build_standard_get_options(opts, options)
120
124
  opts.footer = <<-EOT
@@ -206,9 +210,9 @@ EOT
206
210
  rows = rows.select {|row| row[:code].to_s =~ phrase_regexp || row[:name].to_s =~ phrase_regexp }
207
211
  end
208
212
  print as_pretty_table(rows, [:code, :name, :access], options)
209
- print reset,"\n"
213
+ # print reset,"\n"
210
214
  else
211
- print cyan,"Use --permissions to list permissions","\n"
215
+ print cyan,"Use --permissions to list feature permissions","\n"
212
216
  end
213
217
 
214
218
  has_group_access = true
@@ -220,6 +224,7 @@ EOT
220
224
  "Instance Types" => lambda {|it| get_access_string(it['globalInstanceTypeAccess']) },
221
225
  "Blueprints" => lambda {|it| get_access_string(it['globalAppTemplateAccess'] || it['globalBlueprintAccess']) },
222
226
  "Catalog Item Types" => lambda {|it| get_access_string(it['globalCatalogItemTypeAccess']) },
227
+ "VDI Pools" => lambda {|it| get_access_string(it['globalVdiPoolAccess']) },
223
228
  }
224
229
  if role['roleType'].to_s.downcase == 'account'
225
230
  global_access_columns.delete("Groups")
@@ -228,7 +233,7 @@ EOT
228
233
  global_access_columns.delete("Clouds")
229
234
  has_cloud_access = false
230
235
  end
231
- puts as_pretty_table([json_response], global_access_columns, options)
236
+ print as_pretty_table([json_response], global_access_columns, options)
232
237
 
233
238
  if has_group_access
234
239
  #print_h2 "Group Access: #{get_access_string(json_response['globalSiteAccess'])}", options
@@ -246,7 +251,7 @@ EOT
246
251
  else
247
252
  print cyan,"Use -g, --group-access to list custom access","\n"
248
253
  end
249
- print reset,"\n"
254
+ # print reset,"\n"
250
255
  else
251
256
  # print "\n"
252
257
  # print cyan,bold,"Group Access: #{get_access_string(json_response['globalSiteAccess'])}",reset,"\n"
@@ -270,7 +275,7 @@ EOT
270
275
  else
271
276
  print cyan,"Use -c, --cloud-access to list custom access","\n"
272
277
  end
273
- print reset,"\n"
278
+ # print reset,"\n"
274
279
  else
275
280
  # print "\n"
276
281
  # print cyan,bold,"Cloud Access: #{get_access_string(json_response['globalZoneAccess'])}",reset,"\n"
@@ -293,7 +298,7 @@ EOT
293
298
  else
294
299
  print cyan,"Use -i, --instance-type-access to list custom access","\n"
295
300
  end
296
- print reset,"\n"
301
+ # print reset,"\n"
297
302
  else
298
303
  # print "\n"
299
304
  # print cyan,bold,"Instance Type Access: #{get_access_string(json_response['globalInstanceTypeAccess'])}",reset,"\n"
@@ -317,7 +322,7 @@ EOT
317
322
  else
318
323
  print cyan,"Use -b, --blueprint-access to list custom access","\n"
319
324
  end
320
- print reset,"\n"
325
+ # print reset,"\n"
321
326
  else
322
327
  # print "\n"
323
328
  # print cyan,bold,"Blueprint Access: #{get_access_string(json_response['globalAppTemplateAccess'])}",reset,"\n"
@@ -331,7 +336,7 @@ EOT
331
336
  # print "\n"
332
337
  if catalog_item_type_global_access == 'custom'
333
338
  print_h2 "Catalog Item Type Access", options
334
- if options[:include_catalog_item_types_access]
339
+ if options[:include_catalog_item_type_access]
335
340
  rows = catalog_item_type_permissions.collect do |it|
336
341
  {
337
342
  name: it['name'],
@@ -350,6 +355,7 @@ EOT
350
355
 
351
356
  persona_permissions = json_response['personaPermissions'] || json_response['personas'] || []
352
357
  # if options[:include_personas_access]
358
+ print cyan
353
359
  if persona_permissions
354
360
  print_h2 "Persona Access", options
355
361
  rows = persona_permissions.collect do |it|
@@ -358,13 +364,34 @@ EOT
358
364
  access: format_access_string(it['access'], ["none","read","full"]),
359
365
  }
360
366
  end
361
- print as_pretty_table(rows, [:name, :access], options)
362
- print reset,"\n"
367
+ print as_pretty_table(rows, [:name, :access], options)
363
368
  end
364
369
 
365
370
  # print reset,"\n"
366
371
 
372
+ vdi_pool_global_access = json_response['globalVdiPoolAccess']
373
+ vdi_pool_permissions = json_response['vdiPoolPermissions'] || []
374
+ print cyan
375
+ if vdi_pool_global_access == 'custom'
376
+ print_h2 "VDI Pool Access", options
377
+ if options[:include_vdi_pool_access]
378
+ rows = vdi_pool_permissions.collect do |it|
379
+ {
380
+ name: it['name'],
381
+ access: format_access_string(it['access'], ["none","read","full"]),
382
+ }
383
+ end
384
+ print as_pretty_table(rows, [:name, :access], options)
385
+ else
386
+ print cyan,"Use --vdi-pool-access to list custom access","\n"
387
+ end
388
+ else
389
+ # print "\n"
390
+ # print cyan,bold,"VDI Pool Access: #{get_access_string(json_response['globalVdiPoolAccess'])}",reset,"\n"
391
+ end
392
+
367
393
  end
394
+ print reset,"\n"
368
395
 
369
396
  return 0, nil
370
397
  end
@@ -520,7 +547,7 @@ EOT
520
547
  end
521
548
 
522
549
  # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultPersona', 'fieldLabel' => 'Default Persona', 'type' => 'select', 'optionSource' => 'personas', 'description' => 'Default Persona'}], options[:options], @api_client)
523
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultPersona', 'fieldLabel' => 'Default Persona', 'type' => 'select', 'selectOptions' => [{'name'=>'Service Catalog','value'=>'serviceCatalog'},{'name'=>'Standard','value'=>'standard'}], 'description' => 'Default Persona'}], options[:options], @api_client)
550
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultPersona', 'fieldLabel' => 'Default Persona', 'type' => 'select', 'selectOptions' => get_persona_select_options(), 'description' => 'Default Persona'}], options[:options], @api_client)
524
551
  role_payload['defaultPersona'] = {'code' => v_prompt['defaultPersona']} unless v_prompt['defaultPersona'].to_s.strip.empty?
525
552
 
526
553
  payload = {"role" => role_payload}
@@ -782,14 +809,14 @@ EOT
782
809
  def update_group_access(args)
783
810
  options = {}
784
811
  name = nil
785
- group_name = nil
812
+ group_id = nil
786
813
  access_value = nil
787
814
  do_all = false
788
815
  allowed_access_values = ['full', 'read', 'none']
789
816
  optparse = Morpheus::Cli::OptionParser.new do |opts|
790
817
  opts.banner = subcommand_usage("[role] [group] [access]")
791
818
  opts.on( '-g', '--group GROUP', "Group name or id" ) do |val|
792
- group_name = val
819
+ group_id = val
793
820
  end
794
821
  opts.on( nil, '--all', "Update all groups at once." ) do
795
822
  do_all = true
@@ -845,9 +872,8 @@ EOT
845
872
  end
846
873
 
847
874
  group = nil
848
- group_id = nil
849
875
  if !do_all
850
- group = find_group_by_name_or_id_for_provisioning(group_name)
876
+ group = find_group_by_name_or_id_for_provisioning(group_id)
851
877
  return 1 if group.nil?
852
878
  group_id = group['id']
853
879
  end
@@ -932,15 +958,14 @@ EOT
932
958
 
933
959
  def update_cloud_access(args)
934
960
  options = {}
935
- cloud_name = nil
961
+ cloud_id = nil
936
962
  access_value = nil
937
963
  do_all = false
938
964
  allowed_access_values = ['full', 'read', 'none']
939
965
  optparse = Morpheus::Cli::OptionParser.new do |opts|
940
966
  opts.banner = subcommand_usage("[name]")
941
967
  opts.on( '-c', '--cloud CLOUD', "Cloud name or id" ) do |val|
942
- puts "val is : #{val}"
943
- cloud_name = val
968
+ cloud_id = val
944
969
  end
945
970
  opts.on( nil, '--all', "Update all clouds at once." ) do
946
971
  do_all = true
@@ -948,9 +973,6 @@ EOT
948
973
  opts.on( '--access VALUE', String, "Access value [#{allowed_access_values.join('|')}]" ) do |val|
949
974
  access_value = val
950
975
  end
951
- opts.on( '-g', '--group GROUP', "Group to find cloud in" ) do |val|
952
- options[:group] = val
953
- end
954
976
  build_common_options(opts, options, [:json, :dry_run, :remote])
955
977
  opts.footer = "Update role access for a cloud or all clouds.\n" +
956
978
  "[role] is required. This is the name or id of a role.\n" +
@@ -998,23 +1020,11 @@ EOT
998
1020
  exit 1
999
1021
  end
1000
1022
 
1001
- # crap, group_id is needed for this api, maybe just use infrastructure or some other optionSource instead.
1002
- group_id = nil
1003
- cloud_id = nil
1023
+ cloud = nil
1004
1024
  if !do_all
1005
- group_id = nil
1006
- if !options[:group].nil?
1007
- group = find_group_by_name_or_id_for_provisioning(options[:group])
1008
- group_id = group['id']
1009
- else
1010
- group_id = @active_group_id
1011
- end
1012
- if group_id.nil?
1013
- print_red_alert "Group not found or specified!"
1014
- return 1
1015
- end
1016
- cloud_id = find_cloud_id_by_name(group_id, cloud_name)
1017
- return 1 if cloud_id.nil?
1025
+ cloud = find_cloud_by_name_or_id_for_provisioning(nil, cloud_id)
1026
+ return 1 if cloud.nil?
1027
+ cloud_id = cloud['id']
1018
1028
  end
1019
1029
  params = {}
1020
1030
  if do_all
@@ -1037,7 +1047,7 @@ EOT
1037
1047
  if do_all
1038
1048
  print_green_success "Role #{role['authority']} access updated for all clouds"
1039
1049
  else
1040
- print_green_success "Role #{role['authority']} access updated for cloud id #{cloud_id}"
1050
+ print_green_success "Role #{role['authority']} access updated for cloud #{cloud['name']}"
1041
1051
  end
1042
1052
  end
1043
1053
  return 0
@@ -1534,7 +1544,7 @@ EOT
1534
1544
  build_common_options(opts, options, [:json, :dry_run, :remote])
1535
1545
  opts.footer = "Update role access for a persona or all personas.\n" +
1536
1546
  "[role] is required. This is the name or id of a role.\n" +
1537
- "--persona or --all is required. This is the code of a persona. Service Catalog or Standard\n" +
1547
+ "--persona or --all is required. This is the code of a persona. Service Catalog, Standard, or Virtual Desktop\n" +
1538
1548
  "--access is required. This is the new access value. #{anded_list(allowed_access_values)}"
1539
1549
  end
1540
1550
  optparse.parse!(args)
@@ -1606,6 +1616,160 @@ EOT
1606
1616
  end
1607
1617
  end
1608
1618
 
1619
+ def update_global_vdi_pool_access(args)
1620
+ usage = "Usage: morpheus roles update-global-vdi-pool-access [role] [full|custom|none]"
1621
+ options = {}
1622
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1623
+ opts.banner = subcommand_usage("[role] [full|custom|none]")
1624
+ build_common_options(opts, options, [:json, :dry_run, :remote])
1625
+ end
1626
+ optparse.parse!(args)
1627
+ verify_args!(args:args, optparse:optparse, count: 2)
1628
+ name = args[0]
1629
+ access_value = args[1].to_s.downcase
1630
+ if !['full', 'custom', 'none'].include?(access_value)
1631
+ raise_command_error("invalid access value: #{args[1]}", optparse)
1632
+ end
1633
+
1634
+
1635
+ connect(options)
1636
+ begin
1637
+ account = find_account_from_options(options)
1638
+ account_id = account ? account['id'] : nil
1639
+ role = find_role_by_name_or_id(account_id, name)
1640
+ exit 1 if role.nil?
1641
+ # note: VdiPools being plural is odd, the others are singular
1642
+ params = {permissionCode: 'VdiPools', access: access_value}
1643
+ @roles_interface.setopts(options)
1644
+ if options[:dry_run]
1645
+ print_dry_run @roles_interface.dry.update_permission(account_id, role['id'], params)
1646
+ return
1647
+ end
1648
+ json_response = @roles_interface.update_permission(account_id, role['id'], params)
1649
+
1650
+ if options[:json]
1651
+ print JSON.pretty_generate(json_response)
1652
+ print "\n"
1653
+ else
1654
+ print_green_success "Role #{role['authority']} global vdi pool access updated"
1655
+ end
1656
+ rescue RestClient::Exception => e
1657
+ print_rest_exception(e, options)
1658
+ exit 1
1659
+ end
1660
+ end
1661
+
1662
+ def update_vdi_pool_access(args)
1663
+ options = {}
1664
+ vdi_pool_id = nil
1665
+ access_value = nil
1666
+ do_all = false
1667
+ allowed_access_values = ['full', 'none']
1668
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1669
+ opts.banner = subcommand_usage("[role] [vdi-pool] [access]")
1670
+ opts.on( '--vdi-pool ID', String, "VDI Pool ID or Name" ) do |val|
1671
+ vdi_pool_id = val
1672
+ end
1673
+ opts.on( nil, '--all', "Update all VDI pools at once." ) do
1674
+ do_all = true
1675
+ end
1676
+ opts.on( '--access VALUE', String, "Access value [#{allowed_access_values.join('|')}]" ) do |val|
1677
+ access_value = val
1678
+ end
1679
+ build_common_options(opts, options, [:json, :dry_run, :remote])
1680
+ opts.footer = "Update role access for a VDI pool or all VDI pools.\n" +
1681
+ "[role] is required. This is the name or id of a role.\n" +
1682
+ "--vdi-pool or --all is required. This is the name or id of a VDI pool.\n" +
1683
+ "--access is required. This is the new access value. #{anded_list(allowed_access_values)}"
1684
+ end
1685
+ optparse.parse!(args)
1686
+
1687
+ # usage: update-vdi-pool-access [role] [access] --all
1688
+ # update-vdi-pool-access [role] [vdi-pool] [access]
1689
+ name = args[0]
1690
+ if do_all
1691
+ verify_args!(args:args, optparse:optparse, min:1, max:2)
1692
+ access_value = args[1] if args[1]
1693
+ else
1694
+ verify_args!(args:args, optparse:optparse, min:1, max:3)
1695
+ vdi_pool_id = args[1] if args[1]
1696
+ access_value = args[2] if args[2]
1697
+ end
1698
+ if !vdi_pool_id && !do_all
1699
+ raise_command_error("missing required argument: [vdi-pool] or --all", optparse)
1700
+ end
1701
+ if !access_value
1702
+ raise_command_error("missing required argument: [access]", optparse)
1703
+ end
1704
+ access_value = access_value.to_s.downcase
1705
+ if !allowed_access_values.include?(access_value)
1706
+ raise_command_error("invalid access value: #{access_value}", optparse)
1707
+ puts optparse
1708
+ return 1
1709
+ end
1710
+
1711
+ connect(options)
1712
+ begin
1713
+ account = find_account_from_options(options)
1714
+ account_id = account ? account['id'] : nil
1715
+ role = find_role_by_name_or_id(account_id, name)
1716
+ return 1 if role.nil?
1717
+
1718
+ role_json = @roles_interface.get(account_id, role['id'])
1719
+ vdi_pool_global_access = role_json['globalVdiPoolAccess']
1720
+ vdi_pool_permissions = role_json['vdiPoolPermissions'] || []
1721
+ if vdi_pool_global_access != 'custom'
1722
+ print "\n", red, "Global VDI Pool Access is currently: #{vdi_pool_global_access.to_s.capitalize}"
1723
+ print "\n", "You must first set it to Custom via `morpheus roles update-global-vdi-pool-access \"#{name}\" custom`"
1724
+ print "\n\n", reset
1725
+ return 1
1726
+ end
1727
+
1728
+ # hacky, but support name or code lookup via the list returned in the show payload
1729
+ vdi_pool = nil
1730
+ if !do_all
1731
+ if vdi_pool_id.to_s =~ /\A\d{1,}\Z/
1732
+ vdi_pool = vdi_pool_permissions.find {|b| b['id'] == vdi_pool_id.to_i }
1733
+ else
1734
+ vdi_pool = vdi_pool_permissions.find {|b| b['name'] == vdi_pool_id }
1735
+ end
1736
+ if vdi_pool.nil?
1737
+ print_red_alert "VDI Pool not found: '#{vdi_pool_id}'"
1738
+ return 1
1739
+ end
1740
+ end
1741
+
1742
+ params = {}
1743
+ if do_all
1744
+ params['allVdiPools'] = true
1745
+ else
1746
+ params['vdiPoolId'] = vdi_pool['id']
1747
+ end
1748
+ params['access'] = access_value
1749
+ @roles_interface.setopts(options)
1750
+ if options[:dry_run]
1751
+ print_dry_run @roles_interface.dry.update_vdi_pool(account_id, role['id'], params)
1752
+ return
1753
+ end
1754
+ json_response = @roles_interface.update_vdi_pool(account_id, role['id'], params)
1755
+
1756
+ if options[:json]
1757
+ print JSON.pretty_generate(json_response)
1758
+ print "\n"
1759
+ else
1760
+ if do_all
1761
+ print_green_success "Role #{role['authority']} access updated for all VDI pools"
1762
+ else
1763
+ print_green_success "Role #{role['authority']} access updated for VDI pool #{vdi_pool['name']}"
1764
+ end
1765
+ end
1766
+ return 0
1767
+ rescue RestClient::Exception => e
1768
+ print_rest_exception(e, options)
1769
+ exit 1
1770
+ end
1771
+ end
1772
+
1609
1773
  private
1610
1774
 
1611
1775
  def add_role_option_types
@@ -1616,7 +1780,7 @@ EOT
1616
1780
  {'fieldName' => 'baseRole', 'fieldLabel' => 'Copy From Role', 'type' => 'text'},
1617
1781
  {'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'},
1618
1782
  {'fieldName' => 'multitenantLocked', 'fieldLabel' => 'Multitenant Locked', 'type' => 'checkbox', 'defaultValue' => 'off', 'description' => 'Prevents subtenants from branching off this role/modifying it. '},
1619
- {'fieldName' => 'defaultPersona', 'fieldLabel' => 'Default Persona', 'type' => 'select', 'selectOptions' => [{'name'=>'Service Catalog','value'=>'serviceCatalog'},{'name'=>'Standard','value'=>'standard'}], 'description' => 'Default Persona'}
1783
+ {'fieldName' => 'defaultPersona', 'fieldLabel' => 'Default Persona', 'type' => 'select', 'selectOptions' => get_persona_select_options(), 'description' => 'Default Persona'}
1620
1784
  ]
1621
1785
  end
1622
1786
 
@@ -1624,20 +1788,16 @@ EOT
1624
1788
  add_role_option_types.reject {|it| ['roleType', 'baseRole'].include?(it['fieldName']) }
1625
1789
  end
1626
1790
 
1627
-
1628
- def find_cloud_id_by_name(group_id, name)
1629
- option_results = @options_interface.options_for_source('clouds', {groupId: group_id})
1630
- match = option_results['data'].find { |grp| grp['value'].to_s == name.to_s || grp['name'].downcase == name.downcase}
1631
- if match.nil?
1632
- print_red_alert "Cloud not found by name #{name}"
1633
- return nil
1634
- else
1635
- return match['value']
1636
- end
1637
- end
1638
-
1639
1791
  def role_type_options
1640
1792
  [{'name' => 'User Role', 'value' => 'user'}, {'name' => 'Account Role', 'value' => 'account'}]
1641
1793
  end
1642
1794
 
1795
+ def get_persona_select_options
1796
+ [
1797
+ {'name'=>'Service Catalog','value'=>'serviceCatalog'},
1798
+ {'name'=>'Standard','value'=>'standard'},
1799
+ {'name'=>'Virtual Desktop','value'=>'vdi'}
1800
+ ]
1801
+ end
1802
+
1643
1803
  end