morpheus-cli 3.5.2 → 3.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/lib/morpheus/api/api_client.rb +16 -0
  3. data/lib/morpheus/api/blueprints_interface.rb +84 -0
  4. data/lib/morpheus/api/execution_request_interface.rb +33 -0
  5. data/lib/morpheus/api/instances_interface.rb +21 -0
  6. data/lib/morpheus/api/packages_interface.rb +25 -5
  7. data/lib/morpheus/api/processes_interface.rb +34 -0
  8. data/lib/morpheus/api/roles_interface.rb +7 -0
  9. data/lib/morpheus/api/servers_interface.rb +8 -0
  10. data/lib/morpheus/api/user_settings_interface.rb +76 -0
  11. data/lib/morpheus/cli.rb +5 -1
  12. data/lib/morpheus/cli/alias_command.rb +1 -1
  13. data/lib/morpheus/cli/app_templates.rb +2 -1
  14. data/lib/morpheus/cli/apps.rb +173 -19
  15. data/lib/morpheus/cli/blueprints_command.rb +2134 -0
  16. data/lib/morpheus/cli/cli_command.rb +3 -1
  17. data/lib/morpheus/cli/clouds.rb +4 -10
  18. data/lib/morpheus/cli/coloring_command.rb +14 -8
  19. data/lib/morpheus/cli/containers_command.rb +92 -5
  20. data/lib/morpheus/cli/execution_request_command.rb +313 -0
  21. data/lib/morpheus/cli/hosts.rb +188 -7
  22. data/lib/morpheus/cli/instances.rb +472 -9
  23. data/lib/morpheus/cli/login.rb +1 -1
  24. data/lib/morpheus/cli/mixins/print_helper.rb +8 -0
  25. data/lib/morpheus/cli/mixins/processes_helper.rb +134 -0
  26. data/lib/morpheus/cli/option_types.rb +21 -16
  27. data/lib/morpheus/cli/packages_command.rb +469 -17
  28. data/lib/morpheus/cli/processes_command.rb +313 -0
  29. data/lib/morpheus/cli/remote.rb +20 -9
  30. data/lib/morpheus/cli/roles.rb +186 -6
  31. data/lib/morpheus/cli/shell.rb +10 -1
  32. data/lib/morpheus/cli/tasks.rb +4 -1
  33. data/lib/morpheus/cli/user_settings_command.rb +431 -0
  34. data/lib/morpheus/cli/version.rb +1 -1
  35. data/lib/morpheus/cli/whoami.rb +1 -1
  36. data/lib/morpheus/formatters.rb +14 -0
  37. data/lib/morpheus/morpkg.rb +119 -0
  38. data/morpheus-cli.gemspec +1 -0
  39. metadata +26 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e69dc73a61a5113eda7600546cc3930dfdd4f47a9a882cd0aa27bb9af12a5f97
4
- data.tar.gz: 9d47bacf74b477ab1d887f110b055b5cf9d89e0f65fff187b0bf2471a92b8616
3
+ metadata.gz: 23cf1069887e9d9fc379bb4c5d542ffaf746fb045ba394b281f1bcbe2f6979e0
4
+ data.tar.gz: 544bb68d0fc395fa8d6a76391028641e564d37f9f6f82c515d763420e83230bb
5
5
  SHA512:
6
- metadata.gz: 2187ecea61941471a82f73f0f2a86d555ec739d22bfe4bc30b7aa620fca16aa9b6a3372c9cc0adf21868d4283c83b5bd545cb8fc4cc1a253d1e37accb58e01af
7
- data.tar.gz: b39bc39b4b012dabad7c821b55690c1976d92a671abcb660fd57140506c499042b3cf77d80394d0c6e07669e59b3113856f256a5187ac7461929c8fbb4583d19
6
+ metadata.gz: '09147a460130571ad8a3f30e5e7062b290425d11c9dbf30f14ae5dedf4e99cd821b5fde46b6c3f69c1bd4eb3d2c4477a9df2ae5f766164fda7e99173bb9d877f'
7
+ data.tar.gz: 0d0775dd6ff2b7e9e670a295d44b2fe60e68095cc74df2b6cbd75d5dca3e2ea40e9378f5129fdf86bedae1ec9a1d0d667732ea50eaf03caf45d8c31837c0dc7d
@@ -61,6 +61,10 @@ class Morpheus::APIClient
61
61
  Morpheus::WhoamiInterface.new(@access_token, @refresh_token, @expires_at, @base_url)
62
62
  end
63
63
 
64
+ def user_settings
65
+ Morpheus::UserSettingsInterface.new(@access_token, @refresh_token, @expires_at, @base_url)
66
+ end
67
+
64
68
  def options
65
69
  Morpheus::OptionsInterface.new(@access_token, @refresh_token, @expires_at, @base_url)
66
70
  end
@@ -121,6 +125,10 @@ class Morpheus::APIClient
121
125
  Morpheus::AppsInterface.new(@access_token, @refresh_token, @expires_at, @base_url)
122
126
  end
123
127
 
128
+ def blueprints
129
+ Morpheus::BlueprintsInterface.new(@access_token, @refresh_token, @expires_at, @base_url)
130
+ end
131
+
124
132
  def app_templates
125
133
  Morpheus::AppTemplatesInterface.new(@access_token, @refresh_token, @expires_at, @base_url)
126
134
  end
@@ -303,4 +311,12 @@ class Morpheus::APIClient
303
311
  Morpheus::CypherInterface.new(@access_token, @refresh_token, @expires_at, @base_url)
304
312
  end
305
313
 
314
+ def execution_request
315
+ Morpheus::ExecutionRequestInterface.new(@access_token, @refresh_token, @expires_at, @base_url)
316
+ end
317
+
318
+ def processes
319
+ Morpheus::ProcessesInterface.new(@access_token, @refresh_token, @expires_at, @base_url)
320
+ end
321
+
306
322
  end
@@ -0,0 +1,84 @@
1
+ require 'morpheus/api/api_client'
2
+
3
+ class Morpheus::BlueprintsInterface < Morpheus::APIClient
4
+ def initialize(access_token, refresh_token,expires_at = nil, base_url=nil)
5
+ @access_token = access_token
6
+ @refresh_token = refresh_token
7
+ @base_url = base_url
8
+ @expires_at = expires_at
9
+ end
10
+
11
+ def get(id)
12
+ raise "#{self.class}.get() passed a blank id!" if id.to_s == ''
13
+ url = "#{@base_url}/api/blueprints/#{id}"
14
+ headers = { params: {}, authorization: "Bearer #{@access_token}" }
15
+ execute(method: :get, url: url, headers: headers)
16
+ end
17
+
18
+ def list(options={})
19
+ url = "#{@base_url}/api/blueprints"
20
+ headers = { params: {}, authorization: "Bearer #{@access_token}" }
21
+ headers[:params].merge!(options)
22
+ execute(method: :get, url: url, headers: headers)
23
+ end
24
+
25
+ def create(options)
26
+ url = "#{@base_url}/api/blueprints"
27
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
28
+ payload = options
29
+ execute(method: :post, url: url, headers: headers, payload: payload.to_json)
30
+ end
31
+
32
+ def update(id, options)
33
+ url = "#{@base_url}/api/blueprints/#{id}"
34
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
35
+ payload = options
36
+ execute(method: :put, url: url, headers: headers, payload: payload.to_json)
37
+ end
38
+
39
+ def update_permissions(id, options)
40
+ url = "#{@base_url}/api/blueprints/#{id}/update-permissions"
41
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
42
+ payload = options
43
+ execute(method: :post, url: url, headers: headers, payload: payload.to_json)
44
+ end
45
+
46
+ # multipart image upload
47
+ def save_image(id, image_file, params={})
48
+ url = "#{@base_url}/api/blueprints/#{id}/image"
49
+ headers = { :params => params, :authorization => "Bearer #{@access_token}"}
50
+ payload = {}
51
+ payload[:templateImage] = image_file
52
+ payload[:multipart] = true
53
+ execute(method: :post, url: url, headers: headers, payload: payload)
54
+ end
55
+
56
+ def duplicate(id, options)
57
+ url = "#{@base_url}/api/blueprints/#{id}/duplicate"
58
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
59
+ payload = options
60
+ execute(method: :post, url: url, headers: headers, payload: payload.to_json)
61
+ end
62
+
63
+ def destroy(id)
64
+ url = "#{@base_url}/api/blueprints/#{id}"
65
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
66
+ execute(method: :delete, url: url, headers: headers)
67
+ end
68
+
69
+ def list_tiers(options={})
70
+ url = "#{@base_url}/api/blueprints/tiers"
71
+ headers = { params: {}, authorization: "Bearer #{@access_token}" }
72
+ headers[:params].merge!(options)
73
+ execute(method: :get, url: url, headers: headers)
74
+ end
75
+
76
+ # unused, prefer /options/instanceTypes
77
+ # def list_types(options={})
78
+ # url = "#{@base_url}/api/blueprints/types"
79
+ # headers = { params: {}, authorization: "Bearer #{@access_token}" }
80
+ # headers[:params].merge!(options)
81
+ # execute(method: :get, url: url, headers: headers)
82
+ # end
83
+
84
+ end
@@ -0,0 +1,33 @@
1
+ require 'morpheus/api/api_client'
2
+
3
+ class Morpheus::ExecutionRequestInterface < Morpheus::APIClient
4
+ def initialize(access_token, refresh_token, expires_at = nil, base_url=nil)
5
+ @access_token = access_token
6
+ @refresh_token = refresh_token
7
+ @base_url = base_url
8
+ @expires_at = expires_at
9
+ end
10
+
11
+ def get(id, params={})
12
+ raise "#{self.class}.get() passed a blank id!" if id.to_s == ''
13
+ url = "#{@base_url}/api/execution-request/#{id}"
14
+ headers = { :params => params, authorization: "Bearer #{@access_token}"}
15
+ opts = {method: :get, url: url, headers: headers}
16
+ execute(opts)
17
+ end
18
+
19
+ def create(params, payload)
20
+ url = "#{@base_url}/api/execution-request/execute"
21
+ headers = { :params => params, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json'}
22
+ opts = {method: :post, url: url, headers: headers, payload: payload.to_json}
23
+ execute(opts)
24
+ end
25
+
26
+ def execute_against_lease(id, params, payload)
27
+ url = "#{@base_url}/api/execution-request/#{id}"
28
+ headers = { :params => params, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json'}
29
+ opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
30
+ execute(opts)
31
+ end
32
+
33
+ end
@@ -262,4 +262,25 @@ class Morpheus::InstancesInterface < Morpheus::APIClient
262
262
  execute(opts)
263
263
  end
264
264
 
265
+ def history(id, params={})
266
+ url = "#{@base_url}/api/instances/#{id}/history"
267
+ headers = { params: params, authorization: "Bearer #{@access_token}" }
268
+ opts = {method: :get, url: url, headers: headers}
269
+ execute(opts)
270
+ end
271
+
272
+ def history_details(id, process_id, params={})
273
+ url = "#{@base_url}/api/instances/#{id}/history/#{process_id}"
274
+ headers = { params: params, authorization: "Bearer #{@access_token}" }
275
+ opts = {method: :get, url: url, headers: headers}
276
+ execute(opts)
277
+ end
278
+
279
+ def history_event_details(id, process_event_id, params={})
280
+ url = "#{@base_url}/api/instances/#{id}/history/events/#{process_event_id}"
281
+ headers = { params: params, authorization: "Bearer #{@access_token}" }
282
+ opts = {method: :get, url: url, headers: headers}
283
+ execute(opts)
284
+ end
285
+
265
286
  end
@@ -32,18 +32,38 @@ class Morpheus::PackagesInterface < Morpheus::APIClient
32
32
  execute(opts)
33
33
  end
34
34
 
35
- def install(payload)
35
+ def info(params={})
36
+ url = "#{@base_url}/api/packages/info"
37
+ headers = { params: {}, authorization: "Bearer #{@access_token}" }
38
+ headers[:params].merge!(params)
39
+ opts = {method: :get, url: url, headers: headers}
40
+ execute(opts)
41
+ end
42
+
43
+ def install(params={}, payload={})
36
44
  url = "#{@base_url}/api/packages/install"
37
- headers = { :params => {}, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
45
+ headers = { :params => params, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
38
46
  opts = {method: :post, url: url, headers: headers, payload: payload.to_json}
39
47
  execute(opts)
40
48
  end
41
49
 
42
- def install_file(package_file, params={})
50
+ # def install_file(package_file, params={})
51
+ # url = "#{@base_url}/api/packages/install-file"
52
+ # headers = { :params => params, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/octet-stream'}
53
+ # payload = package_file
54
+ # execute(method: :post, url: url, headers: headers, payload: payload, timeout: 36000)
55
+ # end
56
+
57
+ def install_file(local_file, params={})
43
58
  url = "#{@base_url}/api/packages/install-file"
44
59
  headers = { :params => params, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/octet-stream'}
45
- payload = package_file
46
- execute(method: :post, url: url, headers: headers, payload: payload, timeout: 36000)
60
+ if !local_file.kind_of?(File)
61
+ local_file = File.new(local_file, 'rb')
62
+ end
63
+ payload = local_file
64
+ headers['Content-Length'] = local_file.size # File.size(local_file)
65
+ opts = {method: :post, url: url, headers: headers, payload: payload}
66
+ execute(opts)
47
67
  end
48
68
 
49
69
  def update(id, payload)
@@ -0,0 +1,34 @@
1
+ require 'morpheus/api/api_client'
2
+
3
+ class Morpheus::ProcessesInterface < Morpheus::APIClient
4
+ def initialize(access_token, refresh_token,expires_at = nil, base_url=nil)
5
+ @access_token = access_token
6
+ @refresh_token = refresh_token
7
+ @base_url = base_url
8
+ @expires_at = expires_at
9
+ end
10
+
11
+ def list(params={})
12
+ url = "#{@base_url}/api/processes"
13
+ headers = { params: params, authorization: "Bearer #{@access_token}" }
14
+ opts = {method: :get, url: url, headers: headers}
15
+ execute(opts)
16
+ end
17
+
18
+ def get(id, params={})
19
+ raise "#{self.class}.get() passed a blank id!" if id.to_s == ''
20
+ url = "#{@base_url}/api/processes/#{id}"
21
+ headers = { params: params, authorization: "Bearer #{@access_token}" }
22
+ opts = {method: :get, url: url, headers: headers}
23
+ execute(opts)
24
+ end
25
+
26
+ def get_event(id, params={})
27
+ raise "#{self.class}.get() passed a blank id!" if id.to_s == ''
28
+ url = "#{@base_url}/api/processes/events/#{id}"
29
+ headers = { params: params, authorization: "Bearer #{@access_token}" }
30
+ opts = {method: :get, url: url, headers: headers}
31
+ execute(opts)
32
+ end
33
+
34
+ end
@@ -56,6 +56,13 @@ class Morpheus::RolesInterface < Morpheus::APIClient
56
56
  execute(method: :put, url: url, headers: headers, payload: payload.to_json)
57
57
  end
58
58
 
59
+ def update_blueprint(account_id, id, options)
60
+ url = build_url(account_id, id) + "/update-blueprint"
61
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
62
+ payload = options
63
+ execute(method: :put, url: url, headers: headers, payload: payload.to_json)
64
+ end
65
+
59
66
  def update_group(account_id, id, options)
60
67
  url = build_url(account_id, id) + "/update-group"
61
68
  headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
@@ -34,6 +34,14 @@ class Morpheus::ServersInterface < Morpheus::APIClient
34
34
  execute(opts)
35
35
  end
36
36
 
37
+ def update(serverId, options)
38
+ url = "#{@base_url}/api/servers/#{serverId}"
39
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
40
+ payload = options
41
+ opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
42
+ execute(opts)
43
+ end
44
+
37
45
  def stop(serverId,payload = {})
38
46
  url = "#{@base_url}/api/servers/#{serverId}/stop"
39
47
  headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
@@ -0,0 +1,76 @@
1
+ require 'morpheus/api/api_client'
2
+
3
+ class Morpheus::UserSettingsInterface < Morpheus::APIClient
4
+ def initialize(access_token, refresh_token, expires_at = nil, base_url=nil)
5
+ @access_token = access_token
6
+ @refresh_token = refresh_token
7
+ @base_url = base_url
8
+ @expires_at = expires_at
9
+ end
10
+
11
+ def get(params={})
12
+ url = "#{@base_url}/api/user-settings"
13
+ headers = { :params => params, authorization: "Bearer #{@access_token}"}
14
+ opts = {method: :get, url: url, headers: headers}
15
+ execute(opts)
16
+ end
17
+
18
+ def update(params, payload)
19
+ url = "#{@base_url}/api/user-settings"
20
+ headers = { :params => params, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json'}
21
+ opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
22
+ execute(opts)
23
+ end
24
+
25
+ # NOT json, download file as attachment
26
+ def download_avatar(params, outfile)
27
+ url = "#{@base_url}/api/user-settings/avatar"
28
+ headers = { :params => params, :authorization => "Bearer #{@access_token}"}
29
+ opts = {method: :get, url: url, headers: headers, payload: payload}
30
+ execute(opts)
31
+ end
32
+
33
+ # NOT json, multipart file upload
34
+ def update_avatar(avatar_file, params={})
35
+ url = "#{@base_url}/api/user-settings/avatar"
36
+ headers = { :params => params, :authorization => "Bearer #{@access_token}"}
37
+ payload = {}
38
+ #payload['user'] ||= {}
39
+ #payload['user']['avatar'] = avatar_file
40
+ payload['user.avatar'] = avatar_file
41
+ payload[:multipart] = true
42
+ opts = {method: :post, url: url, headers: headers, payload: payload}
43
+ execute(opts)
44
+ end
45
+
46
+ def remove_avatar(params={})
47
+ url = "#{@base_url}/api/user-settings/avatar"
48
+ headers = { :params => params, :authorization => "Bearer #{@access_token}"}
49
+ # POST empty payload will do
50
+ payload = {}
51
+ opts = {method: :delete, url: url, headers: headers, payload: payload}
52
+ execute(opts)
53
+ end
54
+
55
+ def regenerate_access_token(params, payload={})
56
+ url = "#{@base_url}/api/user-settings/regenerate-access-token"
57
+ headers = { :params => params, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json'}
58
+ opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
59
+ execute(opts)
60
+ end
61
+
62
+ def clear_access_token(params, payload={})
63
+ url = "#{@base_url}/api/user-settings/clear-access-token"
64
+ headers = { :params => params, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json'}
65
+ opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
66
+ execute(opts)
67
+ end
68
+
69
+ def available_clients(params={})
70
+ url = "#{@base_url}/api/user-settings/api-clients"
71
+ headers = { :params => params, authorization: "Bearer #{@access_token}"}
72
+ opts = {method: :get, url: url, headers: headers}
73
+ execute(opts)
74
+ end
75
+
76
+ end
@@ -79,6 +79,7 @@ module Morpheus
79
79
  load 'morpheus/cli/login.rb'
80
80
  load 'morpheus/cli/logout.rb'
81
81
  load 'morpheus/cli/whoami.rb'
82
+ load 'morpheus/cli/user_settings_command.rb'
82
83
  load 'morpheus/cli/dashboard_command.rb'
83
84
  load 'morpheus/cli/power_schedules_command.rb'
84
85
  load 'morpheus/cli/execute_schedules_command.rb'
@@ -95,7 +96,8 @@ module Morpheus
95
96
  load 'morpheus/cli/instances.rb'
96
97
  load 'morpheus/cli/containers_command.rb'
97
98
  load 'morpheus/cli/apps.rb'
98
- load 'morpheus/cli/app_templates.rb'
99
+ load 'morpheus/cli/blueprints_command.rb'
100
+ load 'morpheus/cli/app_templates.rb' # deprecated
99
101
  load 'morpheus/cli/deploys.rb'
100
102
  load 'morpheus/cli/license.rb'
101
103
  load 'morpheus/cli/instance_types.rb'
@@ -145,6 +147,8 @@ module Morpheus
145
147
  load 'morpheus/cli/boot_scripts_command.rb'
146
148
  load 'morpheus/cli/archives_command.rb'
147
149
  load 'morpheus/cli/storage_providers_command.rb'
150
+ load 'morpheus/cli/execution_request_command.rb'
151
+ load 'morpheus/cli/processes_command.rb'
148
152
 
149
153
  # nice to have commands
150
154
  load 'morpheus/cli/curl_command.rb'
@@ -255,7 +255,7 @@ class Morpheus::Cli::AliasCommand
255
255
  out << "\n"
256
256
  out << reset
257
257
  my_aliases.each do |it|
258
- out << "\t#{cyan}#{it[:name]}#{reset}='#{it[:command_string]}'"
258
+ out << " #{cyan}#{it[:name]}#{reset}='#{it[:command_string]}'"
259
259
  out << "\n"
260
260
  end
261
261
  out << reset
@@ -5,11 +5,12 @@ require 'morpheus/cli/cli_command'
5
5
  require 'morpheus/cli/option_types'
6
6
  require 'json'
7
7
 
8
+ # deprecated and replaced with blueprints, hidden for now
8
9
  class Morpheus::Cli::AppTemplates
9
10
  include Morpheus::Cli::CliCommand
10
11
  include Morpheus::Cli::ProvisioningHelper
11
12
 
12
- #set_command_name :templates # instead of app-templates
13
+ set_command_hidden
13
14
 
14
15
  register_subcommands :list, :get, :add, :update, :remove
15
16
  register_subcommands :duplicate
@@ -6,12 +6,14 @@ require 'filesize'
6
6
  require 'table_print'
7
7
  require 'morpheus/cli/cli_command'
8
8
  require 'morpheus/cli/mixins/provisioning_helper'
9
+ require 'morpheus/cli/mixins/processes_helper'
9
10
 
10
11
  class Morpheus::Cli::Apps
11
12
  include Morpheus::Cli::CliCommand
12
13
  include Morpheus::Cli::ProvisioningHelper
14
+ include Morpheus::Cli::ProcessesHelper
13
15
 
14
- register_subcommands :list, :get, :add, :update, :remove, :add_instance, :remove_instance, :logs, :firewall_disable, :firewall_enable, :security_groups, :apply_security_groups
16
+ register_subcommands :list, :get, :add, :update, :remove, :add_instance, :remove_instance, :logs, :firewall_disable, :firewall_enable, :security_groups, :apply_security_groups, :history
15
17
  alias_subcommand :details, :get
16
18
  set_default_subcommand :list
17
19
 
@@ -27,6 +29,7 @@ class Morpheus::Cli::Apps
27
29
  @options_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).options
28
30
  @groups_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).groups
29
31
  @logs_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).logs
32
+ @processes_interface = @api_client.processes
30
33
  @active_group_id = Morpheus::Cli::Groups.active_groups[@appliance_name]
31
34
  end
32
35
 
@@ -97,7 +100,7 @@ class Morpheus::Cli::Apps
97
100
  optparse = Morpheus::Cli::OptionParser.new do |opts|
98
101
  opts.banner = subcommand_usage("[name] [options]")
99
102
  build_option_type_options(opts, options, add_app_option_types(false))
100
- # opts.on( '-t', '--template ID', "App Template ID. The app template to use. The default value is 'existing' which means no template, for creating a blank app and adding existing instances." ) do |val|
103
+ # opts.on( '-b', '--blueprint ID', "Blueprint ID. The blueprint to use. The default value is 'existing' which means no blueprint, for creating a blank app and adding existing instances." ) do |val|
101
104
  # options['template'] = val
102
105
  # end
103
106
  # opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
@@ -158,7 +161,7 @@ class Morpheus::Cli::Apps
158
161
  payload = {}
159
162
  params = Morpheus::Cli::OptionTypes.prompt(add_app_option_types, options[:options], @api_client, options[:params])
160
163
  params = params.deep_compact! # remove nulls and blank strings
161
- template_id = params.delete('template')
164
+ template_id = params.delete('blueprint')
162
165
  if template_id.to_s.empty? || template_id == 'existing'
163
166
  # new API parameter
164
167
  payload['templateId'] = 'existing'
@@ -166,9 +169,9 @@ class Morpheus::Cli::Apps
166
169
  payload['id'] = 'existing'
167
170
  payload['templateName'] = 'Existing Instances'
168
171
  else
169
- found_app_template = get_available_app_templates.find {|it| it['id'].to_s == template_id.to_s || it['name'].to_s == template_id.to_s }
172
+ found_app_template = get_available_blueprints.find {|it| it['id'].to_s == template_id.to_s || it['name'].to_s == template_id.to_s }
170
173
  if found_app_template.nil?
171
- print_red_alert "App Template not found by id #{template_id}"
174
+ print_red_alert "Blueprint not found by id #{template_id}"
172
175
  return 1
173
176
  end
174
177
  payload['templateId'] = found_app_template['id']
@@ -218,9 +221,9 @@ class Morpheus::Cli::Apps
218
221
  options = {}
219
222
  optparse = Morpheus::Cli::OptionParser.new do |opts|
220
223
  opts.banner = subcommand_usage("[app]")
221
- opts.on('--refresh-until [status]', String, "Refresh until status is reached. Default status is running.") do |val|
224
+ opts.on('--refresh [status]', String, "Refresh until status is reached. Default status is running.") do |val|
222
225
  if val.to_s.empty?
223
- options[:refresh_until_status] = "running"
226
+ options[:refresh_until_status] = "running,failed"
224
227
  else
225
228
  options[:refresh_until_status] = val.to_s.downcase
226
229
  end
@@ -314,10 +317,13 @@ class Morpheus::Cli::Apps
314
317
  if options[:refresh_interval].nil? || options[:refresh_interval].to_f < 0
315
318
  options[:refresh_interval] = 5
316
319
  end
317
- while app['status'].to_s.downcase != options[:refresh_until_status].to_s.downcase
320
+ statuses = options[:refresh_until_status].to_s.downcase.split(",").collect {|s| s.strip }.select {|s| !s.to_s.empty? }
321
+ if !statuses.include?(app['status'])
318
322
  print cyan
319
- print "Refreshing until status #{options[:refresh_until_status]} ..."
320
- sleep(options[:refresh_interval])
323
+ print "Status is #{app['status'] || 'unknown'}. Refreshing in #{options[:refresh_interval]} seconds"
324
+ #sleep(options[:refresh_interval])
325
+ sleep_with_dots(options[:refresh_interval])
326
+ print "\n"
321
327
  get(args)
322
328
  end
323
329
  end
@@ -865,11 +871,158 @@ class Morpheus::Cli::Apps
865
871
  end
866
872
  end
867
873
 
874
+ def history(args)
875
+ raw_args = args.dup
876
+ options = {}
877
+ #options[:show_output] = true
878
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
879
+ opts.banner = subcommand_usage("[app]")
880
+ # opts.on( '-n', '--node NODE_ID', "Scope history to specific Container or VM" ) do |node_id|
881
+ # options[:node_id] = node_id.to_i
882
+ # end
883
+ opts.on( nil, '--events', "Display sub processes (events)." ) do
884
+ options[:show_events] = true
885
+ end
886
+ opts.on( nil, '--output', "Display process output." ) do
887
+ options[:show_output] = true
888
+ end
889
+ build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
890
+ opts.footer = "List historical processes for a specific app.\n" +
891
+ "[app] is required. This is the name or id of an app."
892
+ end
893
+ optparse.parse!(args)
894
+
895
+ if args.count != 1
896
+ puts optparse
897
+ return 1
898
+ end
899
+ connect(options)
900
+ begin
901
+ app = find_app_by_name_or_id(args[0])
902
+
903
+ instance_ids = []
904
+ app['appTiers'].each do |app_tier|
905
+ app_tier['appInstances'].each do |app_instance|
906
+ instance_ids << app_instance['instance']['id']
907
+ end
908
+ end
909
+
910
+ # container_ids = instance['containers']
911
+ # if options[:node_id] && container_ids.include?(options[:node_id])
912
+ # container_ids = [options[:node_id]]
913
+ # end
914
+ params = {}
915
+ params['instanceIds'] = instance_ids
916
+ params.merge!(parse_list_options(options))
917
+ # params[:query] = params.delete(:phrase) unless params[:phrase].nil?
918
+ if options[:dry_run]
919
+ print_dry_run @processes_interface.dry.list(params)
920
+ return
921
+ end
922
+ json_response = @processes_interface.list(params)
923
+ if options[:json]
924
+ puts as_json(json_response, options, "processes")
925
+ return 0
926
+ elsif options[:yaml]
927
+ puts as_yaml(json_response, options, "processes")
928
+ return 0
929
+ elsif options[:csv]
930
+ puts records_as_csv(json_response['processes'], options)
931
+ return 0
932
+ else
933
+
934
+ title = "App History: #{app['name']}"
935
+ subtitles = []
936
+ if params[:query]
937
+ subtitles << "Search: #{params[:query]}".strip
938
+ end
939
+ subtitles += parse_list_subtitles(options)
940
+ print_h1 title, subtitles
941
+ if json_response['processes'].empty?
942
+ print "#{cyan}No process history found.#{reset}\n\n"
943
+ else
944
+ history_records = []
945
+ json_response["processes"].each do |process|
946
+ row = {
947
+ id: process['id'],
948
+ eventId: nil,
949
+ uniqueId: process['uniqueId'],
950
+ name: process['displayName'],
951
+ description: process['description'],
952
+ processType: process['processType'] ? (process['processType']['name'] || process['processType']['code']) : process['processTypeName'],
953
+ createdBy: process['createdBy'] ? (process['createdBy']['displayName'] || process['createdBy']['username']) : '',
954
+ startDate: format_local_dt(process['startDate']),
955
+ duration: format_process_duration(process),
956
+ status: format_process_status(process),
957
+ error: format_process_error(process),
958
+ output: format_process_output(process)
959
+ }
960
+ history_records << row
961
+ process_events = process['events'] || process['processEvents']
962
+ if options[:show_events]
963
+ if process_events
964
+ process_events.each do |process_event|
965
+ event_row = {
966
+ id: process['id'],
967
+ eventId: process_event['id'],
968
+ uniqueId: process_event['uniqueId'],
969
+ name: process_event['displayName'], # blank like the UI
970
+ description: process_event['description'],
971
+ processType: process_event['processType'] ? (process_event['processType']['name'] || process_event['processType']['code']) : process['processTypeName'],
972
+ createdBy: process_event['createdBy'] ? (process_event['createdBy']['displayName'] || process_event['createdBy']['username']) : '',
973
+ startDate: format_local_dt(process_event['startDate']),
974
+ duration: format_process_duration(process_event),
975
+ status: format_process_status(process_event),
976
+ error: format_process_error(process_event),
977
+ output: format_process_output(process_event)
978
+ }
979
+ history_records << event_row
980
+ end
981
+ else
982
+
983
+ end
984
+ end
985
+ end
986
+ columns = [
987
+ {:id => {:display_name => "PROCESS ID"} },
988
+ :name,
989
+ :description,
990
+ {:processType => {:display_name => "PROCESS TYPE"} },
991
+ {:createdBy => {:display_name => "CREATED BY"} },
992
+ {:startDate => {:display_name => "START DATE"} },
993
+ {:duration => {:display_name => "ETA/DURATION"} },
994
+ :status,
995
+ :error
996
+ ]
997
+ if options[:show_events]
998
+ columns.insert(1, {:eventId => {:display_name => "EVENT ID"} })
999
+ end
1000
+ if options[:show_output]
1001
+ columns << :output
1002
+ end
1003
+ # custom pretty table columns ...
1004
+ if options[:include_fields]
1005
+ columns = options[:include_fields]
1006
+ end
1007
+ print cyan
1008
+ print as_pretty_table(history_records, columns, options)
1009
+ #print_results_pagination(json_response)
1010
+ print_results_pagination(json_response, {:label => "process", :n_label => "processes"})
1011
+ print reset, "\n"
1012
+ return 0
1013
+ end
1014
+ end
1015
+ rescue RestClient::Exception => e
1016
+ print_rest_exception(e, options)
1017
+ exit 1
1018
+ end
1019
+ end
1020
+
868
1021
  private
869
1022
 
870
1023
  def add_app_option_types(connected=true)
871
1024
  [
872
- {'fieldName' => 'template', 'fieldLabel' => 'Template', 'type' => 'select', 'selectOptions' => (connected ? get_available_app_templates() : []), 'required' => true, 'defaultValue' => 'existing', 'description' => "The app template to use. The default value is 'existing' which means no template, for creating a blank app and adding existing instances."},
1025
+ {'fieldName' => 'blueprint', 'fieldLabel' => 'Blueprint', 'type' => 'select', 'selectOptions' => (connected ? get_available_blueprints() : []), 'required' => true, 'defaultValue' => 'existing', 'description' => "The blueprint to use. The default value is 'existing' which means no template, for creating a blank app and adding existing instances."},
873
1026
  {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Enter a name for this app'},
874
1027
  {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false},
875
1028
  {'fieldName' => 'group', 'fieldLabel' => 'Group', 'type' => 'select', 'selectOptions' => (connected ? get_available_groups() : []), 'required' => true},
@@ -879,7 +1032,7 @@ class Morpheus::Cli::Apps
879
1032
 
880
1033
  def update_app_option_types(connected=true)
881
1034
  list = add_app_option_types(connected)
882
- list = list.reject {|it| ["template", "group"].include? it['fieldName'] }
1035
+ list = list.reject {|it| ["blueprint", "group"].include? it['fieldName'] }
883
1036
  list.each {|it| it['required'] = false }
884
1037
  list
885
1038
  end
@@ -999,17 +1152,18 @@ class Morpheus::Cli::Apps
999
1152
  out
1000
1153
  end
1001
1154
 
1002
- def get_available_app_templates(refresh=false)
1003
- if !@available_app_templates || refresh
1004
- results = @options_interface.options_for_source('appTemplates',{})
1005
- @available_app_templates = results['data'].collect {|it|
1155
+ def get_available_blueprints(refresh=false)
1156
+ if !@available_blueprints || refresh
1157
+ results = @options_interface.options_for_source('appTemplates',{}) # still exists
1158
+ #results = @options_interface.options_for_source('blueprints',{})
1159
+ @available_blueprints = results['data'].collect {|it|
1006
1160
  {"id" => it["value"], "name" => it["name"], "value" => it["value"]}
1007
1161
  }
1008
1162
  default_option = {"id" => "existing", "name" => "Existing Instances", "value" => "existing"}
1009
- @available_app_templates.unshift(default_option)
1163
+ @available_blueprints.unshift(default_option)
1010
1164
  end
1011
- #puts "get_available_app_templates() rtn: #{@available_app_templates.inspect}"
1012
- return @available_app_templates
1165
+ #puts "get_available_blueprints() rtn: #{@available_blueprints.inspect}"
1166
+ return @available_blueprints
1013
1167
  end
1014
1168
 
1015
1169
  def get_available_environments(refresh=false)