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,111 +1,111 @@
1
- module Nucleus
2
- module Adapters
3
- module V1
4
- class CloudFoundryV2 < Stub
5
- module Application
6
- # @see Stub#applications
7
- def applications
8
- response = get('/v2/apps')
9
- apps = []
10
- response.body[:resources].each do |application_resource|
11
- apps << to_nucleus_app(application_resource)
12
- end
13
- apps
14
- end
15
-
16
- # @see Stub#application
17
- def application(application_name_or_id)
18
- app_guid = app_guid(application_name_or_id)
19
- get_response = get("/v2/apps/#{app_guid}")
20
- to_nucleus_app(get_response.body)
21
- end
22
-
23
- # @see Stub#create_application
24
- def create_application(application)
25
- if application.key? :region
26
- unless application[:region].casecmp('default') == 0
27
- fail Errors::SemanticAdapterRequestError,
28
- "Region '#{application[:region]}' does not exist at the endpoint. "\
29
- 'Please check which regions are actually available on this endpoint.'
30
- end
31
- # there is no region in Cloud Foundry --> remove from request
32
- application.delete :region
33
- end
34
-
35
- apply_buildpack(application)
36
-
37
- # apply default values, if not overridden by custom params
38
- default_params = { space_guid: user_space_guid }
39
- application = default_params.merge(application)
40
-
41
- # WORKAROUND: requires numeric input, but rack-test provides characters :/
42
- application['memory'] = application['memory'].to_i if application.key?('memory')
43
-
44
- response = post('/v2/apps', body: application).body
45
-
46
- # now create the default route (similar to when using an UI, e.g. Pivotal, Stackato or Bluemix) == web_url
47
- create_cf_domain(response[:metadata][:guid], @endpoint_app_domain, response[:metadata][:guid])
48
-
49
- # finally build the application response
50
- application(response[:metadata][:guid])
51
- end
52
-
53
- # @see Stub#update_application
54
- def update_application(application_name_or_id, application_form)
55
- app_guid = app_guid(application_name_or_id)
56
- apply_buildpack(application_form)
57
- # update by guid
58
- update_response = put("/v2/apps/#{app_guid}", body: application_form)
59
- to_nucleus_app(update_response.body)
60
- end
61
-
62
- # @see Stub#delete_application
63
- def delete_application(application_name_or_id)
64
- app_guid = app_guid(application_name_or_id)
65
- # first delete all service bindings
66
- remove_all_services(app_guid)
67
- # then delete the default route (otherwise it would remain as orphaned route)
68
- routes = get("/v2/apps/#{app_guid}/routes?q=host:#{app_guid}&inline-relations-depth=1").body[:resources]
69
- default_route = routes.find { |route| route[:entity][:domain][:entity][:name] == @endpoint_app_domain }
70
- delete("/v2/routes/#{default_route[:metadata][:guid]}") if default_route
71
- # and finally delete the app
72
- delete("/v2/apps/#{app_guid}")
73
- end
74
-
75
- private
76
-
77
- def apply_buildpack(application)
78
- # handle desired runtime(s)
79
- runtimes = application.delete(:runtimes)
80
- return unless runtimes
81
- fail_with(:only_one_runtime) if runtimes.length > 1
82
-
83
- buildpack = find_runtime(runtimes[0])
84
- # use the translated buildpack name if available, otherwise pass on the given runtime name
85
- application[:buildpack] = buildpack ? buildpack : runtimes[0]
86
- end
87
-
88
- def to_nucleus_app(app_resource)
89
- metadata = app_resource[:metadata]
90
- app = app_resource[:entity]
91
-
92
- app[:id] = metadata[:guid]
93
- app[:created_at] = metadata[:created_at]
94
- app[:updated_at] = metadata[:updated_at] || metadata[:created_at]
95
- app[:state] = application_state(app_resource)
96
- app[:web_url] = "http://#{app_web_url(metadata[:guid])}"
97
- # route could have been deleted by the user
98
- app[:web_url] = nil unless domain?(metadata[:guid], app[:web_url])
99
- # Stackato does support autoscaling
100
- app[:autoscaled] = app.delete(:autoscale_enabled) || false
101
- app[:region] = 'default'
102
- app[:active_runtime] = app[:detected_buildpack]
103
- app[:runtimes] = app[:buildpack] ? [app[:buildpack]] : []
104
- app[:release_version] = app.delete(:version)
105
- app
106
- end
107
- end
108
- end
109
- end
110
- end
111
- end
1
+ module Nucleus
2
+ module Adapters
3
+ module V1
4
+ class CloudFoundryV2 < Stub
5
+ module Application
6
+ # @see Stub#applications
7
+ def applications
8
+ response = get('/v2/apps')
9
+ apps = []
10
+ response.body[:resources].each do |application_resource|
11
+ apps << to_nucleus_app(application_resource)
12
+ end
13
+ apps
14
+ end
15
+
16
+ # @see Stub#application
17
+ def application(application_name_or_id)
18
+ app_guid = app_guid(application_name_or_id)
19
+ get_response = get("/v2/apps/#{app_guid}")
20
+ to_nucleus_app(get_response.body)
21
+ end
22
+
23
+ # @see Stub#create_application
24
+ def create_application(application)
25
+ if application.key? :region
26
+ unless application[:region].casecmp('default') == 0
27
+ raise Errors::SemanticAdapterRequestError,
28
+ "Region '#{application[:region]}' does not exist at the endpoint. "\
29
+ 'Please check which regions are actually available on this endpoint.'
30
+ end
31
+ # there is no region in Cloud Foundry --> remove from request
32
+ application.delete :region
33
+ end
34
+
35
+ apply_buildpack(application)
36
+
37
+ # apply default values, if not overridden by custom params
38
+ default_params = { space_guid: user_space_guid }
39
+ application = default_params.merge(application)
40
+
41
+ # WORKAROUND: requires numeric input, but rack-test provides characters :/
42
+ application['memory'] = application['memory'].to_i if application.key?('memory')
43
+
44
+ response = post('/v2/apps', body: application).body
45
+
46
+ # now create the default route (similar to when using an UI, e.g. Pivotal, Stackato or Bluemix) == web_url
47
+ create_cf_domain(response[:metadata][:guid], @endpoint_app_domain, response[:metadata][:guid])
48
+
49
+ # finally build the application response
50
+ application(response[:metadata][:guid])
51
+ end
52
+
53
+ # @see Stub#update_application
54
+ def update_application(application_name_or_id, application_form)
55
+ app_guid = app_guid(application_name_or_id)
56
+ apply_buildpack(application_form)
57
+ # update by guid
58
+ update_response = put("/v2/apps/#{app_guid}", body: application_form)
59
+ to_nucleus_app(update_response.body)
60
+ end
61
+
62
+ # @see Stub#delete_application
63
+ def delete_application(application_name_or_id)
64
+ app_guid = app_guid(application_name_or_id)
65
+ # first delete all service bindings
66
+ remove_all_services(app_guid)
67
+ # then delete the default route (otherwise it would remain as orphaned route)
68
+ routes = get("/v2/apps/#{app_guid}/routes?q=host:#{app_guid}&inline-relations-depth=1").body[:resources]
69
+ default_route = routes.find { |route| route[:entity][:domain][:entity][:name] == @endpoint_app_domain }
70
+ delete("/v2/routes/#{default_route[:metadata][:guid]}") if default_route
71
+ # and finally delete the app
72
+ delete("/v2/apps/#{app_guid}")
73
+ end
74
+
75
+ private
76
+
77
+ def apply_buildpack(application)
78
+ # handle desired runtime(s)
79
+ runtimes = application.delete(:runtimes)
80
+ return unless runtimes
81
+ fail_with(:only_one_runtime) if runtimes.length > 1
82
+
83
+ buildpack = find_runtime(runtimes[0])
84
+ # use the translated buildpack name if available, otherwise pass on the given runtime name
85
+ application[:buildpack] = buildpack ? buildpack : runtimes[0]
86
+ end
87
+
88
+ def to_nucleus_app(app_resource)
89
+ metadata = app_resource[:metadata]
90
+ app = app_resource[:entity]
91
+
92
+ app[:id] = metadata[:guid]
93
+ app[:created_at] = metadata[:created_at]
94
+ app[:updated_at] = metadata[:updated_at] || metadata[:created_at]
95
+ app[:state] = application_state(app_resource)
96
+ app[:web_url] = "http://#{app_web_url(metadata[:guid])}"
97
+ # route could have been deleted by the user
98
+ app[:web_url] = nil unless domain?(metadata[:guid], app[:web_url])
99
+ # Stackato does support autoscaling
100
+ app[:autoscaled] = app.delete(:autoscale_enabled) || false
101
+ app[:region] = 'default'
102
+ app[:active_runtime] = app[:detected_buildpack]
103
+ app[:runtimes] = app[:buildpack] ? [app[:buildpack]] : []
104
+ app[:release_version] = app.delete(:version)
105
+ app
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -1,141 +1,141 @@
1
- module Nucleus
2
- module Adapters
3
- module V1
4
- # The {CloudFoundryV2} adapter is designed to support the Cloud Foundry API and uses only commands
5
- # of the API version 2.<br>
6
- # <br>
7
- # Besides native Cloud Foundry installations, this adapter shall also work with forks, such as Stackato 3.4.2.<br>
8
- # <br>
9
- # The Nucleus API is fully supported, there are no known issues.
10
- # @see http://apidocs.cloudfoundry.org The latest Cloud Foundry API documentation
11
- class CloudFoundryV2 < Stub
12
- include Nucleus::Logging
13
- include Nucleus::Adapters::V1::CloudFoundryV2::Authentication
14
- include Nucleus::Adapters::V1::CloudFoundryV2::AppStates
15
- include Nucleus::Adapters::V1::CloudFoundryV2::Buildpacks
16
- include Nucleus::Adapters::V1::CloudFoundryV2::Application
17
- include Nucleus::Adapters::V1::CloudFoundryV2::Domains
18
- include Nucleus::Adapters::V1::CloudFoundryV2::Data
19
- include Nucleus::Adapters::V1::CloudFoundryV2::Lifecycle
20
- include Nucleus::Adapters::V1::CloudFoundryV2::Logs
21
- include Nucleus::Adapters::V1::CloudFoundryV2::Regions
22
- include Nucleus::Adapters::V1::CloudFoundryV2::Scaling
23
- include Nucleus::Adapters::V1::CloudFoundryV2::SemanticErrors
24
- include Nucleus::Adapters::V1::CloudFoundryV2::Services
25
- include Nucleus::Adapters::V1::CloudFoundryV2::Vars
26
-
27
- def initialize(endpoint_url, endpoint_app_domain = nil, check_certificates = true)
28
- super(endpoint_url, endpoint_app_domain, check_certificates)
29
- end
30
-
31
- def handle_error(error)
32
- cf_error = error.body.is_a?(Hash) ? error.body[:code] : nil
33
- case error.status
34
- when 400
35
- handle_400_error(error, cf_error)
36
- when 404
37
- fail Errors::AdapterResourceNotFoundError, error.body[:description] if cf_error > 10_000
38
- else
39
- if [1001].include? cf_error
40
- fail Errors::AdapterRequestError, "#{error.body[:description]} (#{cf_error} - #{error.body[:error_code]})"
41
- elsif [10_002].include?(cf_error) || error.status == 401
42
- fail Errors::EndpointAuthenticationError, 'Endpoint authentication failed with OAuth2 token'
43
- end
44
- end
45
- # error still unhandled, will result in a 500, server error
46
- log.warn "Cloud Foundry error still unhandled: #{error}"
47
- end
48
-
49
- private
50
-
51
- def handle_400_error(error, cf_error)
52
- if cf_error == 150_001 || cf_error == 160_001 || cf_error > 100_000 && cf_error < 109_999
53
- # Indicating semantically invalid parameters
54
- fail Errors::SemanticAdapterRequestError, error.body[:description]
55
- elsif cf_error == 170_002
56
- fail_with(:build_in_progress)
57
- elsif cf_error == 60_002
58
- fail Errors::SemanticAdapterRequestError, 'Service is already assigned to the application'
59
- end
60
- end
61
-
62
- def guid?(name_or_id)
63
- Regexp::UUID_PATTERN.match(name_or_id) ? true : false
64
- end
65
-
66
- def default_organization_guid
67
- get("/v2/spaces/#{user_space_guid}").body[:entity][:organization_guid]
68
- end
69
-
70
- def app_guid(app_name_or_id)
71
- # app name is a UUID and therefore most likely the CF GUID
72
- return app_name_or_id if guid?(app_name_or_id)
73
- find_app_guid_by_name(app_name_or_id)
74
- end
75
-
76
- def find_app_guid_by_name(application_name)
77
- filtered_list_response = get('/v2/apps', query: { q: "name:#{application_name}" })
78
- if filtered_list_response.body[:resources].length == 0
79
- fail Errors::AdapterResourceNotFoundError,
80
- "Couldn't find app with name '#{application_name}' on the platform"
81
- end
82
- # return the found guid
83
- filtered_list_response.body[:resources][0][:metadata][:guid]
84
- end
85
-
86
- def find_app_id_by_name(application_name, previous_response)
87
- filtered_list_response = get('/v2/apps', query: { q: "name:#{application_name}" })
88
- # fail as expected if the app can also not be found by its name
89
- fail Errors::AdapterResourceNotFoundError,
90
- previous_response.body[:description] if filtered_list_response.body[:resources].length == 0
91
- # return the found guid
92
- filtered_list_response.body[:resources][0][:metadata][:guid]
93
- end
94
-
95
- def endpoint_info
96
- get('/v2/info', headers: {}).body
97
- end
98
-
99
- def user_info
100
- get("#{endpoint_info[:authorization_endpoint]}/userinfo").body
101
- end
102
-
103
- def user
104
- get("/v2/users/#{user_info[:user_id]}").body
105
- end
106
-
107
- def user_space_guid
108
- users_spaces = get('/v2/spaces').body[:resources]
109
- # only once space accessible
110
- return users_spaces[0][:metadata][:guid] if users_spaces.length == 1
111
- # use default space (stackato feature)
112
- default_space = users_spaces.detect { |space_resource| space_resource[:entity][:is_default] == true }
113
- return default_space[:metadata][:guid] if default_space
114
- # check the users spaces for default
115
- user_default_space_guid = user[:entity][:default_space_guid]
116
- return user_default_space_guid if user_default_space_guid
117
- # TODO: find a more suitable approach to detect the right space !?
118
- # multiple spaces and no default space (dammit), choose the first one...
119
- return users_spaces[0][:metadata][:guid] if users_spaces
120
- # user has no space assigned, fail since we cant determine a space guid
121
- fail_with(:no_space_assigned)
122
- end
123
-
124
- def headers
125
- super.merge('Basic' => 'Y2Y6', 'Content-Type' => 'application/json')
126
- end
127
-
128
- def deployed?(application_guid)
129
- response = head("/v2/apps/#{application_guid}/download", follow_redirects: false, expects: [200, 302, 404])
130
- return true if response.status == 200 || response.status == 302
131
- return false if response.status == 404
132
- # if the response is neither one of the codes, the call fails anyway...
133
- end
134
-
135
- def app_web_url(app_guid)
136
- "#{app_guid}.#{@endpoint_app_domain}" if @endpoint_app_domain
137
- end
138
- end
139
- end
140
- end
141
- end
1
+ module Nucleus
2
+ module Adapters
3
+ module V1
4
+ # The {CloudFoundryV2} adapter is designed to support the Cloud Foundry API and uses only commands
5
+ # of the API version 2.<br>
6
+ # <br>
7
+ # Besides native Cloud Foundry installations, this adapter shall also work with forks, such as Stackato 3.4.2.<br>
8
+ # <br>
9
+ # The Nucleus API is fully supported, there are no known issues.
10
+ # @see http://apidocs.cloudfoundry.org The latest Cloud Foundry API documentation
11
+ class CloudFoundryV2 < Stub
12
+ include Nucleus::Logging
13
+ include Nucleus::Adapters::V1::CloudFoundryV2::Authentication
14
+ include Nucleus::Adapters::V1::CloudFoundryV2::AppStates
15
+ include Nucleus::Adapters::V1::CloudFoundryV2::Buildpacks
16
+ include Nucleus::Adapters::V1::CloudFoundryV2::Application
17
+ include Nucleus::Adapters::V1::CloudFoundryV2::Domains
18
+ include Nucleus::Adapters::V1::CloudFoundryV2::Data
19
+ include Nucleus::Adapters::V1::CloudFoundryV2::Lifecycle
20
+ include Nucleus::Adapters::V1::CloudFoundryV2::Logs
21
+ include Nucleus::Adapters::V1::CloudFoundryV2::Regions
22
+ include Nucleus::Adapters::V1::CloudFoundryV2::Scaling
23
+ include Nucleus::Adapters::V1::CloudFoundryV2::SemanticErrors
24
+ include Nucleus::Adapters::V1::CloudFoundryV2::Services
25
+ include Nucleus::Adapters::V1::CloudFoundryV2::Vars
26
+
27
+ def initialize(endpoint_url, endpoint_app_domain = nil, check_certificates = true)
28
+ super(endpoint_url, endpoint_app_domain, check_certificates)
29
+ end
30
+
31
+ def handle_error(error)
32
+ cf_error = error.body.is_a?(Hash) ? error.body[:code] : nil
33
+ case error.status
34
+ when 400
35
+ handle_400_error(error, cf_error)
36
+ when 404
37
+ raise Errors::AdapterResourceNotFoundError, error.body[:description] if cf_error > 10_000
38
+ else
39
+ if [1001].include? cf_error
40
+ raise Errors::AdapterRequestError, "#{error.body[:description]} (#{cf_error} - #{error.body[:error_code]})"
41
+ elsif [10_002].include?(cf_error) || error.status == 401
42
+ raise Errors::EndpointAuthenticationError, 'Endpoint authentication failed with OAuth2 token'
43
+ end
44
+ end
45
+ # error still unhandled, will result in a 500, server error
46
+ log.warn "Cloud Foundry error still unhandled: #{error}"
47
+ end
48
+
49
+ private
50
+
51
+ def handle_400_error(error, cf_error)
52
+ if cf_error == 150_001 || cf_error == 160_001 || cf_error > 100_000 && cf_error < 109_999
53
+ # Indicating semantically invalid parameters
54
+ raise Errors::SemanticAdapterRequestError, error.body[:description]
55
+ elsif cf_error == 170_002
56
+ fail_with(:build_in_progress)
57
+ elsif cf_error == 60_002
58
+ raise Errors::SemanticAdapterRequestError, 'Service is already assigned to the application'
59
+ end
60
+ end
61
+
62
+ def guid?(name_or_id)
63
+ Regexp::UUID_PATTERN.match(name_or_id) ? true : false
64
+ end
65
+
66
+ def default_organization_guid
67
+ get("/v2/spaces/#{user_space_guid}").body[:entity][:organization_guid]
68
+ end
69
+
70
+ def app_guid(app_name_or_id)
71
+ # app name is a UUID and therefore most likely the CF GUID
72
+ return app_name_or_id if guid?(app_name_or_id)
73
+ find_app_guid_by_name(app_name_or_id)
74
+ end
75
+
76
+ def find_app_guid_by_name(application_name)
77
+ filtered_list_response = get('/v2/apps', query: { q: "name:#{application_name}" })
78
+ if filtered_list_response.body[:resources].empty?
79
+ raise Errors::AdapterResourceNotFoundError,
80
+ "Couldn't find app with name '#{application_name}' on the platform"
81
+ end
82
+ # return the found guid
83
+ filtered_list_response.body[:resources][0][:metadata][:guid]
84
+ end
85
+
86
+ def find_app_id_by_name(application_name, previous_response)
87
+ filtered_list_response = get('/v2/apps', query: { q: "name:#{application_name}" })
88
+ # fail as expected if the app can also not be found by its name
89
+ raise Errors::AdapterResourceNotFoundError,
90
+ previous_response.body[:description] if filtered_list_response.body[:resources].empty?
91
+ # return the found guid
92
+ filtered_list_response.body[:resources][0][:metadata][:guid]
93
+ end
94
+
95
+ def endpoint_info
96
+ get('/v2/info', headers: {}).body
97
+ end
98
+
99
+ def user_info
100
+ get("#{endpoint_info[:authorization_endpoint]}/userinfo").body
101
+ end
102
+
103
+ def user
104
+ get("/v2/users/#{user_info[:user_id]}").body
105
+ end
106
+
107
+ def user_space_guid
108
+ users_spaces = get('/v2/spaces').body[:resources]
109
+ # only once space accessible
110
+ return users_spaces[0][:metadata][:guid] if users_spaces.length == 1
111
+ # use default space (stackato feature)
112
+ default_space = users_spaces.detect { |space_resource| space_resource[:entity][:is_default] == true }
113
+ return default_space[:metadata][:guid] if default_space
114
+ # check the users spaces for default
115
+ user_default_space_guid = user[:entity][:default_space_guid]
116
+ return user_default_space_guid if user_default_space_guid
117
+ # TODO: find a more suitable approach to detect the right space !?
118
+ # multiple spaces and no default space (dammit), choose the first one...
119
+ return users_spaces[0][:metadata][:guid] if users_spaces
120
+ # user has no space assigned, fail since we cant determine a space guid
121
+ fail_with(:no_space_assigned)
122
+ end
123
+
124
+ def headers
125
+ super.merge('Basic' => 'Y2Y6', 'Content-Type' => 'application/json')
126
+ end
127
+
128
+ def deployed?(application_guid)
129
+ response = head("/v2/apps/#{application_guid}/download", follow_redirects: false, expects: [200, 302, 404])
130
+ return true if response.status == 200 || response.status == 302
131
+ return false if response.status == 404
132
+ # if the response is neither one of the codes, the call fails anyway...
133
+ end
134
+
135
+ def app_web_url(app_guid)
136
+ "#{app_guid}.#{@endpoint_app_domain}" if @endpoint_app_domain
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end