nucleus 0.2.0 → 0.3.1
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/.rubocop.yml +3 -0
- data/CHANGELOG.md +9 -0
- data/README.md +43 -72
- data/lib/nucleus/adapter_resolver.rb +3 -3
- data/lib/nucleus/adapters/base_adapter.rb +109 -109
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/application.rb +111 -111
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/cloud_foundry_v2.rb +141 -141
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/data.rb +97 -97
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/domains.rb +5 -5
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/lifecycle.rb +41 -41
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/logs.rb +6 -6
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/regions.rb +33 -33
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/services.rb +6 -6
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/vars.rb +80 -80
- data/lib/nucleus/adapters/v1/heroku/app_states.rb +57 -57
- data/lib/nucleus/adapters/v1/heroku/data.rb +78 -78
- data/lib/nucleus/adapters/v1/heroku/heroku.rb +146 -146
- data/lib/nucleus/adapters/v1/heroku/lifecycle.rb +51 -51
- data/lib/nucleus/adapters/v1/heroku/logs.rb +2 -2
- data/lib/nucleus/adapters/v1/heroku/regions.rb +42 -42
- data/lib/nucleus/adapters/v1/heroku/services.rb +168 -168
- data/lib/nucleus/adapters/v1/heroku/vars.rb +65 -65
- data/lib/nucleus/adapters/v1/openshift_v2/app_states.rb +68 -68
- data/lib/nucleus/adapters/v1/openshift_v2/application.rb +1 -1
- data/lib/nucleus/adapters/v1/openshift_v2/data.rb +96 -96
- data/lib/nucleus/adapters/v1/openshift_v2/lifecycle.rb +60 -60
- data/lib/nucleus/adapters/v1/openshift_v2/logs.rb +106 -106
- data/lib/nucleus/adapters/v1/openshift_v2/openshift_v2.rb +125 -125
- data/lib/nucleus/adapters/v1/openshift_v2/regions.rb +58 -58
- data/lib/nucleus/adapters/v1/openshift_v2/services.rb +173 -173
- data/lib/nucleus/adapters/v1/openshift_v2/vars.rb +49 -49
- data/lib/nucleus/adapters/v1/stub_adapter.rb +464 -464
- data/lib/nucleus/core/adapter_extensions/auth/auth_client.rb +44 -44
- data/lib/nucleus/core/adapter_extensions/auth/expiring_token_auth_client.rb +53 -53
- data/lib/nucleus/core/adapter_extensions/auth/http_basic_auth_client.rb +3 -3
- data/lib/nucleus/core/adapter_extensions/auth/o_auth2_auth_client.rb +95 -95
- data/lib/nucleus/core/adapter_extensions/auth/token_auth_client.rb +36 -36
- data/lib/nucleus/core/adapter_extensions/http_client.rb +5 -5
- data/lib/nucleus/core/common/files/archive_extractor.rb +1 -1
- data/lib/nucleus/core/common/files/archiver.rb +2 -2
- data/lib/nucleus/core/file_handling/file_manager.rb +64 -64
- data/lib/nucleus/core/file_handling/git_deployer.rb +133 -133
- data/lib/nucleus/core/import/adapter_configuration.rb +53 -53
- data/lib/nucleus/scripts/initialize_config_defaults.rb +26 -26
- data/lib/nucleus/version.rb +1 -1
- data/nucleus.gemspec +2 -2
- data/spec/integration/api/auth_spec.rb +3 -3
- data/spec/spec_helper.rb +98 -98
- data/spec/test_suites.rake +1 -1
- data/spec/unit/adapters/git_deployer_spec.rb +262 -262
- data/spec/unit/common/helpers/auth_helper_spec.rb +1 -1
- data/tasks/evaluation.rake +1 -1
- data/wiki/adapter_tests.md +0 -7
- data/wiki/implement_new_adapter.md +1 -1
- metadata +4 -20
- data/config/adapters/cloud_control.yml +0 -32
- data/lib/nucleus/adapters/v1/cloud_control/application.rb +0 -108
- data/lib/nucleus/adapters/v1/cloud_control/authentication.rb +0 -27
- data/lib/nucleus/adapters/v1/cloud_control/buildpacks.rb +0 -23
- data/lib/nucleus/adapters/v1/cloud_control/cloud_control.rb +0 -153
- data/lib/nucleus/adapters/v1/cloud_control/data.rb +0 -76
- data/lib/nucleus/adapters/v1/cloud_control/domains.rb +0 -68
- data/lib/nucleus/adapters/v1/cloud_control/lifecycle.rb +0 -27
- data/lib/nucleus/adapters/v1/cloud_control/log_poller.rb +0 -71
- data/lib/nucleus/adapters/v1/cloud_control/logs.rb +0 -103
- data/lib/nucleus/adapters/v1/cloud_control/regions.rb +0 -32
- data/lib/nucleus/adapters/v1/cloud_control/scaling.rb +0 -17
- data/lib/nucleus/adapters/v1/cloud_control/semantic_errors.rb +0 -31
- data/lib/nucleus/adapters/v1/cloud_control/services.rb +0 -162
- data/lib/nucleus/adapters/v1/cloud_control/token.rb +0 -17
- data/lib/nucleus/adapters/v1/cloud_control/vars.rb +0 -88
@@ -1,60 +1,60 @@
|
|
1
|
-
module Nucleus
|
2
|
-
module Adapters
|
3
|
-
module V1
|
4
|
-
class OpenshiftV2 < Stub
|
5
|
-
module Lifecycle
|
6
|
-
# @see Stub#start
|
7
|
-
def start(application_id)
|
8
|
-
# if app is only deployed, we must first restore the latest deployment
|
9
|
-
id = app_id_by_name(application_id)
|
10
|
-
validate_start_requirements(id, 'start')
|
11
|
-
to_nucleus_app(send_event(id, 'start'))
|
12
|
-
end
|
13
|
-
|
14
|
-
# @see Stub#stop
|
15
|
-
def stop(application_id)
|
16
|
-
id = app_id_by_name(application_id)
|
17
|
-
unless deployed?(id)
|
18
|
-
|
19
|
-
end
|
20
|
-
to_nucleus_app(send_event(id, 'stop'))
|
21
|
-
end
|
22
|
-
|
23
|
-
# @see Stub#restart
|
24
|
-
def restart(application_id)
|
25
|
-
id = app_id_by_name(application_id)
|
26
|
-
validate_start_requirements(id, 'restart')
|
27
|
-
to_nucleus_app(send_event(id, 'restart'))
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def validate_start_requirements(id, action)
|
33
|
-
state = application_state(get("/application/#{id}").body[:data])
|
34
|
-
if state == Enums::ApplicationStates::DEPLOYED
|
35
|
-
activate(id, latest_deployment(id)[:id])
|
36
|
-
elsif state == Enums::ApplicationStates::CREATED
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def deployed?(application_id)
|
42
|
-
app = get("/application/#{app_id_by_name(application_id)}").body[:data]
|
43
|
-
application_state(app) != Enums::ApplicationStates::CREATED
|
44
|
-
end
|
45
|
-
|
46
|
-
# Send the event and trigger an action.
|
47
|
-
# @return [Hash] Openshift application data
|
48
|
-
def send_event(application_id, event, options = {})
|
49
|
-
options[:event] = event
|
50
|
-
post("/application/#{app_id_by_name(application_id)}/events", body: options).body[:data]
|
51
|
-
end
|
52
|
-
|
53
|
-
def activate(application_id, deployment_id)
|
54
|
-
send_event(application_id, 'activate', deployment_id: deployment_id)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
1
|
+
module Nucleus
|
2
|
+
module Adapters
|
3
|
+
module V1
|
4
|
+
class OpenshiftV2 < Stub
|
5
|
+
module Lifecycle
|
6
|
+
# @see Stub#start
|
7
|
+
def start(application_id)
|
8
|
+
# if app is only deployed, we must first restore the latest deployment
|
9
|
+
id = app_id_by_name(application_id)
|
10
|
+
validate_start_requirements(id, 'start')
|
11
|
+
to_nucleus_app(send_event(id, 'start'))
|
12
|
+
end
|
13
|
+
|
14
|
+
# @see Stub#stop
|
15
|
+
def stop(application_id)
|
16
|
+
id = app_id_by_name(application_id)
|
17
|
+
unless deployed?(id)
|
18
|
+
raise Errors::SemanticAdapterRequestError, 'Application must be deployed before it can be stopped'
|
19
|
+
end
|
20
|
+
to_nucleus_app(send_event(id, 'stop'))
|
21
|
+
end
|
22
|
+
|
23
|
+
# @see Stub#restart
|
24
|
+
def restart(application_id)
|
25
|
+
id = app_id_by_name(application_id)
|
26
|
+
validate_start_requirements(id, 'restart')
|
27
|
+
to_nucleus_app(send_event(id, 'restart'))
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def validate_start_requirements(id, action)
|
33
|
+
state = application_state(get("/application/#{id}").body[:data])
|
34
|
+
if state == Enums::ApplicationStates::DEPLOYED
|
35
|
+
activate(id, latest_deployment(id)[:id])
|
36
|
+
elsif state == Enums::ApplicationStates::CREATED
|
37
|
+
raise Errors::SemanticAdapterRequestError, "Application must be deployed before it can be #{action}ed"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def deployed?(application_id)
|
42
|
+
app = get("/application/#{app_id_by_name(application_id)}").body[:data]
|
43
|
+
application_state(app) != Enums::ApplicationStates::CREATED
|
44
|
+
end
|
45
|
+
|
46
|
+
# Send the event and trigger an action.
|
47
|
+
# @return [Hash] Openshift application data
|
48
|
+
def send_event(application_id, event, options = {})
|
49
|
+
options[:event] = event
|
50
|
+
post("/application/#{app_id_by_name(application_id)}/events", body: options).body[:data]
|
51
|
+
end
|
52
|
+
|
53
|
+
def activate(application_id, deployment_id)
|
54
|
+
send_event(application_id, 'activate', deployment_id: deployment_id)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,106 +1,106 @@
|
|
1
|
-
require 'time'
|
2
|
-
require 'net/ssh'
|
3
|
-
|
4
|
-
module Nucleus
|
5
|
-
module Adapters
|
6
|
-
module V1
|
7
|
-
class OpenshiftV2 < Stub
|
8
|
-
module Logs
|
9
|
-
# @see Stub#logs
|
10
|
-
def logs(application_id)
|
11
|
-
# fails with 404 if application is not available
|
12
|
-
app = get("/application/#{app_id_by_name(application_id)}").body[:data]
|
13
|
-
# ssh uri
|
14
|
-
uri = ssh_uri(app)
|
15
|
-
|
16
|
-
with_ssh_key do
|
17
|
-
remote_log_files(uri, app[:creation_time])
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
# @see Stub#log?
|
22
|
-
def log?(application_id, log_id)
|
23
|
-
# fails with 404 if application is not available
|
24
|
-
app = get("/application/#{app_id_by_name(application_id)}").body[:data]
|
25
|
-
# ssh uri
|
26
|
-
uri = ssh_uri(app)
|
27
|
-
|
28
|
-
with_ssh_key do
|
29
|
-
remote_log_file?(uri)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# @see Stub#tail
|
34
|
-
def tail(application_id, log_id, stream)
|
35
|
-
# TODO: implement me
|
36
|
-
# remote_cmd = "tail#{options.opts ? ' --opts ' + Base64::encode64(options.opts).chomp : ''} #{file_glob}"
|
37
|
-
# ssh_cmd = "ssh -t #{uuid}@#{host} '#{remote_cmd}'"
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
# @see Stub#log_entries
|
42
|
-
def log_entries(application_id, log_id)
|
43
|
-
# fails with 404 if application is not available
|
44
|
-
app = get("/application/#{app_id_by_name(application_id)}").body[:data]
|
45
|
-
# ssh uri
|
46
|
-
uri = ssh_uri(app)
|
47
|
-
|
48
|
-
with_ssh_key do
|
49
|
-
remote_log_entries(uri, application_id, log_id)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
private
|
54
|
-
|
55
|
-
def ssh_uri(application)
|
56
|
-
URI.parse(application[:ssh_url])
|
57
|
-
end
|
58
|
-
|
59
|
-
def remote_log_files(uri, app_creation_time)
|
60
|
-
available_log_files = []
|
61
|
-
# ssh into main instance
|
62
|
-
Net::SSH.start(uri.host, uri.user, keys: [nucleus_config.ssh.handler.key_file]) do |ssh|
|
63
|
-
# https://developers.openshift.com/en/managing-log-files.html#log-location
|
64
|
-
log_files = ssh.exec!('ls $OPENSHIFT_LOG_DIR')
|
65
|
-
|
66
|
-
log_files.split("\n").each do |file|
|
67
|
-
updated_at = ssh.exec!("date -r $OPENSHIFT_LOG_DIR/#{file}")
|
68
|
-
updated_at = Time.parse(updated_at).utc.iso8601
|
69
|
-
# TODO: no unified naming among cartridges: ApplicationLogfileType::APPLICATION by default.
|
70
|
-
available_log_files.push(id: File.basename(file, '.*'), name: file,
|
71
|
-
type: Enums::ApplicationLogfileType::APPLICATION,
|
72
|
-
created_at: app_creation_time, updated_at: updated_at)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
available_log_files
|
76
|
-
end
|
77
|
-
|
78
|
-
def remote_log_file?(uri)
|
79
|
-
Net::SSH.start(uri.host, uri.user, keys: [nucleus_config.ssh.handler.key_file]) do |ssh|
|
80
|
-
remote_file_exists?(ssh, "#{log_id}.log")
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def remote_log_entries(uri, app_id, log_id)
|
85
|
-
Net::SSH.start(uri.host, uri.user, keys: [nucleus_config.ssh.handler.key_file]) do |ssh|
|
86
|
-
# log exists?
|
87
|
-
unless remote_file_exists?(ssh, "#{log_id}.log")
|
88
|
-
|
89
|
-
|
90
|
-
end
|
91
|
-
# process log
|
92
|
-
log = ssh.exec!("cat $OPENSHIFT_LOG_DIR/#{log_id}.log")
|
93
|
-
log.split("\n")
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def remote_file_exists?(connection, file)
|
98
|
-
# file exists? 1 : 0
|
99
|
-
exists = connection.exec!("[ ! -f $OPENSHIFT_LOG_DIR/#{file} ]; echo $?").strip
|
100
|
-
exists == '1'
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
1
|
+
require 'time'
|
2
|
+
require 'net/ssh'
|
3
|
+
|
4
|
+
module Nucleus
|
5
|
+
module Adapters
|
6
|
+
module V1
|
7
|
+
class OpenshiftV2 < Stub
|
8
|
+
module Logs
|
9
|
+
# @see Stub#logs
|
10
|
+
def logs(application_id)
|
11
|
+
# fails with 404 if application is not available
|
12
|
+
app = get("/application/#{app_id_by_name(application_id)}").body[:data]
|
13
|
+
# ssh uri
|
14
|
+
uri = ssh_uri(app)
|
15
|
+
|
16
|
+
with_ssh_key do
|
17
|
+
remote_log_files(uri, app[:creation_time])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @see Stub#log?
|
22
|
+
def log?(application_id, log_id)
|
23
|
+
# fails with 404 if application is not available
|
24
|
+
app = get("/application/#{app_id_by_name(application_id)}").body[:data]
|
25
|
+
# ssh uri
|
26
|
+
uri = ssh_uri(app)
|
27
|
+
|
28
|
+
with_ssh_key do
|
29
|
+
remote_log_file?(uri)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# @see Stub#tail
|
34
|
+
def tail(application_id, log_id, stream)
|
35
|
+
# TODO: implement me
|
36
|
+
# remote_cmd = "tail#{options.opts ? ' --opts ' + Base64::encode64(options.opts).chomp : ''} #{file_glob}"
|
37
|
+
# ssh_cmd = "ssh -t #{uuid}@#{host} '#{remote_cmd}'"
|
38
|
+
raise NOT_IMPLEMENTED_ERROR
|
39
|
+
end
|
40
|
+
|
41
|
+
# @see Stub#log_entries
|
42
|
+
def log_entries(application_id, log_id)
|
43
|
+
# fails with 404 if application is not available
|
44
|
+
app = get("/application/#{app_id_by_name(application_id)}").body[:data]
|
45
|
+
# ssh uri
|
46
|
+
uri = ssh_uri(app)
|
47
|
+
|
48
|
+
with_ssh_key do
|
49
|
+
remote_log_entries(uri, application_id, log_id)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def ssh_uri(application)
|
56
|
+
URI.parse(application[:ssh_url])
|
57
|
+
end
|
58
|
+
|
59
|
+
def remote_log_files(uri, app_creation_time)
|
60
|
+
available_log_files = []
|
61
|
+
# ssh into main instance
|
62
|
+
Net::SSH.start(uri.host, uri.user, keys: [nucleus_config.ssh.handler.key_file]) do |ssh|
|
63
|
+
# https://developers.openshift.com/en/managing-log-files.html#log-location
|
64
|
+
log_files = ssh.exec!('ls $OPENSHIFT_LOG_DIR')
|
65
|
+
|
66
|
+
log_files.split("\n").each do |file|
|
67
|
+
updated_at = ssh.exec!("date -r $OPENSHIFT_LOG_DIR/#{file}")
|
68
|
+
updated_at = Time.parse(updated_at).utc.iso8601
|
69
|
+
# TODO: no unified naming among cartridges: ApplicationLogfileType::APPLICATION by default.
|
70
|
+
available_log_files.push(id: File.basename(file, '.*'), name: file,
|
71
|
+
type: Enums::ApplicationLogfileType::APPLICATION,
|
72
|
+
created_at: app_creation_time, updated_at: updated_at)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
available_log_files
|
76
|
+
end
|
77
|
+
|
78
|
+
def remote_log_file?(uri)
|
79
|
+
Net::SSH.start(uri.host, uri.user, keys: [nucleus_config.ssh.handler.key_file]) do |ssh|
|
80
|
+
remote_file_exists?(ssh, "#{log_id}.log")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def remote_log_entries(uri, app_id, log_id)
|
85
|
+
Net::SSH.start(uri.host, uri.user, keys: [nucleus_config.ssh.handler.key_file]) do |ssh|
|
86
|
+
# log exists?
|
87
|
+
unless remote_file_exists?(ssh, "#{log_id}.log")
|
88
|
+
raise Errors::AdapterResourceNotFoundError,
|
89
|
+
"Invalid log file '#{log_id}', not available for application '#{app_id}'"
|
90
|
+
end
|
91
|
+
# process log
|
92
|
+
log = ssh.exec!("cat $OPENSHIFT_LOG_DIR/#{log_id}.log")
|
93
|
+
log.split("\n")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def remote_file_exists?(connection, file)
|
98
|
+
# file exists? 1 : 0
|
99
|
+
exists = connection.exec!("[ ! -f $OPENSHIFT_LOG_DIR/#{file} ]; echo $?").strip
|
100
|
+
exists == '1'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -1,125 +1,125 @@
|
|
1
|
-
module Nucleus
|
2
|
-
module Adapters
|
3
|
-
module V1
|
4
|
-
# @see https://access.redhat.com/documentation/en-US/OpenShift/2.0/html/REST_API_Guide The Openshift V2
|
5
|
-
# API documentation
|
6
|
-
class OpenshiftV2 < Stub
|
7
|
-
include Nucleus::Logging
|
8
|
-
include Nucleus::Adapters::V1::OpenshiftV2::Authentication
|
9
|
-
include Nucleus::Adapters::V1::OpenshiftV2::Application
|
10
|
-
include Nucleus::Adapters::V1::OpenshiftV2::AppStates
|
11
|
-
include Nucleus::Adapters::V1::OpenshiftV2::Data
|
12
|
-
include Nucleus::Adapters::V1::OpenshiftV2::Domains
|
13
|
-
include Nucleus::Adapters::V1::OpenshiftV2::Lifecycle
|
14
|
-
include Nucleus::Adapters::V1::OpenshiftV2::Logs
|
15
|
-
include Nucleus::Adapters::V1::OpenshiftV2::Regions
|
16
|
-
include Nucleus::Adapters::V1::OpenshiftV2::Scaling
|
17
|
-
include Nucleus::Adapters::V1::OpenshiftV2::SemanticErrors
|
18
|
-
include Nucleus::Adapters::V1::OpenshiftV2::Services
|
19
|
-
include Nucleus::Adapters::V1::OpenshiftV2::Vars
|
20
|
-
|
21
|
-
def initialize(endpoint_url, endpoint_app_domain = nil, check_certificates = true)
|
22
|
-
super(endpoint_url, endpoint_app_domain, check_certificates)
|
23
|
-
end
|
24
|
-
|
25
|
-
def handle_error(error_response)
|
26
|
-
# some error messages do not have the proper error message format
|
27
|
-
errors = openshift_errors(error_response)
|
28
|
-
if error_response.status == 404 && errors.any? { |e| e[:text].include?('not found') }
|
29
|
-
|
30
|
-
elsif error_response.status == 422
|
31
|
-
|
32
|
-
elsif error_response.status == 503
|
33
|
-
|
34
|
-
elsif error_response.status == 504
|
35
|
-
|
36
|
-
'Most likely the request is still being executed. Please make sure to analyse whether the request '\
|
37
|
-
'was successful before invoking further actions.'
|
38
|
-
end
|
39
|
-
# error still unhandled, will result in a 500, server error
|
40
|
-
log.warn "Openshift error still unhandled: #{error_response}"
|
41
|
-
end
|
42
|
-
|
43
|
-
def openshift_errors(error_response)
|
44
|
-
if error_response.body.is_a?(Hash) && error_response.body.key?(:messages)
|
45
|
-
error_response.body[:messages].collect { |error| { field: error[:field], text: error[:text] } }
|
46
|
-
else
|
47
|
-
[]
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def headers
|
54
|
-
super.merge('Accept' => 'application/json; version=1.7', 'Content-Type' => 'application/json')
|
55
|
-
end
|
56
|
-
|
57
|
-
def app_domain
|
58
|
-
# A user always has only 1 domain as described on:
|
59
|
-
# https://access.redhat.com/documentation/en-US/OpenShift/2.0/html/REST_API_Guide/chap-API_Guide-Domains.html
|
60
|
-
user_domains = get('/domains').body[:data]
|
61
|
-
fail_with(:no_user_domain) if user_domains.empty?
|
62
|
-
user_domains.first[:name]
|
63
|
-
end
|
64
|
-
|
65
|
-
def original_deployment(app, deployments = nil)
|
66
|
-
# TODO: this is actually quite scary, could easily fail with wrong timing
|
67
|
-
# What are the alternatives?
|
68
|
-
# 1) Clone git repo and lookup commits --> insanely slow
|
69
|
-
# 2) Identify initial commits by sha1 key --> would require collection of allowed values, which may change!
|
70
|
-
deployments = load_deployments(app[:id]) unless deployments
|
71
|
-
deployments.find do |deployment|
|
72
|
-
diff = (Time.parse(deployment[:created_at]).to_i - Time.parse(app[:creation_time]).to_i).abs
|
73
|
-
log.debug "OS deployment time diff: #{diff}"
|
74
|
-
diff < 20 && deployment[:force_clean_build] == false &&
|
75
|
-
deployment[:hot_deploy] == false && deployment[:ref] == 'master'
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def latest_deployment(application_id, deployments = nil)
|
80
|
-
deployments = load_deployments(application_id) unless deployments
|
81
|
-
latest = nil
|
82
|
-
latest_ts = nil
|
83
|
-
deployments.each do |deployment|
|
84
|
-
ts = Time.parse(deployment[:created_at]).to_i
|
85
|
-
if latest.nil? || ts > latest_ts
|
86
|
-
latest = deployment
|
87
|
-
latest_ts = ts
|
88
|
-
end
|
89
|
-
end
|
90
|
-
latest
|
91
|
-
end
|
92
|
-
|
93
|
-
def active_deployment(app, deployments = nil)
|
94
|
-
deployments = load_deployments(app[:id]) unless deployments
|
95
|
-
active = nil
|
96
|
-
active_ts = nil
|
97
|
-
deployments.each do |deployment|
|
98
|
-
ts = Time.parse(last_activation(deployment[:activations])).to_i
|
99
|
-
if active.nil? || ts > active_ts
|
100
|
-
active = deployment
|
101
|
-
active_ts = ts
|
102
|
-
end
|
103
|
-
end
|
104
|
-
active
|
105
|
-
end
|
106
|
-
|
107
|
-
def last_activation(activations)
|
108
|
-
latest = nil
|
109
|
-
activations.each do |activation|
|
110
|
-
latest = activation if latest.nil? || Time.parse(activation).to_i > Time.parse(latest).to_i
|
111
|
-
end
|
112
|
-
latest
|
113
|
-
end
|
114
|
-
|
115
|
-
def load_deployments(application_id)
|
116
|
-
get("/application/#{application_id}/deployments").body[:data]
|
117
|
-
end
|
118
|
-
|
119
|
-
def load_gears(application_id)
|
120
|
-
get("/application/#{application_id}/gear_groups").body[:data]
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
1
|
+
module Nucleus
|
2
|
+
module Adapters
|
3
|
+
module V1
|
4
|
+
# @see https://access.redhat.com/documentation/en-US/OpenShift/2.0/html/REST_API_Guide The Openshift V2
|
5
|
+
# API documentation
|
6
|
+
class OpenshiftV2 < Stub
|
7
|
+
include Nucleus::Logging
|
8
|
+
include Nucleus::Adapters::V1::OpenshiftV2::Authentication
|
9
|
+
include Nucleus::Adapters::V1::OpenshiftV2::Application
|
10
|
+
include Nucleus::Adapters::V1::OpenshiftV2::AppStates
|
11
|
+
include Nucleus::Adapters::V1::OpenshiftV2::Data
|
12
|
+
include Nucleus::Adapters::V1::OpenshiftV2::Domains
|
13
|
+
include Nucleus::Adapters::V1::OpenshiftV2::Lifecycle
|
14
|
+
include Nucleus::Adapters::V1::OpenshiftV2::Logs
|
15
|
+
include Nucleus::Adapters::V1::OpenshiftV2::Regions
|
16
|
+
include Nucleus::Adapters::V1::OpenshiftV2::Scaling
|
17
|
+
include Nucleus::Adapters::V1::OpenshiftV2::SemanticErrors
|
18
|
+
include Nucleus::Adapters::V1::OpenshiftV2::Services
|
19
|
+
include Nucleus::Adapters::V1::OpenshiftV2::Vars
|
20
|
+
|
21
|
+
def initialize(endpoint_url, endpoint_app_domain = nil, check_certificates = true)
|
22
|
+
super(endpoint_url, endpoint_app_domain, check_certificates)
|
23
|
+
end
|
24
|
+
|
25
|
+
def handle_error(error_response)
|
26
|
+
# some error messages do not have the proper error message format
|
27
|
+
errors = openshift_errors(error_response)
|
28
|
+
if error_response.status == 404 && errors.any? { |e| e[:text].include?('not found') }
|
29
|
+
raise Errors::AdapterResourceNotFoundError, errors.collect { |e| e[:text] }.join(' ')
|
30
|
+
elsif error_response.status == 422
|
31
|
+
raise Errors::SemanticAdapterRequestError, errors.collect { |e| e[:text] }.join(' ')
|
32
|
+
elsif error_response.status == 503
|
33
|
+
raise Errors::PlatformUnavailableError, 'The Openshift API is currently not available'
|
34
|
+
elsif error_response.status == 504
|
35
|
+
raise Errors::PlatformTimeoutError, 'The Openshift API did not receive information from it\'s slaves. '\
|
36
|
+
'Most likely the request is still being executed. Please make sure to analyse whether the request '\
|
37
|
+
'was successful before invoking further actions.'
|
38
|
+
end
|
39
|
+
# error still unhandled, will result in a 500, server error
|
40
|
+
log.warn "Openshift error still unhandled: #{error_response}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def openshift_errors(error_response)
|
44
|
+
if error_response.body.is_a?(Hash) && error_response.body.key?(:messages)
|
45
|
+
error_response.body[:messages].collect { |error| { field: error[:field], text: error[:text] } }
|
46
|
+
else
|
47
|
+
[]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def headers
|
54
|
+
super.merge('Accept' => 'application/json; version=1.7', 'Content-Type' => 'application/json')
|
55
|
+
end
|
56
|
+
|
57
|
+
def app_domain
|
58
|
+
# A user always has only 1 domain as described on:
|
59
|
+
# https://access.redhat.com/documentation/en-US/OpenShift/2.0/html/REST_API_Guide/chap-API_Guide-Domains.html
|
60
|
+
user_domains = get('/domains').body[:data]
|
61
|
+
fail_with(:no_user_domain) if user_domains.empty?
|
62
|
+
user_domains.first[:name]
|
63
|
+
end
|
64
|
+
|
65
|
+
def original_deployment(app, deployments = nil)
|
66
|
+
# TODO: this is actually quite scary, could easily fail with wrong timing
|
67
|
+
# What are the alternatives?
|
68
|
+
# 1) Clone git repo and lookup commits --> insanely slow
|
69
|
+
# 2) Identify initial commits by sha1 key --> would require collection of allowed values, which may change!
|
70
|
+
deployments = load_deployments(app[:id]) unless deployments
|
71
|
+
deployments.find do |deployment|
|
72
|
+
diff = (Time.parse(deployment[:created_at]).to_i - Time.parse(app[:creation_time]).to_i).abs
|
73
|
+
log.debug "OS deployment time diff: #{diff}"
|
74
|
+
diff < 20 && deployment[:force_clean_build] == false &&
|
75
|
+
deployment[:hot_deploy] == false && deployment[:ref] == 'master'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def latest_deployment(application_id, deployments = nil)
|
80
|
+
deployments = load_deployments(application_id) unless deployments
|
81
|
+
latest = nil
|
82
|
+
latest_ts = nil
|
83
|
+
deployments.each do |deployment|
|
84
|
+
ts = Time.parse(deployment[:created_at]).to_i
|
85
|
+
if latest.nil? || ts > latest_ts
|
86
|
+
latest = deployment
|
87
|
+
latest_ts = ts
|
88
|
+
end
|
89
|
+
end
|
90
|
+
latest
|
91
|
+
end
|
92
|
+
|
93
|
+
def active_deployment(app, deployments = nil)
|
94
|
+
deployments = load_deployments(app[:id]) unless deployments
|
95
|
+
active = nil
|
96
|
+
active_ts = nil
|
97
|
+
deployments.each do |deployment|
|
98
|
+
ts = Time.parse(last_activation(deployment[:activations])).to_i
|
99
|
+
if active.nil? || ts > active_ts
|
100
|
+
active = deployment
|
101
|
+
active_ts = ts
|
102
|
+
end
|
103
|
+
end
|
104
|
+
active
|
105
|
+
end
|
106
|
+
|
107
|
+
def last_activation(activations)
|
108
|
+
latest = nil
|
109
|
+
activations.each do |activation|
|
110
|
+
latest = activation if latest.nil? || Time.parse(activation).to_i > Time.parse(latest).to_i
|
111
|
+
end
|
112
|
+
latest
|
113
|
+
end
|
114
|
+
|
115
|
+
def load_deployments(application_id)
|
116
|
+
get("/application/#{application_id}/deployments").body[:data]
|
117
|
+
end
|
118
|
+
|
119
|
+
def load_gears(application_id)
|
120
|
+
get("/application/#{application_id}/gear_groups").body[:data]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|