morpheus-cli 3.5.2 → 3.5.3
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.
- checksums.yaml +4 -4
- data/lib/morpheus/api/api_client.rb +16 -0
- data/lib/morpheus/api/blueprints_interface.rb +84 -0
- data/lib/morpheus/api/execution_request_interface.rb +33 -0
- data/lib/morpheus/api/instances_interface.rb +21 -0
- data/lib/morpheus/api/packages_interface.rb +25 -5
- data/lib/morpheus/api/processes_interface.rb +34 -0
- data/lib/morpheus/api/roles_interface.rb +7 -0
- data/lib/morpheus/api/servers_interface.rb +8 -0
- data/lib/morpheus/api/user_settings_interface.rb +76 -0
- data/lib/morpheus/cli.rb +5 -1
- data/lib/morpheus/cli/alias_command.rb +1 -1
- data/lib/morpheus/cli/app_templates.rb +2 -1
- data/lib/morpheus/cli/apps.rb +173 -19
- data/lib/morpheus/cli/blueprints_command.rb +2134 -0
- data/lib/morpheus/cli/cli_command.rb +3 -1
- data/lib/morpheus/cli/clouds.rb +4 -10
- data/lib/morpheus/cli/coloring_command.rb +14 -8
- data/lib/morpheus/cli/containers_command.rb +92 -5
- data/lib/morpheus/cli/execution_request_command.rb +313 -0
- data/lib/morpheus/cli/hosts.rb +188 -7
- data/lib/morpheus/cli/instances.rb +472 -9
- data/lib/morpheus/cli/login.rb +1 -1
- data/lib/morpheus/cli/mixins/print_helper.rb +8 -0
- data/lib/morpheus/cli/mixins/processes_helper.rb +134 -0
- data/lib/morpheus/cli/option_types.rb +21 -16
- data/lib/morpheus/cli/packages_command.rb +469 -17
- data/lib/morpheus/cli/processes_command.rb +313 -0
- data/lib/morpheus/cli/remote.rb +20 -9
- data/lib/morpheus/cli/roles.rb +186 -6
- data/lib/morpheus/cli/shell.rb +10 -1
- data/lib/morpheus/cli/tasks.rb +4 -1
- data/lib/morpheus/cli/user_settings_command.rb +431 -0
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/whoami.rb +1 -1
- data/lib/morpheus/formatters.rb +14 -0
- data/lib/morpheus/morpkg.rb +119 -0
- data/morpheus-cli.gemspec +1 -0
- metadata +26 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 23cf1069887e9d9fc379bb4c5d542ffaf746fb045ba394b281f1bcbe2f6979e0
|
4
|
+
data.tar.gz: 544bb68d0fc395fa8d6a76391028641e564d37f9f6f82c515d763420e83230bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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 =>
|
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
|
-
|
46
|
-
|
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
|
data/lib/morpheus/cli.rb
CHANGED
@@ -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/
|
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 << "
|
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
|
-
|
13
|
+
set_command_hidden
|
13
14
|
|
14
15
|
register_subcommands :list, :get, :add, :update, :remove
|
15
16
|
register_subcommands :duplicate
|
data/lib/morpheus/cli/apps.rb
CHANGED
@@ -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( '-
|
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('
|
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 =
|
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 "
|
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
|
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
|
-
|
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 "
|
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' => '
|
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| ["
|
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
|
1003
|
-
if !@
|
1004
|
-
results = @options_interface.options_for_source('appTemplates',{})
|
1005
|
-
|
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
|
-
@
|
1163
|
+
@available_blueprints.unshift(default_option)
|
1010
1164
|
end
|
1011
|
-
#puts "
|
1012
|
-
return @
|
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)
|