mtncloud-cli 1.0.0

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 (499) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +20 -0
  3. data/.github/pull_request_template.md +14 -0
  4. data/.github/workflows/ci.yml +56 -0
  5. data/.github/workflows/release.yml +46 -0
  6. data/.gitignore +25 -0
  7. data/CLAUDE.md +24 -0
  8. data/CONTRIBUTING.md +91 -0
  9. data/Dockerfile +19 -0
  10. data/Gemfile +4 -0
  11. data/LICENSE.txt +23 -0
  12. data/README.md +187 -0
  13. data/Rakefile +26 -0
  14. data/bin/mcs +3 -0
  15. data/bin/mtncloud +27 -0
  16. data/lib/mtncloud/api/account_groups_interface.rb +48 -0
  17. data/lib/mtncloud/api/account_users_interface.rb +68 -0
  18. data/lib/mtncloud/api/accounts_interface.rb +9 -0
  19. data/lib/mtncloud/api/activity_interface.rb +9 -0
  20. data/lib/mtncloud/api/affinity_groups_interface.rb +46 -0
  21. data/lib/mtncloud/api/api_client.rb +1091 -0
  22. data/lib/mtncloud/api/appliance_settings_interface.rb +49 -0
  23. data/lib/mtncloud/api/approvals_interface.rb +32 -0
  24. data/lib/mtncloud/api/apps_interface.rb +180 -0
  25. data/lib/mtncloud/api/archive_buckets_interface.rb +116 -0
  26. data/lib/mtncloud/api/archive_files_interface.rb +173 -0
  27. data/lib/mtncloud/api/audit_interface.rb +9 -0
  28. data/lib/mtncloud/api/auth_interface.rb +58 -0
  29. data/lib/mtncloud/api/backup_jobs_interface.rb +13 -0
  30. data/lib/mtncloud/api/backup_restores_interface.rb +27 -0
  31. data/lib/mtncloud/api/backup_results_interface.rb +32 -0
  32. data/lib/mtncloud/api/backup_service_types_interface.rb +9 -0
  33. data/lib/mtncloud/api/backup_services_interface.rb +9 -0
  34. data/lib/mtncloud/api/backup_settings_interface.rb +20 -0
  35. data/lib/mtncloud/api/backup_types_interface.rb +9 -0
  36. data/lib/mtncloud/api/backups_interface.rb +21 -0
  37. data/lib/mtncloud/api/billing_interface.rb +34 -0
  38. data/lib/mtncloud/api/blueprints_interface.rb +70 -0
  39. data/lib/mtncloud/api/body_io.rb +22 -0
  40. data/lib/mtncloud/api/budgets_interface.rb +48 -0
  41. data/lib/mtncloud/api/catalog_item_types_interface.rb +29 -0
  42. data/lib/mtncloud/api/certificate_types_interface.rb +14 -0
  43. data/lib/mtncloud/api/certificates_interface.rb +9 -0
  44. data/lib/mtncloud/api/clients_interface.rb +41 -0
  45. data/lib/mtncloud/api/cloud_datastores_interface.rb +48 -0
  46. data/lib/mtncloud/api/cloud_folders_interface.rb +41 -0
  47. data/lib/mtncloud/api/cloud_policies_interface.rb +41 -0
  48. data/lib/mtncloud/api/cloud_resource_pools_interface.rb +66 -0
  49. data/lib/mtncloud/api/clouds_interface.rb +217 -0
  50. data/lib/mtncloud/api/clusters_interface.rb +471 -0
  51. data/lib/mtncloud/api/containers_interface.rb +145 -0
  52. data/lib/mtncloud/api/credential_types_interface.rb +9 -0
  53. data/lib/mtncloud/api/credentials_interface.rb +9 -0
  54. data/lib/mtncloud/api/custom_instance_types_interface.rb +99 -0
  55. data/lib/mtncloud/api/cypher_interface.rb +51 -0
  56. data/lib/mtncloud/api/dashboard_interface.rb +14 -0
  57. data/lib/mtncloud/api/datastores_interface.rb +21 -0
  58. data/lib/mtncloud/api/deploy_interface.rb +44 -0
  59. data/lib/mtncloud/api/deployments_interface.rb +79 -0
  60. data/lib/mtncloud/api/distributed_workers_interface.rb +41 -0
  61. data/lib/mtncloud/api/email_templates_interface.rb +53 -0
  62. data/lib/mtncloud/api/environments_interface.rb +48 -0
  63. data/lib/mtncloud/api/execute_schedules_interface.rb +71 -0
  64. data/lib/mtncloud/api/execution_request_interface.rb +27 -0
  65. data/lib/mtncloud/api/file_copy_request_interface.rb +68 -0
  66. data/lib/mtncloud/api/forgot_password_interface.rb +17 -0
  67. data/lib/mtncloud/api/group_policies_interface.rb +41 -0
  68. data/lib/mtncloud/api/groups_interface.rb +73 -0
  69. data/lib/mtncloud/api/guidance_interface.rb +44 -0
  70. data/lib/mtncloud/api/guidance_settings_interface.rb +17 -0
  71. data/lib/mtncloud/api/health_interface.rb +100 -0
  72. data/lib/mtncloud/api/host_vm_groups_interface.rb +37 -0
  73. data/lib/mtncloud/api/hub_interface.rb +25 -0
  74. data/lib/mtncloud/api/image_builder_boot_scripts_interface.rb +41 -0
  75. data/lib/mtncloud/api/image_builder_image_builds_interface.rb +73 -0
  76. data/lib/mtncloud/api/image_builder_interface.rb +20 -0
  77. data/lib/mtncloud/api/image_builder_preseed_scripts_interface.rb +41 -0
  78. data/lib/mtncloud/api/instance_types_interface.rb +20 -0
  79. data/lib/mtncloud/api/instances_interface.rb +453 -0
  80. data/lib/mtncloud/api/integration_types_interface.rb +14 -0
  81. data/lib/mtncloud/api/integrations_interface.rb +74 -0
  82. data/lib/mtncloud/api/invoice_line_items_interface.rb +9 -0
  83. data/lib/mtncloud/api/invoices_interface.rb +28 -0
  84. data/lib/mtncloud/api/jobs_interface.rb +83 -0
  85. data/lib/mtncloud/api/key_pairs_interface.rb +57 -0
  86. data/lib/mtncloud/api/library_cluster_layouts_interface.rb +47 -0
  87. data/lib/mtncloud/api/library_cluster_packages_interface.rb +60 -0
  88. data/lib/mtncloud/api/library_container_scripts_interface.rb +43 -0
  89. data/lib/mtncloud/api/library_container_templates_interface.rb +43 -0
  90. data/lib/mtncloud/api/library_container_types_interface.rb +59 -0
  91. data/lib/mtncloud/api/library_container_upgrades_interface.rb +60 -0
  92. data/lib/mtncloud/api/library_instance_types_interface.rb +74 -0
  93. data/lib/mtncloud/api/library_layouts_interface.rb +69 -0
  94. data/lib/mtncloud/api/library_operating_systems_interface.rb +63 -0
  95. data/lib/mtncloud/api/library_spec_template_types_interface.rb +43 -0
  96. data/lib/mtncloud/api/library_spec_templates_interface.rb +43 -0
  97. data/lib/mtncloud/api/license_interface.rb +30 -0
  98. data/lib/mtncloud/api/load_balancer_monitors_interface.rb +9 -0
  99. data/lib/mtncloud/api/load_balancer_pool_nodes_interface.rb +8 -0
  100. data/lib/mtncloud/api/load_balancer_pools_interface.rb +9 -0
  101. data/lib/mtncloud/api/load_balancer_pools_secondary_interface.rb +9 -0
  102. data/lib/mtncloud/api/load_balancer_profiles_interface.rb +9 -0
  103. data/lib/mtncloud/api/load_balancer_types_interface.rb +9 -0
  104. data/lib/mtncloud/api/load_balancer_virtual_servers_interface.rb +18 -0
  105. data/lib/mtncloud/api/load_balancers_interface.rb +14 -0
  106. data/lib/mtncloud/api/log_settings_interface.rb +44 -0
  107. data/lib/mtncloud/api/logs_interface.rb +37 -0
  108. data/lib/mtncloud/api/migrations_interface.rb +49 -0
  109. data/lib/mtncloud/api/monitoring_alerts_interface.rb +39 -0
  110. data/lib/mtncloud/api/monitoring_apps_interface.rb +69 -0
  111. data/lib/mtncloud/api/monitoring_checks_interface.rb +103 -0
  112. data/lib/mtncloud/api/monitoring_contacts_interface.rb +41 -0
  113. data/lib/mtncloud/api/monitoring_groups_interface.rb +77 -0
  114. data/lib/mtncloud/api/monitoring_incidents_interface.rb +107 -0
  115. data/lib/mtncloud/api/monitoring_interface.rb +35 -0
  116. data/lib/mtncloud/api/monitoring_settings_interface.rb +21 -0
  117. data/lib/mtncloud/api/network_dhcp_relays_interface.rb +36 -0
  118. data/lib/mtncloud/api/network_dhcp_servers_interface.rb +36 -0
  119. data/lib/mtncloud/api/network_domain_records_interface.rb +41 -0
  120. data/lib/mtncloud/api/network_domains_interface.rb +41 -0
  121. data/lib/mtncloud/api/network_edge_clusters_interface.rb +26 -0
  122. data/lib/mtncloud/api/network_floating_ips_interface.rb +40 -0
  123. data/lib/mtncloud/api/network_groups_interface.rb +41 -0
  124. data/lib/mtncloud/api/network_pool_ips_interface.rb +41 -0
  125. data/lib/mtncloud/api/network_pool_server_types_interface.rb +9 -0
  126. data/lib/mtncloud/api/network_pool_servers_interface.rb +48 -0
  127. data/lib/mtncloud/api/network_pools_interface.rb +41 -0
  128. data/lib/mtncloud/api/network_proxies_interface.rb +41 -0
  129. data/lib/mtncloud/api/network_routers_interface.rb +181 -0
  130. data/lib/mtncloud/api/network_security_server_types_interface.rb +9 -0
  131. data/lib/mtncloud/api/network_security_servers_interface.rb +27 -0
  132. data/lib/mtncloud/api/network_server_groups_interface.rb +7 -0
  133. data/lib/mtncloud/api/network_server_types_interface.rb +9 -0
  134. data/lib/mtncloud/api/network_servers_interface.rb +102 -0
  135. data/lib/mtncloud/api/network_services_interface.rb +63 -0
  136. data/lib/mtncloud/api/network_static_routes_interface.rb +36 -0
  137. data/lib/mtncloud/api/network_subnets_interface.rb +42 -0
  138. data/lib/mtncloud/api/network_types_interface.rb +20 -0
  139. data/lib/mtncloud/api/networks_interface.rb +48 -0
  140. data/lib/mtncloud/api/option_type_forms_interface.rb +9 -0
  141. data/lib/mtncloud/api/option_type_lists_interface.rb +53 -0
  142. data/lib/mtncloud/api/option_types_interface.rb +41 -0
  143. data/lib/mtncloud/api/options_interface.rb +17 -0
  144. data/lib/mtncloud/api/packages_interface.rb +112 -0
  145. data/lib/mtncloud/api/ping_interface.rb +22 -0
  146. data/lib/mtncloud/api/plugins_interface.rb +22 -0
  147. data/lib/mtncloud/api/policies_interface.rb +56 -0
  148. data/lib/mtncloud/api/power_schedules_interface.rb +71 -0
  149. data/lib/mtncloud/api/price_sets_interface.rb +39 -0
  150. data/lib/mtncloud/api/prices_interface.rb +71 -0
  151. data/lib/mtncloud/api/processes_interface.rb +40 -0
  152. data/lib/mtncloud/api/projects_interface.rb +33 -0
  153. data/lib/mtncloud/api/provision_types_interface.rb +24 -0
  154. data/lib/mtncloud/api/provisioning_license_types_interface.rb +31 -0
  155. data/lib/mtncloud/api/provisioning_licenses_interface.rb +60 -0
  156. data/lib/mtncloud/api/provisioning_settings_interface.rb +26 -0
  157. data/lib/mtncloud/api/read_interface.rb +24 -0
  158. data/lib/mtncloud/api/reports_interface.rb +70 -0
  159. data/lib/mtncloud/api/resource_pool_groups_interface.rb +51 -0
  160. data/lib/mtncloud/api/rest_interface.rb +37 -0
  161. data/lib/mtncloud/api/roles_interface.rb +151 -0
  162. data/lib/mtncloud/api/scale_thresholds_interface.rb +9 -0
  163. data/lib/mtncloud/api/search_interface.rb +13 -0
  164. data/lib/mtncloud/api/secondary_read_interface.rb +25 -0
  165. data/lib/mtncloud/api/secondary_rest_interface.rb +42 -0
  166. data/lib/mtncloud/api/security_group_rules_interface.rb +35 -0
  167. data/lib/mtncloud/api/security_groups_interface.rb +56 -0
  168. data/lib/mtncloud/api/security_package_types_interface.rb +9 -0
  169. data/lib/mtncloud/api/security_packages_interface.rb +9 -0
  170. data/lib/mtncloud/api/security_scans_interface.rb +9 -0
  171. data/lib/mtncloud/api/server_devices_interface.rb +30 -0
  172. data/lib/mtncloud/api/server_types_interface.rb +20 -0
  173. data/lib/mtncloud/api/servers_interface.rb +230 -0
  174. data/lib/mtncloud/api/service_catalog_interface.rb +89 -0
  175. data/lib/mtncloud/api/service_plans_interface.rb +62 -0
  176. data/lib/mtncloud/api/setup_interface.rb +46 -0
  177. data/lib/mtncloud/api/snapshots_interface.rb +19 -0
  178. data/lib/mtncloud/api/storage_datastores_interface.rb +44 -0
  179. data/lib/mtncloud/api/storage_providers_interface.rb +151 -0
  180. data/lib/mtncloud/api/storage_server_types_interface.rb +14 -0
  181. data/lib/mtncloud/api/storage_servers_interface.rb +9 -0
  182. data/lib/mtncloud/api/storage_volume_types_interface.rb +9 -0
  183. data/lib/mtncloud/api/storage_volumes_interface.rb +24 -0
  184. data/lib/mtncloud/api/subnet_types_interface.rb +20 -0
  185. data/lib/mtncloud/api/subnets_interface.rb +41 -0
  186. data/lib/mtncloud/api/support_bundles_interface.rb +46 -0
  187. data/lib/mtncloud/api/system_types_interface.rb +13 -0
  188. data/lib/mtncloud/api/systems_interface.rb +55 -0
  189. data/lib/mtncloud/api/task_sets_interface.rb +52 -0
  190. data/lib/mtncloud/api/tasks_interface.rb +66 -0
  191. data/lib/mtncloud/api/tokens_interface.rb +39 -0
  192. data/lib/mtncloud/api/usage_interface.rb +18 -0
  193. data/lib/mtncloud/api/user_groups_interface.rb +59 -0
  194. data/lib/mtncloud/api/user_settings_interface.rb +90 -0
  195. data/lib/mtncloud/api/user_sources_interface.rb +99 -0
  196. data/lib/mtncloud/api/users_interface.rb +33 -0
  197. data/lib/mtncloud/api/vdi_allocations_interface.rb +9 -0
  198. data/lib/mtncloud/api/vdi_apps_interface.rb +9 -0
  199. data/lib/mtncloud/api/vdi_gateways_interface.rb +9 -0
  200. data/lib/mtncloud/api/vdi_interface.rb +28 -0
  201. data/lib/mtncloud/api/vdi_pools_interface.rb +19 -0
  202. data/lib/mtncloud/api/virtual_images_interface.rb +210 -0
  203. data/lib/mtncloud/api/virtual_servers_interface.rb +9 -0
  204. data/lib/mtncloud/api/virtual_switches_interface.rb +9 -0
  205. data/lib/mtncloud/api/whitelabel_settings_interface.rb +57 -0
  206. data/lib/mtncloud/api/whoami_interface.rb +13 -0
  207. data/lib/mtncloud/api/wiki_interface.rb +48 -0
  208. data/lib/mtncloud/api.rb +12 -0
  209. data/lib/mtncloud/benchmarking.rb +259 -0
  210. data/lib/mtncloud/cli/cli_command.rb +2281 -0
  211. data/lib/mtncloud/cli/cli_registry.rb +337 -0
  212. data/lib/mtncloud/cli/commands/access_token_command.rb +201 -0
  213. data/lib/mtncloud/cli/commands/account_groups_command.rb +530 -0
  214. data/lib/mtncloud/cli/commands/activity_command.rb +149 -0
  215. data/lib/mtncloud/cli/commands/affinity_groups_command.rb +554 -0
  216. data/lib/mtncloud/cli/commands/alias_command.rb +278 -0
  217. data/lib/mtncloud/cli/commands/appliance_settings_command.rb +382 -0
  218. data/lib/mtncloud/cli/commands/approvals_command.rb +236 -0
  219. data/lib/mtncloud/cli/commands/apps.rb +2549 -0
  220. data/lib/mtncloud/cli/commands/archives_command.rb +2161 -0
  221. data/lib/mtncloud/cli/commands/audit.rb +188 -0
  222. data/lib/mtncloud/cli/commands/backup_jobs_command.rb +366 -0
  223. data/lib/mtncloud/cli/commands/backup_restores_command.rb +144 -0
  224. data/lib/mtncloud/cli/commands/backup_results_command.rb +149 -0
  225. data/lib/mtncloud/cli/commands/backup_services_command.rb +44 -0
  226. data/lib/mtncloud/cli/commands/backup_settings_command.rb +184 -0
  227. data/lib/mtncloud/cli/commands/backup_types_command.rb +53 -0
  228. data/lib/mtncloud/cli/commands/backups_command.rb +674 -0
  229. data/lib/mtncloud/cli/commands/benchmark_command.rb +458 -0
  230. data/lib/mtncloud/cli/commands/blueprints_command.rb +2297 -0
  231. data/lib/mtncloud/cli/commands/boot_scripts_command.rb +379 -0
  232. data/lib/mtncloud/cli/commands/budgets_command.rb +754 -0
  233. data/lib/mtncloud/cli/commands/cat_command.rb +45 -0
  234. data/lib/mtncloud/cli/commands/catalog_item_types_command.rb +858 -0
  235. data/lib/mtncloud/cli/commands/certificates_command.rb +575 -0
  236. data/lib/mtncloud/cli/commands/change_password_command.rb +132 -0
  237. data/lib/mtncloud/cli/commands/clients_command.rb +331 -0
  238. data/lib/mtncloud/cli/commands/cloud_datastores_command.rb +543 -0
  239. data/lib/mtncloud/cli/commands/cloud_folders_command.rb +512 -0
  240. data/lib/mtncloud/cli/commands/cloud_resource_pools_command.rb +870 -0
  241. data/lib/mtncloud/cli/commands/clouds.rb +2037 -0
  242. data/lib/mtncloud/cli/commands/clouds_types.rb +140 -0
  243. data/lib/mtncloud/cli/commands/cluster_types.rb +179 -0
  244. data/lib/mtncloud/cli/commands/clusters.rb +5855 -0
  245. data/lib/mtncloud/cli/commands/coloring_command.rb +82 -0
  246. data/lib/mtncloud/cli/commands/containers_command.rb +967 -0
  247. data/lib/mtncloud/cli/commands/credential_types_command.rb +36 -0
  248. data/lib/mtncloud/cli/commands/credentials_command.rb +124 -0
  249. data/lib/mtncloud/cli/commands/curl_command.rb +168 -0
  250. data/lib/mtncloud/cli/commands/cypher_command.rb +587 -0
  251. data/lib/mtncloud/cli/commands/dashboard_command.rb +300 -0
  252. data/lib/mtncloud/cli/commands/debug_command.rb +75 -0
  253. data/lib/mtncloud/cli/commands/deploy.rb +485 -0
  254. data/lib/mtncloud/cli/commands/deployments.rb +923 -0
  255. data/lib/mtncloud/cli/commands/deploys.rb +485 -0
  256. data/lib/mtncloud/cli/commands/distributed_workers_command.rb +282 -0
  257. data/lib/mtncloud/cli/commands/echo_command.rb +61 -0
  258. data/lib/mtncloud/cli/commands/edit_profile_command.rb +57 -0
  259. data/lib/mtncloud/cli/commands/edit_rc_command.rb +77 -0
  260. data/lib/mtncloud/cli/commands/email_templates_command.rb +373 -0
  261. data/lib/mtncloud/cli/commands/environments_command.rb +401 -0
  262. data/lib/mtncloud/cli/commands/execute_schedules_command.rb +735 -0
  263. data/lib/mtncloud/cli/commands/execution_request_command.rb +333 -0
  264. data/lib/mtncloud/cli/commands/exit_command.rb +34 -0
  265. data/lib/mtncloud/cli/commands/file_copy_request_command.rb +352 -0
  266. data/lib/mtncloud/cli/commands/forgot_password.rb +133 -0
  267. data/lib/mtncloud/cli/commands/get_prompt_command.rb +36 -0
  268. data/lib/mtncloud/cli/commands/groups.rb +818 -0
  269. data/lib/mtncloud/cli/commands/guidance_command.rb +529 -0
  270. data/lib/mtncloud/cli/commands/guidance_settings.rb +148 -0
  271. data/lib/mtncloud/cli/commands/health_command.rb +1046 -0
  272. data/lib/mtncloud/cli/commands/history_command.rb +60 -0
  273. data/lib/mtncloud/cli/commands/host_vm_groups_command.rb +423 -0
  274. data/lib/mtncloud/cli/commands/hosts.rb +2986 -0
  275. data/lib/mtncloud/cli/commands/hub.rb +215 -0
  276. data/lib/mtncloud/cli/commands/image_builder_command.rb +1197 -0
  277. data/lib/mtncloud/cli/commands/instance_types.rb +163 -0
  278. data/lib/mtncloud/cli/commands/instances.rb +5813 -0
  279. data/lib/mtncloud/cli/commands/integrations_command.rb +1412 -0
  280. data/lib/mtncloud/cli/commands/invoices_command.rb +1151 -0
  281. data/lib/mtncloud/cli/commands/jobs_command.rb +998 -0
  282. data/lib/mtncloud/cli/commands/key_pairs.rb +470 -0
  283. data/lib/mtncloud/cli/commands/library_cluster_layouts_command.rb +901 -0
  284. data/lib/mtncloud/cli/commands/library_cluster_packages_command.rb +552 -0
  285. data/lib/mtncloud/cli/commands/library_container_scripts_command.rb +446 -0
  286. data/lib/mtncloud/cli/commands/library_container_templates_command.rb +526 -0
  287. data/lib/mtncloud/cli/commands/library_container_types_command.rb +698 -0
  288. data/lib/mtncloud/cli/commands/library_forms_command.rb +625 -0
  289. data/lib/mtncloud/cli/commands/library_instance_types_command.rb +668 -0
  290. data/lib/mtncloud/cli/commands/library_layouts_command.rb +849 -0
  291. data/lib/mtncloud/cli/commands/library_operating_systems_command.rb +671 -0
  292. data/lib/mtncloud/cli/commands/library_option_lists_command.rb +503 -0
  293. data/lib/mtncloud/cli/commands/library_option_types_command.rb +329 -0
  294. data/lib/mtncloud/cli/commands/library_spec_templates_command.rb +547 -0
  295. data/lib/mtncloud/cli/commands/library_upgrades_command.rb +596 -0
  296. data/lib/mtncloud/cli/commands/license.rb +475 -0
  297. data/lib/mtncloud/cli/commands/load_balancer_monitors.rb +70 -0
  298. data/lib/mtncloud/cli/commands/load_balancer_pool_nodes.rb +87 -0
  299. data/lib/mtncloud/cli/commands/load_balancer_pools.rb +129 -0
  300. data/lib/mtncloud/cli/commands/load_balancer_profiles.rb +64 -0
  301. data/lib/mtncloud/cli/commands/load_balancer_types.rb +38 -0
  302. data/lib/mtncloud/cli/commands/load_balancer_virtual_servers.rb +147 -0
  303. data/lib/mtncloud/cli/commands/load_balancers.rb +189 -0
  304. data/lib/mtncloud/cli/commands/log_level_command.rb +54 -0
  305. data/lib/mtncloud/cli/commands/log_settings_command.rb +443 -0
  306. data/lib/mtncloud/cli/commands/login.rb +148 -0
  307. data/lib/mtncloud/cli/commands/logout.rb +63 -0
  308. data/lib/mtncloud/cli/commands/logs_command.rb +140 -0
  309. data/lib/mtncloud/cli/commands/man_command.rb +409 -0
  310. data/lib/mtncloud/cli/commands/migrations.rb +453 -0
  311. data/lib/mtncloud/cli/commands/monitoring_alerts_command.rb +791 -0
  312. data/lib/mtncloud/cli/commands/monitoring_apps_command.rb +716 -0
  313. data/lib/mtncloud/cli/commands/monitoring_checks_command.rb +766 -0
  314. data/lib/mtncloud/cli/commands/monitoring_contacts_command.rb +339 -0
  315. data/lib/mtncloud/cli/commands/monitoring_groups_command.rb +674 -0
  316. data/lib/mtncloud/cli/commands/monitoring_incidents_command.rb +835 -0
  317. data/lib/mtncloud/cli/commands/monitoring_settings.rb +212 -0
  318. data/lib/mtncloud/cli/commands/network_dhcp_relays_command.rb +375 -0
  319. data/lib/mtncloud/cli/commands/network_dhcp_servers_command.rb +366 -0
  320. data/lib/mtncloud/cli/commands/network_domains_command.rb +896 -0
  321. data/lib/mtncloud/cli/commands/network_edge_clusters_command.rb +288 -0
  322. data/lib/mtncloud/cli/commands/network_firewalls_command.rb +783 -0
  323. data/lib/mtncloud/cli/commands/network_floating_ips.rb +147 -0
  324. data/lib/mtncloud/cli/commands/network_groups_command.rb +654 -0
  325. data/lib/mtncloud/cli/commands/network_pool_server_types.rb +20 -0
  326. data/lib/mtncloud/cli/commands/network_pool_servers_command.rb +318 -0
  327. data/lib/mtncloud/cli/commands/network_pools_command.rb +903 -0
  328. data/lib/mtncloud/cli/commands/network_proxies_command.rb +578 -0
  329. data/lib/mtncloud/cli/commands/network_routers_command.rb +2628 -0
  330. data/lib/mtncloud/cli/commands/network_security_server_types.rb +20 -0
  331. data/lib/mtncloud/cli/commands/network_server_groups_command.rb +222 -0
  332. data/lib/mtncloud/cli/commands/network_server_types_command.rb +20 -0
  333. data/lib/mtncloud/cli/commands/network_servers_command.rb +398 -0
  334. data/lib/mtncloud/cli/commands/network_services_command.rb +198 -0
  335. data/lib/mtncloud/cli/commands/network_static_routes_command.rb +451 -0
  336. data/lib/mtncloud/cli/commands/network_transport_zones_command.rb +412 -0
  337. data/lib/mtncloud/cli/commands/networks_command.rb +1692 -0
  338. data/lib/mtncloud/cli/commands/open_command.rb +30 -0
  339. data/lib/mtncloud/cli/commands/options.rb +231 -0
  340. data/lib/mtncloud/cli/commands/packages_command.rb +822 -0
  341. data/lib/mtncloud/cli/commands/ping.rb +242 -0
  342. data/lib/mtncloud/cli/commands/plugins.rb +214 -0
  343. data/lib/mtncloud/cli/commands/policies_command.rb +990 -0
  344. data/lib/mtncloud/cli/commands/power_schedules_command.rb +731 -0
  345. data/lib/mtncloud/cli/commands/preseed_scripts_command.rb +378 -0
  346. data/lib/mtncloud/cli/commands/price_sets_command.rb +557 -0
  347. data/lib/mtncloud/cli/commands/prices_command.rb +692 -0
  348. data/lib/mtncloud/cli/commands/processes_command.rb +469 -0
  349. data/lib/mtncloud/cli/commands/projects_command.rb +537 -0
  350. data/lib/mtncloud/cli/commands/provisioning_licenses_command.rb +509 -0
  351. data/lib/mtncloud/cli/commands/provisioning_settings_command.rb +238 -0
  352. data/lib/mtncloud/cli/commands/recent_activity_command.rb +171 -0
  353. data/lib/mtncloud/cli/commands/remote.rb +1818 -0
  354. data/lib/mtncloud/cli/commands/reports_command.rb +724 -0
  355. data/lib/mtncloud/cli/commands/resource_pool_groups_command.rb +586 -0
  356. data/lib/mtncloud/cli/commands/rm_command.rb +14 -0
  357. data/lib/mtncloud/cli/commands/roles.rb +3120 -0
  358. data/lib/mtncloud/cli/commands/scale_thresholds.rb +103 -0
  359. data/lib/mtncloud/cli/commands/search_command.rb +184 -0
  360. data/lib/mtncloud/cli/commands/security_group_rules.rb +230 -0
  361. data/lib/mtncloud/cli/commands/security_groups.rb +1294 -0
  362. data/lib/mtncloud/cli/commands/security_package_types.rb +32 -0
  363. data/lib/mtncloud/cli/commands/security_packages.rb +84 -0
  364. data/lib/mtncloud/cli/commands/security_scans.rb +107 -0
  365. data/lib/mtncloud/cli/commands/self_service_command.rb +17 -0
  366. data/lib/mtncloud/cli/commands/server_devices_command.rb +207 -0
  367. data/lib/mtncloud/cli/commands/service_catalog_command.rb +1528 -0
  368. data/lib/mtncloud/cli/commands/service_plans_command.rb +895 -0
  369. data/lib/mtncloud/cli/commands/set_prompt_command.rb +51 -0
  370. data/lib/mtncloud/cli/commands/setup.rb +423 -0
  371. data/lib/mtncloud/cli/commands/shell.rb +717 -0
  372. data/lib/mtncloud/cli/commands/sleep_command.rb +43 -0
  373. data/lib/mtncloud/cli/commands/snapshots.rb +156 -0
  374. data/lib/mtncloud/cli/commands/source_command.rb +30 -0
  375. data/lib/mtncloud/cli/commands/ssl_verification_command.rb +47 -0
  376. data/lib/mtncloud/cli/commands/storage_datastores.rb +457 -0
  377. data/lib/mtncloud/cli/commands/storage_providers_command.rb +1401 -0
  378. data/lib/mtncloud/cli/commands/storage_server_types.rb +45 -0
  379. data/lib/mtncloud/cli/commands/storage_servers.rb +116 -0
  380. data/lib/mtncloud/cli/commands/storage_volume_types.rb +45 -0
  381. data/lib/mtncloud/cli/commands/storage_volumes.rb +236 -0
  382. data/lib/mtncloud/cli/commands/subnets_command.rb +819 -0
  383. data/lib/mtncloud/cli/commands/support_bundles_command.rb +606 -0
  384. data/lib/mtncloud/cli/commands/systems.rb +1203 -0
  385. data/lib/mtncloud/cli/commands/tasks.rb +1391 -0
  386. data/lib/mtncloud/cli/commands/tee_command.rb +14 -0
  387. data/lib/mtncloud/cli/commands/tenants_command.rb +315 -0
  388. data/lib/mtncloud/cli/commands/tokens_command.rb +391 -0
  389. data/lib/mtncloud/cli/commands/update_command.rb +46 -0
  390. data/lib/mtncloud/cli/commands/usage_command.rb +203 -0
  391. data/lib/mtncloud/cli/commands/user_groups_command.rb +512 -0
  392. data/lib/mtncloud/cli/commands/user_settings_command.rb +849 -0
  393. data/lib/mtncloud/cli/commands/user_sources_command.rb +1065 -0
  394. data/lib/mtncloud/cli/commands/users.rb +897 -0
  395. data/lib/mtncloud/cli/commands/vdi_allocations_command.rb +159 -0
  396. data/lib/mtncloud/cli/commands/vdi_apps_command.rb +317 -0
  397. data/lib/mtncloud/cli/commands/vdi_command.rb +359 -0
  398. data/lib/mtncloud/cli/commands/vdi_gateways_command.rb +290 -0
  399. data/lib/mtncloud/cli/commands/vdi_pools_command.rb +574 -0
  400. data/lib/mtncloud/cli/commands/version_command.rb +38 -0
  401. data/lib/mtncloud/cli/commands/view.rb +107 -0
  402. data/lib/mtncloud/cli/commands/virtual_images.rb +1362 -0
  403. data/lib/mtncloud/cli/commands/virtual_switches_command.rb +336 -0
  404. data/lib/mtncloud/cli/commands/whitelabel_settings_command.rb +653 -0
  405. data/lib/mtncloud/cli/commands/whoami.rb +323 -0
  406. data/lib/mtncloud/cli/commands/wiki_command.rb +448 -0
  407. data/lib/mtncloud/cli/commands/workflows.rb +1022 -0
  408. data/lib/mtncloud/cli/credentials.rb +482 -0
  409. data/lib/mtncloud/cli/dot_file.rb +180 -0
  410. data/lib/mtncloud/cli/error_handler.rb +307 -0
  411. data/lib/mtncloud/cli/errors.rb +53 -0
  412. data/lib/mtncloud/cli/expression_parser.rb +153 -0
  413. data/lib/mtncloud/cli/mixins/accounts_helper.rb +484 -0
  414. data/lib/mtncloud/cli/mixins/affinity_helper.rb +118 -0
  415. data/lib/mtncloud/cli/mixins/backups_helper.rb +200 -0
  416. data/lib/mtncloud/cli/mixins/deployments_helper.rb +163 -0
  417. data/lib/mtncloud/cli/mixins/execution_request_helper.rb +50 -0
  418. data/lib/mtncloud/cli/mixins/infrastructure_helper.rb +966 -0
  419. data/lib/mtncloud/cli/mixins/jobs_helper.rb +202 -0
  420. data/lib/mtncloud/cli/mixins/library_helper.rb +539 -0
  421. data/lib/mtncloud/cli/mixins/load_balancers_helper.rb +176 -0
  422. data/lib/mtncloud/cli/mixins/logs_helper.rb +131 -0
  423. data/lib/mtncloud/cli/mixins/monitoring_helper.rb +876 -0
  424. data/lib/mtncloud/cli/mixins/networks_helper.rb +62 -0
  425. data/lib/mtncloud/cli/mixins/operations_helper.rb +41 -0
  426. data/lib/mtncloud/cli/mixins/option_source_helper.rb +254 -0
  427. data/lib/mtncloud/cli/mixins/print_helper.rb +1631 -0
  428. data/lib/mtncloud/cli/mixins/processes_helper.rb +286 -0
  429. data/lib/mtncloud/cli/mixins/prompt_helper.rb +136 -0
  430. data/lib/mtncloud/cli/mixins/provisioning_helper.rb +2963 -0
  431. data/lib/mtncloud/cli/mixins/remote_helper.rb +139 -0
  432. data/lib/mtncloud/cli/mixins/rest_command.rb +994 -0
  433. data/lib/mtncloud/cli/mixins/secondary_rest_command.rb +700 -0
  434. data/lib/mtncloud/cli/mixins/storage_servers_helper.rb +93 -0
  435. data/lib/mtncloud/cli/mixins/storage_volumes_helper.rb +76 -0
  436. data/lib/mtncloud/cli/mixins/vdi_helper.rb +246 -0
  437. data/lib/mtncloud/cli/mixins/whoami_helper.rb +73 -0
  438. data/lib/mtncloud/cli/option_parser.rb +127 -0
  439. data/lib/mtncloud/cli/option_types.rb +1622 -0
  440. data/lib/mtncloud/cli/version.rb +6 -0
  441. data/lib/mtncloud/cli.rb +105 -0
  442. data/lib/mtncloud/currency.rb +184 -0
  443. data/lib/mtncloud/ext/hash.rb +109 -0
  444. data/lib/mtncloud/ext/nil_class.rb +5 -0
  445. data/lib/mtncloud/ext/rest_client.rb +37 -0
  446. data/lib/mtncloud/ext/string.rb +66 -0
  447. data/lib/mtncloud/formatters.rb +511 -0
  448. data/lib/mtncloud/logging.rb +185 -0
  449. data/lib/mtncloud/morpkg.rb +119 -0
  450. data/lib/mtncloud/rest_client.rb +104 -0
  451. data/lib/mtncloud/routes.rb +304 -0
  452. data/lib/mtncloud/terminal.rb +528 -0
  453. data/lib/mtncloud/util.rb +29 -0
  454. data/lib/mtncloud.rb +5 -0
  455. data/mtncloud-cli.gemspec +38 -0
  456. data/test/api/affinity_groups_interface_test.rb +43 -0
  457. data/test/api/clients_interface_test.rb +23 -0
  458. data/test/api/clouds_interface_test.rb +67 -0
  459. data/test/api/containers_interface_test.rb +68 -0
  460. data/test/api/host_vm_groups_interface_test.rb +35 -0
  461. data/test/api/instances_interface_test.rb +22 -0
  462. data/test/api/network_routers_interface_test.rb +22 -0
  463. data/test/api/systems_interface_test.rb +26 -0
  464. data/test/api/whoami_interface_test.rb +14 -0
  465. data/test/branding_test.rb +160 -0
  466. data/test/cli/access_token_test.rb +36 -0
  467. data/test/cli/affinity_groups_cloud_cluster_scope_test.rb +270 -0
  468. data/test/cli/affinity_groups_cluster_scope_test.rb +171 -0
  469. data/test/cli/affinity_groups_test.rb +57 -0
  470. data/test/cli/affinity_groups_violations_scope_test.rb +141 -0
  471. data/test/cli/affinity_helper_test.rb +367 -0
  472. data/test/cli/auth_test.rb +88 -0
  473. data/test/cli/backups_test.rb +212 -0
  474. data/test/cli/cli_test.rb +48 -0
  475. data/test/cli/clients_test.rb +45 -0
  476. data/test/cli/clusters_uuid_test.rb +146 -0
  477. data/test/cli/containers_test.rb +92 -0
  478. data/test/cli/distributed_workers_test.rb +68 -0
  479. data/test/cli/help_test.rb +25 -0
  480. data/test/cli/host_vm_groups_cluster_scope_test.rb +187 -0
  481. data/test/cli/host_vm_groups_test.rb +63 -0
  482. data/test/cli/infrastructure_helper_cluster_resolver_test.rb +250 -0
  483. data/test/cli/instances_test.rb +37 -0
  484. data/test/cli/man_test.rb +14 -0
  485. data/test/cli/migrations_test.rb +39 -0
  486. data/test/cli/network_routers_test.rb +65 -0
  487. data/test/cli/remote_test.rb +89 -0
  488. data/test/cli/roles_test.rb +47 -0
  489. data/test/cli/shell_test.rb +81 -0
  490. data/test/cli/storage_volumes_test.rb +79 -0
  491. data/test/cli/systems_test.rb +206 -0
  492. data/test/cli/version_test.rb +23 -0
  493. data/test/cli/view_test.rb +55 -0
  494. data/test/cli/whoami_test.rb +17 -0
  495. data/test/mtncloud_test.rb +16 -0
  496. data/test/test_case.rb +342 -0
  497. data/test/test_config.rb +137 -0
  498. data/test/test_data_helper.rb +97 -0
  499. metadata +807 -0
@@ -0,0 +1,270 @@
1
+ require 'test/unit'
2
+ require 'stringio'
3
+ require 'json'
4
+ require 'mtncloud'
5
+
6
+ # Command-level offline exercise of the MORPH-17279 --cloud + --cluster
7
+ # (vSphere cluster) scope for AffinityGroupsCommand and HostVmGroupsCommand
8
+ # list/add. Runs the real command methods end-to-end (option parsing, scope
9
+ # resolution, --dry-run request construction) against fake interfaces, so no
10
+ # live appliance or credentials are required.
11
+ #
12
+ # This complements infrastructure_helper_cluster_resolver_test.rb (which
13
+ # unit-tests the resolver in isolation) by proving the resolved pool actually
14
+ # flows into list (poolId query param) and add (pool.id in the create
15
+ # payload), exactly as it would against a real appliance.
16
+ class AffinityGroupsCloudClusterScopeTest < Test::Unit::TestCase
17
+
18
+ # Fake for MtnCloud::CloudsInterface -- records every call, answers cloud
19
+ # name/id lookups, and answers .dry.* calls with a print_dry_run-compatible
20
+ # request hash (mirrors how MtnCloud::APIClient#dry / #execute behave).
21
+ class FakeCloudsInterface
22
+ attr_reader :calls
23
+
24
+ def initialize(cloud:)
25
+ @cloud = cloud
26
+ @calls = []
27
+ @dry = false
28
+ end
29
+
30
+ def setopts(options); self; end
31
+ def dry; @dry = true; self; end
32
+
33
+ def get(id, params = {})
34
+ @calls << [:get, id, params]
35
+ {'zone' => @cloud}
36
+ end
37
+
38
+ def list(params = {})
39
+ @calls << [:list, params]
40
+ {'zones' => [@cloud]}
41
+ end
42
+
43
+ def list_affinity_groups(id, params = {})
44
+ @calls << [:list_affinity_groups, id, params]
45
+ respond({'affinityGroups' => []}) { {method: :get, url: "/api/zones/#{id}/affinity-groups", params: params} }
46
+ end
47
+
48
+ def create_affinity_group(id, payload)
49
+ @calls << [:create_affinity_group, id, payload]
50
+ respond({'affinityGroup' => {'id' => 1}}) { {method: :post, url: "/api/zones/#{id}/affinity-groups", payload: payload.to_json} }
51
+ end
52
+
53
+ def affinity_group_form_options(id, params = {})
54
+ @calls << [:affinity_group_form_options, id, params]
55
+ {'supportsCombinedRules' => true, 'availableVmGroups' => [], 'availableHostGroups' => []}
56
+ end
57
+
58
+ def list_host_vm_groups(id, params = {})
59
+ @calls << [:list_host_vm_groups, id, params]
60
+ respond({'hostVmGroups' => []}) { {method: :get, url: "/api/zones/#{id}/host-vm-groups", params: params} }
61
+ end
62
+
63
+ def create_host_vm_group(id, payload)
64
+ @calls << [:create_host_vm_group, id, payload]
65
+ respond({'hostVmGroup' => {'id' => 1}}) { {method: :post, url: "/api/zones/#{id}/host-vm-groups", payload: payload.to_json} }
66
+ end
67
+
68
+ def host_vm_group_form_options(id, params = {})
69
+ @calls << [:host_vm_group_form_options, id, params]
70
+ {'availableServers' => []}
71
+ end
72
+
73
+ private
74
+
75
+ def respond(real_result)
76
+ @dry ? yield : real_result
77
+ end
78
+ end
79
+
80
+ # Fake for MtnCloud::CloudResourcePoolsInterface -- used by
81
+ # find_resource_pool_cluster_by_name_or_id.
82
+ class FakeResourcePoolsInterface
83
+ attr_reader :calls
84
+
85
+ def initialize(pool:)
86
+ @pool = pool
87
+ @calls = []
88
+ end
89
+
90
+ def get(cloud_id, id, params = {})
91
+ @calls << [:get, cloud_id, id, params]
92
+ {'resourcePool' => @pool}
93
+ end
94
+
95
+ def list(cloud_id, params = {})
96
+ @calls << [:list, cloud_id, params]
97
+ {'resourcePools' => [@pool]}
98
+ end
99
+
100
+ def list_without_cloud(params = {})
101
+ @calls << [:list_without_cloud, params]
102
+ {'resourcePools' => [@pool]}
103
+ end
104
+ end
105
+
106
+ class FakeClustersInterface
107
+ attr_reader :calls
108
+
109
+ def initialize(clusters: [])
110
+ @clusters = clusters
111
+ @calls = []
112
+ @dry = false
113
+ end
114
+
115
+ def setopts(options); self; end
116
+ def dry; @dry = true; self; end
117
+
118
+ def get(id, params = {})
119
+ @calls << [:get, id, params]
120
+ {'cluster' => @clusters.find {|cluster| cluster['id'].to_i == id.to_i}}
121
+ end
122
+
123
+ def list(params = {})
124
+ @calls << [:list, params]
125
+ {'clusters' => @clusters.select {|cluster| cluster['name'] == params[:name]}}
126
+ end
127
+
128
+ def list_affinity_groups(id, params = {})
129
+ @calls << [:list_affinity_groups, id, params]
130
+ respond({'affinityGroups' => []}) { {method: :get, url: "/api/clusters/#{id}/affinity-groups", params: params} }
131
+ end
132
+
133
+ def list_host_vm_groups(id, params = {})
134
+ @calls << [:list_host_vm_groups, id, params]
135
+ respond({'hostVmGroups' => []}) { {method: :get, url: "/api/clusters/#{id}/host-vm-groups", params: params} }
136
+ end
137
+
138
+ private
139
+
140
+ def respond(real_result)
141
+ @dry ? yield : real_result
142
+ end
143
+ end
144
+
145
+ def cloud
146
+ {'id' => 59, 'name' => 'vCenter Cloud'}
147
+ end
148
+
149
+ def pool
150
+ {'id' => 501, 'name' => 'QA', 'type' => 'Cluster', 'zone' => {'id' => 59, 'name' => 'vCenter Cloud'}}
151
+ end
152
+
153
+ def build_affinity_command(managed_clusters: [])
154
+ cmd = MtnCloud::Cli::AffinityGroupsCommand.new
155
+ fake_clouds = FakeCloudsInterface.new(cloud: cloud)
156
+ fake_pools = FakeResourcePoolsInterface.new(pool: pool)
157
+ fake_clusters = FakeClustersInterface.new(clusters: managed_clusters)
158
+ cmd.define_singleton_method(:connect) do |opts|
159
+ instance_variable_set(:@affinity_groups_interface, nil)
160
+ instance_variable_set(:@clouds_interface, fake_clouds)
161
+ instance_variable_set(:@clusters_interface, fake_clusters)
162
+ instance_variable_set(:@cloud_resource_pools_interface, fake_pools)
163
+ end
164
+ [cmd, fake_clouds, fake_pools, fake_clusters]
165
+ end
166
+
167
+ def build_host_vm_command(managed_clusters: [])
168
+ cmd = MtnCloud::Cli::HostVmGroupsCommand.new
169
+ fake_clouds = FakeCloudsInterface.new(cloud: cloud)
170
+ fake_pools = FakeResourcePoolsInterface.new(pool: pool)
171
+ fake_clusters = FakeClustersInterface.new(clusters: managed_clusters)
172
+ cmd.define_singleton_method(:connect) do |opts|
173
+ instance_variable_set(:@host_vm_groups_interface, nil)
174
+ instance_variable_set(:@clouds_interface, fake_clouds)
175
+ instance_variable_set(:@clusters_interface, fake_clusters)
176
+ instance_variable_set(:@cloud_resource_pools_interface, fake_pools)
177
+ end
178
+ [cmd, fake_clouds, fake_pools, fake_clusters]
179
+ end
180
+
181
+ def capture_stdout
182
+ terminal = MtnCloud::Terminal.instance
183
+ original = terminal.stdout
184
+ buffer = StringIO.new
185
+ terminal.set_stdout(buffer)
186
+ yield
187
+ buffer.string
188
+ ensure
189
+ terminal.set_stdout(original)
190
+ end
191
+
192
+ ## AffinityGroupsCommand
193
+
194
+ def test_affinity_groups_list_cloud_cluster_combo_sends_pool_id
195
+ cmd, _fake_clouds, fake_pools, _fake_clusters = build_affinity_command
196
+ output = capture_stdout { cmd.list(['--cloud', 'vCenter Cloud', '--cluster', 'QA', '--dry-run']) }
197
+ assert_match(/poolId=501/, output, "dry-run request must carry the resolved poolId, got: #{output}")
198
+ assert_match(%r{/api/zones/59/affinity-groups}, output)
199
+ # Name resolution stayed scoped to the cloud and to type=Cluster.
200
+ assert_equal [[:list, 59, {name: 'QA', type: 'Cluster'}]], fake_pools.calls
201
+ end
202
+
203
+ def test_affinity_groups_add_cloud_cluster_combo_sets_pool_id_payload
204
+ cmd, fake_clouds, _fake_pools, _fake_clusters = build_affinity_command
205
+ payload_json = '{"affinityGroup":{"name":"cli-test","affinityType":"KEEP_TOGETHER","servers":[{"id":1}]}}'
206
+ output = capture_stdout do
207
+ cmd.add(['--cloud', 'vCenter Cloud', '--cluster', 'QA', '--payload-json', payload_json, '--dry-run'])
208
+ end
209
+ assert_match(%r{/api/zones/59/affinity-groups}, output, "must POST to the zone endpoint, not a cluster endpoint")
210
+ create_call = fake_clouds.calls.find {|c| c[0] == :create_affinity_group }
211
+ assert_not_nil create_call, "create_affinity_group must be called on the clouds interface"
212
+ payload = create_call[2].is_a?(String) ? JSON.parse(create_call[2]) : create_call[2]
213
+ assert_equal({'id' => 501}, payload['affinityGroup']['pool'])
214
+ assert_nil payload['affinityGroup']['cloudId']
215
+ assert_nil payload['affinityGroup']['clusterId']
216
+ end
217
+
218
+ def test_affinity_groups_list_cluster_name_falls_back_to_unique_vsphere_cluster
219
+ cmd, _fake_clouds, fake_pools, fake_clusters = build_affinity_command
220
+ output = capture_stdout { cmd.list(['--cluster', 'QA', '--dry-run']) }
221
+ assert_match(%r{/api/zones/59/affinity-groups}, output)
222
+ assert_match(/poolId=501/, output)
223
+ assert_equal [[:list, {name: 'QA'}]], fake_clusters.calls
224
+ assert_equal [[:list_without_cloud, {name: 'QA', type: 'Cluster', max: 1000}]], fake_pools.calls
225
+ end
226
+
227
+ def test_affinity_groups_list_cluster_name_preserves_managed_cluster_precedence
228
+ managed_cluster = {'id' => 8, 'name' => 'QA'}
229
+ cmd, _fake_clouds, fake_pools, fake_clusters = build_affinity_command(managed_clusters: [managed_cluster])
230
+ output = capture_stdout { cmd.list(['--cluster', 'QA', '--dry-run']) }
231
+ assert_match(%r{/api/clusters/8/affinity-groups}, output)
232
+ assert_equal [[:list, {name: 'QA'}], [:list_affinity_groups, 8, {}]], fake_clusters.calls
233
+ assert_empty fake_pools.calls
234
+ end
235
+
236
+ ## HostVmGroupsCommand
237
+
238
+ def test_host_vm_groups_list_cloud_cluster_combo_sends_pool_id
239
+ cmd, _fake_clouds, fake_pools, _fake_clusters = build_host_vm_command
240
+ output = capture_stdout { cmd.list(['--cloud', 'vCenter Cloud', '--cluster', 'QA', '--dry-run']) }
241
+ assert_match(/poolId=501/, output, "dry-run request must carry the resolved poolId, got: #{output}")
242
+ assert_match(%r{/api/zones/59/host-vm-groups}, output)
243
+ assert_equal [[:list, 59, {name: 'QA', type: 'Cluster'}]], fake_pools.calls
244
+ end
245
+
246
+ def test_host_vm_groups_add_cloud_cluster_combo_sets_pool_id_payload
247
+ cmd, fake_clouds, _fake_pools, _fake_clusters = build_host_vm_command
248
+ payload_json = '{"hostVmGroup":{"name":"cli-test","type":"HOST_GROUP","servers":[{"id":1}]}}'
249
+ output = capture_stdout do
250
+ cmd.add(['--cloud', 'vCenter Cloud', '--cluster', 'QA', '--payload-json', payload_json, '--dry-run'])
251
+ end
252
+ assert_match(%r{/api/zones/59/host-vm-groups}, output, "must POST to the zone endpoint, not a cluster endpoint")
253
+ create_call = fake_clouds.calls.find {|c| c[0] == :create_host_vm_group }
254
+ assert_not_nil create_call, "create_host_vm_group must be called on the clouds interface"
255
+ payload = create_call[2].is_a?(String) ? JSON.parse(create_call[2]) : create_call[2]
256
+ assert_equal({'id' => 501}, payload['hostVmGroup']['pool'])
257
+ assert_nil payload['hostVmGroup']['cloudId']
258
+ assert_nil payload['hostVmGroup']['clusterId']
259
+ end
260
+
261
+ def test_host_vm_groups_list_cluster_name_falls_back_to_unique_vsphere_cluster
262
+ cmd, _fake_clouds, fake_pools, fake_clusters = build_host_vm_command
263
+ output = capture_stdout { cmd.list(['--cluster', 'QA', '--dry-run']) }
264
+ assert_match(%r{/api/zones/59/host-vm-groups}, output)
265
+ assert_match(/poolId=501/, output)
266
+ assert_equal [[:list, {name: 'QA'}]], fake_clusters.calls
267
+ assert_equal [[:list_without_cloud, {name: 'QA', type: 'Cluster', max: 1000}]], fake_pools.calls
268
+ end
269
+
270
+ end
@@ -0,0 +1,171 @@
1
+ require 'test/unit'
2
+ require 'stringio'
3
+ require 'mtncloud'
4
+
5
+ class AffinityGroupsClusterScopeTest < Test::Unit::TestCase
6
+ class FakeCloudsInterface
7
+ attr_reader :calls
8
+
9
+ def initialize(cloud)
10
+ @cloud = cloud
11
+ @calls = []
12
+ @dry = false
13
+ end
14
+
15
+ def setopts(_options)
16
+ self
17
+ end
18
+
19
+ def dry
20
+ @dry = true
21
+ self
22
+ end
23
+
24
+ def get(id, params = {})
25
+ @calls << [:get, id, params]
26
+ {'zone' => @cloud}
27
+ end
28
+
29
+ def list(params = {})
30
+ @calls << [:list, params]
31
+ {'zones' => [@cloud]}
32
+ end
33
+
34
+ def list_affinity_groups(id, params = {})
35
+ @calls << [:list_affinity_groups, id, params]
36
+ return {'affinityGroups' => []} unless @dry
37
+
38
+ {method: :get, url: "/api/zones/#{id}/affinity-groups", params: params}
39
+ end
40
+ end
41
+
42
+ class FakeResourcePoolsInterface
43
+ attr_reader :calls
44
+
45
+ def initialize(pool)
46
+ @pool = pool
47
+ @calls = []
48
+ end
49
+
50
+ def get(cloud_id, id, params = {})
51
+ @calls << [:get, cloud_id, id, params]
52
+ {'resourcePool' => @pool}
53
+ end
54
+
55
+ def list(cloud_id, params = {})
56
+ @calls << [:list, cloud_id, params]
57
+ {'resourcePools' => [@pool]}
58
+ end
59
+
60
+ def list_without_cloud(params = {})
61
+ @calls << [:list_without_cloud, params]
62
+ {'resourcePools' => [@pool]}
63
+ end
64
+ end
65
+
66
+ class FakeClustersInterface
67
+ attr_reader :calls
68
+
69
+ def initialize(clusters = [])
70
+ @clusters = clusters
71
+ @calls = []
72
+ @dry = false
73
+ end
74
+
75
+ def setopts(_options)
76
+ self
77
+ end
78
+
79
+ def dry
80
+ @dry = true
81
+ self
82
+ end
83
+
84
+ def list(params = {})
85
+ @calls << [:list, params]
86
+ {'clusters' => @clusters.select {|cluster| cluster['name'] == params[:name]}}
87
+ end
88
+
89
+ def list_affinity_groups(id, params = {})
90
+ @calls << [:list_affinity_groups, id, params]
91
+ return {'affinityGroups' => []} unless @dry
92
+
93
+ {method: :get, url: "/api/clusters/#{id}/affinity-groups", params: params}
94
+ end
95
+ end
96
+
97
+ def setup
98
+ @cloud = {'id' => 59, 'name' => 'vCenter Cloud'}
99
+ @pool = {
100
+ 'id' => 501,
101
+ 'name' => 'QA',
102
+ 'type' => 'Cluster',
103
+ 'zone' => @cloud
104
+ }
105
+ end
106
+
107
+ def test_cloud_qualified_cluster_sends_pool_id
108
+ command, pools, = build_command
109
+
110
+ output = capture_stdout do
111
+ command.list(['--cloud', 'vCenter Cloud', '--cluster', 'QA', '--dry-run'])
112
+ end
113
+
114
+ assert_match(%r{/api/zones/59/affinity-groups}, output)
115
+ assert_match(/poolId=501/, output)
116
+ assert_equal [[:list, 59, {name: 'QA', type: 'Cluster'}]], pools.calls
117
+ end
118
+
119
+ def test_cluster_name_falls_back_to_unique_vsphere_cluster
120
+ command, pools, clusters = build_command
121
+
122
+ output = capture_stdout { command.list(['--cluster', 'QA', '--dry-run']) }
123
+
124
+ assert_match(%r{/api/zones/59/affinity-groups}, output)
125
+ assert_match(/poolId=501/, output)
126
+ assert_equal [[:list, {name: 'QA'}]], clusters.calls
127
+ assert_equal [
128
+ [:list_without_cloud, {name: 'QA', type: 'Cluster', max: 1000}]
129
+ ], pools.calls
130
+ end
131
+
132
+ def test_managed_cluster_takes_precedence
133
+ managed_cluster = {'id' => 8, 'name' => 'QA'}
134
+ command, pools, clusters = build_command([managed_cluster])
135
+
136
+ output = capture_stdout { command.list(['--cluster', 'QA', '--dry-run']) }
137
+
138
+ assert_match(%r{/api/clusters/8/affinity-groups}, output)
139
+ assert_equal [
140
+ [:list, {name: 'QA'}],
141
+ [:list_affinity_groups, 8, {}]
142
+ ], clusters.calls
143
+ assert_empty pools.calls
144
+ end
145
+
146
+ private
147
+
148
+ def build_command(managed_clusters = [])
149
+ clouds = FakeCloudsInterface.new(@cloud)
150
+ pools = FakeResourcePoolsInterface.new(@pool)
151
+ clusters = FakeClustersInterface.new(managed_clusters)
152
+ command = MtnCloud::Cli::AffinityGroupsCommand.new
153
+ command.define_singleton_method(:connect) do |_options|
154
+ @clouds_interface = clouds
155
+ @clusters_interface = clusters
156
+ @cloud_resource_pools_interface = pools
157
+ end
158
+ [command, pools, clusters]
159
+ end
160
+
161
+ def capture_stdout
162
+ terminal = MtnCloud::Terminal.instance
163
+ original = terminal.stdout
164
+ buffer = StringIO.new
165
+ terminal.set_stdout(buffer)
166
+ yield
167
+ buffer.string
168
+ ensure
169
+ terminal.set_stdout(original)
170
+ end
171
+ end
@@ -0,0 +1,57 @@
1
+ require 'mtncloud_test'
2
+
3
+ # Tests for MtnCloud::Cli::AffinityGroupsCommand
4
+ #
5
+ # Scope note: these cover only client-side behaviour -- help output and argument
6
+ # validation -- both of which resolve before any API call is made.
7
+ #
8
+ # Tests that would exercise list/get/add/update/remove against the appliance are
9
+ # deliberately omitted until the /api/affinity-groups request and response
10
+ # contract is confirmed against the MORPH-14136 / MORPH-16074 server work.
11
+ # See test/cli/affinity_helper_test.rb for the offline coverage of the shared
12
+ # affinity enums and formatters.
13
+ class MtnCloudTest::AffinityGroupsTest < MtnCloudTest::TestCase
14
+
15
+ def test_affinity_groups_help
16
+ assert_execute %(affinity-groups --help)
17
+ assert_execute %(affinity-groups list --help)
18
+ assert_execute %(affinity-groups get --help)
19
+ assert_execute %(affinity-groups add --help)
20
+ assert_execute %(affinity-groups update --help)
21
+ assert_execute %(affinity-groups remove --help)
22
+ end
23
+
24
+ ## Argument validation (fails during option parsing, before any request)
25
+
26
+ def test_affinity_groups_unknown_subcommand
27
+ assert_error %(affinity-groups nonsense-subcommand)
28
+ end
29
+
30
+ def test_affinity_groups_get_requires_an_id
31
+ assert_error %(affinity-groups get)
32
+ end
33
+
34
+ def test_affinity_groups_update_requires_an_id
35
+ assert_error %(affinity-groups update)
36
+ end
37
+
38
+ def test_affinity_groups_remove_requires_an_id
39
+ assert_error %(affinity-groups remove -y)
40
+ end
41
+
42
+ def test_affinity_groups_list_rejects_unknown_option
43
+ assert_error %(affinity-groups list --not-a-real-option)
44
+ end
45
+
46
+ # There is no unscoped list/create route -- morpheus-ui ApiV1UrlMappings
47
+ # exposes only /api/affinity-groups/{id} at the top level, so list and add
48
+ # must refuse to run without --cloud or --cluster rather than 404.
49
+ def test_affinity_groups_list_requires_a_scope
50
+ assert_error %(affinity-groups list)
51
+ end
52
+
53
+ def test_affinity_groups_add_requires_a_scope
54
+ assert_error %(affinity-groups add --name cli-test --dry-run)
55
+ end
56
+
57
+ end
@@ -0,0 +1,141 @@
1
+ require 'test/unit'
2
+ require 'stringio'
3
+ require 'mtncloud'
4
+
5
+ # Offline exercise of the MORPH-17279 --cluster scope for
6
+ # AffinityGroupsCommand#violations. Unlike list/add, the violations endpoint
7
+ # (AffinityGroupsController#violations) only accepts clusterId or cloudId -- it
8
+ # has no poolId path and no vSphere-pool-scoped violation data. So a managed
9
+ # cluster name resolves to clusterId, while a cloud-owned vSphere cluster name
10
+ # must produce a clear error instead of silently exiting 1 or broadening scope.
11
+ class AffinityGroupsViolationsScopeTest < Test::Unit::TestCase
12
+ class FakeAffinityGroupsInterface
13
+ attr_reader :calls
14
+
15
+ def initialize
16
+ @calls = []
17
+ @dry = false
18
+ end
19
+
20
+ def setopts(_options)
21
+ self
22
+ end
23
+
24
+ def dry
25
+ @dry = true
26
+ self
27
+ end
28
+
29
+ def violations(params = {})
30
+ @calls << [:violations, params]
31
+ return {'violations' => []} unless @dry
32
+
33
+ {method: :get, url: "/api/affinity-groups/violations", params: params}
34
+ end
35
+ end
36
+
37
+ class FakeCloudsInterface
38
+ def initialize(cloud)
39
+ @cloud = cloud
40
+ end
41
+
42
+ def setopts(_options); self; end
43
+ def dry; self; end
44
+ def get(id, params = {}); {'zone' => @cloud}; end
45
+ def list(params = {}); {'zones' => [@cloud]}; end
46
+ end
47
+
48
+ class FakeResourcePoolsInterface
49
+ def initialize(pools)
50
+ @pools = pools
51
+ end
52
+
53
+ def get(cloud_id, id, params = {})
54
+ {'resourcePool' => @pools.find {|p| p['id'].to_i == id.to_i }}
55
+ end
56
+
57
+ def list(cloud_id, params = {})
58
+ {'resourcePools' => @pools}
59
+ end
60
+
61
+ def list_without_cloud(params = {})
62
+ {'resourcePools' => @pools}
63
+ end
64
+ end
65
+
66
+ class FakeClustersInterface
67
+ def initialize(clusters = [])
68
+ @clusters = clusters
69
+ end
70
+
71
+ def list(params = {})
72
+ {'clusters' => @clusters.select {|cluster| cluster['name'] == params[:name]}}
73
+ end
74
+ end
75
+
76
+ def setup
77
+ @cloud = {'id' => 59, 'name' => 'vCenter Cloud'}
78
+ @pool = {'id' => 501, 'name' => 'QA', 'type' => 'Cluster', 'zone' => @cloud}
79
+ end
80
+
81
+ def test_managed_cluster_name_scopes_violations_by_cluster_id
82
+ command, affinity = build_command([{'id' => 8, 'name' => 'QA'}])
83
+
84
+ output = capture_stdout { command.violations(['--cluster', 'QA', '--dry-run']) }
85
+
86
+ assert_match(%r{/api/affinity-groups/violations}, output)
87
+ assert_match(/clusterId=8/, output)
88
+ assert_equal [[:violations, {'clusterId' => 8}]], affinity.calls
89
+ end
90
+
91
+ def test_vsphere_cluster_name_reports_clear_error_without_calling_violations
92
+ command, affinity = build_command([])
93
+
94
+ result = nil
95
+ err = capture_stderr do
96
+ capture_stdout { result = command.violations(['--cluster', 'QA', '--dry-run']) }
97
+ end
98
+
99
+ assert_equal 1, (result.is_a?(Array) ? result[0] : result)
100
+ assert_match(/only available for MTN Cloud managed clusters/i, err)
101
+ assert_match(/vCenter Cloud/, err)
102
+ assert_empty affinity.calls
103
+ end
104
+
105
+ private
106
+
107
+ def build_command(managed_clusters = [])
108
+ affinity = FakeAffinityGroupsInterface.new
109
+ clouds = FakeCloudsInterface.new(@cloud)
110
+ pools = FakeResourcePoolsInterface.new([@pool])
111
+ clusters = FakeClustersInterface.new(managed_clusters)
112
+ command = MtnCloud::Cli::AffinityGroupsCommand.new
113
+ command.define_singleton_method(:connect) do |_options|
114
+ @affinity_groups_interface = affinity
115
+ @clouds_interface = clouds
116
+ @clusters_interface = clusters
117
+ @cloud_resource_pools_interface = pools
118
+ end
119
+ [command, affinity]
120
+ end
121
+
122
+ def capture_stdout
123
+ terminal = MtnCloud::Terminal.instance
124
+ original = terminal.stdout
125
+ buffer = StringIO.new
126
+ terminal.set_stdout(buffer)
127
+ yield
128
+ buffer.string
129
+ ensure
130
+ terminal.set_stdout(original)
131
+ end
132
+
133
+ def capture_stderr
134
+ original = $stderr
135
+ $stderr = StringIO.new
136
+ yield
137
+ $stderr.string
138
+ ensure
139
+ $stderr = original
140
+ end
141
+ end