morpheus-cli 5.5.1.5 → 5.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +25 -0
  4. data/lib/morpheus/api/archive_buckets_interface.rb +1 -1
  5. data/lib/morpheus/api/body_io.rb +22 -0
  6. data/lib/morpheus/api/catalog_item_types_interface.rb +5 -1
  7. data/lib/morpheus/api/clients_interface.rb +41 -0
  8. data/lib/morpheus/api/clouds_interface.rb +21 -0
  9. data/lib/morpheus/api/instances_interface.rb +8 -1
  10. data/lib/morpheus/api/integrations_interface.rb +30 -0
  11. data/lib/morpheus/api/library_instance_types_interface.rb +15 -3
  12. data/lib/morpheus/api/network_pool_server_types_interface.rb +9 -0
  13. data/lib/morpheus/api/plugins_interface.rb +22 -0
  14. data/lib/morpheus/api/roles_interface.rb +20 -1
  15. data/lib/morpheus/api/security_package_types_interface.rb +9 -0
  16. data/lib/morpheus/api/security_packages_interface.rb +9 -0
  17. data/lib/morpheus/api/security_scans_interface.rb +9 -0
  18. data/lib/morpheus/api/servers_interface.rb +17 -17
  19. data/lib/morpheus/api/storage_providers_interface.rb +1 -1
  20. data/lib/morpheus/api/virtual_images_interface.rb +1 -23
  21. data/lib/morpheus/cli/cli_command.rb +81 -7
  22. data/lib/morpheus/cli/commands/apps.rb +28 -2
  23. data/lib/morpheus/cli/commands/archives_command.rb +2 -2
  24. data/lib/morpheus/cli/commands/blueprints_command.rb +16 -0
  25. data/lib/morpheus/cli/commands/catalog_item_types_command.rb +34 -2
  26. data/lib/morpheus/cli/commands/clients_command.rb +338 -0
  27. data/lib/morpheus/cli/commands/clouds.rb +127 -1
  28. data/lib/morpheus/cli/commands/clusters.rb +42 -12
  29. data/lib/morpheus/cli/commands/curl_command.rb +114 -135
  30. data/lib/morpheus/cli/commands/hosts.rb +108 -11
  31. data/lib/morpheus/cli/commands/instances.rb +115 -14
  32. data/lib/morpheus/cli/commands/integrations_command.rb +215 -4
  33. data/lib/morpheus/cli/commands/invoices_command.rb +20 -11
  34. data/lib/morpheus/cli/commands/jobs_command.rb +299 -190
  35. data/lib/morpheus/cli/commands/library_cluster_layouts_command.rb +16 -2
  36. data/lib/morpheus/cli/commands/library_container_scripts_command.rb +14 -0
  37. data/lib/morpheus/cli/commands/library_container_templates_command.rb +131 -48
  38. data/lib/morpheus/cli/commands/library_container_types_command.rb +17 -4
  39. data/lib/morpheus/cli/commands/library_instance_types_command.rb +85 -7
  40. data/lib/morpheus/cli/commands/library_layouts_command.rb +32 -1
  41. data/lib/morpheus/cli/commands/library_option_lists_command.rb +30 -18
  42. data/lib/morpheus/cli/commands/library_option_types_command.rb +31 -14
  43. data/lib/morpheus/cli/commands/library_spec_templates_command.rb +14 -0
  44. data/lib/morpheus/cli/commands/library_upgrades_command.rb +2 -2
  45. data/lib/morpheus/cli/commands/network_pool_server_types.rb +20 -0
  46. data/lib/morpheus/cli/commands/network_pool_servers_command.rb +55 -158
  47. data/lib/morpheus/cli/commands/network_pools_command.rb +49 -23
  48. data/lib/morpheus/cli/commands/networks_command.rb +262 -45
  49. data/lib/morpheus/cli/commands/plugins.rb +213 -0
  50. data/lib/morpheus/cli/commands/price_sets_command.rb +27 -8
  51. data/lib/morpheus/cli/commands/prices_command.rb +17 -5
  52. data/lib/morpheus/cli/commands/processes_command.rb +2 -1
  53. data/lib/morpheus/cli/commands/remote.rb +7 -10
  54. data/lib/morpheus/cli/commands/roles.rb +924 -335
  55. data/lib/morpheus/cli/commands/search_command.rb +2 -0
  56. data/lib/morpheus/cli/commands/security_groups.rb +72 -84
  57. data/lib/morpheus/cli/commands/security_package_types.rb +32 -0
  58. data/lib/morpheus/cli/commands/security_packages.rb +84 -0
  59. data/lib/morpheus/cli/commands/security_scans.rb +107 -0
  60. data/lib/morpheus/cli/commands/service_plans_command.rb +16 -14
  61. data/lib/morpheus/cli/commands/subnets_command.rb +15 -1
  62. data/lib/morpheus/cli/commands/tasks.rb +34 -1
  63. data/lib/morpheus/cli/commands/tenants_command.rb +1 -1
  64. data/lib/morpheus/cli/commands/user_settings_command.rb +11 -2
  65. data/lib/morpheus/cli/commands/users.rb +50 -9
  66. data/lib/morpheus/cli/commands/virtual_images.rb +14 -0
  67. data/lib/morpheus/cli/commands/workflows.rb +14 -0
  68. data/lib/morpheus/cli/mixins/accounts_helper.rb +6 -5
  69. data/lib/morpheus/cli/mixins/infrastructure_helper.rb +79 -0
  70. data/lib/morpheus/cli/mixins/jobs_helper.rb +4 -5
  71. data/lib/morpheus/cli/mixins/library_helper.rb +2 -0
  72. data/lib/morpheus/cli/mixins/logs_helper.rb +3 -0
  73. data/lib/morpheus/cli/mixins/monitoring_helper.rb +1 -1
  74. data/lib/morpheus/cli/mixins/print_helper.rb +29 -4
  75. data/lib/morpheus/cli/mixins/provisioning_helper.rb +38 -9
  76. data/lib/morpheus/cli/mixins/rest_command.rb +106 -8
  77. data/lib/morpheus/cli/mixins/secondary_rest_command.rb +6 -2
  78. data/lib/morpheus/cli/option_types.rb +94 -25
  79. data/lib/morpheus/cli/version.rb +1 -1
  80. data/lib/morpheus/formatters.rb +10 -1
  81. metadata +15 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8637acf5e4ce4a0673114edf18f3b69604574905bf6507272411efb1abd6c684
4
- data.tar.gz: 5cc836f09c1aa1cf164d5e7ae8fb3fa9a793cfbff0192543f45fe313404226ac
3
+ metadata.gz: 0161a73b2f75bfc74f92f94cb0acf5058cdfb4c307225315b8ed91ec198fae16
4
+ data.tar.gz: 9ae526229db5a69ba1f948e4903844761d2d26e46a354dcc3966d3c2e7538491
5
5
  SHA512:
6
- metadata.gz: c4adf8fb42bfe890394b8c988144ad9153f70e0ff1e4d2159b71557c14360b0b3dd1a11aff94409a8b4bbb61b17c27af5a6ebd61ff484182fd85812c5e0d5b0e
7
- data.tar.gz: '09af6071b1536a08fad258e3ff01330916a6e7a7c655359618d7f2ce9f00f24879b451a70cfd4ebf32498e7a048423addf9af472873fdcd5236ea04730d4fd3d'
6
+ metadata.gz: ea86420d90f1a3c95e6e63b181d27dada07884cf228e617d6031f09caa3d108126b0b2762ad3cb2da1bb8e8b4d816d0b065860d1bbb51d02490b9b25c250c23e
7
+ data.tar.gz: bf62144dc584582b82fcb825bebb26d083df76c2da7180f0b17260410ad84b1f761e5c7d7780711e4db3307ad3a5b71c8a338d35202c382d97ec5b373dee77a7
data/Dockerfile CHANGED
@@ -1,5 +1,5 @@
1
1
  FROM ruby:2.7.5
2
2
 
3
- RUN gem install morpheus-cli -v 5.5.1.5
3
+ RUN gem install morpheus-cli -v 5.5.2
4
4
 
5
5
  ENTRYPOINT ["morpheus"]
@@ -2,6 +2,7 @@ require 'json'
2
2
  require 'uri'
3
3
  require 'cgi'
4
4
  require 'morpheus/rest_client'
5
+ #require 'morpheus/api/body_io'
5
6
  # require 'rest-client'
6
7
 
7
8
  class Morpheus::APIClient
@@ -672,6 +673,10 @@ class Morpheus::APIClient
672
673
  Morpheus::NetworkPoolServersInterface.new(common_interface_options).setopts(@options)
673
674
  end
674
675
 
676
+ def network_pool_server_types
677
+ Morpheus::NetworkPoolServerTypesInterface.new(common_interface_options).setopts(@options)
678
+ end
679
+
675
680
  def network_domains
676
681
  Morpheus::NetworkDomainsInterface.new(common_interface_options).setopts(@options)
677
682
  end
@@ -756,6 +761,10 @@ class Morpheus::APIClient
756
761
  Morpheus::PackagesInterface.new(common_interface_options).setopts(@options)
757
762
  end
758
763
 
764
+ def plugins
765
+ Morpheus::PluginsInterface.new(common_interface_options).setopts(@options)
766
+ end
767
+
759
768
  def cypher
760
769
  Morpheus::CypherInterface.new(common_interface_options).setopts(@options)
761
770
  end
@@ -912,6 +921,22 @@ class Morpheus::APIClient
912
921
  Morpheus::CredentialTypesInterface.new(common_interface_options).setopts(@options)
913
922
  end
914
923
 
924
+ def clients
925
+ Morpheus::ClientsInterface.new(common_interface_options).setopts(@options)
926
+ end
927
+
928
+ def security_packages
929
+ Morpheus::SecurityPackagesInterface.new(common_interface_options).setopts(@options)
930
+ end
931
+
932
+ def security_package_types
933
+ Morpheus::SecurityPackageTypesInterface.new(common_interface_options).setopts(@options)
934
+ end
935
+
936
+ def security_scans
937
+ Morpheus::SecurityScansInterface.new(common_interface_options).setopts(@options)
938
+ end
939
+
915
940
  def rest(endpoint)
916
941
  Morpheus::RestInterface.new(common_interface_options).setopts(@options.merge({base_path: "#{@base_url}/api/#{endpoint}"}))
917
942
  end
@@ -42,7 +42,7 @@ class Morpheus::ArchiveBucketsInterface < Morpheus::APIClient
42
42
  if file_path.to_s.strip == "/"
43
43
  file_path = ""
44
44
  end
45
- url = "#{@base_url}/api/archives/buckets/#{CGI::escape(id.to_s)}" + "/files/#{CGI::escape(file_path)}".squeeze('/')
45
+ url = "#{@base_url}/api/archives/buckets/#{CGI::escape(id.to_s)}" + "/files/#{escape_filepath(file_path)}".squeeze('/')
46
46
  headers = { params: params, authorization: "Bearer #{@access_token}" }
47
47
  opts = {method: :get, url: url, headers: headers}
48
48
  execute(opts)
@@ -0,0 +1,22 @@
1
+ require 'forwardable'
2
+
3
+ # wrapper class for input stream so that HTTP doesn't blow up when using it
4
+ # ie. calling size() and rewind()
5
+ class Morpheus::BodyIO
6
+ extend Forwardable
7
+
8
+ def initialize(io)
9
+ @io = io
10
+ end
11
+
12
+ def size
13
+ 0
14
+ end
15
+
16
+ def rewind
17
+ nil
18
+ end
19
+
20
+ def_delegators :@io, :read, :readpartial, :write
21
+
22
+ end
@@ -19,7 +19,11 @@ class Morpheus::CatalogItemTypesInterface < Morpheus::RestInterface
19
19
  if dark_logo_file
20
20
  payload["catalogItemType"]["darkLogo"] = dark_logo_file
21
21
  end
22
- payload[:multipart] = true
22
+ if logo_file.is_a?(File) || dark_logo_file.is_a?(File)
23
+ payload[:multipart] = true
24
+ else
25
+ headers['Content-Type'] = 'application/x-www-form-urlencoded'
26
+ end
23
27
  execute(method: :put, url: url, headers: headers, payload: payload)
24
28
  end
25
29
 
@@ -0,0 +1,41 @@
1
+ require 'morpheus/api/api_client'
2
+
3
+ class Morpheus::ClientsInterface < Morpheus::APIClient
4
+
5
+ def list(params={}, headers={})
6
+ url = "#{@base_url}/api/clients"
7
+ headers = { params: params, authorization: "Bearer #{@access_token}" }
8
+ opts = {method: :get, url: url, headers: headers}
9
+ execute(opts)
10
+ end
11
+
12
+ def get(id, params={})
13
+ raise "#{self.class}.get() passed a blank name!" if id.to_s == ''
14
+ url = "#{@base_url}/api/clients/#{id}"
15
+ headers = { params: params, authorization: "Bearer #{@access_token}" }
16
+ opts = {method: :get, url: url, headers: headers}
17
+ execute(opts)
18
+ end
19
+
20
+ def create(payload)
21
+ url = "#{@base_url}/api/clients"
22
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
23
+ opts = {method: :post, url: url, headers: headers, payload: payload.to_json}
24
+ execute(opts)
25
+ end
26
+
27
+ def update(id, payload)
28
+ url = "#{@base_url}/api/clients/#{id}"
29
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
30
+ opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
31
+ execute(opts)
32
+ end
33
+
34
+ def destroy(id, params={})
35
+ url = "#{@base_url}/api/clients/#{id}"
36
+ headers = { params: params, authorization: "Bearer #{@access_token}" }
37
+ opts = {method: :delete, url: url, headers: headers}
38
+ execute(opts)
39
+ end
40
+
41
+ end
@@ -116,4 +116,25 @@ class Morpheus::CloudsInterface < Morpheus::APIClient
116
116
  execute(opts)
117
117
  end
118
118
 
119
+ # NOT json, multipart file upload
120
+ def update_logo(id, logo_file, dark_logo_file=nil)
121
+ url = "#{@base_url}/api/zones/#{id}/update-logo"
122
+ headers = { :params => {}, :authorization => "Bearer #{@access_token}"}
123
+ payload = {}
124
+ # payload["zone"] = {}
125
+ if logo_file
126
+ # payload["zone"]["logo"] = logo_file
127
+ payload["logo"] = logo_file
128
+ end
129
+ if dark_logo_file
130
+ # payload["instanceType"]["darkLogo"] = dark_logo_file
131
+ payload["darkLogo"] = dark_logo_file
132
+ end
133
+ if logo_file.is_a?(File) || dark_logo_file.is_a?(File)
134
+ payload[:multipart] = true
135
+ else
136
+ headers['Content-Type'] = 'application/x-www-form-urlencoded'
137
+ end
138
+ execute(method: :post, url: url, headers: headers, payload: payload)
139
+ end
119
140
  end
@@ -367,6 +367,13 @@ class Morpheus::InstancesInterface < Morpheus::APIClient
367
367
  execute(opts)
368
368
  end
369
369
 
370
+ def update_network_label(network_id, instance_id, payload)
371
+ url = "#{@base_url}/api/instances/#{instance_id}/networkInterfaces/#{network_id}"
372
+ headers = {authorization: "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
373
+ opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
374
+ execute(opts)
375
+ end
376
+
370
377
  def deploys(id, params)
371
378
  # todo: make this plural??
372
379
  execute(method: :get, url: "/api/instances/#{id}/deploy", params: params)
@@ -408,7 +415,7 @@ class Morpheus::InstancesInterface < Morpheus::APIClient
408
415
  end
409
416
 
410
417
  def remove_from_control(ids, params={})
411
- url = "#{@base_url}/api/instances/removeFromControl"
418
+ url = "#{@base_url}/api/instances/remove-from-control"
412
419
  payload = { ids: ids }
413
420
  headers = { :params => params,:authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
414
421
  opts = {method: :delete, url: url, headers: headers, payload: payload.to_json}
@@ -41,4 +41,34 @@ class Morpheus::IntegrationsInterface < Morpheus::RestInterface
41
41
  execute(method: :delete, url: "#{base_path}/#{id}/objects/#{obj_id}", params: params, headers: headers)
42
42
  end
43
43
 
44
+ ## Integration Inventory Item CRUD
45
+
46
+ def list_inventory(id, params={}, headers={})
47
+ validate_id!(id)
48
+ execute(method: :get, url: "#{base_path}/#{id}/inventory", params: params, headers: headers)
49
+ end
50
+
51
+ def get_inventory(id, inventory_id, params={}, headers={})
52
+ validate_id!(id)
53
+ validate_id!(inventory_id)
54
+ execute(method: :get, url: "#{base_path}/#{id}/inventory/#{inventory_id}", params: params, headers: headers)
55
+ end
56
+
57
+ # def create_inventory(id, payload, params={}, headers={})
58
+ # validate_id!(id)
59
+ # execute(method: :post, url: "#{base_path}/#{id}/inventory", params: params, payload: payload, headers: headers)
60
+ # end
61
+
62
+ def update_inventory(id, inventory_id, payload, params={}, headers={})
63
+ validate_id!(id)
64
+ validate_id!(inventory_id)
65
+ execute(method: :put, url: "#{base_path}/#{id}/inventory/#{inventory_id}", params: params, payload: payload, headers: headers)
66
+ end
67
+
68
+ # def destroy_inventory(id, inventory_id, params = {}, headers={})
69
+ # validate_id!(id)
70
+ # validate_id!(inventory_id)
71
+ # execute(method: :delete, url: "#{base_path}/#{id}/inventory/#{inventory_id}", params: params, headers: headers)
72
+ # end
73
+
44
74
  end
@@ -50,12 +50,24 @@ class Morpheus::LibraryInstanceTypesInterface < Morpheus::APIClient
50
50
  end
51
51
 
52
52
  # NOT json, multipart file upload
53
- def update_logo(id, logo_file)
53
+ def update_logo(id, logo_file, dark_logo_file=nil)
54
54
  url = "#{@base_url}/api/library/#{id}/update-logo"
55
55
  headers = { :params => {}, :authorization => "Bearer #{@access_token}"}
56
56
  payload = {}
57
- payload[:logo] = logo_file
58
- payload[:multipart] = true
57
+ # payload["instanceType"] = {}
58
+ if logo_file
59
+ # payload["instanceType"]["logo"] = logo_file
60
+ payload["logo"] = logo_file
61
+ end
62
+ if dark_logo_file
63
+ # payload["instanceType"]["darkLogo"] = dark_logo_file
64
+ payload["darkLogo"] = dark_logo_file
65
+ end
66
+ if logo_file.is_a?(File) || dark_logo_file.is_a?(File)
67
+ payload[:multipart] = true
68
+ else
69
+ headers['Content-Type'] = 'application/x-www-form-urlencoded'
70
+ end
59
71
  execute(method: :post, url: url, headers: headers, payload: payload)
60
72
  end
61
73
 
@@ -0,0 +1,9 @@
1
+ require 'morpheus/api/read_interface'
2
+
3
+ class Morpheus::NetworkPoolServerTypesInterface < Morpheus::ReadInterface
4
+
5
+ def base_path
6
+ "/api/networks/pool-server-types"
7
+ end
8
+
9
+ end
@@ -0,0 +1,22 @@
1
+ require 'morpheus/api/rest_interface'
2
+
3
+ class Morpheus::PluginsInterface < Morpheus::RestInterface
4
+
5
+ def base_path
6
+ "/api/plugins"
7
+ end
8
+
9
+ # upload a file with content-type: multipart
10
+ def upload(local_file, params={}, headers={})
11
+ url = "#{base_path}/upload"
12
+ payload = {}
13
+ payload[:multipart] = true
14
+ payload["plugin"] = local_file
15
+ execute(method: :post, url: url, params: params, payload: payload, headers: headers, timeout: 172800)
16
+ end
17
+
18
+ def check_updates(payload={}, params={}, headers={})
19
+ execute(method: :post, url: "#{base_path}/check-updates", params: params, payload: payload, headers: headers)
20
+ end
21
+
22
+ end
@@ -11,7 +11,12 @@ class Morpheus::RolesInterface < Morpheus::APIClient
11
11
 
12
12
  def list(account_id, options={})
13
13
  url = build_url(account_id)
14
- headers = { params: {}, authorization: "Bearer #{@access_token}" }
14
+ params = {}
15
+ if account_id
16
+ params['tenant'] = account_id
17
+ end
18
+
19
+ headers = { params: params, authorization: "Bearer #{@access_token}" }
15
20
  headers[:params].merge!(options)
16
21
  execute(method: :get, url: url, headers: headers)
17
22
  end
@@ -99,6 +104,20 @@ class Morpheus::RolesInterface < Morpheus::APIClient
99
104
  execute(method: :put, url: url, headers: headers, payload: payload.to_json)
100
105
  end
101
106
 
107
+ def update_task(account_id, id, options)
108
+ url = build_url(account_id, id) + "/update-task"
109
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
110
+ payload = options
111
+ execute(method: :put, url: url, headers: headers, payload: payload.to_json)
112
+ end
113
+
114
+ def update_task_set(account_id, id, options)
115
+ url = build_url(account_id, id) + "/update-task-set"
116
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
117
+ payload = options
118
+ execute(method: :put, url: url, headers: headers, payload: payload.to_json)
119
+ end
120
+
102
121
  private
103
122
 
104
123
  def build_url(account_id=nil, role_id=nil)
@@ -0,0 +1,9 @@
1
+ require 'morpheus/api/read_interface'
2
+
3
+ class Morpheus::SecurityPackageTypesInterface < Morpheus::ReadInterface
4
+
5
+ def base_path
6
+ "/api/security-package-types"
7
+ end
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'morpheus/api/rest_interface'
2
+
3
+ class Morpheus::SecurityPackagesInterface < Morpheus::RestInterface
4
+
5
+ def base_path
6
+ "/api/security-packages"
7
+ end
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'morpheus/api/rest_interface'
2
+
3
+ class Morpheus::SecurityScansInterface < Morpheus::RestInterface
4
+
5
+ def base_path
6
+ "/api/security-scans"
7
+ end
8
+
9
+ end
@@ -2,25 +2,17 @@ require 'morpheus/api/api_client'
2
2
 
3
3
  class Morpheus::ServersInterface < Morpheus::APIClient
4
4
 
5
- def get(options=nil)
6
- url = "#{@base_url}/api/servers"
7
- headers = { params: {}, authorization: "Bearer #{@access_token}" }
8
- if options.is_a?(Hash)
9
- headers[:params].merge!(options)
10
- elsif options.is_a?(Numeric)
11
- url = "#{@base_url}/api/servers/#{options}"
12
- elsif options.is_a?(String)
13
- headers[:params]['name'] = options
14
- end
15
- opts = {method: :get, url: url, headers: headers}
16
- execute(opts)
5
+ def base_path
6
+ "/api/servers"
17
7
  end
18
8
 
19
- def list(params={})
20
- url = "#{@base_url}/api/servers"
21
- headers = { params: params, authorization: "Bearer #{@access_token}" }
22
- opts = {method: :get, url: url, headers: headers}
23
- execute(opts)
9
+ def list(params={}, headers={})
10
+ execute(method: :get, url: "#{base_path}", params: params, headers: headers)
11
+ end
12
+
13
+ def get(id, params={}, headers={})
14
+ validate_id!(id)
15
+ execute(method: :get, url: "#{base_path}/#{id}", params: params, headers: headers)
24
16
  end
25
17
 
26
18
  def create(options)
@@ -184,4 +176,12 @@ class Morpheus::ServersInterface < Morpheus::APIClient
184
176
  execute(opts)
185
177
  end
186
178
 
179
+ def update_network_label(network_id, server_id, payload)
180
+ url = "#{@base_url}/api/servers/#{server_id}/networkInterfaces/#{network_id}"
181
+ headers = {authorization: "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
182
+ opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
183
+ execute(opts)
184
+ end
185
+
186
+
187
187
  end
@@ -42,7 +42,7 @@ class Morpheus::StorageProvidersInterface < Morpheus::APIClient
42
42
  if file_path.to_s.strip == "/"
43
43
  file_path = ""
44
44
  end
45
- url = "#{@base_url}/api/storage/buckets/#{CGI::escape(id.to_s)}" + "/files/#{CGI::escape(file_path)}".squeeze('/')
45
+ url = "#{@base_url}/api/storage/buckets/#{CGI::escape(id.to_s)}" + "/files/#{escape_filepath(file_path)}".squeeze('/')
46
46
  headers = { params: params, authorization: "Bearer #{@access_token}" }
47
47
  opts = {method: :get, url: url, headers: headers}
48
48
  execute(opts)
@@ -1,7 +1,6 @@
1
1
  require 'morpheus/api/api_client'
2
2
  require 'http'
3
3
  require 'zlib'
4
- require 'forwardable'
5
4
 
6
5
  class Morpheus::VirtualImagesInterface < Morpheus::APIClient
7
6
 
@@ -61,27 +60,6 @@ class Morpheus::VirtualImagesInterface < Morpheus::APIClient
61
60
  # execute(method: :post, url: url, headers: headers, payload: payload)
62
61
  # end
63
62
 
64
- # wrapper class for input stream so that HTTP doesn't blow up when using it
65
- # ie. calling size() and rewind()
66
- class BodyIO
67
- extend Forwardable
68
-
69
- def initialize(io)
70
- @io = io
71
- end
72
-
73
- def size
74
- 0
75
- end
76
-
77
- def rewind
78
- nil
79
- end
80
-
81
- def_delegators :@io, :read, :readpartial, :write
82
-
83
- end
84
-
85
63
  # no multipart
86
64
  def upload(id, image_file, filename=nil, do_gzip=false)
87
65
  filename = filename || File.basename(image_file)
@@ -132,7 +110,7 @@ class Morpheus::VirtualImagesInterface < Morpheus::APIClient
132
110
  end
133
111
  gz.close
134
112
  }
135
- http_opts[:body] = BodyIO.new(rd)
113
+ http_opts[:body] = Morpheus::BodyIO.new(rd)
136
114
  response = http.post(url, http_opts)
137
115
  else
138
116
  if @dry_run
@@ -114,8 +114,8 @@ module Morpheus
114
114
  [id_list].flatten.collect {|it| it ? it.to_s.split(delim) : nil }.flatten.compact
115
115
  end
116
116
 
117
- def parse_bytes_param(bytes_param, option, assumed_unit = nil)
118
- if bytes_param && bytes_param.to_f > 0
117
+ def parse_bytes_param(bytes_param, option, assumed_unit = nil, allow_zero = false)
118
+ if bytes_param && ( bytes_param.to_f > 0 || ( allow_zero && bytes_param.to_i == 0 ))
119
119
  bytes_param.upcase!
120
120
  multiplier = 1
121
121
  unit = nil
@@ -151,6 +151,10 @@ module Morpheus
151
151
 
152
152
  # add each one to the OptionParser
153
153
  option_types.each do |option_type|
154
+ # skip hidden types
155
+ if option_type['type'] == 'hidden'
156
+ next
157
+ end
154
158
  if option_type['fieldName'].empty?
155
159
  puts_error "Missing fieldName for option type: #{option_type}" if Morpheus::Logging.debug?
156
160
  next
@@ -268,6 +272,10 @@ module Morpheus
268
272
  build_standard_delete_options(opts, options, includes, excludes)
269
273
  end
270
274
 
275
+ def build_standard_api_options(opts, options, includes=[], excludes=[])
276
+ build_common_options(opts, options, includes + [:query, :options, :payload, :json, :yaml, :csv, :fields, :select, :delim, :quiet, :dry_run, :remote], excludes)
277
+ end
278
+
271
279
  # number of decimal places to show with curreny
272
280
  def default_sigdig
273
281
  2
@@ -500,10 +508,14 @@ module Morpheus
500
508
  end
501
509
  end
502
510
 
503
- opts.on( '-D', '--desc', "Reverse Sort Order" ) do |v|
511
+ opts.on( '-D', '--desc', "Descending Sort Direction." ) do |v|
504
512
  options[:direction] = "desc"
505
513
  end
506
514
 
515
+ opts.on( "--reverse", "Reverse order of results. This invert is done by the client, not necessarily the entire dataset." ) do
516
+ options[:reverse] = true
517
+ end
518
+
507
519
  # arbitrary query parameters in the format -Q "category=web&phrase=nginx"
508
520
  # opts.on( '-Q', '--query PARAMS', "Query parameters. PARAMS format is 'foo=bar&category=web'" ) do |val|
509
521
  # options[:query_filters_raw] = val
@@ -743,6 +755,7 @@ module Morpheus
743
755
  options[:include_fields] = val
744
756
  end
745
757
  end
758
+ opts.add_hidden_option('-F, --old-fields') if opts.is_a?(Morpheus::Cli::OptionParser)
746
759
  opts.on('--raw-fields [x,y,z]', String, "Raw fields filters output like --fields except the properties [x,y,z] must be specified from the root of the response instead of relative to the the list or object context for this particular resource.") do |val|
747
760
  if val.size == 1 && val[0].downcase == 'all'
748
761
  options[:all_fields] = true
@@ -1271,6 +1284,23 @@ module Morpheus
1271
1284
  params.merge!(parse_query_options(options))
1272
1285
  end
1273
1286
 
1287
+ # Add a name=value query parameter, building an array if there is more than one
1288
+ # @param [Hash] params the query parameter map to append to
1289
+ # @param [String] key the parameter name
1290
+ # @param [Object] value the parameter value
1291
+ def add_query_parameter(params, key, value)
1292
+ # key = key.to_s
1293
+ if params.key?(key) && !params[key].nil?
1294
+ if !params[key].is_a?(Array)
1295
+ params[key] = [params[key]]
1296
+ end
1297
+ params[key] << value
1298
+ else
1299
+ params[key] = value
1300
+ end
1301
+ params
1302
+ end
1303
+
1274
1304
  # The default way to parse options for the get command
1275
1305
  # @param type [string]
1276
1306
  # @param options [Hash] The command options
@@ -1371,6 +1401,38 @@ module Morpheus
1371
1401
  payload
1372
1402
  end
1373
1403
 
1404
+ def build_payload(options, object_key=nil)
1405
+ payload = {}
1406
+ if options[:payload]
1407
+ parse_payload(options, object_key)
1408
+ else
1409
+ apply_options(payload, options, object_key)
1410
+ end
1411
+ return payload
1412
+ end
1413
+
1414
+ def parse_array(val, opts={})
1415
+ opts = {strip:true, allow_blank:false}.merge(opts)
1416
+ values = []
1417
+ if val.is_a?(Array)
1418
+ values = val
1419
+ else
1420
+ # parse csv and strip white space by default
1421
+ values = val.to_s.split(",")#.collect {|it| it.to_s.strip }
1422
+ if opts[:strip]
1423
+ values = values.collect {|it| it.to_s.strip }
1424
+ end
1425
+ if !opts[:allow_blank]
1426
+ values.reject! {|it| it.to_s.strip.empty? }
1427
+ end
1428
+ end
1429
+ values
1430
+ end
1431
+
1432
+ def parse_labels(val)
1433
+ parse_array(val, {strip:true, allow_blank:false})
1434
+ end
1435
+
1374
1436
  # support -O OPTION switch
1375
1437
  def apply_options(payload, options, object_key=nil)
1376
1438
  payload ||= {}
@@ -1528,8 +1590,20 @@ module Morpheus
1528
1590
  end
1529
1591
  begin
1530
1592
  json_response = interface.get(*ids)
1531
- return json_response[object_key]
1532
- rescue Exception => e
1593
+ if !json_response.key?(object_key)
1594
+ # maybe just use the first key like this:
1595
+ # object_key = json_response.keys.find { |k| json_response[k].is_a?(Hash) }
1596
+ #puts_error(json_response) if Morpheus::Logging.debug?
1597
+ raise "API response is missing object property '#{object_key}'"
1598
+ end
1599
+ record = json_response[object_key]
1600
+ if record.nil?
1601
+ print_red_alert "#{label} not found in API response (#{object_key})"
1602
+ return nil
1603
+ else
1604
+ return json_response[object_key]
1605
+ end
1606
+ rescue ::RestClient::Exception => e
1533
1607
  if e.response && e.response.code == 404
1534
1608
  print_red_alert "#{label} not found by id #{ids.last}"
1535
1609
  return nil
@@ -1593,7 +1667,7 @@ module Morpheus
1593
1667
  if !json_response.key?(list_key)
1594
1668
  # maybe just use the first key like this:
1595
1669
  # list_key = json_response.keys.find { |k| json_response[k].is_a?(Array) }
1596
- # print_error(json_response) if Morpheus::Logging.debug?
1670
+ # puts_error(json_response) if Morpheus::Logging.debug?
1597
1671
  raise "API response is missing list property '#{list_key}'"
1598
1672
  end
1599
1673
  return json_response[list_key]
@@ -1624,7 +1698,7 @@ module Morpheus
1624
1698
  if !json_response.key?(object_key)
1625
1699
  # maybe just use the first key like this:
1626
1700
  # object_key = json_response.keys.find { |k| json_response[k].is_a?(Hash) }
1627
- # print_error(json_response) if Morpheus::Logging.debug?
1701
+ # puts_error(json_response) if Morpheus::Logging.debug?
1628
1702
  raise "API response is missing object property '#{object_key}'"
1629
1703
  end
1630
1704
  return json_response[object_key]