nucleus 0.2.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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