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,1818 @@
1
+ require 'mtncloud/cli/cli_command'
2
+ require 'net/https' # needed?
3
+
4
+
5
+ class MtnCloud::Cli::Remote
6
+ include MtnCloud::Cli::CliCommand
7
+ include MtnCloud::Cli::RemoteHelper
8
+
9
+ register_subcommands :list, :add, :get, :update, :rename, :remove, :use, :unuse, :clone, :current, :view
10
+ # remote setup and remote check
11
+ # are now avaiable under ping and setup
12
+ # they do the same thing
13
+ register_subcommands :setup
14
+ register_subcommands :check
15
+ register_subcommands :'check-all' => :check_all
16
+ register_subcommands :version => :version
17
+
18
+ set_default_subcommand :list
19
+
20
+ set_subcommands_hidden :setup # moved to 'setup'
21
+ set_subcommands_hidden :view # moved to 'view'
22
+
23
+ def initialize()
24
+ @appliance_name, @appliance_url = MtnCloud::Cli::Remote.active_appliance
25
+ end
26
+
27
+ def connect(opts={})
28
+ # no authorization needed, do not verify a token or prompt for login
29
+ @api_client = establish_remote_appliance_connection({:skip_verify_access_token => true, :skip_login => true}.merge(opts))
30
+ @setup_interface = @api_client.setup
31
+ end
32
+
33
+ def handle(args)
34
+ handle_subcommand(args)
35
+ end
36
+
37
+ def list(args)
38
+ options = {}
39
+ params = {}
40
+ show_all_activity = false
41
+ current_only = false
42
+ do_check = false
43
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
44
+ opts.banner = subcommand_usage("[search]")
45
+ opts.on("-a",'--all', "Show all the appliance activity details") do
46
+ show_all_activity = true
47
+ options[:wrap] = true
48
+ end
49
+ opts.on("--current", "--current", "List only the active (current) appliance.") do
50
+ current_only = true
51
+ end
52
+ opts.on("--check", "--check", "Check each appliance in the list to refresh their status, this may take a while.") do
53
+ do_check = true
54
+ end
55
+ build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields])
56
+ opts.footer = <<-EOT
57
+ List the configured remote appliances.
58
+ EOT
59
+ end
60
+ optparse.parse!(args)
61
+ # verify_args!(args:args, optparse:optparse, count:0)
62
+ if args.count > 0
63
+ options[:phrase] = args.join(" ")
64
+ end
65
+ #connect(options)
66
+ params.merge!(parse_list_options(options))
67
+ appliances = ::MtnCloud::Cli::Remote.load_all_remotes(params)
68
+ # if appliances.empty?
69
+ # raise_command_error "You have no appliances configured. See the command `remote add`."
70
+ # end
71
+ if current_only
72
+ appliances = appliances.select {|a| a[:active] }
73
+ end
74
+ if do_check
75
+ # return here because it prints a list() too..
76
+ return _check_all_appliances(options)
77
+ end
78
+ # mock json
79
+ json_response = {"appliances" => appliances}
80
+ # render
81
+ exit_code, err = 0, nil
82
+ render_response(json_response, options, "appliances") do
83
+
84
+ if appliances.empty?
85
+ if params[:phrase]
86
+ print reset,"0 remotes matched '#{params[:phrase]}'", reset, "\n"
87
+ print reset,"Try `remote add #{params[:phrase]}`", reset, "\n"
88
+ return 0, nil # maybe exit non-zero when no records are found, could be nicer
89
+ else
90
+ warning_msg = "No remote appliances configured. See the command `remote add`."
91
+ print yellow, warning_msg, reset, "\n"
92
+ return 2, warning_msg
93
+ end
94
+ else
95
+ title = "Remotes"
96
+ subtitles = parse_list_subtitles(options)
97
+ subtitles << "Current" if current_only
98
+ print_h1 title, subtitles, options
99
+
100
+ columns = {
101
+ "Name" => :name,
102
+ "URL" => lambda {|it| it[:url] || it[:host] },
103
+ "Status" => lambda {|it| format_appliance_status(it, cyan) },
104
+ "Version" => lambda {|it| it[:build_version] ? "#{it[:build_version]}" : '' },
105
+ #"Appliance URL" => lambda {|it| it[:appliance_url] ? "#{it[:appliance_url]}" : '' },
106
+ "Secure" => lambda {|it| format_boolean(it[:insecure] != true && (it[:url] || it[:host]).to_s.include?("https")) },
107
+ "Active" => lambda {|it| it[:active] ? "Yes " + format_is_current() : "No" },
108
+ #"Authenticated" => lambda {|it| format_boolean it[:authenticated] },
109
+ "Username" => :username,
110
+ # "Activity" => lambda {|it| get_appliance_session_blurbs(it).join("\n" + (' '*15)) },
111
+ "Last Login" => lambda {|it| format_duration_ago(it[:last_login_at]) },
112
+ #"Last Logout" => lambda {|it| format_duration_ago(it[:last_logout_at]) },
113
+ "Last Success" => lambda {|it| format_duration_ago(it[:last_success_at]) },
114
+ "Last Check" => lambda {|it|
115
+ check_str = ""
116
+ if it[:last_check]
117
+ check_timestamp = it[:last_check][:timestamp]
118
+ check_status = it[:last_check][:http_status]
119
+ if check_status
120
+ if check_status == 200
121
+ # no need to show this
122
+ else
123
+ check_status = check_status
124
+ end
125
+ end
126
+ if check_timestamp
127
+ check_duration_str = format_duration_ago(check_timestamp)
128
+ # check_str = check_status ? "#{check_duration_str} (HTTP #{check_status})" : check_duration_str
129
+ check_str = check_duration_str
130
+ end
131
+ else
132
+ # check_str = "n/a"
133
+ end
134
+ check_str
135
+ },
136
+ "Response Time" => lambda {|it| format_duration_milliseconds(it[:last_check][:took]) rescue "" },
137
+ "Error" => {display_method: lambda {|it|
138
+ error_str = it[:last_check] ? it[:last_check][:error].to_s : ""
139
+ error_str
140
+ }, max_width: 30},
141
+ }
142
+ # when an active remote is in the list, add => prefix and padding to keep things aligned.
143
+ # this is sucky, use arrays
144
+ has_active_remote = appliances.find {|appliance| appliance[:active] }
145
+ if has_active_remote
146
+ columns.delete("Name")
147
+ columns = {" Name" => lambda {|it| it[:active] ? (bold + "=> #{it[:name]}" + reset + cyan) : " #{it[:name]}" } }.merge(columns)
148
+ end
149
+ has_an_error = appliances.find {|appliance| appliance[:last_check][:error] rescue nil }
150
+ if !has_an_error
151
+ columns.delete("Error")
152
+ end
153
+ if show_all_activity != true
154
+ columns.delete("Secure")
155
+ columns.delete("Appliance URL")
156
+ columns.delete("Active")
157
+ columns.delete("Authenticated")
158
+ columns.delete("Last Login")
159
+ columns.delete("Last Logout")
160
+ columns.delete("Last Success")
161
+ #columns.delete("Error") # unless appliances.find {|appliance| appliance[:last_check][:error] rescue nil }
162
+ else
163
+ # always remove these columns because they are worthless
164
+ columns.delete("Authenticated")
165
+ columns.delete("Active")
166
+ columns.delete("Last Success")
167
+ end
168
+ # oops, table labels are upcase, but description list is not??, make them upcase here
169
+ new_columns = {}
170
+ columns.each {|k,v| new_columns[k.to_s.upcase] = v }
171
+ columns = new_columns
172
+ print as_pretty_table(appliances, columns, options)
173
+ print reset
174
+ print_results_pagination({size:appliances.size,total:appliances.size})
175
+ end
176
+ print reset, "\n"
177
+ end
178
+ return exit_code, err
179
+ end
180
+
181
+ def add(args)
182
+ options, params, payload = {}, {}, {}
183
+ new_appliance_map = {}
184
+ use_it = nil
185
+ secure = nil
186
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
187
+ opts.banner = subcommand_usage('[name] [url]')
188
+ opts.on(nil, '--use [true|false]', "Start using remote right now. By default this is true if it's the first remote, otherwise false." ) do |val|
189
+ use_it = (val == 'no' || val == 'off' || val.to_s == 'false')
190
+ new_appliance_map[:active] = true
191
+ end
192
+ opts.on(nil, "--secure", "Prevent insecure HTTPS communication. Default is true.") do
193
+ secure = true
194
+ end
195
+ opts.on(nil, "--insecure", "Allow insecure HTTPS communication. i.e. Ignore SSL errors. Default is false.") do
196
+ secure = false
197
+ end
198
+ # ok, need to be able to pass every option supported by login() and setup()
199
+ build_common_options(opts, options, [:options, :quiet])
200
+ opts.footer = <<-EOT
201
+ Add a new remote to your #{prog_name} client configuration.
202
+ [name] is required. A unique name for your appliance. eg. demo
203
+ [url] is required. The URL of your appliance eg. https://console.cloud.mtn.ng
204
+ First, this inspects the remote url to check the appliance status and version.
205
+ If remote is ready, it will prompt to login, see the command `login`.
206
+ If remote is freshly installed, it will prompt to initialize the appliance, see the command `setup`.
207
+ The option --use can be included to start using the new remote right away.
208
+ The remote will be used by default if it is the first remote in the configuration.
209
+ The --quiet option can be used to to skip prompting.
210
+
211
+ EOT
212
+ end
213
+ optparse.parse!(args)
214
+ verify_args!(args:args, max:2, optparse:optparse)
215
+
216
+ # payload = options[:payload] ? options[:payload] : {}
217
+ # payload.deep_merge!(parse_passed_options(options))
218
+ # # skip prompting when --payload is used
219
+ # if options[:payload].nil?
220
+ # end
221
+
222
+ # load current appliances
223
+ appliances = ::MtnCloud::Cli::Remote.appliances
224
+
225
+ new_appliance_name = args[0] ? args[0] : nil
226
+ url = args[1] ? args[1] : nil
227
+
228
+ # Name
229
+ still_prompting = true
230
+ while still_prompting do
231
+ if args[0]
232
+ new_appliance_name = args[0]
233
+ still_prompting = false
234
+ else
235
+ if new_appliance_name.to_s.empty?
236
+ v_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'A unique name for the remote MTN Cloud appliance. Example: local'}], options[:options])
237
+ new_appliance_name = v_prompt['name']
238
+ end
239
+ end
240
+ # for the sake of sanity
241
+ if [:current, :all, :'remote-url'].include?(new_appliance_name.to_sym)
242
+ raise_command_error "The specified remote appliance name '#{new_appliance_name}' is invalid."
243
+ new_appliance_name = nil
244
+ end
245
+ # unique name
246
+ existing_appliance = appliances[new_appliance_name.to_sym]
247
+ if existing_appliance
248
+ print_error red,"The specified remote appliance name '#{new_appliance_name}' already exists: #{display_appliance(existing_appliance[:name], (existing_appliance[:url]))}",reset,"\n"
249
+ new_appliance_name = nil
250
+ end
251
+ if new_appliance_name
252
+ still_prompting = false
253
+ end
254
+ if new_appliance_name.nil? && still_prompting == false
255
+ return 1
256
+ end
257
+ end
258
+
259
+ new_appliance_map[:name] = new_appliance_name.to_sym
260
+
261
+ # URL
262
+ still_prompting = true
263
+ while still_prompting do
264
+ if args[1]
265
+ url = args[1]
266
+ still_prompting = false
267
+ else
268
+ if !url
269
+ default_url = nil
270
+ # use Name: dev to get a happy default.
271
+ # if new_appliance_name == "dev"
272
+ if new_appliance_name == "local" || new_appliance_name == "localhost" || new_appliance_name == "dev"
273
+ default_url = "http://localhost:8080"
274
+ end
275
+ v_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'url', 'fieldLabel' => 'URL', 'type' => 'text', 'required' => true, 'description' => 'The URL of the remote MTN Cloud appliance. Example: https://console.cloud.mtn.ng', 'defaultValue' => default_url}], options[:options])
276
+ url = v_prompt['url']
277
+ end
278
+ end
279
+
280
+ # strip whitespace from URL
281
+ url = url.to_s.strip
282
+
283
+ if url.to_s !~ /^https?\:\/\/.+/
284
+ print_error red,"The specified remote appliance url '#{url}' is invalid.",reset,"\n"
285
+ #still_prompting = true
286
+ url = nil
287
+ else
288
+ still_prompting = false
289
+ end
290
+ if url.nil? && still_prompting == false
291
+ return 1
292
+ end
293
+ end
294
+
295
+ new_appliance_map[:url] = url
296
+
297
+ # --insecure or --secure
298
+ # Secure? (Ignore SSL errors)
299
+ # secure is the default,
300
+ # try to only store insecure:false in the appliances config
301
+ if url.to_s =~ /^https\:/ && secure.nil?
302
+ v_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'insecure', 'fieldLabel' => 'Insecure (Ignore SSL Errors)', 'type' => 'checkbox', 'required' => false, 'defaultValue' => false, 'description' => 'Allow insecure HTTPS communication, ignore SSL errors.'}], options[:options])
303
+ if v_prompt['insecure'].to_s == 'true' || v_prompt['insecure'].to_s == 'on'
304
+ new_appliance_map[:insecure] = true
305
+ end
306
+ elsif secure != nil
307
+ new_appliance_map[:insecure] = !secure
308
+ end
309
+
310
+ # --use
311
+ if use_it != nil
312
+ if use_it
313
+ new_appliance_map[:active] = true
314
+ end
315
+ else
316
+ # if ::MtnCloud::Cli::OptionTypes::confirm("Would you like to switch to using this remote now?", options.merge({default: appliances.empty?}))
317
+ # new_appliance_map[:active] = true
318
+ # end
319
+ v_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'use', 'fieldLabel' => 'Use?', 'type' => 'checkbox', 'defaultValue' => appliances.empty?, 'description' => 'Start using this remote right away'}], options[:options])
320
+ if v_prompt['use'].to_s == 'true' || v_prompt['use'].to_s == 'on'
321
+ new_appliance_map[:active] = true
322
+ end
323
+ end
324
+
325
+ # save it
326
+ appliance = ::MtnCloud::Cli::Remote.save_remote(new_appliance_name.to_sym, new_appliance_map)
327
+
328
+ # refresh it (does /api/setup/check to refresh status and build
329
+ # todo: this should happen in save eh?
330
+ #MtnCloud::Logging::DarkPrinter.puts "inspecting remote #{appliance[:name]} #{appliance[:url]}" if MtnCloud::Logging.debug? && !options[:quiet]
331
+ appliance, json_response = ::MtnCloud::Cli::Remote.refresh_remote(new_appliance_name.to_sym)
332
+
333
+ # hit /setup/check api and update version and status
334
+ if !options[:quiet]
335
+ # print_green_success "Added remote #{new_appliance_name}, status is #{format_appliance_status(appliance)}"
336
+ print cyan,"Added remote #{new_appliance_name}, status is #{format_appliance_status(appliance)}",reset,"\n"
337
+ end
338
+
339
+ #appliance, json_response = ::MtnCloud::Cli::Remote.refresh_remote(new_appliance_name.to_sym)
340
+ # if !options[:quiet]
341
+ # print cyan
342
+ # puts "Status: #{format_appliance_status(appliance)}"
343
+ # print reset
344
+ # end
345
+ # puts "refreshed appliance #{appliance.inspect}"
346
+ # determine command exit_code and err
347
+ exit_code, err = 0, nil
348
+ if (appliance[:status] != 'ready' && appliance[:status] != 'fresh')
349
+ exit_code = 1
350
+ err = "remote status is #{appliance[:status]}"
351
+ end
352
+
353
+ # just skip prompting no prompt -q is used.
354
+ if options[:quiet]
355
+ return exit_code, err
356
+ end
357
+ # just skip prompting no prompt -N is used.
358
+ if options[:no_prompt]
359
+ return exit_code, err
360
+ end
361
+
362
+ # setup fresh appliance?
363
+ if appliance[:status] == 'fresh'
364
+ print cyan
365
+ puts "It looks like this appliance needs to be setup. Starting setup ..."
366
+ #return setup([new_appliance_name] + [MtnCloud::Logging.debug? ? ["--debug"] : []])
367
+ return MtnCloud::Cli::Setup.new.handle(["-r", new_appliance_name] + (MtnCloud::Logging.debug? ? ["--debug"] : []))
368
+ end
369
+
370
+ # only login if you are using this remote
371
+ # maybe remote use should do the login prompting eh?
372
+ # if appliance[:active] && appliance[:status] == 'ready'
373
+ if appliance[:status] == 'ready'
374
+ print reset
375
+ if ::MtnCloud::Cli::OptionTypes::confirm("Would you like to login now?", options.merge({default: true}))
376
+ login_result = ::MtnCloud::Cli::Login.new.handle(["-r", appliance[:name].to_s])
377
+ keep_trying = true
378
+ if login_result == 0
379
+ keep_trying = false
380
+ end
381
+ while keep_trying do
382
+ if ::MtnCloud::Cli::OptionTypes::confirm("Login attempt failed. Would you like to try again?", options.merge({default: true}))
383
+ login_result = ::MtnCloud::Cli::Login.new.handle(["-r", appliance[:name].to_s])
384
+ if login_result == 0
385
+ keep_trying = false
386
+ end
387
+ else
388
+ keep_trying = false
389
+ end
390
+ end
391
+
392
+ end
393
+ # refresh to get buildVersion now that we are logged in
394
+ appliance, json_response = ::MtnCloud::Cli::Remote.refresh_remote(new_appliance_name.to_sym)
395
+ else
396
+ #puts "Status is #{format_appliance_status(appliance)}"
397
+ end
398
+
399
+ # print new appliance details
400
+ print_h1 "Remote", [], options
401
+ print cyan
402
+ print format_remote_details(appliance, options)
403
+ print reset, "\n"
404
+ #_get(appliance[:name], {})
405
+
406
+ return exit_code, err
407
+ end
408
+
409
+ def refresh(args)
410
+ check_appliance(args)
411
+ end
412
+
413
+ def check(args)
414
+ options = {}
415
+ checkall = false
416
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
417
+ opts.banner = subcommand_usage("[name]")
418
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :quiet])
419
+ opts.on('-a', '--all', "Check all remotes.") do
420
+ checkall = true
421
+ end
422
+ opts.footer = <<-EOT
423
+ Check the status of a remote appliance.
424
+ [name] is optional. This is the name of a remote. Default is the current remote. Can be passed as 'all'. to perform remote check-all.
425
+ This makes a request to the remote url and updates the status and version.
426
+ EOT
427
+ end
428
+ optparse.parse!(args)
429
+ if checkall == true
430
+ return _check_all_appliances(options)
431
+ end
432
+ if args.count == 0
433
+ id_list = ['current']
434
+ else
435
+ id_list = parse_id_list(args)
436
+ end
437
+ # trick for remote check all
438
+ if id_list.length == 1 && id_list[0].to_s.downcase == 'all'
439
+ return _check_all_appliances(options)
440
+ end
441
+ #connect(options)
442
+ return run_command_for_each_arg(id_list) do |arg|
443
+ _check_appliance(arg, options)
444
+ end
445
+ end
446
+
447
+ def version(args)
448
+ options = {}
449
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
450
+ opts.banner = subcommand_usage("[remote]")
451
+ opts.on('--offline', '--offline', "Do this offline without an api request to refresh the remote appliance status.") do
452
+ options[:do_offline] = true
453
+ end
454
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :quiet])
455
+ opts.footer = <<-EOT
456
+ Print version of remote appliance.
457
+ [name] is optional. This is the name of a remote. Default is the current remote.
458
+ This makes a request to the configured appliance url and updates the status and version.
459
+ EOT
460
+ end
461
+ optparse.parse!(args)
462
+ verify_args!(args:args, max:1, optparse:optparse)
463
+ #connect(options)
464
+ # print version, default is current remote
465
+ appliance_name = nil
466
+ if args.count == 0
467
+ appliance_name = 'current'
468
+ elsif args.count == 1
469
+ appliance_name = args[0]
470
+ else
471
+ raise_command_error "No current appliance, see the command `remote use`"
472
+ end
473
+ exit_code, err = 0, nil
474
+
475
+ appliance = load_remote_by_name(appliance_name)
476
+ appliance_name = appliance[:name]
477
+ appliance_url = appliance[:url]
478
+
479
+ # found appliance, now refresh it
480
+ # print "Checking remote url: #{appliance[:url]} ..."
481
+ json_response = nil
482
+ if options[:do_offline] == true
483
+ json_response = {'appliance' => appliance}
484
+ else
485
+ appliance, json_response = ::MtnCloud::Cli::Remote.refresh_remote(appliance_name)
486
+ end
487
+
488
+ # render
489
+ render_response(json_response, options) do
490
+ end
491
+ # if options[:json] || options[:yml] || options[:csv] || options[:quiet]
492
+ render_result = render_with_format(json_response, options)
493
+ return exit_code if render_result
494
+
495
+ build_version = appliance[:build_version]
496
+ if build_version
497
+ print cyan,build_version.to_s,reset,"\n"
498
+ return 0
499
+ else
500
+ print yellow,"version unknown".to_s,reset,"\n"
501
+ return 1
502
+ end
503
+
504
+ end
505
+
506
+ def check(args)
507
+ options = {}
508
+ checkall = false
509
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
510
+ opts.banner = subcommand_usage("[name]")
511
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :quiet])
512
+ opts.on('-a', '--all', "Check all remotes.") do
513
+ checkall = true
514
+ end
515
+ opts.on('--offline', '--offline', "Do this offline without an api request to refresh the remote appliance status.") do
516
+ options[:do_offline] = true
517
+ end
518
+ opts.footer = <<-EOT
519
+ Check the status of a remote appliance.
520
+ [name] is optional. This is the name of a remote. Default is the current remote. Can be passed as 'all'. to perform remote check-all.
521
+ This makes a request to the configured appliance url and updates the status and version.
522
+ EOT
523
+ end
524
+ optparse.parse!(args)
525
+ if checkall == true
526
+ return _check_all_appliances(options)
527
+ end
528
+ if args.count == 0
529
+ id_list = ['current']
530
+ else
531
+ id_list = parse_id_list(args)
532
+ end
533
+ # trick for remote check all
534
+ if id_list.length == 1 && id_list[0].to_s.downcase == 'all'
535
+ return _check_all_appliances(options)
536
+ end
537
+ #connect(options)
538
+ return run_command_for_each_arg(id_list) do |arg|
539
+ _check_appliance(arg, options)
540
+ end
541
+ end
542
+
543
+ def _check_appliance(appliance_name, options)
544
+ exit_code, err = 0, nil
545
+ begin
546
+ appliance = load_remote_by_name(appliance_name)
547
+ appliance_name = appliance[:name]
548
+ appliance_url = appliance[:url]
549
+
550
+ # found appliance, now refresh it
551
+
552
+ if options[:do_offline]
553
+ json_response = {'appliance' => appliance} # mock payload
554
+ else
555
+ appliance, json_response = ::MtnCloud::Cli::Remote.refresh_remote(appliance_name.to_sym)
556
+ json_response = {'appliance' => appliance} # mock payload
557
+ appliance, json_response = ::MtnCloud::Cli::Remote.refresh_remote(appliance_name)
558
+ # json_response = {'appliance' => appliance} # mock payload
559
+ end
560
+ # appliance, json_response = ::MtnCloud::Cli::Remote.refresh_remote(appliance_name)
561
+
562
+ if (appliance[:status] != 'ready' && appliance[:status] != 'fresh')
563
+ exit_code = 1
564
+ # err = appliance[:last_check] && appliance[:last_check][:error] ? appliance[:last_check][:error] : nil
565
+ end
566
+
567
+ render_response(json_response, options) do
568
+ print_h1 "Remote", [], options
569
+ print cyan
570
+ print format_remote_details(appliance, options)
571
+ print reset, "\n"
572
+ end
573
+ return exit_code, err
574
+ rescue RestClient::Exception => e
575
+ print_rest_exception(e, options)
576
+ exit 1
577
+ end
578
+ end
579
+
580
+ def check_all(args)
581
+ options = {}
582
+ checkall = false
583
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
584
+ opts.banner = subcommand_usage()
585
+ build_common_options(opts, options, [:quiet])
586
+ opts.footer = <<-EOT
587
+ Refresh all remote appliances.
588
+ This makes a request to each of the configured appliance urls and updates the status and version.
589
+ EOT
590
+ end
591
+ optparse.parse!(args)
592
+
593
+ if args.count != 0
594
+ raise_command_error "wrong number of arguments, expected 0-1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
595
+ end
596
+ #connect(options) # needed?
597
+ _check_all_appliances(options)
598
+ end
599
+
600
+ def _check_all_appliances(options)
601
+ start_time = Time.now
602
+ # reresh all appliances and then display the list view
603
+ id_list = ::MtnCloud::Cli::Remote.appliances.keys # sort ?
604
+ if id_list.size > 1
605
+ print cyan
606
+ puts "Checking #{id_list.size} remotes"
607
+ elsif id_list.size == 1
608
+ puts "Checking #{MtnCloud::Cli::Remote.appliances.keys.first}"
609
+ end
610
+ id_list.each do |appliance_name|
611
+ #print "."
612
+ appliance, json_response = ::MtnCloud::Cli::Remote.refresh_remote(appliance_name)
613
+ end
614
+ took_sec = (Time.now - start_time)
615
+ print_green_success "Completed check of #{id_list.size} #{id_list.size == 1 ? 'remote' : 'remotes'} in #{format_duration_seconds(took_sec)}"
616
+
617
+ if options[:quiet]
618
+ return 0
619
+ end
620
+ list([])
621
+ return 0
622
+ end
623
+
624
+ def rename(args)
625
+ exit_code, err, options, params, payload = 0, nil, {}, {}, {}
626
+ use_it = false
627
+ is_insecure = nil
628
+ new_name = nil
629
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
630
+ opts.banner = subcommand_usage("[name] [new name]")
631
+ opts.on(nil, "--name NAME", "Update the name of your remote appliance") do |val|
632
+ new_name = val
633
+ end
634
+ # opts.on(nil, '--use', "Make this the current appliance" ) do
635
+ # use_it = true
636
+ # end
637
+ build_common_options(opts, options, [:auto_confirm, :quiet])
638
+ opts.footer = <<-EOT
639
+ Rename a remote.
640
+ This changes your client configuration remote name, not the appliance itself.
641
+ [name] is required. This is the current name of a remote.
642
+ [new name] is required. This is the new name for the remote. This must not already be in use.
643
+ EOT
644
+ end
645
+ optparse.parse!(args)
646
+ verify_args!(args:args, count:2, optparse:optparse)
647
+ appliance_name = args[0].to_sym
648
+ new_appliance_name = args[1].to_sym
649
+ appliance = ::MtnCloud::Cli::Remote.load_remote(appliance_name)
650
+ if !appliance
651
+ raise_command_error "Remote appliance not found by the name '#{appliance_name}', see the command `remote list`"
652
+ end
653
+ # don't allow overwrite yet
654
+ matching_appliance = ::MtnCloud::Cli::Remote.load_remote(new_appliance_name)
655
+ if matching_appliance
656
+ raise_command_error "Remote appliance already exists with the name '#{new_appliance_name}', see the command `, see the command `remote get #{new_appliance_name}`"
657
+ end
658
+
659
+ unless options[:yes] || ::MtnCloud::Cli::OptionTypes::confirm("Are you sure you want to rename remote '#{appliance_name}' to '#{new_appliance_name}'?", options)
660
+ return 9, "aborted command"
661
+ end
662
+ # this does all the work
663
+ ::MtnCloud::Cli::Remote.rename_remote(appliance_name, new_appliance_name)
664
+
665
+ print_green_success "Renamed remote #{appliance_name} to #{new_appliance_name}"
666
+ # todo: just go ahead and refresh it now...
667
+ # _check(appliance_name, {:quiet => true})
668
+ # appliance, json_response = ::MtnCloud::Cli::Remote.refresh_remote(new_appliance_name)
669
+ # print new appliance details
670
+ _get(new_appliance_name, {})
671
+ return 0, nil
672
+ end
673
+
674
+ def update(args)
675
+ exit_code, err, options, params, payload = 0, nil, {}, {}, {}
676
+ use_it = false
677
+ is_insecure = nil
678
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
679
+ opts.banner = subcommand_usage("[name]")
680
+ opts.on("--name NAME", String, "Update the name of your remote appliance") do |val|
681
+ params[:name] = val
682
+ end
683
+ opts.on("--url URL", String, "Update the url of your remote appliance") do |val|
684
+ params[:host] = val
685
+ end
686
+ opts.on(nil, "--secure", "Prevent insecure HTTPS communication. This is enabled by default") do
687
+ params[:secure] = true
688
+ end
689
+ opts.on(nil, "--insecure", "Allow insecure HTTPS communication. i.e. Ignore SSL errors.") do
690
+ params[:insecure] = true
691
+ end
692
+ opts.on(nil, '--use', "Make this the current appliance" ) do
693
+ use_it = true
694
+ params[:active] = true
695
+ end
696
+ build_common_options(opts, options, [:quiet])
697
+ opts.footer = "This can be used to update remote appliance settings.\n"
698
+ end
699
+ optparse.parse!(args)
700
+ verify_args!(args:args, count:1, optparse:optparse)
701
+
702
+ appliance_name = args[0].to_sym
703
+ appliance = load_remote_by_name(appliance_name)
704
+ appliance_name = appliance[:name]
705
+ appliance_url = appliance[:url]
706
+
707
+ # params[:url] = args[1] if args[1]
708
+
709
+ if params.empty?
710
+ print_error MtnCloud::Terminal.angry_prompt
711
+ puts_error "Specify at least one option to update"
712
+ puts_error optparse
713
+ return 1
714
+ end
715
+
716
+ if params[:insecure]
717
+ appliance[:insecure] = true
718
+ elsif params[:secure]
719
+ appliance.delete(:insecure)
720
+ end
721
+ if params[:url] || params[:host]
722
+ appliance[:host] = params[:url] || params[:host]
723
+ end
724
+
725
+ ::MtnCloud::Cli::Remote.save_remote(appliance_name, appliance)
726
+ # rename_remote() should be inside save_remote()
727
+ if params[:name] && params[:name].to_s != appliance_name.to_s
728
+ ::MtnCloud::Cli::Remote.save_remote(appliance_name, appliance)
729
+ ::MtnCloud::Cli::Remote.rename_remote(appliance_name, params[:name])
730
+ print_green_success "Updated remote #{appliance_name} (renamed #{params[:name]})"
731
+ appliance_name = params[:name]
732
+ else
733
+ ::MtnCloud::Cli::Remote.save_remote(appliance_name, appliance)
734
+ print_green_success "Updated remote #{appliance_name}"
735
+ end
736
+
737
+ # todo: just go ahead and refresh it now...
738
+ # _check(appliance_name, {:quiet => true})
739
+ appliance, json_response = ::MtnCloud::Cli::Remote.refresh_remote(appliance_name)
740
+ # print new appliance details
741
+ _get(appliance[:name], {})
742
+ return exit_code, err
743
+ end
744
+
745
+ def clone(args)
746
+ exit_code, err, options, params, payload = 0, nil, {}, {}, {}
747
+ use_it = false
748
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
749
+ opts.banner = subcommand_usage("[remote] [name]")
750
+ # opts.on(nil, "--secure", "Prevent insecure HTTPS communication. This is enabled by default") do
751
+ # params[:secure] = true
752
+ # end
753
+ # opts.on(nil, "--insecure", "Allow insecure HTTPS communication. i.e. Ignore SSL errors.") do
754
+ # params[:insecure] = true
755
+ # end
756
+ opts.on(nil, '--use', "Make it the current appliance" ) do
757
+ use_it = true
758
+ params[:active] = true
759
+ end
760
+ build_common_options(opts, options, [:quiet])
761
+ opts.footer = <<-EOT
762
+ Clone remote appliance configuration, including any existing credentials.
763
+ [remote] is required. This is the name of an existing remote.
764
+ [name] is optional. This is the name of the new remote that will be created.
765
+ EOT
766
+ end
767
+ optparse.parse!(args)
768
+ verify_args!(args:args, optparse:optparse, count:2)
769
+
770
+
771
+ appliance_name = args[0].to_sym
772
+ appliance = load_remote_by_name(appliance_name)
773
+ if !appliance
774
+ raise_command_error "Remote appliance not found by the name '#{appliance_name}', see the command `remote list`"
775
+ end
776
+
777
+ new_appliance_name = args[1].to_sym
778
+ matching_appliance = ::MtnCloud::Cli::Remote.appliances[new_appliance_name.to_sym]
779
+ if matching_appliance
780
+ raise_command_error "Remote already exists with the name '#{matching_appliance[:name]}', see the command `remote get #{matching_appliance[:name]}`"
781
+ end
782
+
783
+ # ok clone it
784
+ original_appliance = appliance
785
+ appliance = original_appliance.clone
786
+ appliance[:name] = new_appliance_name
787
+
788
+ if params[:insecure]
789
+ appliance[:insecure] = true
790
+ elsif params[:secure]
791
+ appliance.delete(:insecure)
792
+ end
793
+ if params[:url] || params[:host]
794
+ appliance[:url] = params[:url] || params[:host]
795
+ # appliance.delete(:host)
796
+ end
797
+ if use_it
798
+ appliance[:active] = true
799
+ end
800
+ # save the new remote
801
+ appliance = ::MtnCloud::Cli::Remote.save_remote(new_appliance_name, appliance)
802
+ # refresh it now?
803
+ appliance, json_response = ::MtnCloud::Cli::Remote.refresh_remote(new_appliance_name)
804
+ # render
805
+ if !options[:quiet]
806
+ print_green_success "Cloned remote #{original_appliance[:name]} to #{appliance[:name]}, status is #{format_appliance_status(appliance)}"
807
+ # print new appliance details
808
+ _get(appliance[:name].to_s, {})
809
+ end
810
+ return exit_code, err
811
+ end
812
+
813
+ def get(args)
814
+ exit_code, err, options, params, payload = 0, nil, {}, {}, {}
815
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
816
+ opts.banner = subcommand_usage("[name]")
817
+ opts.on( '-u', '--url', "Print only the url." ) do
818
+ options[:url_only] = true
819
+ end
820
+ opts.on('--offline', '--offline', "Do this offline without an api request to refresh the remote appliance status.") do
821
+ options[:do_offline] = true
822
+ end
823
+ build_common_options(opts, options, [:json,:yaml,:csv,:fields, :quiet])
824
+ opts.footer = <<-EOT
825
+ Print details about the a remote appliance.
826
+ [name] is optional. This is the name of a remote.
827
+ By default, the current appliance is used.
828
+ Returns an error if the specified remote is not found, or there is no current remote.
829
+ EOT
830
+ end
831
+ optparse.parse!(args)
832
+ id_list = nil
833
+ # verify_args!(args:args, min:1, optparse:optparse)
834
+ if args.count == 0
835
+ id_list = ['current']
836
+ else
837
+ id_list = parse_id_list(args)
838
+ end
839
+ #connect(options)
840
+ return run_command_for_each_arg(id_list) do |arg|
841
+ _get(arg, options)
842
+ end
843
+ end
844
+
845
+ def _get(appliance_name, options)
846
+ exit_code, err = 0, nil
847
+ if appliance_name == 'current'
848
+ current_appliance = ::MtnCloud::Cli::Remote.load_active_remote()
849
+ if current_appliance.nil?
850
+ #raise_command_error "No current appliance, see the command `remote use`"
851
+ unless options[:quiet]
852
+ print yellow, "No current appliance, see the command `remote use`", reset, "\n"
853
+ end
854
+ return 1, "No current appliance"
855
+ end
856
+ end
857
+ appliance = load_remote_by_name(appliance_name)
858
+ appliance_name = appliance[:name]
859
+ appliance_url = appliance[:url]
860
+
861
+ # refresh remote status and version by default
862
+ # should json just be appliance instead maybe?
863
+ json_response = nil
864
+ if options[:do_offline]
865
+ json_response = {'appliance' => appliance} # mock payload
866
+ else
867
+ appliance, json_response = ::MtnCloud::Cli::Remote.refresh_remote(appliance_name.to_sym)
868
+ json_response = {'appliance' => appliance} # mock payload
869
+ end
870
+
871
+ # render
872
+ render_response(json_response, options) do
873
+ if options[:url_only]
874
+ if appliance
875
+ print cyan, (appliance[:url] || appliance[:host]),"\n",reset
876
+ return exit_code, err
877
+ else
878
+ print_error red, err,"\n",reset
879
+ return exit_code, err
880
+ end
881
+ end
882
+ if exit_code != 0
883
+ print_error red, err,"\n",reset
884
+ return exit_code, err
885
+ end
886
+
887
+ print_h1 "Remote", [], options
888
+ print cyan
889
+ print format_remote_details(appliance, options)
890
+ print reset, "\n"
891
+ end
892
+ return exit_code, err
893
+
894
+ end
895
+
896
+ def view(args)
897
+ print_error "#{yellow}DEPRECATION WARNING: `remote view` has been deprecated and replaced with `view`. Please use `view` instead.#{reset}\n"
898
+ options = {}
899
+ path = "/"
900
+ no_auth = false
901
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
902
+ opts.banner = subcommand_usage("[name]")
903
+ opts.on('--path PATH', String, "Specify a path to load. eg '/logs'" ) do |val|
904
+ path = val
905
+ end
906
+ opts.on('--no-auth', "Do not attempt to login with access token." ) do |val|
907
+ no_auth = true
908
+ end
909
+ build_common_options(opts, options, [:dry_run])
910
+ opts.footer = <<-EOT
911
+ View remote appliance in a web browser.
912
+ [name] is optional. This is the name of a remote. Default is the current remote.
913
+ This will automatically login with the current access token.
914
+ EOT
915
+ end
916
+ optparse.parse!(args)
917
+ # verify_args!(args:args, optparse:optparse)
918
+ if args.count == 0
919
+ id_list = ['current']
920
+ #raise_command_error "wrong number of arguments, expected 1-N and got 0\n#{optparse}"
921
+ else
922
+ id_list = parse_id_list(args)
923
+ end
924
+ #connect(options)
925
+ return run_command_for_each_arg(id_list) do |arg|
926
+ _view_appliance(arg, path, no_auth, options)
927
+ end
928
+ end
929
+
930
+ def _view_appliance(appliance_name, path, no_auth, options)
931
+ appliance = load_remote_by_name(appliance_name)
932
+ appliance_name = appliance[:name]
933
+ appliance_url = appliance[:url]
934
+ if appliance_url.to_s.empty?
935
+ raise_command_error "Remote appliance does not have a url?"
936
+ end
937
+ path = path.to_s.empty? ? "/" : path
938
+ if path[0].chr != "/"
939
+ path = "/#{path}"
940
+ end
941
+ wallet = ::MtnCloud::Cli::Credentials.new(appliance_name, nil).load_saved_credentials()
942
+ # try to auto login if we have a token
943
+ link = "#{appliance_url}#{path}"
944
+ if no_auth == false
945
+ if wallet && wallet['access_token']
946
+ link = "#{appliance_url}/login/oauth-redirect?access_token=#{wallet['access_token']}\\&redirectUri=#{path}"
947
+ end
948
+ end
949
+
950
+ if options[:dry_run]
951
+ puts MtnCloud::Util.open_url_command(link)
952
+ return 0
953
+ end
954
+ return MtnCloud::Util.open_url(link)
955
+ end
956
+
957
+ def remove(args)
958
+ options = {}
959
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
960
+ opts.banner = subcommand_usage("[name]")
961
+ build_common_options(opts, options, [:auto_confirm, :quiet])
962
+ opts.footer = <<-EOT
963
+ This will delete the specified remote appliance(s) from your local configuration.
964
+ [name] is required. This is the name of a remote. More than one can be passed.
965
+ EOT
966
+ end
967
+ optparse.parse!(args)
968
+ verify_args!(args:args, min:1, optparse:optparse)
969
+ id_list = parse_id_list(args)
970
+ #connect(options)
971
+ # verify they all exist first, this a cheap lookup and raises and error if not found
972
+ id_list.each do |remote_id|
973
+ found_remote = load_remote_by_name(remote_id)
974
+ return 1, "Remote appliance not found by the name '#{remote_id}', see the command `remote list`" if found_remote.nil?
975
+ end
976
+ unless options[:yes] || ::MtnCloud::Cli::OptionTypes::confirm("Are you sure you would like to delete #{id_list.size == 1 ? 'remote' : id_list.size.to_s + ' remotes'}: #{anded_list(id_list)}?", options)
977
+ return 9, "aborted command"
978
+ end
979
+ return run_command_for_each_arg(id_list) do |arg|
980
+ _remove_appliance(arg, options)
981
+ end
982
+ end
983
+
984
+ def _remove_appliance(appliance_name, options)
985
+ if ::MtnCloud::Cli::Remote.appliances[appliance_name.to_sym].nil?
986
+ raise_command_error "Remote does not exist with name '#{appliance_name.to_s}'"
987
+ end
988
+ # ok, delete it
989
+ ::MtnCloud::Cli::Remote.delete_remote(appliance_name)
990
+ # return result
991
+ if options[:quiet]
992
+ return 0
993
+ end
994
+ print_green_success "Deleted remote #{appliance_name}"
995
+ # list([])
996
+ return 0
997
+ end
998
+
999
+ def remove_all(args)
1000
+ options = {}
1001
+ checkall = false
1002
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
1003
+ opts.banner = subcommand_usage()
1004
+ build_common_options(opts, options, [:auto_confirm, :quiet])
1005
+ opts.footer = <<-EOT
1006
+ Remove all remote appliances, clearing the client configuration.
1007
+ This clears all the configured remotes and credentials.
1008
+ EOT
1009
+ end
1010
+ optparse.parse!(args)
1011
+ verify_args!(args:args, count:0, optparse:optparse)
1012
+ connect(options) # needed?
1013
+ _remove_all_appliances(options)
1014
+ end
1015
+
1016
+ def _remove_all_appliances(options)
1017
+ exit_code, err = 0, nil
1018
+ all_appliance_names = ::MtnCloud::Cli::Remote.appliances.keys.size
1019
+ if all_appliance_names.empty?
1020
+ if options[:quiet] != true
1021
+ print_green_success "No remotes found, nothing to remove"
1022
+ return 0, nil
1023
+ end
1024
+ end
1025
+ unless options[:yes] || ::MtnCloud::Cli::OptionTypes::confirm("Are you sure you want to remove all of your remotes (#{all_appliance_names.size})?", options)
1026
+ return 9, "aborted command"
1027
+ end
1028
+ # ok, do it
1029
+ deleted_list = ::MtnCloud::Cli::Remote.delete_all_remotes()
1030
+
1031
+ # render
1032
+ if options[:quiet]
1033
+ return exit_code, err
1034
+ end
1035
+ if all_appliance_names.size == 1
1036
+ print_green_success "Removed 1 remote (#{all_appliance_names.join(', ')})"
1037
+ else
1038
+ print_green_success "Removed 1 remote () "
1039
+ end
1040
+ #list([])
1041
+ return exit_code, err
1042
+ end
1043
+
1044
+ def use(args)
1045
+ options = {}
1046
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
1047
+ opts.banner = subcommand_usage("[name]")
1048
+ opts.on('--offline', '--offline', "Do this offline without an api request to refresh the remote appliance status.") do
1049
+ options[:do_offline] = true
1050
+ end
1051
+ build_common_options(opts, options, [:quiet])
1052
+ opts.footer = <<-EOT
1053
+ [name] is required. This is the name of a remote to begin using.
1054
+ Start using a remote, making it the active (current) remote appliance.
1055
+ This switches the remote context of your client configuration for all subsequent commands.
1056
+ It is important to always be aware of the context your commands are running in.
1057
+ The command `remote current` will return the current remote information.
1058
+ Instead of using an active remote, the -r option can be specified with each command.
1059
+
1060
+ It is recommeneded to set a custom prompt to show the current remote name.
1061
+ For example, add the following to your .mtncloudrc file:
1062
+
1063
+ # set your shell prompt to display the current username and remote
1064
+ set-prompt "%green%username%reset@%magenta%remote %cyanmtncloud> %reset"
1065
+
1066
+ EOT
1067
+ end
1068
+ optparse.parse!(args)
1069
+ verify_args!(args:args, count:1, optparse:optparse)
1070
+ exit_code, err = 0, nil
1071
+ # connect()
1072
+ current_appliance_name, current_appliance_url = @appliance_name, @appliance_url
1073
+ current_appliance = ::MtnCloud::Cli::Remote.load_active_remote()
1074
+ if current_appliance
1075
+ current_appliance_name, current_appliance_url = current_appliance[:name], current_appliance[:url]
1076
+ end
1077
+
1078
+ # current_appliance_name, current_appliance_url = @appliance_name, @appliance_url
1079
+ appliance_name = args[0].to_sym
1080
+ appliance = load_remote_by_name(appliance_name)
1081
+ # appliance = ::MtnCloud::Cli::Remote.load_remote(appliance_name)
1082
+ # if !appliance
1083
+ # raise_command_error "Remote not found by the name '#{appliance_name}', see the command `remote list`"
1084
+ # end
1085
+
1086
+ # appliance = ::MtnCloud::Cli::Remote.set_active_appliance(appliance_name)
1087
+ appliance[:active] = true
1088
+ appliance = ::MtnCloud::Cli::Remote.save_remote(appliance_name, appliance)
1089
+
1090
+ if options[:quiet]
1091
+ return 0
1092
+ end
1093
+
1094
+ if current_appliance_name.to_s == appliance_name.to_s
1095
+ print_green_success "Using remote #{display_appliance(appliance[:name], appliance[:url])}"
1096
+ else
1097
+ print_green_success "Using remote #{display_appliance(appliance[:name], appliance[:url])}"
1098
+ end
1099
+
1100
+ # recalculate session variables
1101
+ ::MtnCloud::Cli::Remote.recalculate_variable_map()
1102
+
1103
+ # could just do this
1104
+ # return _get(appliance_name, options)
1105
+
1106
+ # ok need to refresh here unless --offline
1107
+ # refresh status and version
1108
+ # maybe just make json_response = appliance here
1109
+ unless options[:do_offline]
1110
+ appliance, json_response = ::MtnCloud::Cli::Remote.refresh_remote(appliance[:name])
1111
+ end
1112
+ # return list([])
1113
+ return exit_code, err
1114
+ end
1115
+
1116
+ def unuse(args)
1117
+ options = {}
1118
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
1119
+ opts.banner = subcommand_usage()
1120
+ opts.footer = "" +
1121
+ "Stop using the current remote appliance.\n"
1122
+ build_common_options(opts, options, [])
1123
+ end
1124
+ optparse.parse!(args)
1125
+ verify_args!(args:args, count:0, optparse:optparse)
1126
+ #connect(options)
1127
+ exit_code, err = 0, nil
1128
+ @appliance_name, @appliance_url = MtnCloud::Cli::Remote.active_appliance
1129
+ if !@appliance_name
1130
+ print reset,"You are not using any remote appliance",reset,"\n"
1131
+ return 0
1132
+ end
1133
+ MtnCloud::Cli::Remote.clear_active_appliance()
1134
+ print_green_success "Stopped using remote #{display_appliance(@appliance_name, @appliance_url)}"
1135
+ # recalculate session variables
1136
+ ::MtnCloud::Cli::Remote.recalculate_variable_map()
1137
+ # return list([])
1138
+ return exit_code, err
1139
+ end
1140
+
1141
+ def current(args)
1142
+ options = {}
1143
+ name_only = false
1144
+ url_only = false
1145
+ version_only = false
1146
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
1147
+ opts.banner = subcommand_usage()
1148
+ opts.on( '-n', '--name', "Print only the name." ) do
1149
+ name_only = true
1150
+ end
1151
+ opts.on( '-u', '--url', "Print only the url." ) do
1152
+ url_only = true
1153
+ end
1154
+ opts.on( '-v', '--version', "Print only the build version." ) do
1155
+ version_only = true
1156
+ end
1157
+ opts.on('--offline', '--offline', "Do this offline without an api request to refresh the remote appliance status.") do
1158
+ options[:do_offline] = true
1159
+ end
1160
+ build_common_options(opts, options, [:json,:yaml,:csv,:fields, :quiet])
1161
+ opts.footer = <<-EOT
1162
+ Print details about the current remote appliance.
1163
+ This behaves the same as `remote get current`.
1164
+ EOT
1165
+ end
1166
+ optparse.parse!(args)
1167
+ verify_args!(args:args, count:0, optparse:optparse)
1168
+ #connect(options)
1169
+
1170
+ current_appliance = ::MtnCloud::Cli::Remote.load_active_remote()
1171
+ if current_appliance.nil?
1172
+ #raise_command_error "No current appliance, see the command `remote use`"
1173
+ unless options[:quiet]
1174
+ print yellow, "No current appliance, see the command `remote use`", reset, "\n"
1175
+ end
1176
+ return 1, "No current appliance"
1177
+ end
1178
+
1179
+ # this does the same thing
1180
+ #return _get("current", options)
1181
+ appliance = current_appliance
1182
+ #appliance = load_remote_by_name("current")
1183
+ #appliance = @remote_appliance
1184
+ exit_code, err = 0, nil
1185
+ if appliance.nil?
1186
+ raise_command_error "no current remote appliance, see command `remote add`."
1187
+ end
1188
+
1189
+ # ok need to refresh here unless do_offline
1190
+ # refresh status and version
1191
+ # maybe just make json_response = appliance here
1192
+ json_response = nil
1193
+ if options[:do_offline]
1194
+ json_response = {'appliance' => appliance} # mock payload
1195
+ else
1196
+ appliance, json_response = ::MtnCloud::Cli::Remote.refresh_remote(appliance[:name])
1197
+ json_response = {'appliance' => appliance} # mock payload
1198
+ end
1199
+ # could set exit_code if appliance[:build_version].nil?
1200
+ render_response(json_response, options) do
1201
+ if name_only && url_only
1202
+ #print cyan, display_appliance(appliance[:name], appliance[:url]),"\n",reset
1203
+ print cyan, appliance[:name], " ", appliance[:url],"\n",reset
1204
+ elsif name_only
1205
+ print cyan, appliance[:name],"\n",reset
1206
+ elsif url_only
1207
+ print cyan, appliance[:url],"\n",reset
1208
+ elsif version_only
1209
+ print cyan, appliance[:build_version],"\n",reset
1210
+ else
1211
+ print_h1 "Remote", [], options
1212
+ print cyan
1213
+ print format_remote_details(appliance, options)
1214
+ print reset, "\n"
1215
+ end
1216
+ end
1217
+ return exit_code, err
1218
+ end
1219
+
1220
+
1221
+ # This moved to the SetupCommand
1222
+ def setup(args)
1223
+ print_error yellow,"[DEPRECATED] The command `remote setup` is deprecated. It has been replaced by `setup`.",reset,"\n"
1224
+ options = {}
1225
+ optparse = MtnCloud::Cli::OptionParser.new do|opts|
1226
+ opts.banner = subcommand_usage()
1227
+ build_common_options(opts, options, [:payload, :options, :json, :dry_run, :quiet])
1228
+ opts.on('--hubmode MODE','--hubmode MODE', "Choose an option for hub registration possible values are login, register, skip.") do |val|
1229
+ options[:hubmode] = val.to_s.downcase
1230
+ end
1231
+ opts.footer = <<-EOT
1232
+ Setup a fresh remote appliance, initializing it.
1233
+ First, this checks if setup is available, and returns an error if not.
1234
+ Then it prompts to create the master tenant and admin user.
1235
+ If Morpheus Hub registration is enabled, you may login or register to retrieve a license key,
1236
+ or you can pass `--hubmode skip`.
1237
+ This is only available on a new, freshly installed remote appliance,
1238
+ and it may only be executed successfully one time.
1239
+ EOT
1240
+ end
1241
+ optparse.parse!(args)
1242
+ verify_args!(args:args, optparse:optparse, max:1)
1243
+ # just invoke the setup command.
1244
+ # for this to work, the argument [remote] must be the first argument.
1245
+ cmd_args = []
1246
+ remote_name = nil
1247
+ if args[0]
1248
+ remote_name = args.shift
1249
+ # cmd_args = cmd_args + ["-r",remote_name, args]
1250
+ cmd_args = args + ["-r",remote_name, args]
1251
+ end
1252
+ return MtnCloud::Cli::Setup.new.handle(cmd_args)
1253
+ end
1254
+
1255
+ def load_remote_by_name(appliance_name)
1256
+ appliance = nil
1257
+ if appliance_name.to_s == "current"
1258
+ appliance = ::MtnCloud::Cli::Remote.load_active_remote()
1259
+ if !appliance
1260
+ raise_command_error "No current appliance, see the command `remote use`"
1261
+ end
1262
+ else
1263
+ appliance = ::MtnCloud::Cli::Remote.load_remote(appliance_name)
1264
+ if !appliance
1265
+ raise_command_error "Remote not found by name '#{appliance_name}', see the command `remote list`"
1266
+ end
1267
+ end
1268
+ return appliance
1269
+ end
1270
+
1271
+ def format_remote_details(appliance, options={})
1272
+ columns = {
1273
+ #"Name" => :name,
1274
+ "Name" => lambda {|it| it[:name].to_s },
1275
+ #"Name" => lambda {|it| it[:active] ? "#{it[:name]} #{bold}(current)#{reset}#{cyan}" : it[:name] },
1276
+ "URL" => lambda {|it| it[:url] || it[:host] },
1277
+ #"Status" => lambda {|it| format_appliance_status(it, cyan) },
1278
+ "Version" => lambda {|it| it[:build_version] ? "#{it[:build_version]}" : '' },
1279
+ #"Appliance URL" => lambda {|it| it[:appliance_url] ? "#{it[:appliance_url]}" : '' },
1280
+ "Secure" => lambda {|it| format_appliance_secure(it) },
1281
+ "Active" => lambda {|it| it[:active] ? "Yes " + format_is_current() : "No" },
1282
+ # "Active" => lambda {|it| format_boolean(it[:active]) },
1283
+ #"Authenticated" => lambda {|it| format_boolean it[:authenticated] },
1284
+ "Username" => :username,
1285
+ # "Activity" => lambda {|it| get_appliance_session_blurbs(it).join("\n" + (' '*15)) },
1286
+ "Last Login" => lambda {|it| format_duration_ago(it[:last_login_at]) },
1287
+ #"Last Logout" => lambda {|it| format_duration_ago(it[:last_logout_at]) },
1288
+ "Last Success" => lambda {|it| format_duration_ago(it[:last_success_at]) },
1289
+ "Last Check" => lambda {|it|
1290
+ check_timestamp = nil
1291
+ if it[:last_check] && it[:last_check][:timestamp]
1292
+ check_timestamp = it[:last_check][:timestamp]
1293
+ end
1294
+ check_status = nil
1295
+ if it[:last_check] && it[:last_check][:http_status]
1296
+ check_status = it[:last_check][:http_status]
1297
+ end
1298
+ if check_timestamp
1299
+ format_duration_ago(check_timestamp) # + (check_status ? " (HTTP #{check_status})" : "")
1300
+ else
1301
+ ""
1302
+ end
1303
+ },
1304
+ "Response Time" => lambda {|it| format_duration_milliseconds(it[:last_check][:took]) rescue "" },
1305
+ "Status" => lambda {|it| format_appliance_status(it, cyan) },
1306
+ "Error" => lambda {|it|
1307
+ error_str = it[:last_check] ? it[:last_check][:error] : ""
1308
+ # meh no need to show http status, :error explains it well enough
1309
+ # check_status = it[:last_check] ? it[:last_check][:http_status] : nil
1310
+ # if check_status && check_status != 200
1311
+ # #"(HTTP #{check_status}) #{error_str}"
1312
+ # else
1313
+ # error_str
1314
+ # end
1315
+ error_str
1316
+ },
1317
+
1318
+ }
1319
+ if appliance[:last_success_at].nil?
1320
+ columns.delete("Last Success")
1321
+ else
1322
+ columns.delete("Last Success")
1323
+ end
1324
+ if appliance[:last_check].nil? || appliance[:last_check][:error].nil?
1325
+ columns.delete("Error")
1326
+ end
1327
+ return as_description_list(appliance, columns, options)
1328
+ end
1329
+
1330
+ class << self
1331
+ include Term::ANSIColor
1332
+
1333
+ # for caching the the contents of YAML file $home/appliances
1334
+ # it is structured like :appliance_name => {:host => "https://api.gomorpheus.com", :active => true}
1335
+ # not named @@appliances to avoid confusion with the instance variable . This is also a command class...
1336
+ @@appliance_config = nil
1337
+
1338
+ def appliances
1339
+ self.appliance_config
1340
+ end
1341
+
1342
+ def appliance_config
1343
+ if @@appliance_config.nil?
1344
+ @@appliance_config
1345
+ @@appliance_config = load_appliance_file
1346
+ # fix things right away, replace deprecated :host with :url
1347
+ @@appliance_config.each do |app_name, appliance|
1348
+ host = appliance.delete(:host)
1349
+ if host && appliance[:url].to_s.empty?
1350
+ appliance[:url] = host
1351
+ end
1352
+ end
1353
+ end
1354
+ return @@appliance_config
1355
+ end
1356
+
1357
+ # Returns two things, the remote appliance name and url
1358
+ def active_appliance
1359
+ if self.appliances.empty?
1360
+ return nil, nil
1361
+ end
1362
+ app_name, app_map = self.appliances.find {|k,v| v[:active] == true }
1363
+ app_url = app_map ? (app_map[:host] || app_map[:url]).to_s : nil
1364
+ if app_name
1365
+ return app_name, app_url
1366
+ else
1367
+ return nil, nil
1368
+ end
1369
+ end
1370
+
1371
+ # Returns all the appliances in the configuration
1372
+ # @param params [Hash] not used right now
1373
+ # @return [Array] of appliances, all of them.
1374
+ def load_all_remotes(params={})
1375
+ if self.appliances.empty?
1376
+ return []
1377
+ end
1378
+ all_appliances = self.appliances.collect do |app_name, app_map|
1379
+ row = app_map.clone # OStruct.new(app_map) tempting
1380
+ row[:name] = app_name
1381
+ row
1382
+ # {
1383
+ # active: v[:active],
1384
+ # name: app_name,
1385
+ # host: v[:host], # || v[:url],
1386
+ # #"LICENSE": v[:licenseIsInstalled] ? "Installed" : "(unknown)" # never return a license key from the server, ever!
1387
+ # status: v[:status],
1388
+ # username: v[:username],
1389
+ # last_check: v[:last_check],
1390
+ # last_whoami: v[:last_whoami],
1391
+ # last_api_request: v[:last_api_request],
1392
+ # last_api_result: v[:last_api_result],
1393
+ # last_command: v[:last_command],
1394
+ # last_command_result: v[:last_command_result]
1395
+ # }
1396
+ end
1397
+
1398
+ # filter results
1399
+ params[:phrase] = params['phrase'] if params['phrase']
1400
+ params[:name] = params['name'] if params['name']
1401
+ params[:url] = params['url'] if params['url']
1402
+ # params[:insecure] = params['insecure'] if params['insecure']
1403
+ params[:max] = params['max'] if params['max']
1404
+ params[:offset] = params['offset'] if params['offset']
1405
+ params[:sort] = params['sort'] if params['sort']
1406
+ params[:direction] = params['direction'] if params['direction']
1407
+
1408
+
1409
+ if all_appliances
1410
+ # apply filters
1411
+ if params[:phrase]
1412
+ all_appliances = all_appliances.select do |app|
1413
+ app_name = app[:name] || app['name']
1414
+ app_url = app[:url] || app['url'] || app[:host]
1415
+ app_name.to_s.include?(params[:phrase]) || app_url.to_s.include?(params[:phrase])
1416
+ end
1417
+ end
1418
+ # apply sort
1419
+ sort_key = params[:sort] ? params[:sort].to_sym : :name
1420
+ # :url used to be stored as :host
1421
+ if sort_key == :url || sort_key == :host
1422
+ all_appliances = all_appliances.sort {|a,b| (a[:url] || a[:host]).to_s <=> (b[:url] || b[:host]).to_s }
1423
+ elsif sort_key
1424
+ all_appliances = all_appliances.sort {|a,b| a[sort_key].to_s <=> b[sort_key].to_s }
1425
+ end
1426
+ if params['direction'] == 'desc'
1427
+ all_appliances.reverse!
1428
+ end
1429
+ # limit
1430
+ if params[:max]
1431
+ all_appliances = all_appliances.first(params[:max])
1432
+ end
1433
+ end
1434
+ return all_appliances
1435
+ end
1436
+
1437
+ # @return Hash info about the active appliance
1438
+ def load_active_remote()
1439
+ # todo: use this in favor of Remote.active_appliance perhaps?
1440
+ if self.appliances.empty?
1441
+ return nil
1442
+ end
1443
+ result = nil
1444
+ app_name, app_map = self.appliances.find {|k,v| v[:active] == true }
1445
+ if app_map
1446
+ result = app_map
1447
+ result[:name] = app_name # app_name.to_s to be more consistant with other display values
1448
+ end
1449
+ return result
1450
+ end
1451
+
1452
+ # @param [String or Symbol] name of the remote to load (converted to symbol)
1453
+ # @return [Hash] info about the appliance
1454
+ def load_remote(app_name)
1455
+ if self.appliances.empty? || app_name.nil?
1456
+ return nil
1457
+ end
1458
+ result = nil
1459
+ app_map = self.appliances[app_name.to_sym]
1460
+ if app_map
1461
+ result = app_map
1462
+ result[:name] = app_name # .to_s probably better
1463
+ end
1464
+ return result
1465
+ end
1466
+
1467
+ def set_active_appliance(app_name)
1468
+ app_name = app_name.to_sym
1469
+ new_appliances = self.appliances
1470
+ new_appliances.each do |k,v|
1471
+ is_match = (app_name ? (k == app_name) : false)
1472
+ if is_match
1473
+ v[:active] = true
1474
+ else
1475
+ v.delete(:active)
1476
+ # v.delete('active')
1477
+ # v[:active] = false
1478
+ end
1479
+ end
1480
+ save_appliances(new_appliances)
1481
+ return load_remote(app_name)
1482
+ end
1483
+
1484
+ def clear_active_appliance
1485
+ #return set_active_appliance(nil)
1486
+ new_appliances = self.appliances
1487
+ new_appliances.each do |k,v|
1488
+ v.delete(:active)
1489
+ end
1490
+ save_appliances(new_appliances)
1491
+ end
1492
+
1493
+ def load_appliance_file
1494
+ fn = appliances_file_path
1495
+ if File.exist? fn
1496
+ #MtnCloud::Logging::DarkPrinter.puts "loading appliances file #{fn}" if MtnCloud::Logging.debug?
1497
+ return YAML.load_file(fn)
1498
+ else
1499
+ return {}
1500
+ # return {
1501
+ # mtncloud: {
1502
+ # host: 'https://api.gomorpheus.com',
1503
+ # active: true
1504
+ # }
1505
+ # }
1506
+ end
1507
+ end
1508
+
1509
+ def appliances_file_path
1510
+ File.join(MtnCloud::Cli.home_directory,"appliances")
1511
+ end
1512
+
1513
+ def save_appliances(new_config)
1514
+ fn = appliances_file_path
1515
+ if !Dir.exist?(File.dirname(fn))
1516
+ FileUtils.mkdir_p(File.dirname(fn))
1517
+ end
1518
+ File.open(fn, 'w') {|f| f.write new_config.to_yaml } #Store
1519
+ FileUtils.chmod(0600, fn)
1520
+ #@@appliance_config = load_appliance_file
1521
+ @@appliance_config = new_config
1522
+ end
1523
+
1524
+ # save_remote updates the appliance info
1525
+ # @param app_name [Symbol] name and key for the appliance
1526
+ # @param app_map [Hash] appliance configuration data :url, :insecure, :active, :etc
1527
+ # @return [Hash] updated appliance config data
1528
+ def save_remote(app_name, app_map)
1529
+ # need an app_name to save it
1530
+ if app_name.to_s.empty?
1531
+ puts "skipped save of remote with a blank name"
1532
+ return nil
1533
+ end
1534
+ # in case a temporary config gets passed in here, do not save it.. this should be avoided though
1535
+ if app_map[:temporary]
1536
+ puts "skipped save of temporary remote '#{app_name}'"
1537
+ return nil
1538
+ end
1539
+ app_name = app_name.to_sym
1540
+ # it's probably better to use load_appliance_file() here instead
1541
+ cur_appliances = self.appliances #.clone
1542
+ cur_appliances[app_name] = app_map
1543
+ #cur_appliances[app_name] ||= {:status => "unknown", :error => "Bad configuration. Missing url. See 'remote update --url'" }
1544
+ cur_appliances[app_name] ||= {:status => "unknown"}
1545
+ # :host is gone, use :url please
1546
+ if cur_appliances[app_name][:host]
1547
+ cur_appliances[app_name][:url] = cur_appliances[app_name].delete(:host)
1548
+ end
1549
+ # this is the new set_active_appliance(), instead just pass :active => true
1550
+ # remove active flag from others
1551
+ if app_map[:active]
1552
+ cur_appliances.each do |k,v|
1553
+ is_match = (app_name ? (k == app_name) : false)
1554
+ if is_match
1555
+ v[:active] = true
1556
+ else
1557
+ v.delete(:active)
1558
+ # v.delete('active')
1559
+ # v[:active] = false
1560
+ end
1561
+ end
1562
+ end
1563
+
1564
+ # persist all appliances
1565
+ save_appliances(cur_appliances)
1566
+ # recalculate session variables
1567
+ recalculate_variable_map()
1568
+ return app_map
1569
+ end
1570
+
1571
+ # use this to rename, it update appliances file and others.
1572
+ # oh maybe just put this in the command handler
1573
+ #
1574
+ # first check if the requested name exits
1575
+ # and that the new name does not exist.
1576
+ #
1577
+ # clone it and delete the old one.
1578
+ # todo: switch replace symbols with strings please, makes for nicer appliances.yaml
1579
+ def rename_remote(app_name, new_app_name)
1580
+ app_name = app_name.to_sym
1581
+ new_app_name = new_app_name.to_sym
1582
+ cur_appliances = self.appliances #.clone
1583
+ app_map = cur_appliances[app_name]
1584
+ if app_map.nil?
1585
+ print_red_alert "Remote not found by the name '#{app_name}', see the command `remote list`"
1586
+ #print "Did you mean one of these commands: #{suggestions.join(', ')?", reset, "\n"
1587
+ return nil
1588
+ end
1589
+ if cur_appliances[new_app_name]
1590
+ print_red_alert "A remote already exists with name '#{new_app_name}', see the command `remote get #{new_app_name}`"
1591
+ puts "First, you must rename or remove the existing remote."
1592
+ return nil
1593
+ end
1594
+
1595
+ # clone the existing data
1596
+
1597
+ # copy remote
1598
+ new_appliance_map = app_map.clone()
1599
+ new_appliance_map[:name] = new_app_name # inject name
1600
+ save_remote(new_app_name, new_appliance_map)
1601
+
1602
+ # clone credentials...just overwrite keys there, f it.
1603
+ old_wallet = ::MtnCloud::Cli::Credentials.new(app_name, nil).load_saved_credentials()
1604
+ if old_wallet
1605
+ ::MtnCloud::Cli::Credentials.new(new_app_name, nil).save_credentials(new_app_name, old_wallet)
1606
+ #::MtnCloud::Cli::Credentials.new(app_name, nil).clear_saved_credentials(app_name)
1607
+ end
1608
+ # clone groups...just overwrite keys there, f it.
1609
+ old_active_group = ::MtnCloud::Cli::Groups.active_group(app_name)
1610
+ if old_active_group
1611
+ ::MtnCloud::Cli::Groups.set_active_group(new_app_name, old_active_group)
1612
+ #::MtnCloud::Cli::Groups.clear_active_group(app_name)
1613
+ end
1614
+
1615
+ # delete stuff last
1616
+
1617
+ # delete creds
1618
+ if old_wallet
1619
+ ::MtnCloud::Cli::Credentials.new(app_name, nil).clear_saved_credentials(app_name)
1620
+ end
1621
+
1622
+ # delete groups
1623
+ if old_active_group
1624
+ ::MtnCloud::Cli::Groups.clear_active_group(app_name)
1625
+ end
1626
+
1627
+ # delete remote
1628
+ delete_remote(app_name)
1629
+
1630
+ # this is all redundant after above
1631
+ # # this should be a class method too
1632
+ # ::MtnCloud::Cli::Credentials.new(app_name, nil).clear_saved_credentials(app_name)
1633
+ # # delete from groups too..
1634
+ # ::MtnCloud::Cli::Groups.clear_active_group(app_name)
1635
+ # # recalculate session variables
1636
+ # recalculate_variable_map()
1637
+ # return the deleted value
1638
+ return app_map
1639
+ end
1640
+
1641
+ def delete_remote(app_name)
1642
+ app_name = app_name.to_sym
1643
+ cur_appliances = self.appliances #.clone
1644
+ app_map = cur_appliances[app_name]
1645
+ if !app_map
1646
+ return nil
1647
+ end
1648
+ # remove it from config and delete credentials
1649
+ cur_appliances.delete(app_name)
1650
+ ::MtnCloud::Cli::Remote.save_appliances(cur_appliances)
1651
+ # this should be a class method too
1652
+ ::MtnCloud::Cli::Credentials.new(app_name, nil).clear_saved_credentials(app_name)
1653
+ # delete from groups too..
1654
+ ::MtnCloud::Cli::Groups.clear_active_group(app_name)
1655
+ # recalculate session variables
1656
+ recalculate_variable_map()
1657
+ # return the deleted value
1658
+ return app_map
1659
+ end
1660
+
1661
+ def delete_all_remotes()
1662
+ deleted_list = []
1663
+ self.appliances.each do |app_name, appliance|
1664
+ deleted_list << delete_remote(app_name)
1665
+ end
1666
+ # self.appliances = {}
1667
+ # MtnCloud::Cli::Remote.save_appliances({})
1668
+ # recalculate_variable_map()
1669
+ # return deleted_list
1670
+ return self.appliances
1671
+ end
1672
+
1673
+ # refresh_remote makes an api request to the configured appliance url
1674
+ # and updates the appliance's build version, status and last_check attributes
1675
+ def refresh_remote(app_name, params={}, timeout=5)
1676
+ app_name = app_name.to_sym
1677
+ cur_appliances = self.appliances
1678
+ appliance = cur_appliances[app_name] || {}
1679
+ appliance_url = (appliance[:url] || appliance[:host]).to_s
1680
+ if !appliance_url
1681
+ raise "appliance config is missing url!" # should not need this
1682
+ end
1683
+ # todo: this insecure flag needs to applied everywhere now tho..
1684
+ if appliance[:insecure]
1685
+ MtnCloud::RestClient.enable_ssl_verification = false
1686
+ # MtnCloud::RestClient.enable_http = true
1687
+ end
1688
+ err = nil
1689
+ json_response = nil
1690
+ # make request to /api/setup/check
1691
+ # and update appliance :status, :build_version, :last_check{}
1692
+ if appliance_url.to_s.empty?
1693
+ err = "no url specified"
1694
+ # wtf, no url...
1695
+ return appliance, json_response
1696
+ else
1697
+ # access token is needed for buildVersion
1698
+ wallet = MtnCloud::Cli::Credentials.new(app_name, appliance_url).load_saved_credentials()
1699
+ setup_interface = MtnCloud::SetupInterface.new({url:appliance_url, verify_ssl: !appliance[:insecure], timeout: timeout,
1700
+ access_token: (wallet && wallet['access_token']) ? wallet['access_token'] : nil})
1701
+ start_time = Time.now
1702
+ begin
1703
+ json_response = setup_interface.check(params)
1704
+ rescue => ex
1705
+ err = ex
1706
+ ensure
1707
+ took_sec = Time.now - start_time
1708
+ end
1709
+
1710
+ # save and update appliance info
1711
+ return save_remote_last_check(appliance, json_response, err, took_sec)
1712
+ end
1713
+ end
1714
+
1715
+ # save the app status and last request information
1716
+ # looks for json_response like /setup/check and /ping
1717
+ def save_remote_last_check(appliance, json_response, err=nil, took_sec=nil)
1718
+ #puts "save_remote_last_check: #{appliance}, #{json_response}"
1719
+ app_name = appliance[:name] ? appliance[:name].to_sym : nil
1720
+ cur_appliances = self.appliances
1721
+ app_map = appliance
1722
+ app_url = (app_map[:url] || app_map[:host]).to_s
1723
+ if !app_url
1724
+ raise "appliance config is missing url!"
1725
+ end
1726
+
1727
+ # only change stuff that was contained in the response
1728
+ # this stores things under the context last_check
1729
+ appliance[:last_check] = {}
1730
+ appliance[:last_check][:success] = json_response.nil?
1731
+ appliance[:last_check][:timestamp] = Time.now.to_i
1732
+ appliance[:last_check][:http_status] = json_response ? 200 : nil
1733
+ if took_sec
1734
+ # store in ms
1735
+ appliance[:last_check][:took] = (took_sec.to_f*1000).round
1736
+ end
1737
+ if json_response
1738
+ # if json_response.key?('applianceUrl')
1739
+ # appliance[:appliance_url] = json_response['applianceUrl']
1740
+ # end
1741
+ if json_response['success'] == true
1742
+ appliance[:status] = 'ready'
1743
+ appliance[:last_check][:success] = true
1744
+ # consider bumping this after every successful api command
1745
+ appliance[:last_success_at] = Time.now.to_i
1746
+ appliance.delete(:error)
1747
+ end
1748
+ if !json_response['buildVersion'].to_s.empty?
1749
+ appliance[:build_version] = json_response['buildVersion']
1750
+ end
1751
+ if json_response.key?('setupNeeded')
1752
+ if json_response['setupNeeded'] == true
1753
+ appliance[:setup_needed] = true
1754
+ appliance[:status] = 'fresh'
1755
+ else
1756
+ appliance.delete(:setup_needed)
1757
+ end
1758
+ end
1759
+ else
1760
+ # no response body eh?
1761
+ appliance[:last_check][:success] = false
1762
+ appliance[:last_check][:error] = "Invalid api response"
1763
+ appliance[:status] = 'error'
1764
+ end
1765
+ # handle error
1766
+ if err
1767
+ case(err)
1768
+ when SocketError
1769
+ appliance[:status] = 'unreachable'
1770
+ appliance[:last_check][:http_status] = nil
1771
+ appliance[:last_check][:error] = err.message
1772
+ when RestClient::Exceptions::Timeout
1773
+ # print_rest_exception(e, options)
1774
+ # exit 1
1775
+ appliance[:status] = 'http-timeout'
1776
+ appliance[:last_check][:http_status] = nil
1777
+ when Errno::ECONNREFUSED
1778
+ appliance[:status] = 'net-error'
1779
+ appliance[:last_check][:error] = err.message
1780
+ when OpenSSL::SSL::SSLError
1781
+ appliance[:status] = 'ssl-error'
1782
+ appliance[:last_check][:error] = err.message
1783
+ when JSON::ParserError
1784
+ appliance[:status] = 'unrecognized'
1785
+ appliance[:last_check][:error] = err.message
1786
+ when RestClient::Exception
1787
+ appliance[:status] = 'http-error'
1788
+ # appliance[:http_status] = err.response ? err.response.code : nil
1789
+ appliance[:last_check][:http_status] = err.response ? err.response.code : nil
1790
+ appliance[:last_check][:error] = err.message
1791
+ # if err.response.code == 404
1792
+ # appliance[:status] = 'ready' # 'ok'
1793
+ # MtnCloud::Logging::DarkPrinter.puts "ping failed but it is ready" if MtnCloud::Logging.debug?
1794
+ # end
1795
+ else
1796
+ appliance[:status] = 'error' # err.class.to_s.dasherize
1797
+ appliance[:last_check][:error] = err.message
1798
+ end
1799
+ end
1800
+
1801
+ # save to disk
1802
+ save_remote(app_name, appliance)
1803
+
1804
+ # return map and response
1805
+ return appliance, json_response
1806
+ end
1807
+
1808
+ def recalculate_variable_map()
1809
+ MtnCloud::Cli::Echo.recalculate_variable_map()
1810
+ # recalculate shell prompt after this change
1811
+ if MtnCloud::Cli::Shell.has_instance?
1812
+ MtnCloud::Cli::Shell.instance.reinitialize()
1813
+ end
1814
+ end
1815
+
1816
+ end
1817
+
1818
+ end