morpheus-cli 5.3.3 → 5.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/account_users_interface.rb +68 -0
  4. data/lib/morpheus/api/api_client.rb +75 -8
  5. data/lib/morpheus/api/audit_interface.rb +9 -0
  6. data/lib/morpheus/api/clouds_interface.rb +4 -11
  7. data/lib/morpheus/api/health_interface.rb +37 -3
  8. data/lib/morpheus/api/instances_interface.rb +21 -0
  9. data/lib/morpheus/api/load_balancer_monitors_interface.rb +9 -0
  10. data/lib/morpheus/api/load_balancer_profiles_interface.rb +9 -0
  11. data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +9 -0
  12. data/lib/morpheus/api/load_balancers_interface.rb +5 -0
  13. data/lib/morpheus/api/network_dhcp_relays_interface.rb +36 -0
  14. data/lib/morpheus/api/network_dhcp_servers_interface.rb +36 -0
  15. data/lib/morpheus/api/network_edge_clusters_interface.rb +26 -0
  16. data/lib/morpheus/api/network_routers_interface.rb +30 -0
  17. data/lib/morpheus/api/network_servers_interface.rb +98 -0
  18. data/lib/morpheus/api/network_static_routes_interface.rb +36 -0
  19. data/lib/morpheus/api/read_interface.rb +4 -3
  20. data/lib/morpheus/api/rest_interface.rb +5 -4
  21. data/lib/morpheus/api/roles_interface.rb +7 -0
  22. data/lib/morpheus/api/secondary_read_interface.rb +1 -1
  23. data/lib/morpheus/api/secondary_rest_interface.rb +19 -19
  24. data/lib/morpheus/api/storage_server_types_interface.rb +14 -0
  25. data/lib/morpheus/api/storage_servers_interface.rb +9 -0
  26. data/lib/morpheus/api/storage_volume_types_interface.rb +9 -0
  27. data/lib/morpheus/api/storage_volumes_interface.rb +9 -0
  28. data/lib/morpheus/api/users_interface.rb +16 -63
  29. data/lib/morpheus/api/virtual_servers_interface.rb +9 -0
  30. data/lib/morpheus/cli/cli_command.rb +262 -14
  31. data/lib/morpheus/cli/cli_registry.rb +2 -1
  32. data/lib/morpheus/cli/{access_token_command.rb → commands/access_token_command.rb} +1 -1
  33. data/lib/morpheus/cli/{account_groups_command.rb → commands/account_groups_command.rb} +0 -8
  34. data/lib/morpheus/cli/{activity_command.rb → commands/activity_command.rb} +0 -0
  35. data/lib/morpheus/cli/commands/{standard/alias_command.rb → alias_command.rb} +1 -4
  36. data/lib/morpheus/cli/{appliance_settings_command.rb → commands/appliance_settings_command.rb} +0 -0
  37. data/lib/morpheus/cli/{approvals_command.rb → commands/approvals_command.rb} +0 -0
  38. data/lib/morpheus/cli/{apps.rb → commands/apps.rb} +14 -87
  39. data/lib/morpheus/cli/{archives_command.rb → commands/archives_command.rb} +0 -6
  40. data/lib/morpheus/cli/commands/audit.rb +188 -0
  41. data/lib/morpheus/cli/{backup_jobs_command.rb → commands/backup_jobs_command.rb} +0 -0
  42. data/lib/morpheus/cli/{backup_settings_command.rb → commands/backup_settings_command.rb} +0 -0
  43. data/lib/morpheus/cli/{backups_command.rb → commands/backups_command.rb} +0 -0
  44. data/lib/morpheus/cli/commands/{standard/benchmark_command.rb → benchmark_command.rb} +0 -3
  45. data/lib/morpheus/cli/{blueprints_command.rb → commands/blueprints_command.rb} +1 -1
  46. data/lib/morpheus/cli/{boot_scripts_command.rb → commands/boot_scripts_command.rb} +0 -3
  47. data/lib/morpheus/cli/{budgets_command.rb → commands/budgets_command.rb} +0 -0
  48. data/lib/morpheus/cli/commands/{standard/cat_command.rb → cat_command.rb} +0 -0
  49. data/lib/morpheus/cli/{catalog_item_types_command.rb → commands/catalog_item_types_command.rb} +0 -0
  50. data/lib/morpheus/cli/{certificates_command.rb → commands/certificates_command.rb} +0 -0
  51. data/lib/morpheus/cli/commands/change_password_command.rb +132 -0
  52. data/lib/morpheus/cli/{cloud_datastores_command.rb → commands/cloud_datastores_command.rb} +0 -4
  53. data/lib/morpheus/cli/{cloud_folders_command.rb → commands/cloud_folders_command.rb} +0 -4
  54. data/lib/morpheus/cli/{cloud_resource_pools_command.rb → commands/cloud_resource_pools_command.rb} +1 -5
  55. data/lib/morpheus/cli/{clouds.rb → commands/clouds.rb} +22 -47
  56. data/lib/morpheus/cli/{clusters.rb → commands/clusters.rb} +38 -19
  57. data/lib/morpheus/cli/commands/{standard/coloring_command.rb → coloring_command.rb} +0 -2
  58. data/lib/morpheus/cli/{containers_command.rb → commands/containers_command.rb} +0 -7
  59. data/lib/morpheus/cli/commands/{standard/curl_command.rb → curl_command.rb} +0 -3
  60. data/lib/morpheus/cli/{cypher_command.rb → commands/cypher_command.rb} +0 -1
  61. data/lib/morpheus/cli/{dashboard_command.rb → commands/dashboard_command.rb} +0 -2
  62. data/lib/morpheus/cli/commands/{standard/debug_command.rb → debug_command.rb} +0 -1
  63. data/lib/morpheus/cli/{deploy.rb → commands/deploy.rb} +0 -1
  64. data/lib/morpheus/cli/{deployments.rb → commands/deployments.rb} +0 -0
  65. data/lib/morpheus/cli/{deploys.rb → commands/deploys.rb} +0 -1
  66. data/lib/morpheus/cli/{doc.rb → commands/doc.rb} +1 -1
  67. data/lib/morpheus/cli/commands/{standard/echo_command.rb → echo_command.rb} +0 -2
  68. data/lib/morpheus/cli/commands/{standard/edit_profile_command.rb → edit_profile_command.rb} +15 -4
  69. data/lib/morpheus/cli/commands/{standard/edit_rc_command.rb → edit_rc_command.rb} +19 -3
  70. data/lib/morpheus/cli/{environments_command.rb → commands/environments_command.rb} +0 -5
  71. data/lib/morpheus/cli/{execute_schedules_command.rb → commands/execute_schedules_command.rb} +0 -0
  72. data/lib/morpheus/cli/{execution_request_command.rb → commands/execution_request_command.rb} +0 -2
  73. data/lib/morpheus/cli/commands/{standard/exit_command.rb → exit_command.rb} +0 -2
  74. data/lib/morpheus/cli/{file_copy_request_command.rb → commands/file_copy_request_command.rb} +0 -4
  75. data/lib/morpheus/cli/{forgot_password.rb → commands/forgot_password.rb} +0 -0
  76. data/lib/morpheus/cli/commands/{standard/get_prompt_command.rb → get_prompt_command.rb} +0 -3
  77. data/lib/morpheus/cli/{groups.rb → commands/groups.rb} +0 -7
  78. data/lib/morpheus/cli/{guidance_command.rb → commands/guidance_command.rb} +1 -1
  79. data/lib/morpheus/cli/{health_command.rb → commands/health_command.rb} +104 -19
  80. data/lib/morpheus/cli/commands/{standard/history_command.rb → history_command.rb} +0 -3
  81. data/lib/morpheus/cli/{hosts.rb → commands/hosts.rb} +15 -25
  82. data/lib/morpheus/cli/{image_builder_command.rb → commands/image_builder_command.rb} +6 -16
  83. data/lib/morpheus/cli/{instance_types.rb → commands/instance_types.rb} +0 -3
  84. data/lib/morpheus/cli/{instances.rb → commands/instances.rb} +220 -13
  85. data/lib/morpheus/cli/{integrations_command.rb → commands/integrations_command.rb} +1 -12
  86. data/lib/morpheus/cli/{invoices_command.rb → commands/invoices_command.rb} +43 -39
  87. data/lib/morpheus/cli/{jobs_command.rb → commands/jobs_command.rb} +0 -0
  88. data/lib/morpheus/cli/{key_pairs.rb → commands/key_pairs.rb} +0 -6
  89. data/lib/morpheus/cli/{library_cluster_layouts_command.rb → commands/library_cluster_layouts_command.rb} +0 -4
  90. data/lib/morpheus/cli/{library_container_scripts_command.rb → commands/library_container_scripts_command.rb} +0 -0
  91. data/lib/morpheus/cli/{library_container_templates_command.rb → commands/library_container_templates_command.rb} +0 -1
  92. data/lib/morpheus/cli/{library_container_types_command.rb → commands/library_container_types_command.rb} +0 -4
  93. data/lib/morpheus/cli/{library_instance_types_command.rb → commands/library_instance_types_command.rb} +0 -4
  94. data/lib/morpheus/cli/{library_layouts_command.rb → commands/library_layouts_command.rb} +0 -4
  95. data/lib/morpheus/cli/{library_option_lists_command.rb → commands/library_option_lists_command.rb} +3 -7
  96. data/lib/morpheus/cli/{library_option_types_command.rb → commands/library_option_types_command.rb} +0 -4
  97. data/lib/morpheus/cli/{library_spec_templates_command.rb → commands/library_spec_templates_command.rb} +0 -1
  98. data/lib/morpheus/cli/{library_upgrades_command.rb → commands/library_upgrades_command.rb} +0 -4
  99. data/lib/morpheus/cli/{license.rb → commands/license.rb} +0 -3
  100. data/lib/morpheus/cli/commands/load_balancer_monitors.rb +70 -0
  101. data/lib/morpheus/cli/commands/load_balancer_pools.rb +90 -0
  102. data/lib/morpheus/cli/commands/load_balancer_profiles.rb +64 -0
  103. data/lib/morpheus/cli/{load_balancer_types.rb → commands/load_balancer_types.rb} +9 -8
  104. data/lib/morpheus/cli/commands/load_balancer_virtual_servers.rb +147 -0
  105. data/lib/morpheus/cli/commands/load_balancers.rb +192 -0
  106. data/lib/morpheus/cli/commands/{standard/log_level_command.rb → log_level_command.rb} +0 -3
  107. data/lib/morpheus/cli/{log_settings_command.rb → commands/log_settings_command.rb} +0 -0
  108. data/lib/morpheus/cli/{login.rb → commands/login.rb} +0 -5
  109. data/lib/morpheus/cli/commands/logout.rb +63 -0
  110. data/lib/morpheus/cli/{logs_command.rb → commands/logs_command.rb} +0 -3
  111. data/lib/morpheus/cli/commands/{standard/man_command.rb → man_command.rb} +0 -2
  112. data/lib/morpheus/cli/{monitoring_alerts_command.rb → commands/monitoring_alerts_command.rb} +0 -7
  113. data/lib/morpheus/cli/{monitoring_apps_command.rb → commands/monitoring_apps_command.rb} +0 -1
  114. data/lib/morpheus/cli/{monitoring_checks_command.rb → commands/monitoring_checks_command.rb} +0 -1
  115. data/lib/morpheus/cli/{monitoring_contacts_command.rb → commands/monitoring_contacts_command.rb} +0 -7
  116. data/lib/morpheus/cli/{monitoring_groups_command.rb → commands/monitoring_groups_command.rb} +0 -1
  117. data/lib/morpheus/cli/{monitoring_incidents_command.rb → commands/monitoring_incidents_command.rb} +0 -1
  118. data/lib/morpheus/cli/commands/network_dhcp_relays_command.rb +416 -0
  119. data/lib/morpheus/cli/commands/network_dhcp_servers_command.rb +407 -0
  120. data/lib/morpheus/cli/{network_domains_command.rb → commands/network_domains_command.rb} +0 -4
  121. data/lib/morpheus/cli/commands/network_edge_clusters_command.rb +329 -0
  122. data/lib/morpheus/cli/commands/network_firewalls_command.rb +823 -0
  123. data/lib/morpheus/cli/{network_groups_command.rb → commands/network_groups_command.rb} +0 -4
  124. data/lib/morpheus/cli/{network_pool_servers_command.rb → commands/network_pool_servers_command.rb} +0 -4
  125. data/lib/morpheus/cli/{network_pools_command.rb → commands/network_pools_command.rb} +0 -4
  126. data/lib/morpheus/cli/{network_proxies_command.rb → commands/network_proxies_command.rb} +0 -4
  127. data/lib/morpheus/cli/{network_routers_command.rb → commands/network_routers_command.rb} +387 -57
  128. data/lib/morpheus/cli/{network_services_command.rb → commands/network_services_command.rb} +0 -4
  129. data/lib/morpheus/cli/commands/network_static_routes_command.rb +446 -0
  130. data/lib/morpheus/cli/commands/network_transport_zones_command.rb +452 -0
  131. data/lib/morpheus/cli/{networks_command.rb → commands/networks_command.rb} +20 -20
  132. data/lib/morpheus/cli/commands/open_command.rb +30 -0
  133. data/lib/morpheus/cli/commands/options.rb +98 -0
  134. data/lib/morpheus/cli/{packages_command.rb → commands/packages_command.rb} +0 -2
  135. data/lib/morpheus/cli/{ping.rb → commands/ping.rb} +0 -7
  136. data/lib/morpheus/cli/{policies_command.rb → commands/policies_command.rb} +1 -8
  137. data/lib/morpheus/cli/{power_schedules_command.rb → commands/power_schedules_command.rb} +0 -0
  138. data/lib/morpheus/cli/{preseed_scripts_command.rb → commands/preseed_scripts_command.rb} +0 -3
  139. data/lib/morpheus/cli/{price_sets_command.rb → commands/price_sets_command.rb} +0 -0
  140. data/lib/morpheus/cli/{prices_command.rb → commands/prices_command.rb} +7 -7
  141. data/lib/morpheus/cli/{processes_command.rb → commands/processes_command.rb} +0 -1
  142. data/lib/morpheus/cli/{projects_command.rb → commands/projects_command.rb} +0 -0
  143. data/lib/morpheus/cli/{provisioning_licenses_command.rb → commands/provisioning_licenses_command.rb} +0 -0
  144. data/lib/morpheus/cli/{provisioning_settings_command.rb → commands/provisioning_settings_command.rb} +0 -0
  145. data/lib/morpheus/cli/{recent_activity_command.rb → commands/recent_activity_command.rb} +0 -0
  146. data/lib/morpheus/cli/{remote.rb → commands/remote.rb} +5 -9
  147. data/lib/morpheus/cli/{reports_command.rb → commands/reports_command.rb} +0 -2
  148. data/lib/morpheus/cli/commands/{standard/rm_command.rb → rm_command.rb} +0 -0
  149. data/lib/morpheus/cli/{roles.rb → commands/roles.rb} +245 -40
  150. data/lib/morpheus/cli/{search_command.rb → commands/search_command.rb} +0 -0
  151. data/lib/morpheus/cli/{security_group_rules.rb → commands/security_group_rules.rb} +0 -5
  152. data/lib/morpheus/cli/{security_groups.rb → commands/security_groups.rb} +0 -6
  153. data/lib/morpheus/cli/{service_catalog_command.rb → commands/service_catalog_command.rb} +0 -0
  154. data/lib/morpheus/cli/{service_plans_command.rb → commands/service_plans_command.rb} +0 -0
  155. data/lib/morpheus/cli/commands/{standard/set_prompt_command.rb → set_prompt_command.rb} +0 -3
  156. data/lib/morpheus/cli/{setup.rb → commands/setup.rb} +0 -0
  157. data/lib/morpheus/cli/{shell.rb → commands/shell.rb} +4 -105
  158. data/lib/morpheus/cli/commands/{standard/sleep_command.rb → sleep_command.rb} +0 -2
  159. data/lib/morpheus/cli/commands/{standard/source_command.rb → source_command.rb} +0 -2
  160. data/lib/morpheus/cli/commands/{standard/ssl_verification_command.rb → ssl_verification_command.rb} +0 -3
  161. data/lib/morpheus/cli/{storage_providers_command.rb → commands/storage_providers_command.rb} +0 -4
  162. data/lib/morpheus/cli/commands/storage_server_types.rb +50 -0
  163. data/lib/morpheus/cli/commands/storage_servers.rb +122 -0
  164. data/lib/morpheus/cli/commands/storage_volume_types.rb +50 -0
  165. data/lib/morpheus/cli/commands/storage_volumes.rb +103 -0
  166. data/lib/morpheus/cli/{subnets_command.rb → commands/subnets_command.rb} +7 -6
  167. data/lib/morpheus/cli/{tasks.rb → commands/tasks.rb} +25 -6
  168. data/lib/morpheus/cli/commands/{standard/tee_command.rb → tee_command.rb} +0 -0
  169. data/lib/morpheus/cli/{tenants_command.rb → commands/tenants_command.rb} +1 -8
  170. data/lib/morpheus/cli/commands/{standard/update_command.rb → update_command.rb} +0 -1
  171. data/lib/morpheus/cli/{usage_command.rb → commands/usage_command.rb} +0 -0
  172. data/lib/morpheus/cli/{user_groups_command.rb → commands/user_groups_command.rb} +1 -2
  173. data/lib/morpheus/cli/{user_settings_command.rb → commands/user_settings_command.rb} +2 -1
  174. data/lib/morpheus/cli/{user_sources_command.rb → commands/user_sources_command.rb} +1 -2
  175. data/lib/morpheus/cli/{users.rb → commands/users.rb} +28 -35
  176. data/lib/morpheus/cli/{vdi_allocations_command.rb → commands/vdi_allocations_command.rb} +0 -0
  177. data/lib/morpheus/cli/{vdi_apps_command.rb → commands/vdi_apps_command.rb} +0 -0
  178. data/lib/morpheus/cli/{vdi_command.rb → commands/vdi_command.rb} +0 -0
  179. data/lib/morpheus/cli/{vdi_gateways_command.rb → commands/vdi_gateways_command.rb} +0 -0
  180. data/lib/morpheus/cli/{vdi_pools_command.rb → commands/vdi_pools_command.rb} +0 -0
  181. data/lib/morpheus/cli/commands/{standard/version_command.rb → version_command.rb} +0 -0
  182. data/lib/morpheus/cli/commands/view.rb +102 -0
  183. data/lib/morpheus/cli/{virtual_images.rb → commands/virtual_images.rb} +2 -4
  184. data/lib/morpheus/cli/{whitelabel_settings_command.rb → commands/whitelabel_settings_command.rb} +0 -1
  185. data/lib/morpheus/cli/{whoami.rb → commands/whoami.rb} +0 -4
  186. data/lib/morpheus/cli/{wiki_command.rb → commands/wiki_command.rb} +0 -5
  187. data/lib/morpheus/cli/{workflows.rb → commands/workflows.rb} +0 -3
  188. data/lib/morpheus/cli/mixins/accounts_helper.rb +5 -5
  189. data/lib/morpheus/cli/mixins/load_balancers_helper.rb +26 -6
  190. data/lib/morpheus/cli/mixins/logs_helper.rb +1 -1
  191. data/lib/morpheus/cli/mixins/print_helper.rb +51 -18
  192. data/lib/morpheus/cli/mixins/processes_helper.rb +1 -2
  193. data/lib/morpheus/cli/mixins/provisioning_helper.rb +48 -17
  194. data/lib/morpheus/cli/mixins/rest_command.rb +270 -94
  195. data/lib/morpheus/cli/mixins/secondary_rest_command.rb +667 -0
  196. data/lib/morpheus/cli/mixins/storage_servers_helper.rb +156 -0
  197. data/lib/morpheus/cli/mixins/storage_volumes_helper.rb +119 -0
  198. data/lib/morpheus/cli/option_types.rb +149 -40
  199. data/lib/morpheus/cli/version.rb +1 -1
  200. data/lib/morpheus/cli.rb +6 -128
  201. data/lib/morpheus/ext/string.rb +29 -6
  202. data/lib/morpheus/routes.rb +238 -0
  203. data/lib/morpheus/terminal.rb +5 -6
  204. data/lib/morpheus/util.rb +6 -1
  205. metadata +176 -141
  206. data/lib/morpheus/cli/change_password_command.rb +0 -147
  207. data/lib/morpheus/cli/library.rb +0 -1
  208. data/lib/morpheus/cli/load_balancers.rb +0 -245
  209. data/lib/morpheus/cli/logout.rb +0 -81
@@ -6,9 +6,10 @@ require 'morpheus/api/api_client'
6
6
  class Morpheus::ReadInterface < Morpheus::APIClient
7
7
 
8
8
  # subclasses should override in your interface
9
- # Example: "/api/thing-types"
9
+ # Example: "/api/things"
10
10
  def base_path
11
- raise "#{self.class} has not defined base_path!"
11
+ raise "#{self.class} has not defined base_path!" if @options[:base_path].nil?
12
+ @options[:base_path]
12
13
  end
13
14
 
14
15
  def list(params={}, headers={})
@@ -17,7 +18,7 @@ class Morpheus::ReadInterface < Morpheus::APIClient
17
18
 
18
19
  def get(id, params={}, headers={})
19
20
  validate_id!(id)
20
- execute(method: :get, url: "#{base_path}/#{id}", params: params, headers: headers)
21
+ execute(method: :get, url: "#{base_path}/#{CGI::escape(id.to_s)}", params: params, headers: headers)
21
22
  end
22
23
 
23
24
  end
@@ -7,7 +7,8 @@ class Morpheus::RestInterface < Morpheus::APIClient
7
7
  # subclasses should override in your interface
8
8
  # Example: "/api/things"
9
9
  def base_path
10
- raise "#{self.class} has not defined base_path!"
10
+ raise "#{self.class} has not defined base_path!" if @options[:base_path].nil?
11
+ @options[:base_path]
11
12
  end
12
13
 
13
14
  def list(params={}, headers={})
@@ -16,7 +17,7 @@ class Morpheus::RestInterface < Morpheus::APIClient
16
17
 
17
18
  def get(id, params={}, headers={})
18
19
  validate_id!(id)
19
- execute(method: :get, url: "#{base_path}/#{id}", params: params, headers: headers)
20
+ execute(method: :get, url: "#{base_path}/#{CGI::escape(id.to_s)}", params: params, headers: headers)
20
21
  end
21
22
 
22
23
  def create(payload, params={}, headers={})
@@ -25,12 +26,12 @@ class Morpheus::RestInterface < Morpheus::APIClient
25
26
 
26
27
  def update(id, payload, params={}, headers={})
27
28
  validate_id!(id)
28
- execute(method: :put, url: "#{base_path}/#{id}", params: params, payload: payload, headers: headers)
29
+ execute(method: :put, url: "#{base_path}/#{CGI::escape(id.to_s)}", params: params, payload: payload, headers: headers)
29
30
  end
30
31
 
31
32
  def destroy(id, params = {}, headers={})
32
33
  validate_id!(id)
33
- execute(method: :delete, url: "#{base_path}/#{id}", params: params, headers: headers)
34
+ execute(method: :delete, url: "#{base_path}/#{CGI::escape(id.to_s)}", params: params, headers: headers)
34
35
  end
35
36
 
36
37
  end
@@ -92,6 +92,13 @@ class Morpheus::RolesInterface < Morpheus::APIClient
92
92
  execute(method: :put, url: url, headers: headers, payload: payload.to_json)
93
93
  end
94
94
 
95
+ def update_report_type(account_id, id, options)
96
+ url = build_url(account_id, id) + "/update-report-type"
97
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
98
+ payload = options
99
+ execute(method: :put, url: url, headers: headers, payload: payload.to_json)
100
+ end
101
+
95
102
  private
96
103
 
97
104
  def build_url(account_id=nil, role_id=nil)
@@ -19,7 +19,7 @@ class Morpheus::SecondaryReadInterface < Morpheus::APIClient
19
19
  def get(resource_id, id, params={}, headers={})
20
20
  validate_id!(resource_id)
21
21
  validate_id!(id)
22
- execute(method: :get, url: "#{base_path(resource_id)}/#{id}", params: params, headers: headers)
22
+ execute(method: :get, url: "#{base_path(resource_id)}/#{CGI::escape(id.to_s)}", params: params, headers: headers)
23
23
  end
24
24
 
25
25
  end
@@ -2,41 +2,41 @@ require 'morpheus/api/api_client'
2
2
 
3
3
  # Interface class to be subclassed by interfaces that provide CRUD endpoints
4
4
  # for objects underneath another resource
5
- # Subclasses must override the base_path(resource_id) method
5
+ # Subclasses must override the base_path(parent_id) method
6
6
  class Morpheus::SecondaryRestInterface < Morpheus::APIClient
7
7
 
8
8
  # subclasses should override in your interface
9
- # Example: "/api/things/#{resource_id}/widgets"
10
- def base_path(resource_id)
11
- raise "#{self.class} has not defined base_path(resource_id)!"
9
+ # Example: "/api/things/#{parent_id}/widgets"
10
+ def base_path(parent_id)
11
+ raise "#{self.class} has not defined base_path(parent_id)!"
12
12
  end
13
13
 
14
- def list(resource_id, params={}, headers={})
15
- validate_id!(resource_id)
16
- execute(method: :get, url: "#{base_path(resource_id)}", params: params, headers: headers)
14
+ def list(parent_id, params={}, headers={})
15
+ validate_id!(parent_id)
16
+ execute(method: :get, url: "#{base_path(parent_id)}", params: params, headers: headers)
17
17
  end
18
18
 
19
- def get(resource_id, id, params={}, headers={})
20
- validate_id!(resource_id)
19
+ def get(parent_id, id, params={}, headers={})
20
+ validate_id!(parent_id)
21
21
  validate_id!(id)
22
- execute(method: :get, url: "#{base_path(resource_id)}/#{id}", params: params, headers: headers)
22
+ execute(method: :get, url: "#{base_path(parent_id)}/#{CGI::escape(id.to_s)}", params: params, headers: headers)
23
23
  end
24
24
 
25
- def create(resource_id, payload, params={}, headers={})
26
- validate_id!(resource_id)
27
- execute(method: :post, url: "#{base_path(resource_id)}", params: params, payload: payload, headers: headers)
25
+ def create(parent_id, payload, params={}, headers={})
26
+ validate_id!(parent_id)
27
+ execute(method: :post, url: "#{base_path(parent_id)}", params: params, payload: payload, headers: headers)
28
28
  end
29
29
 
30
- def update(resource_id, id, payload, params={}, headers={})
31
- validate_id!(resource_id)
30
+ def update(parent_id, id, payload, params={}, headers={})
31
+ validate_id!(parent_id)
32
32
  validate_id!(id)
33
- execute(method: :put, url: "#{base_path(resource_id)}/#{id}", params: params, payload: payload, headers: headers)
33
+ execute(method: :put, url: "#{base_path(parent_id)}/#{CGI::escape(id.to_s)}", params: params, payload: payload, headers: headers)
34
34
  end
35
35
 
36
- def destroy(resource_id, id, params = {}, headers={})
37
- validate_id!(resource_id)
36
+ def destroy(parent_id, id, params = {}, headers={})
37
+ validate_id!(parent_id)
38
38
  validate_id!(id)
39
- execute(method: :delete, url: "#{base_path(resource_id)}/#{id}", params: params, headers: headers)
39
+ execute(method: :delete, url: "#{base_path(parent_id)}/#{CGI::escape(id.to_s)}", params: params, headers: headers)
40
40
  end
41
41
 
42
42
  end
@@ -0,0 +1,14 @@
1
+ require 'morpheus/api/read_interface'
2
+
3
+ class Morpheus::StorageServerTypesInterface < Morpheus::ReadInterface
4
+
5
+ def base_path
6
+ "/api/storage-server-types"
7
+ end
8
+
9
+ # def option_types(id, params={}, headers={})
10
+ # validate_id!(id)
11
+ # execute(method: :get, url: "#{base_path}/#{id}/option-types", params: params, headers: headers)
12
+ # end
13
+
14
+ end
@@ -0,0 +1,9 @@
1
+ require 'morpheus/api/rest_interface'
2
+
3
+ class Morpheus::StorageServersInterface < Morpheus::RestInterface
4
+
5
+ def base_path
6
+ "/api/storage-servers"
7
+ end
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'morpheus/api/read_interface'
2
+
3
+ class Morpheus::StorageVolumeTypesInterface < Morpheus::ReadInterface
4
+
5
+ def base_path
6
+ "/api/storage-volume-types"
7
+ end
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'morpheus/api/rest_interface'
2
+
3
+ class Morpheus::StorageVolumesInterface < Morpheus::RestInterface
4
+
5
+ def base_path
6
+ "/api/storage-volumes"
7
+ end
8
+
9
+ end
@@ -1,78 +1,31 @@
1
- require 'morpheus/api/api_client'
1
+ require 'morpheus/api/rest_interface'
2
2
 
3
- class Morpheus::UsersInterface < Morpheus::APIClient
3
+ class Morpheus::UsersInterface < Morpheus::RestInterface
4
4
 
5
- def get(account_id, id, params={})
6
- raise "#{self.class}.get() passed a blank id!" if id.to_s == ''
7
- url = build_url(account_id, id)
8
- headers = { params: params, authorization: "Bearer #{@access_token}" }
9
- opts = {method: :get, url: url, timeout: 10, headers: headers}
10
- execute(opts)
5
+ def base_path
6
+ "/api/users"
11
7
  end
12
8
 
13
- def list(account_id, params={})
14
- url = build_url(account_id)
15
- headers = { params: params, authorization: "Bearer #{@access_token}" }
16
- opts = {method: :get, url: url, timeout: 10, headers: headers}
17
- execute(opts)
9
+ def feature_permissions(id, params={}, headers={})
10
+ validate_id!(id)
11
+ execute(method: :get, url: "#{base_path}/#{id}/feature-permissions", params: params, headers: headers)
18
12
  end
19
13
 
20
- def feature_permissions(account_id, id)
21
- url = build_url(account_id, id) + "/feature-permissions"
22
- headers = { params: {}, authorization: "Bearer #{@access_token}" }
23
- opts = {method: :get, url: url, timeout: 10, headers: headers}
24
- execute(opts)
14
+ def permissions(id, params={}, headers={})
15
+ validate_id!(id)
16
+ execute(method: :get, url: "#{base_path}/#{id}/permissions", params: params, headers: headers)
25
17
  end
26
18
 
27
- def permissions(account_id, id)
28
- url = build_url(account_id, id) + "/permissions"
29
- headers = { params: {}, authorization: "Bearer #{@access_token}" }
30
- opts = {method: :get, url: url, timeout: 10, headers: headers}
31
- execute(opts)
32
- end
33
-
34
- def available_roles(account_id, id=nil, options={})
35
- url = build_url(account_id, id) + "/available-roles"
36
- headers = { params: {}, authorization: "Bearer #{@access_token}" }
37
- headers[:params].merge!(options)
38
- opts = {method: :get, url: url, timeout: 10, headers: headers}
39
- execute(opts)
40
- end
41
-
42
- def create(account_id, options)
43
- url = build_url(account_id)
44
- headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
45
- payload = options
46
- opts = {method: :post, url: url, timeout: 10, headers: headers, payload: payload.to_json}
47
- execute(opts)
48
- end
49
-
50
- def update(account_id, id, options)
51
- url = build_url(account_id, id)
52
- headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
53
- payload = options
54
- opts = {method: :put, url: url, timeout: 10, headers: headers, payload: payload.to_json}
55
- execute(opts)
56
- end
57
-
58
- def destroy(account_id, id)
59
- url = build_url(account_id, id)
60
- headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
61
- opts = {method: :delete, url: url, timeout: 10, headers: headers}
62
- execute(opts)
19
+ def available_roles(id=nil, params={}, headers={})
20
+ execute(method: :get, url: "#{build_url(id)}/available-roles", params: params, headers: headers)
63
21
  end
64
22
 
65
23
  private
66
24
 
67
- def build_url(account_id=nil, user_id=nil)
68
- url = "#{@base_url}/api"
69
- if account_id
70
- url += "/accounts/#{account_id}/users"
71
- else
72
- url += "/users"
73
- end
74
- if user_id
75
- url += "/#{user_id}"
25
+ def build_url(id=nil)
26
+ url = base_path
27
+ if id
28
+ url += "/#{id}"
76
29
  end
77
30
  url
78
31
  end
@@ -0,0 +1,9 @@
1
+ require 'morpheus/api/rest_interface'
2
+
3
+ class Morpheus::VirtualServersInterface < Morpheus::RestInterface
4
+
5
+ def base_path
6
+ "/api/load-balancer-virtual-servers"
7
+ end
8
+
9
+ end
@@ -1,15 +1,14 @@
1
- require 'yaml'
2
- require 'json'
3
- require 'fileutils'
4
1
  require 'morpheus/logging'
5
2
  require 'morpheus/benchmarking'
6
- require 'morpheus/cli/option_parser'
3
+ require 'morpheus/terminal'
7
4
  require 'morpheus/cli/cli_registry'
5
+ require 'morpheus/cli/option_parser'
6
+ require 'morpheus/cli/option_types'
8
7
  require 'morpheus/cli/mixins/print_helper'
9
8
  require 'morpheus/cli/credentials'
9
+ #require 'morpheus/cli/commands/shell'
10
+ #require 'morpheus/cli/commands/remote'
10
11
  require 'morpheus/api/api_client'
11
- require 'morpheus/cli/remote'
12
- require 'morpheus/terminal'
13
12
 
14
13
  module Morpheus
15
14
  module Cli
@@ -215,7 +214,8 @@ module Morpheus
215
214
  opts.on(arg1, arg2, description) do |val|
216
215
  if option_type['type'] == 'checkbox'
217
216
  val = (val.to_s != 'false' && val.to_s != 'off')
218
- else
217
+ elsif option_type['dataType'] != 'string'
218
+ # 'dataType': 'string' added to cli to avoid auto conversion to JSON
219
219
  # attempt to parse JSON, this allows blank arrays for multiSelect like --tenants []
220
220
  if (val.to_s[0] == '{' && val.to_s[-1] == '}') || (val.to_s[0] == '[' && val.to_s[-1] == ']')
221
221
  begin
@@ -1011,7 +1011,7 @@ module Morpheus
1011
1011
  # meh, could deprecate and make subcommand define handle() itself
1012
1012
  # if args.count == 0 && default_subcommand
1013
1013
  # # p "using default subcommand #{default_subcommand}"
1014
- # return self.send(default_subcommand, args || [])
1014
+ # return send(default_subcommand, args || [])
1015
1015
  # end
1016
1016
  subcommand_name = args[0]
1017
1017
  if args.empty?
@@ -1032,7 +1032,7 @@ module Morpheus
1032
1032
  error_msg = "'#{command_name} #{subcommand_name}' is not a #{prog_name} command.\n#{full_command_usage}"
1033
1033
  raise CommandNotFoundError.new(error_msg)
1034
1034
  end
1035
- self.send(cmd_method, args[1..-1])
1035
+ send(cmd_method, args[1..-1])
1036
1036
  end
1037
1037
 
1038
1038
  def handle(args)
@@ -1230,6 +1230,72 @@ module Morpheus
1230
1230
  true
1231
1231
  end
1232
1232
 
1233
+ # The default way to build options for the list command
1234
+ # @param [OptionParser] opts
1235
+ # @param [Hash] options
1236
+ # @param [Hash] params
1237
+ def build_list_options(opts, options, params)
1238
+ build_standard_list_options(opts, options)
1239
+ end
1240
+
1241
+ # The default way to parse options for the list command
1242
+ # @param [Array] args
1243
+ # @param [Hash] options
1244
+ # @param [Hash] params
1245
+ def parse_list_options!(args, options, params)
1246
+ if args.count > 0
1247
+ options[:phrase] = args.join(" ")
1248
+ # params['phrase'] = = args.join(" ")
1249
+ end
1250
+ params.merge!(parse_list_options(options))
1251
+ end
1252
+
1253
+ # The default way to build options for the list command
1254
+ # @param [OptionParser] opts
1255
+ # @param [Hash] options
1256
+ # @param [Hash] params
1257
+ def build_get_options(opts, options, params)
1258
+ build_standard_get_options(opts, options)
1259
+ end
1260
+
1261
+ # The default way to parse options for the get command
1262
+ # @param [OptionParser] opts
1263
+ # @param [Hash] options
1264
+ # @param [Hash] params
1265
+ def parse_get_options!(args, options, params)
1266
+ params.merge!(parse_query_options(options))
1267
+ end
1268
+
1269
+ # The default way to parse options for the get command
1270
+ # @param type [string]
1271
+ # @param options [Hash] The command options
1272
+ # @param params [Hash] The query parameters the output is being appended to
1273
+ # @param param_name [String]
1274
+ # @param lookup_ids [Boolean] Also lookup ids to make sure they exist or else error
1275
+ # @return
1276
+ def parse_parameter_as_resource_id!(type, options, params, param_name=nil, lookup_ids=false)
1277
+ # type = type.to_s.singularize
1278
+ if options.key?(type)
1279
+ val = options[type].to_s
1280
+ param_name ||= "#{type.to_s.camelcase}Id"
1281
+ if val
1282
+ if val.to_s !~ /\A\d{1,}\Z/ || lookup_ids
1283
+ record = find_by_name(type, val)
1284
+ if record.nil?
1285
+ # avoid double error render by exiting here, ew
1286
+ exit 1
1287
+ raise_command_error "Storage Server not found for '#{val}'"
1288
+ end
1289
+ params[param_name] = record['id']
1290
+ else
1291
+ params[param_name] = val
1292
+ end
1293
+ return params[param_name]
1294
+ end
1295
+ end
1296
+ return nil
1297
+ end
1298
+
1233
1299
  # parse the parameters provided by the common :list options
1234
1300
  # this includes the :query options too via parse_query_options().
1235
1301
  # returns Hash of params the format {"phrase": => "foobar", "max": 100}
@@ -1244,7 +1310,11 @@ module Morpheus
1244
1310
  end
1245
1311
  # arbitrary filters
1246
1312
  list_params.merge!(parse_query_options(options))
1247
-
1313
+ # ok, any string keys in options can become query parameters, eg. options['name'] = 'foobar'
1314
+ # do it!
1315
+ # options.each do |k, v|
1316
+ # list_params[k] = v
1317
+ # end
1248
1318
  return list_params
1249
1319
  end
1250
1320
 
@@ -1365,7 +1435,7 @@ module Morpheus
1365
1435
  full_outfile = File.expand_path(options[:outfile])
1366
1436
  if output
1367
1437
  print_to_file(output, options[:outfile], options[:overwrite])
1368
- print "#{cyan}Wrote output to file #{options[:outfile]} (#{File.size(full_outfile)} B)\n" unless options[:quiet]
1438
+ print "#{cyan}Wrote output to file #{options[:outfile]} (#{format_bytes(File.size(full_outfile))})\n" unless options[:quiet]
1369
1439
  else
1370
1440
  # uhhh ok lets try this
1371
1441
  Morpheus::Logging::DarkPrinter.puts "using experimental feature: --out without a common format like json, yml or csv" if Morpheus::Logging.debug?
@@ -1373,7 +1443,7 @@ module Morpheus
1373
1443
  if result && result != 0
1374
1444
  return result
1375
1445
  end
1376
- print "#{cyan}Wrote output to file #{options[:outfile]} (#{File.size(full_outfile)} B)\n" unless options[:quiet]
1446
+ print "#{cyan}Wrote output to file #{options[:outfile]} (#{format_bytes(File.size(full_outfile))})\n" unless options[:quiet]
1377
1447
  return 0, nil
1378
1448
  end
1379
1449
  else
@@ -1404,6 +1474,184 @@ module Morpheus
1404
1474
 
1405
1475
  alias :render_with_format :render_response
1406
1476
 
1477
+ # Dynamic find methods to load a record of any type
1478
+ # def find_by_name_or_id(type, val)
1479
+ # interface = instance_variable_get "@#{type}s_interface"
1480
+ # typeCamelCase = type.gsub(/(?:^|_)([a-z])/) do $1.upcase end
1481
+ # typeCamelCase = typeCamelCase[0, 1].downcase + typeCamelCase[1..-1]
1482
+ # (val.to_s =~ /\A\d{1,}\Z/) ? interface.get(val.to_i)[typeCamelCase] : interface.list({'name' => val})["#{typeCamelCase}s"].first
1483
+ # end
1484
+
1485
+ # Find a resource by type and name or id
1486
+ # @param type [String of Symbol] Type of resource formatted as singular, lowerscore with underscores.
1487
+ # @param *id [String or Numeric] ID of resource, multiple arguments may be passed when using a secondary interface where parent_id, id is required.
1488
+ # Example: find_by_name_or_id("instance", "K2")
1489
+ # find_by_name_or_id("storage_volume", 42)
1490
+ # find_by_name_or_id("instance", "My Instance")
1491
+ # find_by_name_or_id("load_balancer_pool", load_balancer_id, id)
1492
+ def find_by_name_or_id(*args)
1493
+ val = args.last
1494
+ if val.to_s =~ /\A\d{1,}\Z/
1495
+ return find_by_id(*args)
1496
+ else
1497
+ return find_by_name(*args)
1498
+ end
1499
+ end
1500
+
1501
+
1502
+ # Find a resource by type and id
1503
+ # Usage: find_by_name_or_id("app", 3)
1504
+ def find_by_id(*args)
1505
+ #Morpheus::Logging::DarkPrinter.puts "find_by_id(#{args.join(', ')})" if Morpheus::Logging.debug?
1506
+ # type, ids = args.first, args[1..-1]
1507
+ type, *ids = args
1508
+ type = type.to_s.singularize.underscore
1509
+ # still relying on the command or helper to define these _label and _key methods
1510
+ label = send("#{type}_label")
1511
+ object_key = send("#{type}_object_key")
1512
+ interface_name = "@#{type.pluralize}_interface"
1513
+ interface = instance_variable_get(interface_name)
1514
+ if interface.nil?
1515
+ raise "#{self.class} has not defined interface #{interface_name}"
1516
+ end
1517
+ begin
1518
+ json_response = interface.get(*ids)
1519
+ return json_response[object_key]
1520
+ rescue Exception => e
1521
+ if e.response && e.response.code == 404
1522
+ print_red_alert "#{label} not found by id #{ids.last}"
1523
+ return nil
1524
+ else
1525
+ raise e
1526
+ end
1527
+ end
1528
+ end
1529
+
1530
+ # Find a record by type and name
1531
+ # Usage: find_by_name_or_id("network", "Skynet")
1532
+ def find_by_name(*args)
1533
+ #Morpheus::Logging::DarkPrinter.puts "find_by_name(#{args.join(', ')})" if Morpheus::Logging.debug?
1534
+ # type, ids = args.first, args[1..-1]
1535
+ type, *ids = args
1536
+ type = type.to_s.singularize.underscore
1537
+ val = ids.pop
1538
+ params = {}
1539
+ name_property = 'name'
1540
+ if type == 'user'
1541
+ name_property = 'username'
1542
+ params['global'] = 'true'
1543
+ end
1544
+ params[name_property] = val.to_s
1545
+ request_args = ids + [params]
1546
+ request_args.unshift(type)
1547
+ records = find_all(*request_args)
1548
+ # still relying on the command or helper to define these _label and _key methods
1549
+ label = respond_to?("#{type}_label", true) ? send("#{type}_label") : type.titleize
1550
+ if records.empty?
1551
+ print_red_alert "#{label} not found by name '#{val}'"
1552
+ return nil
1553
+ elsif records.size > 1
1554
+ print_red_alert "More than one #{label.downcase} found by #{name_property} '#{val}'"
1555
+ print_error "\n"
1556
+ if type == "user"
1557
+ puts_error as_pretty_table(records, [:id, :username, {"FIRST NAME" => "firstName"}, {"LAST NAME" => "lastName"}, {"TENANT" => lambda {|it| it['account']['name'] rescue ''}}], {color:red})
1558
+ else
1559
+ puts_error as_pretty_table(records, [:id, :name], {color:red})
1560
+ end
1561
+ print_red_alert "Try using ID instead"
1562
+ print_error reset,"\n"
1563
+ return nil
1564
+ else
1565
+ return records[0]
1566
+ end
1567
+ end
1568
+
1569
+ # Load a list of records by type
1570
+ # @example Find an app by id
1571
+ # find_record(:app, 1)
1572
+ # report_types = find_all("reportTypes", {phrase:"amazon"})
1573
+ # pools = find_all("loadBalancerPool", load_balancer_id)
1574
+ # @return Array of records
1575
+ def find_all(*args)
1576
+ #Morpheus::Logging::DarkPrinter.puts "find_all(#{args.join(', ')})" if Morpheus::Logging.debug?
1577
+ type, *request_args = args
1578
+ type = type.to_s.singularize.underscore
1579
+ list_key = respond_to?("#{type}_list_key", true) ? send("#{type}_list_key") : type.camelcase.pluralize
1580
+ json_response = find_all_json(*args)
1581
+ if !json_response.key?(list_key)
1582
+ # maybe just use the first key like this:
1583
+ # list_key = json_response.keys.find { |k| json_response[k].is_a?(Array) }
1584
+ # print_error(json_response) if Morpheus::Logging.debug?
1585
+ raise "API response is missing list property '#{list_key}'"
1586
+ end
1587
+ return json_response[list_key]
1588
+ end
1589
+
1590
+ # Load json response for a list of records by type
1591
+ # @return Hash of JSON data
1592
+ def find_all_json(*args)
1593
+ type, *request_args = args
1594
+ get_interface(type).list(*request_args)
1595
+ end
1596
+
1597
+ alias :find_all_records :find_all
1598
+ alias :find_all_records_json :find_all_json
1599
+
1600
+ # Load a single record (Hash) by type and id and optional parameters
1601
+ # Examples:
1602
+ # apps = find_record(:app)
1603
+ # report_types = find_record("reportTypes", {phrase:"amazon"})
1604
+ # pools = find_record("loadBalancerPool", balancer_id)
1605
+ # @return [Hash] of the object that was found or raises an exception if 404 not found encountered.
1606
+ def find_record(*args)
1607
+ #Morpheus::Logging::DarkPrinter.puts "find_record(#{args.join(', ')})" if Morpheus::Logging.debug?
1608
+ type, *request_args = args
1609
+ type = type.to_s.singularize.underscore
1610
+ object_key = respond_to?("#{type}_object_key", true) ? send("#{type}_object_key") : type.camelcase.singularize
1611
+ json_response = find_record_json(*args)
1612
+ if !json_response.key?(object_key)
1613
+ # maybe just use the first key like this:
1614
+ # object_key = json_response.keys.find { |k| json_response[k].is_a?(Hash) }
1615
+ # print_error(json_response) if Morpheus::Logging.debug?
1616
+ raise "API response is missing object property '#{object_key}'"
1617
+ end
1618
+ return json_response[object_key]
1619
+ end
1620
+
1621
+ # Load list of records by type and (optional) parameters
1622
+ # Examples:
1623
+ # apps = find_record(:app, 1)
1624
+ # report_types = find_record("reportType", 1)
1625
+ # pools = find_all("loadBalancerPool", load_balancer_id)
1626
+ def find_record_json(*args)
1627
+ #Morpheus::Logging::DarkPrinter.puts "find_record_json(#{args.join(', ')})" if Morpheus::Logging.debug?
1628
+ type, *request_args = args
1629
+ get_interface(type).get(*request_args)
1630
+ end
1631
+
1632
+ # Load json response for a list of records by type
1633
+ def get_interface(type)
1634
+ #Morpheus::Logging::DarkPrinter.puts "get_interface(#{type})" if Morpheus::Logging.debug?
1635
+ # todo: can probably just do @api_client ? @api_client.interface(interface_name) : nil
1636
+ type = type.to_s.singularize.underscore
1637
+ interface_name = "@#{type.pluralize}_interface"
1638
+ interface = nil
1639
+ if instance_variable_defined?(interface_name)
1640
+ interface = instance_variable_get(interface_name)
1641
+ if interface.nil?
1642
+ # Fix is to update connect() to do @apps_interface = @api_client.apps
1643
+ raise "API Interface #{interface_name} is nil"
1644
+ end
1645
+ else
1646
+ if @api_client.is_a?(Morpheus::APIClient)
1647
+ interface = @api_client.interface(type.pluralize)
1648
+ else
1649
+ raise "#{self.class} has not initalized @api_client"
1650
+ end
1651
+ end
1652
+ return interface
1653
+ end
1654
+
1407
1655
  module ClassMethods
1408
1656
 
1409
1657
  def prog_name
@@ -1411,14 +1659,14 @@ module Morpheus
1411
1659
  end
1412
1660
 
1413
1661
  def set_command_name(cmd_name)
1414
- @command_name = cmd_name
1662
+ @command_name = cmd_name.to_sym
1415
1663
  Morpheus::Cli::CliRegistry.add(self, self.command_name)
1416
1664
  end
1417
1665
 
1418
1666
  def default_command_name
1419
1667
  class_name = self.name.split('::')[-1]
1420
1668
  #class_name.sub!(/Command$/, '')
1421
- Morpheus::Cli::CliRegistry.cli_ize(class_name)
1669
+ Morpheus::Cli::CliRegistry.cli_ize(class_name).to_sym
1422
1670
  end
1423
1671
 
1424
1672
  def command_name
@@ -4,6 +4,7 @@ require 'morpheus/logging'
4
4
  require 'morpheus/cli/errors'
5
5
  require 'morpheus/cli/error_handler'
6
6
  require 'morpheus/cli/expression_parser'
7
+ require 'morpheus/ext/string'
7
8
 
8
9
  module Morpheus
9
10
  module Cli
@@ -297,7 +298,7 @@ module Morpheus
297
298
  every_command = cached_command_list
298
299
  guess = command_name
299
300
  suggestions = []
300
- while guess.size >= 3
301
+ while suggestions.empty? && guess.size >= 3
301
302
  plural_guess = guess.pluralize
302
303
  if every_command.include?(guess)
303
304
  suggestions << guess