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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/CHANGELOG.md +9 -0
  4. data/README.md +43 -72
  5. data/lib/nucleus/adapter_resolver.rb +3 -3
  6. data/lib/nucleus/adapters/base_adapter.rb +109 -109
  7. data/lib/nucleus/adapters/v1/cloud_foundry_v2/application.rb +111 -111
  8. data/lib/nucleus/adapters/v1/cloud_foundry_v2/cloud_foundry_v2.rb +141 -141
  9. data/lib/nucleus/adapters/v1/cloud_foundry_v2/data.rb +97 -97
  10. data/lib/nucleus/adapters/v1/cloud_foundry_v2/domains.rb +5 -5
  11. data/lib/nucleus/adapters/v1/cloud_foundry_v2/lifecycle.rb +41 -41
  12. data/lib/nucleus/adapters/v1/cloud_foundry_v2/logs.rb +6 -6
  13. data/lib/nucleus/adapters/v1/cloud_foundry_v2/regions.rb +33 -33
  14. data/lib/nucleus/adapters/v1/cloud_foundry_v2/services.rb +6 -6
  15. data/lib/nucleus/adapters/v1/cloud_foundry_v2/vars.rb +80 -80
  16. data/lib/nucleus/adapters/v1/heroku/app_states.rb +57 -57
  17. data/lib/nucleus/adapters/v1/heroku/data.rb +78 -78
  18. data/lib/nucleus/adapters/v1/heroku/heroku.rb +146 -146
  19. data/lib/nucleus/adapters/v1/heroku/lifecycle.rb +51 -51
  20. data/lib/nucleus/adapters/v1/heroku/logs.rb +2 -2
  21. data/lib/nucleus/adapters/v1/heroku/regions.rb +42 -42
  22. data/lib/nucleus/adapters/v1/heroku/services.rb +168 -168
  23. data/lib/nucleus/adapters/v1/heroku/vars.rb +65 -65
  24. data/lib/nucleus/adapters/v1/openshift_v2/app_states.rb +68 -68
  25. data/lib/nucleus/adapters/v1/openshift_v2/application.rb +1 -1
  26. data/lib/nucleus/adapters/v1/openshift_v2/data.rb +96 -96
  27. data/lib/nucleus/adapters/v1/openshift_v2/lifecycle.rb +60 -60
  28. data/lib/nucleus/adapters/v1/openshift_v2/logs.rb +106 -106
  29. data/lib/nucleus/adapters/v1/openshift_v2/openshift_v2.rb +125 -125
  30. data/lib/nucleus/adapters/v1/openshift_v2/regions.rb +58 -58
  31. data/lib/nucleus/adapters/v1/openshift_v2/services.rb +173 -173
  32. data/lib/nucleus/adapters/v1/openshift_v2/vars.rb +49 -49
  33. data/lib/nucleus/adapters/v1/stub_adapter.rb +464 -464
  34. data/lib/nucleus/core/adapter_extensions/auth/auth_client.rb +44 -44
  35. data/lib/nucleus/core/adapter_extensions/auth/expiring_token_auth_client.rb +53 -53
  36. data/lib/nucleus/core/adapter_extensions/auth/http_basic_auth_client.rb +3 -3
  37. data/lib/nucleus/core/adapter_extensions/auth/o_auth2_auth_client.rb +95 -95
  38. data/lib/nucleus/core/adapter_extensions/auth/token_auth_client.rb +36 -36
  39. data/lib/nucleus/core/adapter_extensions/http_client.rb +5 -5
  40. data/lib/nucleus/core/common/files/archive_extractor.rb +1 -1
  41. data/lib/nucleus/core/common/files/archiver.rb +2 -2
  42. data/lib/nucleus/core/file_handling/file_manager.rb +64 -64
  43. data/lib/nucleus/core/file_handling/git_deployer.rb +133 -133
  44. data/lib/nucleus/core/import/adapter_configuration.rb +53 -53
  45. data/lib/nucleus/scripts/initialize_config_defaults.rb +26 -26
  46. data/lib/nucleus/version.rb +1 -1
  47. data/nucleus.gemspec +2 -2
  48. data/spec/integration/api/auth_spec.rb +3 -3
  49. data/spec/spec_helper.rb +98 -98
  50. data/spec/test_suites.rake +1 -1
  51. data/spec/unit/adapters/git_deployer_spec.rb +262 -262
  52. data/spec/unit/common/helpers/auth_helper_spec.rb +1 -1
  53. data/tasks/evaluation.rake +1 -1
  54. data/wiki/adapter_tests.md +0 -7
  55. data/wiki/implement_new_adapter.md +1 -1
  56. metadata +4 -20
  57. data/config/adapters/cloud_control.yml +0 -32
  58. data/lib/nucleus/adapters/v1/cloud_control/application.rb +0 -108
  59. data/lib/nucleus/adapters/v1/cloud_control/authentication.rb +0 -27
  60. data/lib/nucleus/adapters/v1/cloud_control/buildpacks.rb +0 -23
  61. data/lib/nucleus/adapters/v1/cloud_control/cloud_control.rb +0 -153
  62. data/lib/nucleus/adapters/v1/cloud_control/data.rb +0 -76
  63. data/lib/nucleus/adapters/v1/cloud_control/domains.rb +0 -68
  64. data/lib/nucleus/adapters/v1/cloud_control/lifecycle.rb +0 -27
  65. data/lib/nucleus/adapters/v1/cloud_control/log_poller.rb +0 -71
  66. data/lib/nucleus/adapters/v1/cloud_control/logs.rb +0 -103
  67. data/lib/nucleus/adapters/v1/cloud_control/regions.rb +0 -32
  68. data/lib/nucleus/adapters/v1/cloud_control/scaling.rb +0 -17
  69. data/lib/nucleus/adapters/v1/cloud_control/semantic_errors.rb +0 -31
  70. data/lib/nucleus/adapters/v1/cloud_control/services.rb +0 -162
  71. data/lib/nucleus/adapters/v1/cloud_control/token.rb +0 -17
  72. 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
- fail 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
- fail 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
+ 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
- fail 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
- fail 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
+ 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
- fail Errors::AdapterResourceNotFoundError, errors.collect { |e| e[:text] }.join(' ')
30
- elsif error_response.status == 422
31
- fail Errors::SemanticAdapterRequestError, errors.collect { |e| e[:text] }.join(' ')
32
- elsif error_response.status == 503
33
- fail Errors::PlatformUnavailableError, 'The Openshift API is currently not available'
34
- elsif error_response.status == 504
35
- fail 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
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