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,2161 @@
1
+ require 'mtncloud/cli/cli_command'
2
+
3
+ class MtnCloud::Cli::ArchivesCommand
4
+ include MtnCloud::Cli::CliCommand
5
+ include MtnCloud::Cli::ProvisioningHelper
6
+
7
+ set_command_name :archives
8
+
9
+ # bucket commands
10
+ # register_subcommands :list_buckets, :get_bucket, :add_bucket, :update_bucket, :remove_bucket
11
+ register_subcommands :'list' => :list_buckets
12
+ register_subcommands :'get' => :get_bucket
13
+ register_subcommands :'add' => :add_bucket
14
+ register_subcommands :'update' => :update_bucket
15
+ register_subcommands :'remove' => :remove_bucket
16
+ register_subcommands :'download-bucket' => :download_bucket_zip
17
+ # file commands
18
+ register_subcommands :'list-files' => :list_files
19
+ register_subcommands :'ls' => :ls
20
+ register_subcommands :'file' => :get_file
21
+ register_subcommands :'file-history' => :file_history
22
+ register_subcommands :'file-links' => :file_links
23
+ # register_subcommands :'history' => :file_history
24
+ register_subcommands :'upload' => :upload_file
25
+ register_subcommands :'download' => :download_file
26
+ register_subcommands :'read' => :read_file
27
+ register_subcommands :'remove-file' => :remove_file
28
+ register_subcommands :'rm' => :remove_file
29
+
30
+ # file link commands
31
+ register_subcommands :'add-file-link' => :add_file_link
32
+ # register_subcommands :'get-file-link' => :get_file_link
33
+ register_subcommands :'remove-file-link' => :remove_file_link
34
+ register_subcommands :'download-link' => :download_file_link
35
+
36
+
37
+ # set_default_subcommand :list
38
+
39
+ def initialize()
40
+ # @appliance_name, @appliance_url = MtnCloud::Cli::Remote.active_appliance
41
+ end
42
+
43
+ def connect(opts)
44
+ @api_client = establish_remote_appliance_connection(opts)
45
+ @archive_buckets_interface = @api_client.archive_buckets
46
+ @archive_files_interface = @api_client.archive_files
47
+ @options_interface = @api_client.options
48
+ # @active_group_id = MtnCloud::Cli::Groups.active_groups[@appliance_name]
49
+ end
50
+
51
+ def handle(args)
52
+ handle_subcommand(args)
53
+ end
54
+
55
+ def list_buckets(args)
56
+ options = {}
57
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
58
+ opts.banner = subcommand_usage()
59
+ build_common_options(opts, options, [:list, :json, :dry_run, :remote])
60
+ opts.footer = "List archive buckets."
61
+ end
62
+ optparse.parse!(args)
63
+ if args.count != 0
64
+ raise_command_error "#{command_name} list expects 0 arguments\n#{optparse}"
65
+ end
66
+ connect(options)
67
+ begin
68
+ params = {}
69
+ [:phrase, :offset, :max, :sort, :direction].each do |k|
70
+ params[k] = options[k] unless options[k].nil?
71
+ end
72
+ @archive_buckets_interface.setopts(options)
73
+ if options[:dry_run]
74
+ print_dry_run @archive_buckets_interface.dry.list(params)
75
+ return
76
+ end
77
+
78
+ json_response = @archive_buckets_interface.list(params)
79
+ if options[:json]
80
+ print JSON.pretty_generate(json_response)
81
+ print "\n"
82
+ return
83
+ end
84
+ archive_buckets = json_response['archiveBuckets']
85
+ title = "Archive Buckets"
86
+ subtitles = []
87
+ # if group
88
+ # subtitles << "Group: #{group['name']}".strip
89
+ # end
90
+ # if cloud
91
+ # subtitles << "Cloud: #{cloud['name']}".strip
92
+ # end
93
+ if params[:phrase]
94
+ subtitles << "Search: #{params[:phrase]}".strip
95
+ end
96
+ print_h1 title, subtitles
97
+ if archive_buckets.empty?
98
+ print cyan,"No archive buckets found.",reset,"\n"
99
+ else
100
+ rows = archive_buckets.collect {|archive_bucket|
101
+ row = {
102
+ id: archive_bucket['id'],
103
+ name: archive_bucket['name'],
104
+ description: archive_bucket['description'],
105
+ storageProvider: archive_bucket['storageProvider'] ? archive_bucket['storageProvider']['name'] : 'N/A',
106
+ fileCount: archive_bucket['fileCount'],
107
+ # createdBy: archive_bucket['createdBy'] ? archive_bucket['createdBy']['username'] : '',
108
+ size: format_bytes(archive_bucket['rawSize']),
109
+ owner: archive_bucket['owner'] ? archive_bucket['owner']['name'] : '',
110
+ tenants: archive_bucket['accounts'] ? archive_bucket['accounts'].collect {|it| it['name'] }.join(', ') : '',
111
+ visibility: archive_bucket['visibility'] ? archive_bucket['visibility'].capitalize() : '',
112
+ isPublic: archive_bucket['isPublic'] ? 'Yes' : 'No'
113
+ }
114
+ row
115
+ }
116
+ columns = [
117
+ :id,
118
+ :name,
119
+ {:storageProvider => {label: 'Storage'.upcase}},
120
+ {:fileCount => {label: '# Files'.upcase}},
121
+ :size,
122
+ :owner,
123
+ :tenants,
124
+ :visibility,
125
+ {:isPublic => {label: 'Public URL'.upcase}}
126
+ ]
127
+
128
+ if options[:include_fields]
129
+ columns = options[:include_fields]
130
+ end
131
+ print cyan
132
+ print as_pretty_table(rows, columns, options)
133
+ print reset
134
+ print_results_pagination(json_response, {:label => "bucket", :n_label => "buckets"})
135
+ print reset,"\n"
136
+ end
137
+ return 0
138
+ rescue RestClient::Exception => e
139
+ print_rest_exception(e, options)
140
+ exit 1
141
+ end
142
+ end
143
+
144
+ def get_bucket(args)
145
+ options = {}
146
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
147
+ opts.banner = subcommand_usage("[bucket:/path]")
148
+ build_common_options(opts, options, [:json, :dry_run, :remote])
149
+ opts.footer = "Display archive bucket details and files. " +
150
+ "\nThe [bucket] component of the argument is the name or id of an archive bucket." +
151
+ "\nThe [:/path] component is optional and can be used to display files under a sub-directory."
152
+ end
153
+ optparse.parse!(args)
154
+ if args.count != 1
155
+ print_error MtnCloud::Terminal.angry_prompt
156
+ puts_error "#{command_name} get expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
157
+ return 1
158
+ end
159
+ bucket_id, search_file_path = parse_bucket_id_and_file_path(args[0])
160
+ connect(options)
161
+ begin
162
+ @archive_buckets_interface.setopts(options)
163
+ if options[:dry_run]
164
+ if args[0].to_s =~ /\A\d{1,}\Z/
165
+ print_dry_run @archive_buckets_interface.dry.get(bucket_id.to_i)
166
+ else
167
+ print_dry_run @archive_buckets_interface.dry.list({name:bucket_id})
168
+ end
169
+ return
170
+ end
171
+ archive_bucket = find_archive_bucket_by_name_or_id(bucket_id)
172
+ return 1 if archive_bucket.nil?
173
+ json_response = {'archiveBucket' => archive_bucket} # skip redundant request
174
+ # json_response = @archive_buckets_interface.get(archive_bucket['id'])
175
+ archive_bucket = json_response['archiveBucket']
176
+ if options[:json]
177
+ print JSON.pretty_generate(json_response)
178
+ return
179
+ end
180
+ subtitles = []
181
+ if search_file_path != "/"
182
+ subtitles << "Path: #{search_file_path}"
183
+ end
184
+ print_h1 "Archive Bucket Details", subtitles
185
+ print cyan
186
+
187
+ description_cols = {
188
+ "ID" => 'id',
189
+ "Name" => 'name',
190
+ "Description" => 'description',
191
+ # "Created By" => lambda {|it| it['createdBy'] ? it['createdBy']['username'] : '' },
192
+ "Owner" => lambda {|it| it['owner'] ? it['owner']['name'] : '' },
193
+ "Tenants" => lambda {|it| it['accounts'] ? it['accounts'].collect {|acnt| acnt['name']}.join(', ') : '' },
194
+ "Visibility" => lambda {|it| it['visibility'] ? it['visibility'].capitalize() : '' },
195
+ "Public URL" => lambda {|it| it['isPublic'] ? 'Yes' : 'No' },
196
+ "Storage" => lambda {|it| it['storageProvider'] ? it['storageProvider']['name'] : '' },
197
+ "# Files" => lambda {|it| it['fileCount'] },
198
+ "Size" => lambda {|it| format_bytes(it['rawSize']) },
199
+ "Date Created" => lambda {|it| format_local_dt(it['dateCreated']) },
200
+ "Last Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
201
+ }
202
+ print_description_list(description_cols, archive_bucket)
203
+
204
+ # show files
205
+ # search_file_path = "/"
206
+ # if args[1]
207
+ # search_file_path = args[1]
208
+ # end
209
+ # if search_file_path[0].chr != "/"
210
+ # search_file_path = "/" + search_file_path
211
+ # end
212
+ # print_h2 "Path: #{search_file_path}"
213
+ print "\n"
214
+ archive_files_json_response = @archive_buckets_interface.list_files(archive_bucket['name'], search_file_path)
215
+ archive_files = archive_files_json_response['archiveFiles']
216
+ if archive_files && archive_files.size > 0
217
+ # archive_files.each do |archive_file|
218
+ # puts " = #{archive_file['name']}"
219
+ # end
220
+ print_archive_files_table(archive_files)
221
+ else
222
+ if search_file_path.empty? || search_file_path == "/"
223
+ puts "This archive bucket has no files."
224
+ else
225
+ puts "No files found for path #{search_file_path}"
226
+ end
227
+ end
228
+ print cyan
229
+
230
+ print reset,"\n"
231
+
232
+ rescue RestClient::Exception => e
233
+ print_rest_exception(e, options)
234
+ return 1
235
+ end
236
+ end
237
+
238
+ def add_bucket(args)
239
+ options = {}
240
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
241
+ opts.banner = subcommand_usage("[options]")
242
+ opts.on('--name VALUE', String, "Name") do |val|
243
+ options['name'] = val
244
+ end
245
+ opts.on('--description VALUE', String, "Description") do |val|
246
+ options['description'] = val
247
+ end
248
+ opts.on('--storageProvider VALUE', String, "Storage Provider ID") do |val|
249
+ options['storageProvider'] = val.to_s
250
+ end
251
+ opts.on('--visibility [private|public]', String, "Visibility determines if read access is restricted to the specified Tenants (Private) or all tenants (Public).") do |val|
252
+ options['visibility'] = val.to_s
253
+ end
254
+ opts.on('--accounts LIST', String, "Tenant Accounts (comma separated ids)") do |val|
255
+ # uh don't put commas or leading/trailing spaces in script names pl
256
+ options['accounts'] = val.to_s.split(",").collect {|it| it.to_s.strip }.select {|it| it }.compact
257
+ end
258
+ opts.on('--isPublic [on|off]', String, "Enabling Public URL allows files to be downloaded without any authentication.") do |val|
259
+ options['isPublic'] = (val.to_s == 'on' || val.to_s == 'true')
260
+ end
261
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
262
+ opts.footer = "Create a new archive bucket."
263
+ end
264
+ optparse.parse!(args)
265
+ connect(options)
266
+ begin
267
+ options.merge!(options[:options]) if options[:options] # so -O var= works..
268
+ option_params = options.reject {|k,v| k.is_a?(Symbol) }
269
+ # use the -g GROUP or active group by default
270
+ # options['group'] ||= @active_group_id
271
+
272
+ # support first arg as name instead of --name
273
+ if args[0] && !options['name']
274
+ options['name'] = args[0]
275
+ end
276
+ payload = nil
277
+ if options[:payload]
278
+ payload = options[:payload]
279
+ payload.deep_merge!({'archiveBucket' => option_params}) if !option_params.empty?
280
+ else
281
+ archive_bucket_payload = prompt_new_archive_bucket(options)
282
+ return 1 if !archive_bucket_payload
283
+ payload = {'archiveBucket' => archive_bucket_payload}
284
+ end
285
+ @archive_buckets_interface.setopts(options)
286
+ if options[:dry_run]
287
+ print_dry_run @archive_buckets_interface.dry.create(payload)
288
+ return
289
+ end
290
+ json_response = @archive_buckets_interface.create(payload)
291
+ if options[:json]
292
+ print JSON.pretty_generate(json_response)
293
+ print "\n"
294
+ elsif !options[:quiet]
295
+ new_archive_bucket = json_response['archiveBucket']
296
+ print_green_success "Added archive bucket #{new_archive_bucket['name']}"
297
+ get_bucket([new_archive_bucket['id']])
298
+ # list([])
299
+ end
300
+
301
+ rescue RestClient::Exception => e
302
+ print_rest_exception(e, options)
303
+ return 1
304
+ end
305
+ end
306
+
307
+ def update_bucket(args)
308
+ options = {}
309
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
310
+ opts.banner = subcommand_usage("[bucket] [options]")
311
+ opts.on('--name VALUE', String, "Name") do |val|
312
+ options['name'] = val
313
+ end
314
+ opts.on('--description VALUE', String, "Description") do |val|
315
+ options['description'] = val
316
+ end
317
+ # storage provider cannot be changed
318
+ # opts.on('--storageProvider VALUE', String, "Storage Provider ID") do |val|
319
+ # options['storageProvider'] = val.to_s
320
+ # end
321
+ opts.on('--payload JSON', String, "JSON Payload") do |val|
322
+ options['payload'] = JSON.parse(val.to_s)
323
+ end
324
+ opts.on('--payload-file FILE', String, "JSON Payload from a local file") do |val|
325
+ payload_file = val.to_s
326
+ options['payload'] = JSON.parse(File.read(payload_file))
327
+ end
328
+
329
+ opts.on('--visibility [private|public]', String, "Visibility determines if read access is restricted to the specified Tenants (Private) or all tenants (Public).") do |val|
330
+ options['visibility'] = val.to_s
331
+ end
332
+ opts.on('--accounts LIST', String, "Tenant Accounts (comma separated ids)") do |val|
333
+ # uh don't put commas or leading/trailing spaces in script names pl
334
+ options['accounts'] = val.to_s.split(",").collect {|it| it.to_s.strip }.select {|it| it }.compact
335
+ end
336
+ opts.on('--isPublic [on|off]', String, "Enabling Public URL allows files to be downloaded without any authentication.") do |val|
337
+ options['isPublic'] = (val.to_s == 'on' || val.to_s == 'true')
338
+ end
339
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
340
+ opts.footer = "Update an existing archive bucket."
341
+ end
342
+ optparse.parse!(args)
343
+ if args.count < 1
344
+ puts optparse
345
+ return 1
346
+ end
347
+ connect(options)
348
+
349
+ begin
350
+ archive_bucket = find_archive_bucket_by_name_or_id(args[0])
351
+
352
+ options.merge!(options[:options]) if options[:options] # so -O var= works..
353
+ option_params = options.reject {|k,v| k.is_a?(Symbol) }
354
+
355
+ payload = nil
356
+ if options[:payload]
357
+ payload = options[:payload]
358
+ payload.deep_merge!({'archiveBucket' => option_params}) if !option_params.empty?
359
+ else
360
+ archive_bucket_payload = prompt_edit_archive_bucket(archive_bucket, options)
361
+ return 1 if !archive_bucket_payload
362
+ payload = {'archiveBucket' => archive_bucket_payload}
363
+ end
364
+ @archive_buckets_interface.setopts(options)
365
+ if options[:dry_run]
366
+ print_dry_run @archive_buckets_interface.dry.update(archive_bucket["id"], payload)
367
+ return
368
+ end
369
+
370
+ json_response = @archive_buckets_interface.update(archive_bucket["id"], payload)
371
+ if options[:json]
372
+ print JSON.pretty_generate(json_response)
373
+ print "\n"
374
+ elsif !options[:quiet]
375
+ print_green_success "Updated archive bucket #{archive_bucket['name']}"
376
+ get([archive_bucket['id']])
377
+ end
378
+ return 0
379
+ rescue RestClient::Exception => e
380
+ print_rest_exception(e, options)
381
+ return 1
382
+ end
383
+ end
384
+
385
+ def remove_bucket(args)
386
+ options = {}
387
+ query_params = {}
388
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
389
+ opts.banner = subcommand_usage("[bucket]")
390
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
391
+ end
392
+ optparse.parse!(args)
393
+
394
+ if args.count < 1
395
+ print_error MtnCloud::Terminal.angry_prompt
396
+ puts_error "#{command_name} remove expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
397
+ return 1
398
+ end
399
+ bucket_id = args[0]
400
+ connect(options)
401
+ begin
402
+ # archive_bucket = find_archive_bucket_by_name_or_id(args[0])
403
+ json_response = @archive_buckets_interface.get(bucket_id, {})
404
+ archive_bucket = json_response['archiveBucket']
405
+ is_owner = json_response['isOwner']
406
+ return 1 if archive_bucket.nil?
407
+ if is_owner == false
408
+ print_red_alert "You must be the owner of archive bucket to remove it."
409
+ return 3
410
+ end
411
+ unless options[:yes] || MtnCloud::Cli::OptionTypes.confirm("Are you sure you want to delete the archive bucket: #{archive_bucket['name']}?")
412
+ return 9, "aborted command"
413
+ end
414
+ @archive_buckets_interface.setopts(options)
415
+ if options[:dry_run]
416
+ print_dry_run @archive_buckets_interface.dry.destroy(archive_bucket['id'], query_params)
417
+ return 0
418
+ end
419
+ json_response = @archive_buckets_interface.destroy(archive_bucket['id'], query_params)
420
+ if options[:json]
421
+ print JSON.pretty_generate(json_response)
422
+ print "\n"
423
+ else
424
+ print_green_success "Removed archive bucket #{archive_bucket['name']}"
425
+ # list([])
426
+ end
427
+ return 0
428
+ rescue RestClient::Exception => e
429
+ print_rest_exception(e, options)
430
+ return 1
431
+ end
432
+ end
433
+
434
+ def upload_file(args)
435
+ options = {}
436
+ query_params = {}
437
+ do_recursive = false
438
+ ignore_regexp = nil
439
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
440
+ opts.banner = subcommand_usage("[local-file] [bucket:/path]")
441
+ # opts.on('--filename FILEPATH', String, "Remote file path for the file or folder being uploaded, this is an alternative to [remote-file-path]." ) do |val|
442
+ # options['type'] = val
443
+ # end
444
+ opts.on( '-R', '--recursive', "Upload a directory and all of its files. This must be passed if [local-file] is a directory." ) do
445
+ do_recursive = true
446
+ end
447
+ opts.on('--ignore-files PATTERN', String, "Pattern of files to be ignored when uploading a directory." ) do |val|
448
+ ignore_regexp = /#{Regexp.escape(val)}/
449
+ end
450
+ opts.footer = "Upload a local file or folder to an archive bucket. " +
451
+ "\nThe first argument [local-file] should be the path of a local file or directory." +
452
+ "\nThe second argument [bucket:/path] should contain the bucket name." +
453
+ "\nThe [:/path] component is optional and can be used to specify the destination of the uploaded file or folder." +
454
+ "\nThe default destination is the same name as the [local-file], under the root bucket directory '/'. " +
455
+ "\nThis will overwrite any existing remote files that match the destination /path."
456
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
457
+ end
458
+ optparse.parse!(args)
459
+
460
+ if args.count != 2
461
+ print_error MtnCloud::Terminal.angry_prompt
462
+ puts_error "#{command_name} upload expects 2 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
463
+ return 1
464
+ end
465
+ # validate local file path
466
+ local_file_path = File.expand_path(args[0].squeeze('/'))
467
+ if local_file_path == "" || local_file_path == "/" || local_file_path == "."
468
+ print_error MtnCloud::Terminal.angry_prompt
469
+ puts_error "#{command_name} missing argument: [local-file]\n#{optparse}"
470
+ return 1
471
+ end
472
+ if !File.exist?(local_file_path)
473
+ print_error MtnCloud::Terminal.angry_prompt
474
+ puts_error "#{command_name} bad argument: [local-file]\nFile '#{local_file_path}' was not found.\n#{optparse}"
475
+ return 1
476
+ end
477
+
478
+ # validate bucket:/path
479
+ bucket_id, remote_file_path = parse_bucket_id_and_file_path(args[1])
480
+
481
+ # if local_file_path.include?('../') # || options[:yes]
482
+ # raise_command_error "Sorry, you may not use relative paths in your local filepath."
483
+ # end
484
+
485
+ # validate bucket name (or id)
486
+ if !bucket_id
487
+ print_error MtnCloud::Terminal.angry_prompt
488
+ puts_error "#{command_name} missing argument: [bucket]\n#{optparse}"
489
+ return 1
490
+ end
491
+
492
+ # strip leading slash of remote name
493
+ # if remote_file_path[0].chr == "/"
494
+ # remote_file_path = remote_file_path[1..-1]
495
+ # end
496
+
497
+ if remote_file_path.include?('./') # || options[:yes]
498
+ raise_command_error "Sorry, you may not use relative paths in your remote filepath."
499
+ end
500
+
501
+ # if !options[:yes]
502
+ scary_local_paths = ["/", "/root", "C:\\"]
503
+ if scary_local_paths.include?(local_file_path)
504
+ unless MtnCloud::Cli::OptionTypes.confirm("Are you sure you want to upload all the files in local directory '#{local_file_path}' !?")
505
+ return 9, "aborted command"
506
+ end
507
+ end
508
+ # end
509
+
510
+ connect(options)
511
+ begin
512
+ archive_bucket = find_archive_bucket_by_name_or_id(bucket_id)
513
+ return 1 if archive_bucket.nil?
514
+
515
+ # how many files we dealing with?
516
+ files_to_upload = []
517
+ if File.directory?(local_file_path)
518
+ # upload directory
519
+ if !do_recursive
520
+ print_error MtnCloud::Terminal.angry_prompt
521
+ puts_error "bad argument: '#{local_file_path}' is a directory. Use -R or --recursive to upload a directory.\n#{optparse}"
522
+ return 1
523
+ end
524
+ found_files = Dir.glob("#{local_file_path}/**/*")
525
+ # note: api call for directories is not needed
526
+ found_files = found_files.select {|file| File.file?(file) }
527
+ if ignore_regexp
528
+ found_files = found_files.reject {|it| it =~ ignore_regexp}
529
+ end
530
+ files_to_upload = found_files
531
+
532
+ if files_to_upload.size == 0
533
+ print_error MtnCloud::Terminal.angry_prompt
534
+ puts_error "bad argument: Local directory '#{local_file_path}' contains 0 files."
535
+ return 1
536
+ end
537
+
538
+ unless options[:yes] || MtnCloud::Cli::OptionTypes.confirm("Are you sure you want to upload directory #{local_file_path} (#{files_to_upload.size} files) to #{archive_bucket['name']}:#{remote_file_path}?")
539
+ return 9, "aborted command"
540
+ end
541
+
542
+ if !options[:yes]
543
+ if files_to_upload.size > 100
544
+ unless MtnCloud::Cli::OptionTypes.confirm("Are you REALLY sure you want to upload #{files_to_upload.size} files ?")
545
+ return 9, "aborted command"
546
+ end
547
+ end
548
+ end
549
+
550
+ # local_dirname = File.dirname(local_file_path)
551
+ # local_basename = File.basename(local_file_path)
552
+ upload_file_list = []
553
+ files_to_upload.each do |file|
554
+ destination = file.sub(local_file_path, (remote_file_path || "")).squeeze('/')
555
+ upload_file_list << {file: file, destination: destination}
556
+ end
557
+
558
+ @archive_buckets_interface.setopts(options)
559
+ if options[:dry_run]
560
+ # print_h1 "DRY RUN"
561
+ print "\n",cyan, bold, "Uploading #{upload_file_list.size} Files...", reset, "\n"
562
+ upload_file_list.each do |obj|
563
+ file, destination = obj[:file], obj[:destination]
564
+ #print cyan,bold, " - Uploading #{file} to #{bucket_id}:#{destination} DRY RUN", reset, "\n"
565
+ print_dry_run @archive_buckets_interface.dry.upload_file(bucket_id, file, destination)
566
+ print "\n"
567
+ end
568
+ return 0
569
+ end
570
+
571
+ print "\n",cyan, bold, "Uploading #{upload_file_list.size} Files...", reset, "\n"
572
+ bad_upload_responses = []
573
+ upload_file_list.each do |obj|
574
+ file, destination = obj[:file], obj[:destination]
575
+ print cyan,bold, " - Uploading #{file} to #{bucket_id}:#{destination}", reset
576
+ upload_response = @archive_buckets_interface.upload_file(bucket_id, file, destination)
577
+ if upload_response['success']
578
+ print bold," #{green}SUCCESS#{reset}"
579
+ else
580
+ print bold," #{red}ERROR#{reset}"
581
+ if upload_response['msg']
582
+ bad_upload_responses << upload_response
583
+ print " #{upload_response['msg']}#{reset}"
584
+ end
585
+ end
586
+ print "\n"
587
+ end
588
+ if bad_upload_responses.size > 0
589
+ print cyan, bold, "Completed Upload of #{upload_file_list.size} Files. #{red}#{bad_upload_responses.size} Errors!", reset, "\n"
590
+ else
591
+ print cyan, bold, "Completed Upload of #{upload_file_list.size} Files!", reset, "\n"
592
+ end
593
+
594
+ else
595
+
596
+ # upload file
597
+ if !File.exist?(local_file_path) && !File.file?(local_file_path)
598
+ print_error MtnCloud::Terminal.angry_prompt
599
+ puts_error "#{command_name} bad argument: [local-file]\nFile '#{local_file_path}' was not found.\n#{optparse}"
600
+ return 1
601
+ end
602
+
603
+ # local_dirname = File.dirname(local_file_path)
604
+ # local_basename = File.basename(local_file_path)
605
+
606
+ file = local_file_path
607
+ destination = File.basename(file)
608
+ if remote_file_path[-1].chr == "/"
609
+ # work like `cp`, and place into the directory
610
+ destination = remote_file_path + File.basename(file)
611
+ elsif remote_file_path
612
+ # renaming file
613
+ destination = remote_file_path
614
+ end
615
+ destination = destination.squeeze('/')
616
+
617
+ unless options[:yes] || MtnCloud::Cli::OptionTypes.confirm("Are you sure you want to upload #{local_file_path} to #{archive_bucket['name']}:#{destination}?")
618
+ return 9, "aborted command"
619
+ end
620
+
621
+ @archive_buckets_interface.setopts(options)
622
+ if options[:dry_run]
623
+ #print cyan,bold, " - Uploading #{file} to #{bucket_id}:#{destination} DRY RUN", reset, "\n"
624
+ # print_h1 "DRY RUN"
625
+ print_dry_run @archive_buckets_interface.dry.upload_file(bucket_id, file, destination)
626
+ print "\n"
627
+ return 0
628
+ end
629
+
630
+ print cyan,bold, " - Uploading #{file} to #{bucket_id}:#{destination}", reset
631
+ upload_response = @archive_buckets_interface.upload_file(bucket_id, file, destination)
632
+ if upload_response['success']
633
+ print bold," #{green}Success#{reset}"
634
+ else
635
+ print bold," #{red}Error#{reset}"
636
+ if upload_response['msg']
637
+ print " #{upload_response['msg']}#{reset}"
638
+ end
639
+ end
640
+ print "\n"
641
+
642
+ end
643
+ #print cyan, bold, "Upload Complete!", reset, "\n"
644
+
645
+ return 0
646
+ rescue RestClient::Exception => e
647
+ print_rest_exception(e, options)
648
+ return 1
649
+ end
650
+ end
651
+
652
+ def list_files(args)
653
+ options = {}
654
+ params = {}
655
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
656
+ opts.banner = subcommand_usage("[bucket:/path]")
657
+ opts.on('-a', '--all', "Show all files, including subdirectories under the /path.") do
658
+ params[:fullTree] = true
659
+ end
660
+ build_common_options(opts, options, [:list, :json, :dry_run, :remote])
661
+ opts.footer = "List files in an archive bucket. \nInclude [/path] to show files under a directory."
662
+ end
663
+ optparse.parse!(args)
664
+ if args.count != 1
665
+ print_error MtnCloud::Terminal.angry_prompt
666
+ puts_error "#{command_name} list-files expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
667
+ return 1
668
+ end
669
+ bucket_id, search_file_path = parse_bucket_id_and_file_path(args[0])
670
+ connect(options)
671
+ begin
672
+ archive_bucket = find_archive_bucket_by_name_or_id(bucket_id)
673
+ return 1 if archive_bucket.nil?
674
+ [:phrase, :offset, :max, :sort, :direction, :fullTree].each do |k|
675
+ params[k] = options[k] unless options[k].nil?
676
+ end
677
+ if params[:phrase]
678
+ params[:fullTree] = true # these are not exclusively supported by api yet
679
+ end
680
+ @archive_buckets_interface.setopts(options)
681
+ if options[:dry_run]
682
+ print_dry_run @archive_buckets_interface.dry.list_files(bucket_id, search_file_path, params)
683
+ return
684
+ end
685
+ json_response = @archive_buckets_interface.list_files(bucket_id, search_file_path, params)
686
+ archive_files = json_response['archiveFiles']
687
+ # archive_bucket = json_response['archiveBucket']
688
+ if options[:json]
689
+ print JSON.pretty_generate(json_response)
690
+ return
691
+ end
692
+ print_h1 "Archive Files", ["#{archive_bucket['name']}:#{search_file_path}"]
693
+ print cyan
694
+ description_cols = {
695
+ "Bucket ID" => 'id',
696
+ "Bucket Name" => 'name',
697
+ #"Path" => lambda {|it| search_file_path }
698
+ }
699
+ #print_description_list(description_cols, archive_bucket)
700
+ #print "\n"
701
+ #print_h2 "Path: #{search_file_path}"
702
+ # print "Directory: #{search_file_path}"
703
+ if archive_files && archive_files.size > 0
704
+ print_archive_files_table(archive_files, {fullTree: params[:fullTree]})
705
+ print_results_pagination(json_response, {:label => "file", :n_label => "files"})
706
+ else
707
+ # puts "No files found for path #{search_file_path}"
708
+ if search_file_path.empty? || search_file_path == "/"
709
+ puts "This archive bucket has no files."
710
+ else
711
+ puts "No files found for path #{search_file_path}"
712
+ return 1
713
+ end
714
+ end
715
+ print reset,"\n"
716
+ return 0
717
+ rescue RestClient::Exception => e
718
+ print_rest_exception(e, options)
719
+ return 1
720
+ end
721
+ end
722
+
723
+ def ls(args)
724
+ options = {}
725
+ params = {}
726
+ do_one_file_per_line = false
727
+ do_long_format = false
728
+ do_human_bytes = false
729
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
730
+ opts.banner = subcommand_usage("[bucket/path]")
731
+ opts.on('-a', '--all', "Show all files, including subdirectories under the /path.") do
732
+ params[:fullTree] = true
733
+ do_one_file_per_line = true
734
+ end
735
+ opts.on('-l', '--long', "Lists files in the long format, which contains lots of useful information, e.g. the exact size of the file, the file type, and when it was last modified.") do
736
+ do_long_format = true
737
+ do_one_file_per_line
738
+ end
739
+ opts.on('-H', '--human', "Humanized file sizes. The default is just the number of bytes.") do
740
+ do_human_bytes = true
741
+ end
742
+ opts.on('-1', '--oneline', "One file per line. The default delimiter is a single space.") do
743
+ do_one_file_per_line = true
744
+ end
745
+ build_common_options(opts, options, [:list, :json, :dry_run, :remote])
746
+ opts.footer = "Print filenames for a given archive location.\nPass archive location in the format bucket/path."
747
+ end
748
+ optparse.parse!(args)
749
+ if args.count != 1
750
+ print_error MtnCloud::Terminal.angry_prompt
751
+ puts_error "#{command_name} ls expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
752
+ return 1
753
+ end
754
+ bucket_id, search_file_path = parse_bucket_id_and_file_path(args[0])
755
+ connect(options)
756
+ begin
757
+ # archive_bucket = find_archive_bucket_by_name_or_id(bucket_id)
758
+ # return 1 if archive_bucket.nil?
759
+ [:phrase, :offset, :max, :sort, :direction, :fullTree].each do |k|
760
+ params[k] = options[k] unless options[k].nil?
761
+ end
762
+ @archive_buckets_interface.setopts(options)
763
+ if options[:dry_run]
764
+ print_dry_run @archive_buckets_interface.dry.list_files(bucket_id, search_file_path, params)
765
+ return 0
766
+ end
767
+ json_response = @archive_buckets_interface.list_files(bucket_id, search_file_path, params)
768
+ if options[:json]
769
+ puts as_json(json_response, options)
770
+ # no files is an error condition for this command
771
+ if !json_response['archiveFiles'] || json_response['archiveFiles'].size == 0
772
+ return 1
773
+ end
774
+ return 0
775
+ end
776
+ archive_bucket = json_response['archiveBucket'] # yep, this is returned too
777
+ archive_files = json_response['archiveFiles']
778
+ # archive_bucket = json_response['archiveBucket']
779
+ # print_h2 "Directory: #{search_file_path}"
780
+ # print "Directory: #{search_file_path}"
781
+ if archive_files && archive_files.size > 0
782
+ if do_long_format
783
+ # ls long format
784
+ # owner groups filesize type filename
785
+ now = Time.now
786
+ archive_files.each do |archive_file|
787
+ # -rw-r--r-- 1 jdickson staff 1361 Oct 23 08:00 voltron_2.10.log
788
+ file_color = cyan # reset
789
+ if archive_file['isDirectory']
790
+ file_color = blue
791
+ end
792
+ file_info = []
793
+ # Number of links
794
+ # file_info << file["linkCount"].to_i + 1
795
+ # Owner
796
+ owner_str = ""
797
+ if archive_file['owner']
798
+ owner_str = archive_file['owner']['name']
799
+ elsif archive_bucket['owner']
800
+ owner_str = archive_bucket['owner']['name']
801
+ else
802
+ owner_str = "noone"
803
+ end
804
+ file_info << truncate_string(owner_str, 15).ljust(15, " ")
805
+ # Group (Tenants)
806
+ groups_str = ""
807
+ if archive_file['visibility'] == 'public'
808
+ # this is confusing because of Public URL (isPublic) setting
809
+ groups_str = "public"
810
+ else
811
+ if archive_file['accounts'].instance_of?(Array) && archive_file['accounts'].size > 0
812
+ # groups_str = archive_file['accounts'].collect {|it| it['name'] }.join(',')
813
+ groups_str = (archive_file['accounts'].size == 1) ? "#{archive_file['accounts'][0]['name']}" : "#{archive_file['accounts'].size} tenants"
814
+ elsif archive_bucket['accounts'].instance_of?(Array) && archive_bucket['accounts'].size > 0
815
+ # groups_str = archive_bucket['accounts'].collect {|it| it['name'] }.join(',')
816
+ groups_str = (archive_bucket['accounts'].size == 1) ? "#{archive_bucket['accounts'][0]['name']}" : "#{archive_bucket['accounts'].size} tenants"
817
+ else
818
+ groups_str = owner_str
819
+ end
820
+ end
821
+ file_info << truncate_string(groups_str, 15).ljust(15, " ")
822
+ # File Type
823
+ content_type = archive_file['contentType'].to_s
824
+ if archive_file['isDirectory']
825
+ content_type = "directory"
826
+ else
827
+ content_type = archive_file['contentType'].to_s
828
+ end
829
+ file_info << content_type.ljust(25, " ")
830
+ filesize_str = ""
831
+ if do_human_bytes
832
+ # filesize_str = format_bytes(archive_file['rawSize'])
833
+ filesize_str = format_bytes_short(archive_file['rawSize'])
834
+ else
835
+ filesize_str = archive_file['rawSize'].to_i.to_s
836
+ end
837
+ # file_info << filesize_str.ljust(12, " ")
838
+ file_info << filesize_str.ljust(7, " ")
839
+ mtime = ""
840
+ last_updated = parse_time(archive_file['lastUpdated'])
841
+ if last_updated
842
+ if last_updated.year == now.year
843
+ mtime = format_local_dt(last_updated, {format: "%b %e %H:%M"})
844
+ else
845
+ mtime = format_local_dt(last_updated, {format: "%b %e %Y"})
846
+ end
847
+ end
848
+ file_info << mtime.ljust(12, " ")
849
+ if params[:fullTree]
850
+ file_info << file_color + archive_file["filePath"].to_s + cyan
851
+ else
852
+ file_info << file_color + archive_file["name"].to_s + cyan
853
+ end
854
+ print cyan, file_info.join(" "), reset, "\n"
855
+ end
856
+ else
857
+ file_names = archive_files.collect do |archive_file|
858
+ file_color = cyan # reset
859
+ if archive_file['isDirectory']
860
+ file_color = blue
861
+ end
862
+ if params[:fullTree]
863
+ file_color + archive_file["filePath"].to_s + reset
864
+ else
865
+ file_color + archive_file["name"].to_s + reset
866
+ end
867
+ end
868
+ if do_one_file_per_line
869
+ print file_names.join("\n")
870
+ else
871
+ print file_names.join("\t")
872
+ end
873
+ print "\n"
874
+ end
875
+ else
876
+ print_error yellow, "No files found for path: #{search_file_path}", reset, "\n"
877
+ return 1
878
+ end
879
+
880
+ return 0
881
+ rescue RestClient::Exception => e
882
+ print_rest_exception(e, options)
883
+ return 1
884
+ end
885
+ end
886
+
887
+ def get_file(args)
888
+ options = {}
889
+ max_links = 10
890
+ max_history = 10
891
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
892
+ opts.banner = subcommand_usage("[bucket:/path]")
893
+ opts.on('-L', '--all-links', "Display all links instead of only 10." ) do
894
+ max_links = 10000
895
+ end
896
+ opts.on('-H', '--all-history', "Display all history instead of only 10." ) do
897
+ max_history = 10000
898
+ end
899
+ build_common_options(opts, options, [:json, :dry_run, :remote])
900
+ opts.footer = "Get details about an archive file.\n" +
901
+ "[bucket:/path] is required. This is the name of the bucket and /path the file or folder to be fetched." + "\n" +
902
+ "[id] can be passed instead of [bucket:/path]. This is the numeric File ID."
903
+ end
904
+ optparse.parse!(args)
905
+ # consider only allowing args.count == 1 here in the format [bucket:/path]
906
+ if args.count != 1
907
+ print_error MtnCloud::Terminal.angry_prompt
908
+ puts_error "#{command_name} get-file expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
909
+ return 1
910
+ end
911
+ file_id = nil
912
+ bucket_id = nil
913
+ file_path = nil
914
+ # allow id in place of bucket:path
915
+ if args[0].to_s =~ /\A\d{1,}\Z/
916
+ file_id = args[0]
917
+ else
918
+ bucket_id, file_path = parse_bucket_id_and_file_path(args[0])
919
+ end
920
+
921
+ connect(options)
922
+ begin
923
+ # archive_bucket = find_archive_bucket_by_name_or_id(bucket_id)
924
+ # return 1 if archive_bucket.nil?
925
+ params = {}
926
+ @archive_buckets_interface.setopts(options)
927
+ @archive_files_interface.setopts(options)
928
+ if options[:dry_run]
929
+ if file_id
930
+ print_dry_run @archive_files_interface.dry.get(file_id, params)
931
+ else
932
+ print_dry_run @archive_buckets_interface.dry.list_files(bucket_id, file_path, params)
933
+ end
934
+ return 0
935
+ end
936
+ archive_file = nil
937
+ json_response = nil
938
+ if !file_id
939
+ archive_file = find_archive_file_by_bucket_and_path(bucket_id, file_path)
940
+ return 1 if archive_file.nil?
941
+ file_id = archive_file['id']
942
+ end
943
+ # archive_file = find_archive_file_by_id(file_id)
944
+ json_response = @archive_files_interface.get(file_id, params)
945
+ if options[:json]
946
+ puts as_json(json_response, options)
947
+ return 0
948
+ end
949
+ archive_file = json_response['archiveFile']
950
+ archive_logs = json_response['archiveLogs']
951
+ is_owner = json_response['isOwner']
952
+ if !bucket_id && archive_file["archiveBucket"]
953
+ bucket_id = archive_file["archiveBucket"]["name"]
954
+ end
955
+
956
+ print_h1 "Archive File Details"
957
+ print cyan
958
+ description_cols = {
959
+ "File ID" => 'id',
960
+ "Bucket" => lambda {|it| bucket_id },
961
+ "File Path" => lambda {|it| it['filePath'] },
962
+ "Type" => lambda {|it| it['isDirectory'] ? 'directory' : (it['contentType']) },
963
+ "Size" => lambda {|it| format_bytes(it['rawSize']) },
964
+ "Downloads" => lambda {|it| it['downloadCount'] },
965
+ "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
966
+ "Last Modified" => lambda {|it| format_local_dt(it['lastUpdated']) }
967
+ }
968
+ print_description_list(description_cols, archive_file)
969
+
970
+ # print "\n"
971
+
972
+
973
+ print_h2 "Download URLs"
974
+ private_download_url = "#{@appliance_url}/api/archives/download/#{CGI::escape(bucket_id)}" + "/#{escape_filepath(archive_file['filePath'])}".squeeze('/')
975
+ public_download_url = nil
976
+ if archive_file['archiveBucket'] && archive_file['archiveBucket']['isPublic']
977
+ public_download_url = "#{@appliance_url}/public-archives/download/#{CGI::escape(bucket_id)}" + "/#{escape_filepath(archive_file['filePath'])}".squeeze('/')
978
+ end
979
+ print cyan
980
+ puts "Private URL: #{private_download_url}"
981
+ if public_download_url
982
+ puts " Public URL: #{public_download_url}"
983
+ end
984
+
985
+ do_show_links = is_owner
986
+ if do_show_links
987
+ links_json_response = @archive_files_interface.list_links(archive_file['id'], {max: max_links})
988
+ archive_file_links = links_json_response['archiveFileLinks']
989
+ if archive_file_links && archive_file_links.size > 0
990
+ print_h2 "Links"
991
+ print_archive_file_links_table(archive_file_links)
992
+ print_results_pagination(links_json_response, {:label => "link", :n_label => "links"})
993
+ else
994
+ print_h2 "File Links"
995
+ puts "No links found"
996
+ end
997
+ end
998
+ # print "\n"
999
+ do_show_history = is_owner
1000
+ if do_show_history
1001
+ history_json_response = @archive_files_interface.history(archive_file['id'], {max: max_history})
1002
+ archive_logs = history_json_response['archiveLogs']
1003
+ print_h2 "History"
1004
+ if archive_logs && archive_logs.size > 0
1005
+ print_archive_logs_table(archive_logs, {exclude:[:bucket]})
1006
+ print_results_pagination(history_json_response, {:label => "history record", :n_label => "history records"})
1007
+ else
1008
+ puts "No history found"
1009
+ end
1010
+ end
1011
+ print reset,"\n"
1012
+ return 0
1013
+ rescue RestClient::Exception => e
1014
+ print_rest_exception(e, options)
1015
+ return 1
1016
+ end
1017
+ end
1018
+
1019
+ # Use upload file bucket:/path
1020
+ # def add_file(args)
1021
+ # raise "not yet implemented"
1022
+ # end
1023
+
1024
+ def remove_file(args)
1025
+ options = {}
1026
+ query_params = {}
1027
+ do_recursive = false
1028
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
1029
+ opts.banner = subcommand_usage("[bucket:/path]")
1030
+ opts.on( '-R', '--recursive', "Delete a directory and all of its files. This must be passed if specifying a directory." ) do
1031
+ do_recursive = true
1032
+ end
1033
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
1034
+ opts.footer = "Delete an archive file or directory."
1035
+ end
1036
+ optparse.parse!(args)
1037
+ # consider only allowing args.count == 1 here in the format [bucket:/path]
1038
+ if args.count != 1
1039
+ print_error MtnCloud::Terminal.angry_prompt
1040
+ puts_error "#{command_name} remove-file expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
1041
+ return 1
1042
+ end
1043
+ bucket_id, file_path = parse_bucket_id_and_file_path(args[0])
1044
+ connect(options)
1045
+ begin
1046
+
1047
+ archive_file = find_archive_file_by_bucket_and_path(bucket_id, file_path)
1048
+ return 1 if archive_file.nil?
1049
+ if archive_file['isDirectory']
1050
+ if !do_recursive
1051
+ print_error MtnCloud::Terminal.angry_prompt
1052
+ puts_error "bad argument: '#{file_path}' is a directory. Use -R or --recursive to delete a directory.\n#{optparse}"
1053
+ return 1
1054
+ end
1055
+ unless options[:yes] || MtnCloud::Cli::OptionTypes.confirm("Are you sure you want to delete the archive directory: #{args[0]}?")
1056
+ return 9, "aborted command"
1057
+ end
1058
+ else
1059
+ unless options[:yes] || MtnCloud::Cli::OptionTypes.confirm("Are you sure you want to delete the archive file: #{args[0]}?")
1060
+ return 9, "aborted command"
1061
+ end
1062
+ end
1063
+ @archive_files_interface.setopts(options)
1064
+ if options[:dry_run]
1065
+ print_dry_run @archive_files_interface.dry.destroy(archive_file['id'], query_params)
1066
+ return 0
1067
+ end
1068
+ json_response = @archive_files_interface.destroy(archive_file['id'], query_params)
1069
+ if options[:json]
1070
+ print JSON.pretty_generate(json_response)
1071
+ print "\n"
1072
+ else
1073
+ print_green_success "Removed archive file #{args[0]}"
1074
+ end
1075
+ return 0
1076
+
1077
+ rescue RestClient::Exception => e
1078
+ print_rest_exception(e, options)
1079
+ return 1
1080
+ end
1081
+
1082
+ end
1083
+
1084
+ def file_history(args)
1085
+ options = {}
1086
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
1087
+ opts.banner = subcommand_usage("[bucket:/path]")
1088
+ build_common_options(opts, options, [:list, :json, :dry_run, :remote])
1089
+ opts.footer = "List history log events for an archive file."
1090
+ end
1091
+ optparse.parse!(args)
1092
+ if args.count != 1
1093
+ print_error MtnCloud::Terminal.angry_prompt
1094
+ puts_error "#{command_name} file-history expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
1095
+ return 1
1096
+ end
1097
+ bucket_id, file_path = parse_bucket_id_and_file_path(args[0])
1098
+ connect(options)
1099
+ begin
1100
+ # todo: only 1 api call needed here.
1101
+ # archive_bucket = find_archive_bucket_by_name_or_id(bucket_id)
1102
+ # return 1 if archive_bucket.nil?
1103
+ archive_file = find_archive_file_by_bucket_and_path(bucket_id, file_path)
1104
+ return 1 if archive_file.nil?
1105
+ # ok, load history
1106
+ params = {}
1107
+ [:phrase, :offset, :max, :sort, :direction].each do |k|
1108
+ params[k] = options[k] unless options[k].nil?
1109
+ end
1110
+ @archive_files_interface.setopts(options)
1111
+ if options[:dry_run]
1112
+ print_dry_run @archive_files_interface.dry.history(archive_file['id'], params)
1113
+ return
1114
+ end
1115
+ json_response = @archive_files_interface.history(archive_file['id'], params)
1116
+ archive_logs = json_response['archiveLogs']
1117
+
1118
+ if options[:json]
1119
+ print JSON.pretty_generate(json_response)
1120
+ return
1121
+ end
1122
+
1123
+ print_h1 "Archive File History", ["#{bucket_id}:#{file_path}"]
1124
+ # print cyan
1125
+ # description_cols = {
1126
+ # "File ID" => 'id',
1127
+ # "Bucket" => lambda {|it| bucket_id },
1128
+ # "File Path" => lambda {|it| file_path }
1129
+ # }
1130
+ # print_description_list(description_cols, archive_file)
1131
+ # print "\n"
1132
+ # print_h2 "History"
1133
+ if archive_logs && archive_logs.size > 0
1134
+ print_archive_logs_table(archive_logs)
1135
+ print_results_pagination(json_response, {:label => "history record", :n_label => "history records"})
1136
+ else
1137
+ puts "No history found"
1138
+ end
1139
+ print reset,"\n"
1140
+ return 0
1141
+ rescue RestClient::Exception => e
1142
+ print_rest_exception(e, options)
1143
+ return 1
1144
+ end
1145
+ end
1146
+
1147
+ def file_links(args)
1148
+ options = {}
1149
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
1150
+ opts.banner = subcommand_usage("[bucket:/path]")
1151
+ build_common_options(opts, options, [:list, :json, :dry_run, :remote])
1152
+ opts.footer = "List links for an archive file."
1153
+ end
1154
+ optparse.parse!(args)
1155
+ if args.count != 1
1156
+ print_error MtnCloud::Terminal.angry_prompt
1157
+ puts_error "#{command_name} file-history expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
1158
+ return 1
1159
+ end
1160
+ bucket_id, file_path = parse_bucket_id_and_file_path(args[0])
1161
+ connect(options)
1162
+ begin
1163
+ # todo: only 1 api call needed here.
1164
+ # archive_bucket = find_archive_bucket_by_name_or_id(bucket_id)
1165
+ # return 1 if archive_bucket.nil?
1166
+ archive_file = find_archive_file_by_bucket_and_path(bucket_id, file_path)
1167
+ return 1 if archive_file.nil?
1168
+ # ok, load links
1169
+ params = {}
1170
+ [:phrase, :offset, :max, :sort, :direction].each do |k|
1171
+ params[k] = options[k] unless options[k].nil?
1172
+ end
1173
+ @archive_files_interface.setopts(options)
1174
+ if options[:dry_run]
1175
+ print_dry_run @archive_files_interface.dry.list_links(archive_file['id'], params)
1176
+ return
1177
+ end
1178
+ json_response = @archive_files_interface.list_links(archive_file['id'], params)
1179
+ archive_file_links = json_response['archiveFileLinks']
1180
+
1181
+ if options[:json]
1182
+ print JSON.pretty_generate(json_response)
1183
+ return
1184
+ end
1185
+
1186
+ print_h1 "Archive File Links", ["#{bucket_id}:#{file_path}"]
1187
+ # print_h1 "Archive File"
1188
+ # print cyan
1189
+ # description_cols = {
1190
+ # "File ID" => 'id',
1191
+ # "Bucket" => lambda {|it| bucket_id },
1192
+ # "File Path" => lambda {|it| file_path }
1193
+ # }
1194
+ # print_description_list(description_cols, archive_file)
1195
+ # print "\n"
1196
+ # print_h2 "Links"
1197
+ if archive_file_links && archive_file_links.size > 0
1198
+ print_archive_file_links_table(archive_file_links)
1199
+ print_results_pagination(json_response, {:label => "link", :n_label => "links"})
1200
+ else
1201
+ puts "No file links found"
1202
+ end
1203
+ print reset,"\n"
1204
+ return 0
1205
+ rescue RestClient::Exception => e
1206
+ print_rest_exception(e, options)
1207
+ return 1
1208
+ end
1209
+ end
1210
+
1211
+ def download_file(args)
1212
+ options = {}
1213
+ outfile = nil
1214
+ do_overwrite = false
1215
+ do_mkdir = false
1216
+ use_public_url = false
1217
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
1218
+ opts.banner = subcommand_usage("[bucket:/path] [local-file]")
1219
+ opts.on( '-f', '--force', "Overwrite existing [local-file] if it exists." ) do
1220
+ do_overwrite = true
1221
+ # do_mkdir = true
1222
+ end
1223
+ opts.on( '-p', '--mkdir', "Create missing directories for [local-file] if they do not exist." ) do
1224
+ do_mkdir = true
1225
+ end
1226
+ opts.on( '-p', '--public', "Use Public Download URL instead of Private. The file must be in a public archives." ) do
1227
+ use_public_url = true
1228
+ # do_mkdir = true
1229
+ end
1230
+ build_common_options(opts, options, [:dry_run, :quiet, :remote])
1231
+ opts.footer = "Download an archive file or directory.\n" +
1232
+ "[bucket:/path] is required. This is the name of the bucket and /path the file or folder to be downloaded.\n" +
1233
+ "[local-file] is required. This is the full local filepath for the downloaded file.\n" +
1234
+ "Directories will be downloaded as a .zip file, so you'll want to specify a [local-file] with a .zip extension."
1235
+ end
1236
+ optparse.parse!(args)
1237
+ if args.count != 2
1238
+ print_error MtnCloud::Terminal.angry_prompt
1239
+ puts_error "#{command_name} download expects 2 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
1240
+ return 1
1241
+ end
1242
+ connect(options)
1243
+ begin
1244
+ bucket_id, file_path = parse_bucket_id_and_file_path(args[0])
1245
+ # just make 1 api call for now
1246
+ # archive_file = find_archive_file_by_bucket_and_path(bucket_id, file_path)
1247
+ # return 1 if archive_file.nil?
1248
+ full_file_path = "#{bucket_id}/#{file_path}".squeeze('/')
1249
+ # full_file_path = args[0]
1250
+ # end download destination with a slash to use the local file basename
1251
+ outfile = args[1]
1252
+ # if outfile[-1] == "/" || outfile[-1] == "\\"
1253
+ # outfile = File.join(outfile, File.basename(full_file_path))
1254
+ # end
1255
+ outfile = File.expand_path(outfile)
1256
+ if Dir.exist?(outfile)
1257
+ outfile = File.join(outfile, File.basename(full_file_path))
1258
+ end
1259
+ if Dir.exist?(outfile)
1260
+ print_red_alert "[local-file] is invalid. It is the name of an existing directory: #{outfile}"
1261
+ return 1
1262
+ end
1263
+ destination_dir = File.dirname(outfile)
1264
+ if !Dir.exist?(destination_dir)
1265
+ if do_mkdir
1266
+ print cyan,"Creating local directory #{destination_dir}",reset,"\n"
1267
+ FileUtils.mkdir_p(destination_dir)
1268
+ else
1269
+ print_red_alert "[local-file] is invalid. Directory not found: #{destination_dir}"
1270
+ return 1
1271
+ end
1272
+ end
1273
+ if File.exist?(outfile)
1274
+ if do_overwrite
1275
+ # uhh need to be careful wih the passed filepath here..
1276
+ # don't delete, just overwrite.
1277
+ # File.delete(outfile)
1278
+ else
1279
+ print_error MtnCloud::Terminal.angry_prompt
1280
+ puts_error "[local-file] is invalid. File already exists: #{outfile}", "Use -f to overwrite the existing file."
1281
+ # puts_error optparse
1282
+ return 1
1283
+ end
1284
+ end
1285
+ begin
1286
+ @archive_files_interface.setopts(options)
1287
+ if options[:dry_run]
1288
+ if use_public_url
1289
+ print_dry_run @archive_files_interface.dry.download_public_file_by_path_chunked(full_file_path, outfile)
1290
+ else
1291
+ print_dry_run @archive_files_interface.dry.download_file_by_path_chunked(full_file_path, outfile)
1292
+ end
1293
+ return 0
1294
+ end
1295
+ if !options[:quiet]
1296
+ print cyan + "Downloading archive file #{bucket_id}:#{file_path} to #{outfile} ... "
1297
+ end
1298
+ # file_response = @archive_files_interface.download_file_by_path(full_file_path)
1299
+ # File.write(outfile, file_response.body)
1300
+ # err, maybe write to a random tmp file, then mv to outfile
1301
+ # currently, whatever the response is, it's written to the outfile. eg. 404 html
1302
+ http_response = nil
1303
+ if use_public_url
1304
+ http_response = @archive_files_interface.download_public_file_by_path_chunked(full_file_path, outfile)
1305
+ else
1306
+ http_response = @archive_files_interface.download_file_by_path_chunked(full_file_path, outfile)
1307
+ end
1308
+
1309
+ # FileUtils.chmod(0600, outfile)
1310
+ success = http_response.code.to_i == 200
1311
+ if success
1312
+ if !options[:quiet]
1313
+ print green + "SUCCESS" + reset + "\n"
1314
+ end
1315
+ return 0
1316
+ else
1317
+ if !options[:quiet]
1318
+ print red + "ERROR" + reset + " HTTP #{http_response.code}" + "\n"
1319
+ end
1320
+ # F it, just remove a bad result
1321
+ if File.exist?(outfile) && File.file?(outfile)
1322
+ MtnCloud::Logging::DarkPrinter.puts "Deleting bad file download: #{outfile}" if MtnCloud::Logging.debug?
1323
+ File.delete(outfile)
1324
+ end
1325
+ if options[:debug]
1326
+ puts_error http_response.inspect
1327
+ end
1328
+ return 1
1329
+ end
1330
+ rescue RestClient::Exception => e
1331
+ # this is not reached
1332
+ if e.response && e.response.code == 404
1333
+ print_red_alert "Archive file not found by path #{full_file_path}"
1334
+ return nil
1335
+ else
1336
+ raise e
1337
+ end
1338
+ end
1339
+ rescue RestClient::Exception => e
1340
+ print_rest_exception(e, options)
1341
+ return 1
1342
+ end
1343
+
1344
+ end
1345
+
1346
+ def read_file(args)
1347
+ options = {}
1348
+ outfile = nil
1349
+ do_overwrite = false
1350
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
1351
+ opts.banner = subcommand_usage("[bucket:/path]")
1352
+ build_common_options(opts, options, [:auto_confirm, :dry_run, :remote])
1353
+ opts.footer = "Print the contents of an archive file.\n" +
1354
+ "[bucket:/path] is required. This is the name of the bucket and /path the file or folder to be downloaded.\n" +
1355
+ "Confirmation is needed if the specified file is more than 1KB.\n" +
1356
+ "This confirmation can be skipped with the -y option."
1357
+ end
1358
+ optparse.parse!(args)
1359
+ if args.count != 1
1360
+ print_error MtnCloud::Terminal.angry_prompt
1361
+ puts_error "#{command_name} read expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
1362
+ return 1
1363
+ end
1364
+ connect(options)
1365
+ begin
1366
+ bucket_id, file_path = parse_bucket_id_and_file_path(args[0])
1367
+ archive_file = find_archive_file_by_bucket_and_path(bucket_id, file_path)
1368
+ return 1 if archive_file.nil?
1369
+ full_file_path = "#{bucket_id}/#{file_path}".squeeze('/')
1370
+ @archive_files_interface.setopts(options)
1371
+ if options[:dry_run]
1372
+ print_dry_run @archive_files_interface.dry.download_file_by_path(full_file_path)
1373
+ return 1
1374
+ end
1375
+ if archive_file['rawSize'].to_i > 1024
1376
+ pretty_size = format_bytes(archive_file['rawSize'])
1377
+ unless options[:yes] || MtnCloud::Cli::OptionTypes.confirm("Are you sure you want to print the contents of this file (#{pretty_size}) ?")
1378
+ return 9, "aborted command"
1379
+ end
1380
+ end
1381
+ file_response = @archive_files_interface.download_file_by_path(full_file_path)
1382
+ puts file_response.body.to_s
1383
+ return 0
1384
+ rescue RestClient::Exception => e
1385
+ print_rest_exception(e, options)
1386
+ return 1
1387
+ end
1388
+
1389
+ end
1390
+
1391
+ def add_file_link(args)
1392
+ options = {}
1393
+ expiration_seconds = 20*60 # default expiration is 20 minutes
1394
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
1395
+ opts.banner = subcommand_usage("[bucket:/path]")
1396
+ opts.on('-e', '--expire SECONDS', "The time to live for this link. The default is 1200 (20 minutes). A value less than 1 means never expire.") do |val|
1397
+ expiration_seconds = val.to_i
1398
+ end
1399
+ build_common_options(opts, options, [:json, :dry_run, :quiet, :remote])
1400
+ opts.footer = "Create a public link to a file.\n" +
1401
+ "[bucket:/path] is required. This is the name of the bucket and /path the file or folder to be fetched."
1402
+ end
1403
+ optparse.parse!(args)
1404
+ # consider only allowing args.count == 1 here in the format [bucket:/path]
1405
+ if args.count != 1
1406
+ print_error MtnCloud::Terminal.angry_prompt
1407
+ puts_error "#{command_name} add-file-link expects 1 argument and received #{args.count}: #{args.join(' ')}\n#{optparse}"
1408
+ return 1
1409
+ end
1410
+ bucket_id, file_path = parse_bucket_id_and_file_path(args[0])
1411
+ connect(options)
1412
+ begin
1413
+ archive_file = find_archive_file_by_bucket_and_path(bucket_id, file_path)
1414
+ return 1 if archive_file.nil?
1415
+
1416
+ params = {}
1417
+ if expiration_seconds.to_i > 0
1418
+ params['expireSeconds'] = expiration_seconds.to_i
1419
+ end
1420
+ @archive_files_interface.setopts(options)
1421
+ if options[:dry_run]
1422
+ print_dry_run @archive_files_interface.dry.create_file_link(archive_file['id'], params)
1423
+ return
1424
+ end
1425
+ json_response = @archive_files_interface.create_file_link(archive_file['id'], params)
1426
+
1427
+ if options[:json]
1428
+ print JSON.pretty_generate(json_response)
1429
+ return 0
1430
+ elsif !options[:quiet]
1431
+ print_green_success "Created archive file link #{bucket_id}:/#{archive_file['filePath']} token: #{json_response['secretAccessKey']}"
1432
+ end
1433
+ return 0
1434
+ rescue RestClient::Exception => e
1435
+ print_rest_exception(e, options)
1436
+ return 1
1437
+ end
1438
+ end
1439
+
1440
+ def remove_file_link(args)
1441
+ options = {}
1442
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
1443
+ opts.banner = subcommand_usage("[bucket:/path] [token]")
1444
+ build_common_options(opts, options, [:auto_confirm, :dry_run, :quiet, :remote])
1445
+ opts.footer = "Delete a public link to a file.\n" +
1446
+ "[bucket:/path] is required. This is the name of the bucket and /path the file or folder to be fetched." +
1447
+ "[token] is required. This is the secret access key that identifies the link."
1448
+ end
1449
+ optparse.parse!(args)
1450
+ # consider only allowing args.count == 1 here in the format [bucket:/path]
1451
+ if args.count != 2
1452
+ print_error MtnCloud::Terminal.angry_prompt
1453
+ puts_error "#{command_name} remove-file-link expects 2 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
1454
+ return 1
1455
+ end
1456
+ bucket_id, file_path = parse_bucket_id_and_file_path(args[0])
1457
+ connect(options)
1458
+ begin
1459
+ archive_file = find_archive_file_by_bucket_and_path(bucket_id, file_path)
1460
+ return 1 if archive_file.nil?
1461
+ link_id = nil
1462
+ secret_access_key = args[1]
1463
+ secret_access_key = secret_access_key.sub('/public-archives/link?s=', '')
1464
+ # find the int id via token...
1465
+ links_json_response = @archive_files_interface.list_links(archive_file['id'], {s: secret_access_key})
1466
+ if links_json_response['archiveFileLinks'] && links_json_response['archiveFileLinks'][0]
1467
+ link_id = links_json_response['archiveFileLinks'][0]['id']
1468
+ end
1469
+ if !link_id
1470
+ print_red_alert "Archive file link not found for #{bucket_id}:/#{archive_file['filePath']} token: #{secret_access_key}"
1471
+ return 1
1472
+ end
1473
+ params = {}
1474
+ @archive_files_interface.setopts(options)
1475
+ if options[:dry_run]
1476
+ print_dry_run @archive_files_interface.dry.destroy_file_link(archive_file['id'], link_id, params)
1477
+ return
1478
+ end
1479
+ json_response = @archive_files_interface.destroy_file_link(archive_file['id'], link_id, params)
1480
+
1481
+ if options[:json]
1482
+ print JSON.pretty_generate(json_response)
1483
+ return 0
1484
+ elsif !options[:quiet]
1485
+ print_green_success "Deleted archive file link #{bucket_id}:/#{archive_file['filePath']} token: #{secret_access_key}"
1486
+ end
1487
+ return 0
1488
+ rescue RestClient::Exception => e
1489
+ print_rest_exception(e, options)
1490
+ return 1
1491
+ end
1492
+ end
1493
+
1494
+ def download_file_link(args)
1495
+ options = {}
1496
+ outfile = nil
1497
+ do_overwrite = false
1498
+ dor_mkdir = false
1499
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
1500
+ opts.banner = subcommand_usage("[link-key] [local-file]")
1501
+ opts.on( '-f', '--force', "Overwrite existing [local-file] if it exists." ) do
1502
+ do_overwrite = true
1503
+ # do_mkdir = true
1504
+ end
1505
+ opts.on( '-p', '--mkdir', "Create missing directories for [local-file] if they do not exist." ) do
1506
+ do_mkdir = true
1507
+ end
1508
+ build_common_options(opts, options, [:dry_run, :quiet, :remote])
1509
+ opts.footer = "Download an archive file link.\n" +
1510
+ "[link-key] is required. This is the secret access key for the archive file link.\n" +
1511
+ "[local-file] is required. This is the full local filepath for the downloaded file."
1512
+ end
1513
+ optparse.parse!(args)
1514
+ if args.count != 2
1515
+ print_error MtnCloud::Terminal.angry_prompt
1516
+ puts_error "#{command_name} download-link expects 2 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
1517
+ return 1
1518
+ end
1519
+ connect(options)
1520
+ begin
1521
+ link_key = args[0]
1522
+ # archive_file_link = find_archive_file_link_by_key(link_key)
1523
+ # just make 1 api call for now
1524
+ # archive_file = find_archive_file_by_bucket_and_path(bucket_id, file_path)
1525
+ # return 1 if archive_file.nil?
1526
+ full_file_path = "#{bucket_id}/#{file_path}".squeeze('/')
1527
+ # full_file_path = args[0]
1528
+ outfile = File.expand_path(args[1])
1529
+ # [local-file] must include the full file name when downloading a link
1530
+ # if Dir.exist?(outfile)
1531
+ # outfile = File.join(outfile, File.basename(archive_file['name']))
1532
+ # end
1533
+ if Dir.exist?(outfile)
1534
+ print_red_alert "[local-file] is invalid. It is the name of an existing directory: #{outfile}"
1535
+ return 1
1536
+ end
1537
+ destination_dir = File.dirname(outfile)
1538
+ if !Dir.exist?(destination_dir)
1539
+ if do_mkdir
1540
+ print cyan,"Creating local directory #{destination_dir}",reset,"\n"
1541
+ FileUtils.mkdir_p(destination_dir)
1542
+ else
1543
+ print_red_alert "[local-file] is invalid. Directory not found: #{destination_dir}"
1544
+ return 1
1545
+ end
1546
+ end
1547
+ if File.exist?(outfile)
1548
+ if do_overwrite
1549
+ # uhh need to be careful wih the passed filepath here..
1550
+ # don't delete, just overwrite.
1551
+ # File.delete(outfile)
1552
+ else
1553
+ print_red_alert "[local-file] is invalid. File already exists: #{outfile}"
1554
+ # print_error MtnCloud::Terminal.angry_prompt
1555
+ # puts_error "[local-file] is invalid. File already exists: #{outfile}\n#{optparse}"
1556
+ puts_error "Use -f to overwrite the existing file."
1557
+ # puts_error optparse
1558
+ return 1
1559
+ end
1560
+ end
1561
+ @archive_files_interface.setopts(options)
1562
+ if options[:dry_run]
1563
+ print_dry_run @archive_files_interface.dry.download_file_by_link_chunked(link_key, outfile)
1564
+ return 1
1565
+ end
1566
+ if !options[:quiet]
1567
+ print cyan + "Downloading archive file link #{link_key} to #{outfile} ... "
1568
+ end
1569
+ # file_response = @archive_files_interface.download_file_by_path(full_file_path)
1570
+ # File.write(outfile, file_response.body)
1571
+ # err, maybe write to a random tmp file, then mv to outfile
1572
+ # currently, whatever the response is, it's written to the outfile. eg. 404 html
1573
+ http_response = @archive_files_interface.download_file_by_link_chunked(link_key, outfile)
1574
+
1575
+ # FileUtils.chmod(0600, outfile)
1576
+ success = http_response.code.to_i == 200
1577
+ if success
1578
+ if !options[:quiet]
1579
+ print green + "SUCCESS" + reset + "\n"
1580
+ end
1581
+ return 0
1582
+ else
1583
+ if !options[:quiet]
1584
+ print red + "ERROR" + reset + " HTTP #{http_response.code}" + "\n"
1585
+ end
1586
+ # F it, just remove a bad result
1587
+ if File.exist?(outfile) && File.file?(outfile)
1588
+ MtnCloud::Logging::DarkPrinter.puts "Deleting bad file download: #{outfile}" if MtnCloud::Logging.debug?
1589
+ File.delete(outfile)
1590
+ end
1591
+ if options[:debug]
1592
+ puts_error http_response.inspect
1593
+ end
1594
+ return 1
1595
+ end
1596
+ rescue RestClient::Exception => e
1597
+ print_rest_exception(e, options)
1598
+ return 1
1599
+ end
1600
+
1601
+ end
1602
+
1603
+ def download_bucket_zip(args)
1604
+ options = {}
1605
+ outfile = nil
1606
+ do_overwrite = false
1607
+ do_mkdir = false
1608
+ use_public_url = false
1609
+ optparse = MtnCloud::Cli::OptionParser.new do |opts|
1610
+ opts.banner = subcommand_usage("[bucket] [local-file]")
1611
+ opts.on( '-f', '--force', "Overwrite existing [local-file] if it exists." ) do
1612
+ do_overwrite = true
1613
+ # do_mkdir = true
1614
+ end
1615
+ opts.on( '-p', '--mkdir', "Create missing directories for [local-file] if they do not exist." ) do
1616
+ do_mkdir = true
1617
+ end
1618
+ # api endpoint needed still for public bucket.zip
1619
+ # opts.on( '-p', '--public', "Use Public Download URL instead of Private. The bucket must be have Public URL enabled." ) do
1620
+ # use_public_url = true
1621
+ # # do_mkdir = true
1622
+ # end
1623
+ build_common_options(opts, options, [:dry_run, :quiet, :remote])
1624
+ opts.footer = "Download an entire archive bucket as a .zip file.\n" +
1625
+ "[bucket] is required. This is the name of the bucket.\n" +
1626
+ "[local-file] is required. This is the full local filepath for the downloaded file.\n" +
1627
+ "Buckets are be downloaded as a .zip file, so you'll want to specify a [local-file] with a .zip extension."
1628
+ end
1629
+ optparse.parse!(args)
1630
+ if args.count != 2
1631
+ print_error MtnCloud::Terminal.angry_prompt
1632
+ puts_error "#{command_name} download-bucket expects 2 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
1633
+ return 1
1634
+ end
1635
+ connect(options)
1636
+ begin
1637
+ bucket_id = args[0].to_s
1638
+ archive_bucket = find_archive_bucket_by_name_or_id(bucket_id)
1639
+ return 1 if archive_bucket.nil?
1640
+
1641
+ outfile = args[1]
1642
+ # if outfile[-1] == "/" || outfile[-1] == "\\"
1643
+ # outfile = File.join(outfile, archive_bucket['name'].to_s) + ".zip"
1644
+ # end
1645
+ outfile = File.expand_path(outfile)
1646
+ if Dir.exist?(outfile)
1647
+ outfile = File.join(outfile, archive_bucket['name'].to_s) + ".zip"
1648
+ end
1649
+ if Dir.exist?(outfile)
1650
+ print_red_alert "[local-file] is invalid. It is the name of an existing directory: #{outfile}"
1651
+ return 1
1652
+ end
1653
+ # always a .zip
1654
+ if outfile[-4..-1] != ".zip"
1655
+ outfile << ".zip"
1656
+ end
1657
+ destination_dir = File.dirname(outfile)
1658
+ if !Dir.exist?(destination_dir)
1659
+ if do_mkdir
1660
+ print cyan,"Creating local directory #{destination_dir}",reset,"\n"
1661
+ FileUtils.mkdir_p(destination_dir)
1662
+ else
1663
+ print_red_alert "[local-file] is invalid. Directory not found: #{destination_dir}"
1664
+ return 1
1665
+ end
1666
+ end
1667
+ if File.exist?(outfile)
1668
+ if do_overwrite
1669
+ # uhh need to be careful wih the passed filepath here..
1670
+ # don't delete, just overwrite.
1671
+ # File.delete(outfile)
1672
+ else
1673
+ print_error MtnCloud::Terminal.angry_prompt
1674
+ puts_error "[local-file] is invalid. File already exists: #{outfile}", "Use -f to overwrite the existing file."
1675
+ # puts_error optparse
1676
+ return 1
1677
+ end
1678
+ end
1679
+ @archive_buckets_interface.setopts(options)
1680
+ if options[:dry_run]
1681
+ print_dry_run @archive_buckets_interface.dry.download_bucket_zip_chunked(bucket_id, outfile)
1682
+ return 1
1683
+ end
1684
+ if !options[:quiet]
1685
+ print cyan + "Downloading archive bucket #{bucket_id} to #{outfile} ... "
1686
+ end
1687
+
1688
+ http_response = @archive_buckets_interface.download_bucket_zip_chunked(bucket_id, outfile)
1689
+
1690
+ # FileUtils.chmod(0600, outfile)
1691
+ success = http_response.code.to_i == 200
1692
+ if success
1693
+ if !options[:quiet]
1694
+ print green + "SUCCESS" + reset + "\n"
1695
+ end
1696
+ return 0
1697
+ else
1698
+ if !options[:quiet]
1699
+ print red + "ERROR" + reset + " HTTP #{http_response.code}" + "\n"
1700
+ end
1701
+ # F it, just remove a bad result
1702
+ if File.exist?(outfile) && File.file?(outfile)
1703
+ MtnCloud::Logging::DarkPrinter.puts "Deleting bad file download: #{outfile}" if MtnCloud::Logging.debug?
1704
+ File.delete(outfile)
1705
+ end
1706
+ if options[:debug]
1707
+ puts_error http_response.inspect
1708
+ end
1709
+ return 1
1710
+ end
1711
+
1712
+ rescue RestClient::Exception => e
1713
+ print_rest_exception(e, options)
1714
+ return 1
1715
+ end
1716
+ end
1717
+
1718
+
1719
+ private
1720
+
1721
+ def find_archive_bucket_by_name_or_id(val)
1722
+ return find_archive_bucket_by_id(val)
1723
+ # if val.to_s =~ /\A\d{1,}\Z/
1724
+ # return find_archive_bucket_by_id(val)
1725
+ # else
1726
+ # return find_archive_bucket_by_name(val)
1727
+ # end
1728
+ end
1729
+
1730
+ def find_archive_bucket_by_id(id)
1731
+ begin
1732
+ # this is typically passed as name, the api supports either name or id
1733
+ json_response = @archive_buckets_interface.get(id.to_s)
1734
+ archive_bucket = json_response['archiveBucket']
1735
+ archive_bucket['isOwner'] = !!json_response['isOwner']
1736
+ return archive_bucket
1737
+ rescue RestClient::Exception => e
1738
+ if e.response && e.response.code == 404
1739
+ print_red_alert "Archive bucket not found by id #{id}"
1740
+ return nil
1741
+ else
1742
+ raise e
1743
+ end
1744
+ end
1745
+ end
1746
+
1747
+ def find_archive_bucket_by_name(name)
1748
+ archive_buckets = @archive_buckets_interface.list({name: name.to_s})['archiveBuckets']
1749
+ if archive_buckets.empty?
1750
+ print_red_alert "Archive bucket not found by name #{name}"
1751
+ return nil
1752
+ elsif archive_buckets.size > 1
1753
+ print_red_alert "#{archive_buckets.size} archive buckets found by name #{name}"
1754
+ # print_archive_buckets_table(archive_buckets, {color: red})
1755
+ rows = archive_buckets.collect do |it|
1756
+ {id: it['id'], name: it['name']}
1757
+ end
1758
+ puts as_pretty_table(rows, [:id, :name], {color:red})
1759
+ return nil
1760
+ else
1761
+ return archive_buckets[0]
1762
+ end
1763
+ end
1764
+
1765
+ def find_archive_file_by_id(id)
1766
+ begin
1767
+ json_response = @archive_files_interface.get(id.to_s)
1768
+ return json_response['archiveFile']
1769
+ rescue RestClient::Exception => e
1770
+ if e.response && e.response.code == 404
1771
+ print_red_alert "Archive file not found by id #{id}"
1772
+ return nil
1773
+ else
1774
+ raise e
1775
+ end
1776
+ end
1777
+ end
1778
+
1779
+ def find_archive_file_by_bucket_and_path(bucket_id, file_path)
1780
+ if file_path.to_s.empty? || file_path.to_s.strip == "/"
1781
+ print_red_alert "Archive file not found for bucket: '#{bucket_id}' file: (blank)"
1782
+ return nil
1783
+ end
1784
+ # chomp leading and trailing slashes, the api isn't doin this right now.
1785
+ if file_path.size > 1 && file_path[-1] == "/"
1786
+ file_path = file_path[0..-2]
1787
+ end
1788
+ if file_path[0] && file_path[0].chr == "/"
1789
+ file_path = file_path[1..-1]
1790
+ end
1791
+ # ok, find the file id by searching /archives/buckets/$bucketId/files/$filePath
1792
+ json_response = @archive_buckets_interface.list_files(bucket_id, file_path)
1793
+ # json_response = @archive_buckets_interface.list_files(bucket_id, "/", {phrase: file_path})
1794
+ # json_response = @archive_buckets_interface.list_files(bucket_id, "/", {absoluteFilePath: file_path})
1795
+ # puts "find_archive_file() json_response is: ", JSON.pretty_generate(json_response)
1796
+ archive_file = nil
1797
+ archive_files = json_response['archiveFiles']
1798
+ # silly hack, not needed while using ?absoluteFilePath=
1799
+ if json_response['parentDirectory'] && json_response['parentDirectory']['filePath'] == file_path
1800
+ archive_file = json_response['parentDirectory']
1801
+ else
1802
+ archive_file = archive_files[0]
1803
+ end
1804
+ if archive_file.nil?
1805
+ print_red_alert "Archive file not found for bucket: '#{bucket_id}' file: '#{file_path}'"
1806
+ return nil
1807
+ end
1808
+ return archive_file
1809
+ end
1810
+
1811
+ def format_archive_bucket_full_status(archive_bucket, return_color=cyan)
1812
+ out = ""
1813
+ if archive_bucket['lastResult']
1814
+ out << format_archive_bucket_execution_status(archive_bucket['lastResult'])
1815
+ else
1816
+ out << ""
1817
+ end
1818
+ out
1819
+ end
1820
+
1821
+ def format_archive_bucket_status(archive_bucket, return_color=cyan)
1822
+ out = ""
1823
+ if archive_bucket['lastResult']
1824
+ out << format_archive_bucket_execution_status(archive_bucket['lastResult'])
1825
+ else
1826
+ out << ""
1827
+ end
1828
+ out
1829
+ end
1830
+
1831
+ def format_archive_bucket_execution_status(archive_bucket_execution, return_color=cyan)
1832
+ out = ""
1833
+ status_string = archive_bucket_execution['status']
1834
+ if status_string == 'running'
1835
+ out << "#{green}#{status_string.upcase}#{return_color}"
1836
+ elsif status_string == 'success'
1837
+ out << "#{green}#{status_string.upcase}#{return_color}"
1838
+ elsif status_string == 'failed'
1839
+ out << "#{red}#{status_string.upcase}#{return_color}"
1840
+ elsif status_string == 'pending'
1841
+ out << "#{white}#{status_string.upcase}#{return_color}"
1842
+ elsif status_string
1843
+ out << "#{yellow}#{status_string.upcase}#{return_color}"
1844
+ else
1845
+ out << ""
1846
+ end
1847
+ out
1848
+ end
1849
+
1850
+ def format_archive_bucket_execution_result(archive_bucket_execution, return_color=cyan)
1851
+ out = ""
1852
+ status_string = archive_bucket_execution['status']
1853
+ if status_string == 'running' # || status_string == 'pending'
1854
+ out << generate_usage_bar(archive_bucket_execution['statusPercent'], 100, {max_bars: 10})
1855
+ out << return_color if return_color
1856
+ out << " - #{archive_bucket_execution['statusMessage']}"
1857
+ elsif archive_bucket_execution['statusMessage']
1858
+ out << "#{archive_bucket_execution['statusMessage']}"
1859
+ end
1860
+ if archive_bucket_execution['errorMessage']
1861
+ out << " - #{red}#{archive_bucket_execution['errorMessage']}#{return_color}"
1862
+ end
1863
+ out
1864
+ end
1865
+
1866
+ # def get_available_boot_scripts()
1867
+ # boot_scripts_dropdown = []
1868
+ # scripts = @boot_scripts_interface.list({max:1000})['bootScripts']
1869
+ # scripts.each do |it|
1870
+ # boot_scripts_dropdown << {'name'=>it['fileName'],'value'=>it['id']}
1871
+ # end
1872
+ # boot_scripts_dropdown << {'name'=>'Custom','value'=> 'custom'}
1873
+ # return boot_scripts_dropdown
1874
+ # end
1875
+
1876
+ def get_available_boot_scripts(refresh=false)
1877
+ if !@available_boot_scripts || refresh
1878
+ # option_results = options_interface.options_for_source('bootScripts',{})['data']
1879
+ boot_scripts_dropdown = []
1880
+ scripts = @boot_scripts_interface.list({max:1000})['bootScripts']
1881
+ scripts.each do |it|
1882
+ boot_scripts_dropdown << {'name'=>it['fileName'],'value'=>it['id'],'id'=>it['id']}
1883
+ end
1884
+ boot_scripts_dropdown << {'name'=>'Custom','value'=> 'custom','id'=> 'custom'}
1885
+ @available_boot_scripts = boot_scripts_dropdown
1886
+ end
1887
+ #puts "available_boot_scripts() rtn: #{@available_boot_scripts.inspect}"
1888
+ return @available_boot_scripts
1889
+ end
1890
+
1891
+ def find_boot_script(val)
1892
+ if val.nil? || val.to_s.empty?
1893
+ return nil
1894
+ else
1895
+ return get_available_boot_scripts().find { |it|
1896
+ (it['id'].to_s.downcase == val.to_s.downcase) ||
1897
+ (it['name'].to_s.downcase == val.to_s.downcase)
1898
+ }
1899
+ end
1900
+ end
1901
+
1902
+ def get_available_preseed_scripts(refresh=false)
1903
+ if !@available_preseed_scripts || refresh
1904
+ # option_results = options_interface.options_for_source('preseedScripts',{})['data']
1905
+ preseed_scripts_dropdown = []
1906
+ scripts = @preseed_scripts_interface.list({max:1000})['preseedScripts']
1907
+ scripts.each do |it|
1908
+ preseed_scripts_dropdown << {'name'=>it['fileName'],'value'=>it['id'],'id'=>it['id']}
1909
+ end
1910
+ # preseed_scripts_dropdown << {'name'=>'Custom','value'=> 'custom','value'=> 'custom'}
1911
+ @available_preseed_scripts = preseed_scripts_dropdown
1912
+ end
1913
+ #puts "available_preseed_scripts() rtn: #{@available_preseed_scripts.inspect}"
1914
+ return @available_preseed_scripts
1915
+ end
1916
+
1917
+ def find_preseed_script(val)
1918
+ if val.nil? || val.to_s.empty?
1919
+ return nil
1920
+ else
1921
+ return get_available_preseed_scripts().find { |it|
1922
+ (it['id'].to_s.downcase == val.to_s.downcase) ||
1923
+ (it['name'].to_s.downcase == val.to_s.downcase)
1924
+ }
1925
+ end
1926
+ end
1927
+
1928
+ def prompt_edit_archive_bucket(archive_bucket, options={})
1929
+ # populate default prompt values with the existing archive bucket
1930
+ default_values = archive_bucket.dup # lazy, but works as long as GET matches POST api structure
1931
+ # storage provider (cannot be edited anyhow..)
1932
+ if archive_bucket['storageProvider'].kind_of?(Hash)
1933
+ default_values['storageProvider'] = archive_bucket['storageProvider']['id']
1934
+ end
1935
+ # tenants
1936
+ if archive_bucket['accounts'].kind_of?(Array) && archive_bucket['accounts'].size > 0
1937
+ default_values['accounts'] = archive_bucket['accounts'].collect {|it| it['name'] }.join(", ")
1938
+ end
1939
+ # any other mismatches? preseedScript, bootScript?
1940
+ options[:is_edit] = true
1941
+ return prompt_new_archive_bucket(options, default_values)
1942
+ end
1943
+
1944
+ def prompt_new_archive_bucket(options={}, default_values={})
1945
+ payload = {}
1946
+
1947
+ # Name
1948
+ if options['name']
1949
+ payload['name'] = options['name']
1950
+ else
1951
+ v_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Enter a name for this archive bucket.', 'defaultValue' => default_values['name']}], options, @api_client)
1952
+ payload['name'] = v_prompt['name']
1953
+ end
1954
+
1955
+ # Description
1956
+ if options['description']
1957
+ payload['description'] = options['description']
1958
+ else
1959
+ v_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'defaultValue' => default_values['description']}], options, @api_client)
1960
+ payload['description'] = v_prompt['description']
1961
+ end
1962
+
1963
+ # Storage Provider
1964
+ unless options[:is_edit]
1965
+ if options['storageProvider']
1966
+ # payload['storageProvider'] = options['storageProvider']
1967
+ # prompt is skipped when options['fieldName'] is passed in, this will return an id from a name
1968
+ v_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'storageProvider', 'fieldLabel' => 'Storage Provider', 'type' => 'select', 'optionSource' => 'storageProviders', 'description' => 'Storage Provider', 'defaultValue' => options['storageProvider'], 'required' => true}], options, @api_client, {})
1969
+ payload['storageProvider'] = {id: v_prompt['storageProvider']}
1970
+ else
1971
+ v_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'storageProvider', 'fieldLabel' => 'Storage Provider', 'type' => 'select', 'optionSource' => 'storageProviders', 'description' => 'Storage Provider', 'defaultValue' => default_values['storageProvider'], 'required' => true}], options, @api_client, {})
1972
+ payload['storageProvider'] = {id: v_prompt['storageProvider']}
1973
+ end
1974
+ end
1975
+
1976
+ # Tenants
1977
+ # TODO: a nice select component for adding/removing from this array
1978
+ if options['accounts']
1979
+ payload['accounts'] = options['accounts'] #.to_s.split(",").collect {|it| it.to_s.strip }.select {|it| it }.compact
1980
+ else
1981
+ tenants_default_value = default_values['accounts']
1982
+ if tenants_default_value.kind_of?(Array)
1983
+ tenants_default_value = tenants_default_value.collect {|it| it["id"] }.join(", ")
1984
+ end
1985
+ v_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'accounts', 'fieldLabel' => 'Tenants', 'type' => 'text', 'description' => 'Tenant Accounts (comma separated ids)', 'defaultValue' => tenants_default_value}], options, @api_client)
1986
+ payload['accounts'] = v_prompt['accounts'].to_s.split(",").collect {|it| it.to_s.strip }.select {|it| it }.compact
1987
+ end
1988
+
1989
+ # Visibility
1990
+ if options['visibility']
1991
+ payload['visibility'] = options['visibility']
1992
+ else
1993
+ v_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'selectOptions' => [{'name' => 'Private', 'value' => 'private'}, {'name' => 'Public', 'value' => 'public'}], 'defaultValue' => (default_values['visibility'] || 'private'), 'required' => true}], options, @api_client, {})
1994
+ payload['visibility'] = v_prompt['visibility']
1995
+ end
1996
+
1997
+ # Public URL
1998
+ if options['isPublic']
1999
+ payload['isPublic'] = options['isPublic']
2000
+ else
2001
+ v_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'isPublic', 'fieldLabel' => 'Public URL', 'type' => 'checkbox', 'description' => 'Enabling Public URL allows files to be downloaded without any authentication.', 'defaultValue' => (default_values['isPublic'].nil? ? false : default_values['isPublic']), 'required' => true}], options, @api_client, {})
2002
+ payload['isPublic'] = v_prompt['isPublic']
2003
+ end
2004
+
2005
+ return payload
2006
+ end
2007
+
2008
+ def print_archive_files_table(archive_files, options={})
2009
+ table_color = options[:color] || cyan
2010
+ rows = archive_files.collect do |archive_file|
2011
+ {
2012
+ id: archive_file['id'],
2013
+ name: options[:fullTree] ? archive_file['filePath'] : archive_file['name'],
2014
+ type: archive_file['isDirectory'] ? 'directory' : (archive_file['contentType']),
2015
+ size: format_bytes(archive_file['rawSize']),
2016
+ dateCreated: format_local_dt(archive_file['dateCreated']),
2017
+ lastUpdated: format_local_dt(archive_file['lastUpdated'])
2018
+ }
2019
+ end
2020
+ columns = [
2021
+ # :id,
2022
+ {:name => {:display_name => "File".upcase} },
2023
+ :type,
2024
+ :size,
2025
+ # {:dateCreated => {:display_name => "Date Created"} },
2026
+ {:lastUpdated => {:display_name => "Last Modified".upcase} }
2027
+ ]
2028
+ print table_color
2029
+ print as_pretty_table(rows, columns, options)
2030
+ print reset
2031
+ end
2032
+
2033
+ def print_archive_logs_table(archive_logs, opts={})
2034
+ table_color = opts[:color] || cyan
2035
+ rows = archive_logs.collect do |archive_log|
2036
+ response_str = ""
2037
+ if archive_log['responseCode']
2038
+ if archive_log['responseCode'].to_i == 200
2039
+ response_str = "#{green}#{archive_log['responseCode']} #{archive_log['responseMessage']}".strip + table_color
2040
+ else
2041
+ response_str = "#{red}#{archive_log['responseCode']}#{reset} #{archive_log['responseMessage']}".strip + table_color
2042
+ end
2043
+ end
2044
+ if archive_log['fileSize'] && archive_log['fileSize'].to_i > 0
2045
+ response_str << " (#{format_bytes(archive_log['fileSize'])})"
2046
+ end
2047
+ request_str = "#{archive_log['requestUrl']}".strip
2048
+ # if archive_log['archiveFileLink']
2049
+ # request_str << " [Link #{archive_log['archiveFileLink']['shortKey']}]"
2050
+ # end
2051
+ {
2052
+ id: archive_log['id'],
2053
+ eventType: archive_log['eventType'] ? archive_log['eventType'] : '',
2054
+ bucket: archive_log['archiveBucket'] ? archive_log['archiveBucket']['name'] : '',
2055
+ file: archive_log['archiveFile'] ? archive_log['archiveFile']['filePath'] : '',
2056
+ link: archive_log['archiveFileLink'] ? archive_log['archiveFileLink']['shortKey'] : '',
2057
+ description: archive_log['description'] ? archive_log['description'] : '',
2058
+ fileSize: format_bytes(archive_log['fileSize']),
2059
+ dateCreated: format_local_dt(archive_log['dateCreated']),
2060
+ user: archive_log['user'] ? archive_log['user']['username'] : '',
2061
+ webInterface: archive_log['webInterface'],
2062
+ #request: request_str,
2063
+ response: response_str
2064
+ }
2065
+ end
2066
+ columns = [
2067
+ {:dateCreated => {:display_name => "Date".upcase} },
2068
+ {:eventType => {:display_name => "Event".upcase} },
2069
+ :bucket,
2070
+ :file,
2071
+ :link,
2072
+ # :fileSize,
2073
+ :description,
2074
+ :user,
2075
+ {:webInterface => {:display_name => "Interface".upcase} },
2076
+ #:request,
2077
+ :response
2078
+ ]
2079
+ if opts[:exclude]
2080
+ columns = columns.reject {|c|
2081
+ c.is_a?(Hash) ? opts[:exclude].include?(c.keys[0]) : opts[:exclude].include?(c)
2082
+ }
2083
+ end
2084
+ print table_color
2085
+ print as_pretty_table(rows, columns, opts)
2086
+ print reset
2087
+ end
2088
+
2089
+ def print_archive_file_links_table(archive_file_links, opts={})
2090
+ table_color = opts[:color] || cyan
2091
+ rows = archive_file_links.collect do |archive_file_link|
2092
+ status_str = ""
2093
+ begin
2094
+ if archive_file_link['expirationDate'] && Time.now.utc > parse_time(archive_file_link['expirationDate'])
2095
+ status_str = red + "EXPIRED" + table_color
2096
+ else
2097
+ status_str = green + "ACTIVE" + table_color
2098
+ end
2099
+ rescue => ex
2100
+ MtnCloud::Logging::DarkPrinter.puts "trouble parsing expiration date: #{ex.inspect}" if MtnCloud::Logging.debug?
2101
+ end
2102
+ link_url = "/public-archives/link?s=" + archive_file_link['secretAccessKey'].to_s
2103
+ {
2104
+ url: link_url,
2105
+ created: format_local_dt(archive_file_link['dateCreated']),
2106
+ expires: archive_file_link['expirationDate'] ? format_local_dt(archive_file_link['expirationDate']) : 'Never',
2107
+ downloads: archive_file_link['downloadCount'],
2108
+ status: status_str
2109
+ }
2110
+ end
2111
+ columns = [
2112
+ {:url => {:display_name => "Link URL".upcase} },
2113
+ :created,
2114
+ :expires,
2115
+ :downloads,
2116
+ :status
2117
+ ]
2118
+ print table_color
2119
+ print as_pretty_table(rows, columns, opts)
2120
+ print reset
2121
+ end
2122
+
2123
+ # parse_bucket_id_and_file_path() provides flexible argument formats for bucket and path
2124
+ # it looks for [bucket:/path] or [bucket] [path]
2125
+ # @param delim [String] Default is a comma and any surrounding white space.
2126
+ # @return [Array] 2 elements, bucket name (or id) and the file path.
2127
+ # The default file path is "/".
2128
+ # Examples:
2129
+ # parse_bucket_id_and_file_path("test") == ["test", "/"]
2130
+ # parse_bucket_id_and_file_path("test:/global.cfg") == ["test", "/global.cfg"]
2131
+ # parse_bucket_id_and_file_path("test:/node1/node.cfg") == ["test", "/node1/node.cfg"]
2132
+ # parse_bucket_id_and_file_path("test/node1/node.cfg") == ["test", "/node1/node.cfg"]
2133
+ # parse_bucket_id_and_file_path("test", "node1/node.cfg") == ["test", "/node1/node.cfg"]
2134
+ #
2135
+ def parse_bucket_id_and_file_path(*args)
2136
+ if args.size < 1 || args.size > 2
2137
+ return nil, nil
2138
+ end
2139
+ if !args[0]
2140
+ return nil, nil
2141
+ end
2142
+ full_path = args[0].to_s
2143
+ if args[1]
2144
+ if full_path.include?(":")
2145
+ full_path = "#{full_path}/#{args[1]}"
2146
+ else
2147
+ full_path = "#{full_path}:#{args[1]}"
2148
+ end
2149
+ end
2150
+ # ok fine, allow just bucketId/filePath, without a colon.
2151
+ if !full_path.include?(":") && full_path.include?("/")
2152
+ path_elements = full_path.split("/")
2153
+ full_path = path_elements[0] + ":" + path_elements[1..-1].join("/")
2154
+ end
2155
+ uri_elements = full_path.split(":")
2156
+ bucket_id = uri_elements[0]
2157
+ file_path = uri_elements[1..-1].join("/") # [1]
2158
+ file_path = "/#{file_path}".squeeze("/")
2159
+ return bucket_id, file_path
2160
+ end
2161
+ end