nucleus 0.1.0 → 0.2.0
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 +18 -4
- data/README.md +28 -40
- data/Rakefile +137 -137
- data/config/nucleus_config.rb +0 -4
- data/lib/nucleus/adapter_resolver.rb +115 -115
- data/lib/nucleus/adapters/buildpack_translator.rb +79 -79
- data/lib/nucleus/adapters/v1/cloud_control/application.rb +108 -108
- data/lib/nucleus/adapters/v1/cloud_control/authentication.rb +27 -27
- data/lib/nucleus/adapters/v1/cloud_control/cloud_control.rb +153 -153
- data/lib/nucleus/adapters/v1/cloud_control/domains.rb +68 -68
- data/lib/nucleus/adapters/v1/cloud_control/logs.rb +103 -103
- data/lib/nucleus/adapters/v1/cloud_control/vars.rb +88 -88
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/domains.rb +149 -149
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/logs.rb +303 -303
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/services.rb +286 -286
- data/lib/nucleus/adapters/v1/heroku/heroku.rb +2 -2
- data/lib/nucleus/adapters/v1/heroku/logs.rb +108 -108
- data/lib/nucleus/core/adapter_authentication_inductor.rb +0 -2
- data/lib/nucleus/core/adapter_extensions/auth/http_basic_auth_client.rb +37 -37
- data/lib/nucleus/core/adapter_extensions/http_client.rb +177 -177
- data/lib/nucleus/core/common/files/archive_extractor.rb +112 -112
- data/lib/nucleus/core/common/files/archiver.rb +91 -91
- data/lib/nucleus/core/common/logging/request_log_formatter.rb +48 -48
- data/lib/nucleus/core/error_messages.rb +127 -127
- data/lib/nucleus/core/models/abstract_model.rb +29 -29
- data/lib/nucleus/scripts/load_dependencies.rb +0 -1
- data/lib/nucleus/scripts/setup_config.rb +28 -28
- data/lib/nucleus/version.rb +3 -3
- data/nucleus.gemspec +10 -12
- data/spec/factories/models.rb +63 -61
- data/spec/integration/api/auth_spec.rb +58 -58
- data/spec/test_suites.rake +31 -31
- data/spec/unit/common/helpers/auth_helper_spec.rb +73 -73
- data/spec/unit/common/oauth2_auth_client_spec.rb +1 -1
- data/tasks/compatibility.rake +113 -113
- data/tasks/evaluation.rake +162 -162
- metadata +16 -30
@@ -1,103 +1,103 @@
|
|
1
|
-
module Nucleus
|
2
|
-
module Adapters
|
3
|
-
module V1
|
4
|
-
class CloudControl < Stub
|
5
|
-
# cloud control application's log management operations
|
6
|
-
module Logs
|
7
|
-
# Cloud control log types. The +key+ and +id+ shall match the Nucleus definitions of log files,
|
8
|
-
# whereas the +name+ shall match the cloud control log id.
|
9
|
-
LOG_TYPES = {
|
10
|
-
all: { id: 'all', name: 'all', type: Enums::ApplicationLogfileType::OTHER },
|
11
|
-
request: { id: 'request', name: 'access', type: Enums::ApplicationLogfileType::REQUEST },
|
12
|
-
application: { id: 'application', name: 'error', type: Enums::ApplicationLogfileType::APPLICATION },
|
13
|
-
api: { id: 'api', name: 'deploy', type: Enums::ApplicationLogfileType::API },
|
14
|
-
system: { id: 'system', name: 'worker', type: Enums::ApplicationLogfileType::SYSTEM }
|
15
|
-
}
|
16
|
-
|
17
|
-
# @see Stub#logs
|
18
|
-
def logs(application_name)
|
19
|
-
# fails with 404 if application is not available and serves for timestamps
|
20
|
-
app = get("/app/#{application_name}").body
|
21
|
-
|
22
|
-
LOG_TYPES.values.collect do |log|
|
23
|
-
log[:created_at] = app[:date_created]
|
24
|
-
log[:updated_at] = app[:date_modified]
|
25
|
-
log
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# @see Stub#log?
|
30
|
-
def log?(application_name, log_id)
|
31
|
-
# fails with 404 if application is not available
|
32
|
-
get("/app/#{application_name}")
|
33
|
-
|
34
|
-
LOG_TYPES.key? log_id.to_sym
|
35
|
-
end
|
36
|
-
|
37
|
-
# cloud control shows the last 500 log messages if applicable
|
38
|
-
# @see Stub#tail
|
39
|
-
def tail(application_name, log_id, stream)
|
40
|
-
# cache headers as they are bound to a request and could be lost with the next tick
|
41
|
-
headers_to_use = headers
|
42
|
-
logs_to_poll = log_id == 'all' ? LOG_TYPES.keys - [:all] : [log_id]
|
43
|
-
poller = LogPoller.new(self, headers_to_use)
|
44
|
-
poller.start(application_name, logs_to_poll, stream)
|
45
|
-
TailStopper.new(poller, :stop)
|
46
|
-
end
|
47
|
-
|
48
|
-
# cloud control shows the last 500 log messages if applicable
|
49
|
-
# @see Stub#log_entries
|
50
|
-
def log_entries(application_name, log_id)
|
51
|
-
unless log?(application_name, log_id)
|
52
|
-
fail Errors::AdapterResourceNotFoundError,
|
53
|
-
"Invalid log file '#{log_id}', not available for application '#{application_name}'"
|
54
|
-
end
|
55
|
-
if log_id == 'all'
|
56
|
-
fetched_lines = []
|
57
|
-
(LOG_TYPES.keys - [:all]).each do |current_log_id|
|
58
|
-
cc_log_entries(application_name, current_log_id).each do |line|
|
59
|
-
line[:nucleus_origin] = current_log_id
|
60
|
-
fetched_lines.push(line)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
fetched_lines.sort_by! { |line| line[:time] }
|
64
|
-
fetched_lines.collect { |line| format_log_entry(line[:nucleus_origin], line) }
|
65
|
-
else
|
66
|
-
cc_log_entries(application_name, log_id).collect { |line| format_log_entry(log_id, line) }
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
|
72
|
-
def cc_log_entries(app_name, log_id, time = nil, headers_to_use = nil)
|
73
|
-
log_name = LOG_TYPES[log_id.to_sym][:name]
|
74
|
-
# Hack, do not create fresh headers (which would fail) when in a deferred action
|
75
|
-
headers_to_use = headers unless headers_to_use
|
76
|
-
if time
|
77
|
-
get("/app/#{app_name}/deployment/#{NUCLEUS_DEPLOYMENT}/log/#{log_name}?timestamp=#{time}",
|
78
|
-
headers: headers_to_use).body
|
79
|
-
else
|
80
|
-
get("/app/#{app_name}/deployment/#{NUCLEUS_DEPLOYMENT}/log/#{log_name}", headers: headers_to_use).body
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def format_log_entry(log_id, line)
|
85
|
-
# format according to: https://github.com/cloudControl/cctrl/blob/master/cctrl/output.py
|
86
|
-
case log_id.to_sym
|
87
|
-
when :request
|
88
|
-
"#{line[:remote_host]} #{line[:remote_user]} #{line[:remote_logname]} [#{Time.at(line[:time]).iso8601}] "\
|
89
|
-
"#{line[:first_request_line]} #{line[:status]} #{line[:response_size_CLF]} #{line[:referer]} "\
|
90
|
-
"#{line[:user_agent]}"
|
91
|
-
when :system
|
92
|
-
"#{line[:time]} #{line[:wrk_id]} #{line[:message]}"
|
93
|
-
when :build
|
94
|
-
"#{Time.at(line[:time]).iso8601} [#{line[:hostname]}/#{line[:depl_id]}] #{line[:level]} #{line[:message]}"
|
95
|
-
when :error
|
96
|
-
"#{line[:time]} #{line[:type]} #{line[:message]}"
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
1
|
+
module Nucleus
|
2
|
+
module Adapters
|
3
|
+
module V1
|
4
|
+
class CloudControl < Stub
|
5
|
+
# cloud control application's log management operations
|
6
|
+
module Logs
|
7
|
+
# Cloud control log types. The +key+ and +id+ shall match the Nucleus definitions of log files,
|
8
|
+
# whereas the +name+ shall match the cloud control log id.
|
9
|
+
LOG_TYPES = {
|
10
|
+
all: { id: 'all', name: 'all', type: Enums::ApplicationLogfileType::OTHER },
|
11
|
+
request: { id: 'request', name: 'access', type: Enums::ApplicationLogfileType::REQUEST },
|
12
|
+
application: { id: 'application', name: 'error', type: Enums::ApplicationLogfileType::APPLICATION },
|
13
|
+
api: { id: 'api', name: 'deploy', type: Enums::ApplicationLogfileType::API },
|
14
|
+
system: { id: 'system', name: 'worker', type: Enums::ApplicationLogfileType::SYSTEM }
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
# @see Stub#logs
|
18
|
+
def logs(application_name)
|
19
|
+
# fails with 404 if application is not available and serves for timestamps
|
20
|
+
app = get("/app/#{application_name}").body
|
21
|
+
|
22
|
+
LOG_TYPES.values.collect do |log|
|
23
|
+
log[:created_at] = app[:date_created]
|
24
|
+
log[:updated_at] = app[:date_modified]
|
25
|
+
log
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# @see Stub#log?
|
30
|
+
def log?(application_name, log_id)
|
31
|
+
# fails with 404 if application is not available
|
32
|
+
get("/app/#{application_name}")
|
33
|
+
|
34
|
+
LOG_TYPES.key? log_id.to_sym
|
35
|
+
end
|
36
|
+
|
37
|
+
# cloud control shows the last 500 log messages if applicable
|
38
|
+
# @see Stub#tail
|
39
|
+
def tail(application_name, log_id, stream)
|
40
|
+
# cache headers as they are bound to a request and could be lost with the next tick
|
41
|
+
headers_to_use = headers
|
42
|
+
logs_to_poll = log_id == 'all' ? LOG_TYPES.keys - [:all] : [log_id]
|
43
|
+
poller = LogPoller.new(self, headers_to_use)
|
44
|
+
poller.start(application_name, logs_to_poll, stream)
|
45
|
+
TailStopper.new(poller, :stop)
|
46
|
+
end
|
47
|
+
|
48
|
+
# cloud control shows the last 500 log messages if applicable
|
49
|
+
# @see Stub#log_entries
|
50
|
+
def log_entries(application_name, log_id)
|
51
|
+
unless log?(application_name, log_id)
|
52
|
+
fail Errors::AdapterResourceNotFoundError,
|
53
|
+
"Invalid log file '#{log_id}', not available for application '#{application_name}'"
|
54
|
+
end
|
55
|
+
if log_id == 'all'
|
56
|
+
fetched_lines = []
|
57
|
+
(LOG_TYPES.keys - [:all]).each do |current_log_id|
|
58
|
+
cc_log_entries(application_name, current_log_id).each do |line|
|
59
|
+
line[:nucleus_origin] = current_log_id
|
60
|
+
fetched_lines.push(line)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
fetched_lines.sort_by! { |line| line[:time] }
|
64
|
+
fetched_lines.collect { |line| format_log_entry(line[:nucleus_origin], line) }
|
65
|
+
else
|
66
|
+
cc_log_entries(application_name, log_id).collect { |line| format_log_entry(log_id, line) }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def cc_log_entries(app_name, log_id, time = nil, headers_to_use = nil)
|
73
|
+
log_name = LOG_TYPES[log_id.to_sym][:name]
|
74
|
+
# Hack, do not create fresh headers (which would fail) when in a deferred action
|
75
|
+
headers_to_use = headers unless headers_to_use
|
76
|
+
if time
|
77
|
+
get("/app/#{app_name}/deployment/#{NUCLEUS_DEPLOYMENT}/log/#{log_name}?timestamp=#{time}",
|
78
|
+
headers: headers_to_use).body
|
79
|
+
else
|
80
|
+
get("/app/#{app_name}/deployment/#{NUCLEUS_DEPLOYMENT}/log/#{log_name}", headers: headers_to_use).body
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def format_log_entry(log_id, line)
|
85
|
+
# format according to: https://github.com/cloudControl/cctrl/blob/master/cctrl/output.py
|
86
|
+
case log_id.to_sym
|
87
|
+
when :request
|
88
|
+
"#{line[:remote_host]} #{line[:remote_user]} #{line[:remote_logname]} [#{Time.at(line[:time]).iso8601}] "\
|
89
|
+
"#{line[:first_request_line]} #{line[:status]} #{line[:response_size_CLF]} #{line[:referer]} "\
|
90
|
+
"#{line[:user_agent]}"
|
91
|
+
when :system
|
92
|
+
"#{line[:time]} #{line[:wrk_id]} #{line[:message]}"
|
93
|
+
when :build
|
94
|
+
"#{Time.at(line[:time]).iso8601} [#{line[:hostname]}/#{line[:depl_id]}] #{line[:level]} #{line[:message]}"
|
95
|
+
when :error
|
96
|
+
"#{line[:time]} #{line[:type]} #{line[:message]}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -1,88 +1,88 @@
|
|
1
|
-
module Nucleus
|
2
|
-
module Adapters
|
3
|
-
module V1
|
4
|
-
class CloudControl < Stub
|
5
|
-
# cloud control, CRUD operations for the application's environment variable object,
|
6
|
-
# which is referred to as +config addon+ on the platform.
|
7
|
-
module Vars
|
8
|
-
# @see Stub#env_vars
|
9
|
-
def env_vars(application_id)
|
10
|
-
cc_vars = cc_vars(application_id)
|
11
|
-
cc_vars.collect do |key, value|
|
12
|
-
{ id: key, key: key, value: value }
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
# @see Stub#env_var
|
17
|
-
def env_var(application_id, env_var_key)
|
18
|
-
cc_vars = cc_vars(application_id)
|
19
|
-
fail Errors::AdapterResourceNotFoundError,
|
20
|
-
"Env. var key '#{env_var_key}' does not exist" unless env_var?(application_id, env_var_key, cc_vars)
|
21
|
-
{ id: env_var_key, key: env_var_key, value: cc_vars[env_var_key.to_sym] }
|
22
|
-
end
|
23
|
-
|
24
|
-
# @see Stub#create_env_var
|
25
|
-
def create_env_var(application_id, env_var)
|
26
|
-
cc_vars = cc_vars(application_id)
|
27
|
-
fail Errors::SemanticAdapterRequestError,
|
28
|
-
"Env. var key '#{env_var[:key]}' already taken" if env_var?(application_id, env_var[:key], cc_vars)
|
29
|
-
set_var(application_id, env_var[:key], env_var[:value])
|
30
|
-
end
|
31
|
-
|
32
|
-
# @see Stub#update_env_var
|
33
|
-
def update_env_var(application_id, env_var_key, env_var)
|
34
|
-
cc_vars = cc_vars(application_id)
|
35
|
-
fail Errors::AdapterResourceNotFoundError,
|
36
|
-
"Env. var key '#{env_var_key}' does not exist" unless env_var?(application_id, env_var_key, cc_vars)
|
37
|
-
set_var(application_id, env_var_key, env_var[:value])
|
38
|
-
end
|
39
|
-
|
40
|
-
# @see Stub#delete_env_var
|
41
|
-
def delete_env_var(application_id, env_var_key)
|
42
|
-
cc_vars = cc_vars(application_id)
|
43
|
-
fail Errors::AdapterResourceNotFoundError,
|
44
|
-
"Env. var key '#{env_var_key}' does not exist" unless env_var?(application_id, env_var_key, cc_vars)
|
45
|
-
set_var(application_id, env_var_key, nil)
|
46
|
-
end
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
def cc_vars(application_id)
|
51
|
-
cc_vars_response = get("app/#{application_id}/deployment/#{NUCLEUS_DEPLOYMENT}/addon/config.free")
|
52
|
-
cc_vars_response.body[:settings][:CONFIG_VARS]
|
53
|
-
end
|
54
|
-
|
55
|
-
# Set the variable value (create or update)
|
56
|
-
# @param [String] application_id id of the cloud control application
|
57
|
-
# @param [Symbol] key variable key name
|
58
|
-
# @param [String, Integer, Float, Double] value value to apply to the variable
|
59
|
-
# @return [Hash] Nucleus representation of the modified variable
|
60
|
-
def set_var(application_id, key, value)
|
61
|
-
if value.nil?
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
response = put("/app/#{application_id}/deployment/#{NUCLEUS_DEPLOYMENT}/addon/config.free",
|
68
|
-
body: { addon: 'config.free',
|
69
|
-
settings: settings,
|
70
|
-
force: true })
|
71
|
-
all_vars = response.body[:settings][:CONFIG_VARS]
|
72
|
-
{ id: key, key: key, value: all_vars[key.to_sym] }
|
73
|
-
end
|
74
|
-
|
75
|
-
# Checks if a variable with the env_var_key already exists.
|
76
|
-
# @param [String] application_id id of the cloud control application
|
77
|
-
# @param [Symbol] env_var_key key name that shall be checked for existence
|
78
|
-
# @param [Hash] all_vars collection of currently existing variables for the application
|
79
|
-
# @return [Boolean] true if there is a variable with the env_var_key, otherwise false
|
80
|
-
def env_var?(application_id, env_var_key, all_vars = nil)
|
81
|
-
all_vars = cc_vars(application_id) if all_vars.nil?
|
82
|
-
all_vars.key? env_var_key.to_sym
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
1
|
+
module Nucleus
|
2
|
+
module Adapters
|
3
|
+
module V1
|
4
|
+
class CloudControl < Stub
|
5
|
+
# cloud control, CRUD operations for the application's environment variable object,
|
6
|
+
# which is referred to as +config addon+ on the platform.
|
7
|
+
module Vars
|
8
|
+
# @see Stub#env_vars
|
9
|
+
def env_vars(application_id)
|
10
|
+
cc_vars = cc_vars(application_id)
|
11
|
+
cc_vars.collect do |key, value|
|
12
|
+
{ id: key, key: key, value: value }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# @see Stub#env_var
|
17
|
+
def env_var(application_id, env_var_key)
|
18
|
+
cc_vars = cc_vars(application_id)
|
19
|
+
fail Errors::AdapterResourceNotFoundError,
|
20
|
+
"Env. var key '#{env_var_key}' does not exist" unless env_var?(application_id, env_var_key, cc_vars)
|
21
|
+
{ id: env_var_key, key: env_var_key, value: cc_vars[env_var_key.to_sym] }
|
22
|
+
end
|
23
|
+
|
24
|
+
# @see Stub#create_env_var
|
25
|
+
def create_env_var(application_id, env_var)
|
26
|
+
cc_vars = cc_vars(application_id)
|
27
|
+
fail Errors::SemanticAdapterRequestError,
|
28
|
+
"Env. var key '#{env_var[:key]}' already taken" if env_var?(application_id, env_var[:key], cc_vars)
|
29
|
+
set_var(application_id, env_var[:key], env_var[:value])
|
30
|
+
end
|
31
|
+
|
32
|
+
# @see Stub#update_env_var
|
33
|
+
def update_env_var(application_id, env_var_key, env_var)
|
34
|
+
cc_vars = cc_vars(application_id)
|
35
|
+
fail Errors::AdapterResourceNotFoundError,
|
36
|
+
"Env. var key '#{env_var_key}' does not exist" unless env_var?(application_id, env_var_key, cc_vars)
|
37
|
+
set_var(application_id, env_var_key, env_var[:value])
|
38
|
+
end
|
39
|
+
|
40
|
+
# @see Stub#delete_env_var
|
41
|
+
def delete_env_var(application_id, env_var_key)
|
42
|
+
cc_vars = cc_vars(application_id)
|
43
|
+
fail Errors::AdapterResourceNotFoundError,
|
44
|
+
"Env. var key '#{env_var_key}' does not exist" unless env_var?(application_id, env_var_key, cc_vars)
|
45
|
+
set_var(application_id, env_var_key, nil)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def cc_vars(application_id)
|
51
|
+
cc_vars_response = get("app/#{application_id}/deployment/#{NUCLEUS_DEPLOYMENT}/addon/config.free")
|
52
|
+
cc_vars_response.body[:settings][:CONFIG_VARS]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Set the variable value (create or update)
|
56
|
+
# @param [String] application_id id of the cloud control application
|
57
|
+
# @param [Symbol] key variable key name
|
58
|
+
# @param [String, Integer, Float, Double] value value to apply to the variable
|
59
|
+
# @return [Hash] Nucleus representation of the modified variable
|
60
|
+
def set_var(application_id, key, value)
|
61
|
+
settings = if value.nil?
|
62
|
+
# delete the var, set to 'null'
|
63
|
+
"{\"#{key}\":null}"
|
64
|
+
else
|
65
|
+
"{\"#{key}\":\"#{value}\"}"
|
66
|
+
end
|
67
|
+
response = put("/app/#{application_id}/deployment/#{NUCLEUS_DEPLOYMENT}/addon/config.free",
|
68
|
+
body: { addon: 'config.free',
|
69
|
+
settings: settings,
|
70
|
+
force: true })
|
71
|
+
all_vars = response.body[:settings][:CONFIG_VARS]
|
72
|
+
{ id: key, key: key, value: all_vars[key.to_sym] }
|
73
|
+
end
|
74
|
+
|
75
|
+
# Checks if a variable with the env_var_key already exists.
|
76
|
+
# @param [String] application_id id of the cloud control application
|
77
|
+
# @param [Symbol] env_var_key key name that shall be checked for existence
|
78
|
+
# @param [Hash] all_vars collection of currently existing variables for the application
|
79
|
+
# @return [Boolean] true if there is a variable with the env_var_key, otherwise false
|
80
|
+
def env_var?(application_id, env_var_key, all_vars = nil)
|
81
|
+
all_vars = cc_vars(application_id) if all_vars.nil?
|
82
|
+
all_vars.key? env_var_key.to_sym
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -1,149 +1,149 @@
|
|
1
|
-
module Nucleus
|
2
|
-
module Adapters
|
3
|
-
module V1
|
4
|
-
class CloudFoundryV2 < Stub
|
5
|
-
# Application domain / route functionality to support the Cloud Foundry API.<br>
|
6
|
-
module Domains
|
7
|
-
# @see Stub#domains
|
8
|
-
def domains(domain_id)
|
9
|
-
app_guid = app_guid(domain_id)
|
10
|
-
assigned_routes = get("/v2/apps/#{app_guid}/routes").body
|
11
|
-
domains = []
|
12
|
-
assigned_routes[:resources].each do |assigned_route|
|
13
|
-
nucleus_domain = route_to_nucleus_domain(assigned_route)
|
14
|
-
domains.push(nucleus_domain) unless nucleus_domain[:name] == app_web_url(app_guid)
|
15
|
-
end
|
16
|
-
domains
|
17
|
-
end
|
18
|
-
|
19
|
-
# @see Stub#domain
|
20
|
-
def domain(application_name_or_id, domain_id)
|
21
|
-
app_guid = app_guid(application_name_or_id)
|
22
|
-
assigned_routes = get("/v2/apps/#{app_guid}/routes").body
|
23
|
-
assigned_routes[:resources].each do |assigned_route|
|
24
|
-
return route_to_nucleus_domain(assigned_route) if assigned_route[:metadata][:guid] == domain_id
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# @see Stub#create_domain
|
29
|
-
def create_domain(application_name_or_id, domain)
|
30
|
-
domains(application_name_or_id).each do |existing_domain|
|
31
|
-
if existing_domain[:name] == domain[:name]
|
32
|
-
fail Errors::SemanticAdapterRequestError,
|
33
|
-
"Domain '#{domain[:name]}' is already assigned to the application"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
app_guid = app_guid(application_name_or_id)
|
38
|
-
# extract the hostname and the domain name from the FQDN
|
39
|
-
/(?<domain_host>([-\w]+\.)*)(?<domain_name>([-\w]+\.[-\w]+))/ =~ domain[:name]
|
40
|
-
domain_host.chomp!('.') unless domain_host.nil?
|
41
|
-
|
42
|
-
# finally build the response
|
43
|
-
route_to_nucleus_domain(create_cf_domain(app_guid, domain_name, domain_host))
|
44
|
-
end
|
45
|
-
|
46
|
-
# @see Stub#delete_domain
|
47
|
-
def delete_domain(application_name_or_id, route_id)
|
48
|
-
app_guid = app_guid(application_name_or_id)
|
49
|
-
# remove route from the app
|
50
|
-
delete_response = delete("/v2/apps/#{app_guid}/routes/#{route_id}", expects: [201, 400])
|
51
|
-
if delete_response.status == 400
|
52
|
-
cf_error = delete_response.body[:code]
|
53
|
-
if cf_error == 1002
|
54
|
-
fail Errors::AdapterResourceNotFoundError, 'Domain not found. '\
|
55
|
-
'CF context specific: Route does not exist or is not assigned with this application'
|
56
|
-
else
|
57
|
-
# delete failed with 400, but not due to invalid domain
|
58
|
-
fail Errors::AdapterRequestError,
|
59
|
-
"#{delete_response.body[:description]} (#{cf_error} - #{delete_response.body[:error_code]})"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# check route usage
|
64
|
-
route_in_apps = get("/v2/routes/#{route_id}/apps").body
|
65
|
-
return unless route_in_apps[:total_results] == 0
|
66
|
-
|
67
|
-
# route is no longer needed, delete
|
68
|
-
delete("/v2/routes/#{route_id}")
|
69
|
-
end
|
70
|
-
|
71
|
-
private
|
72
|
-
|
73
|
-
def domain?(application_name_or_id, domain_name)
|
74
|
-
app_guid = app_guid(application_name_or_id)
|
75
|
-
domain_without_protocol = %r{([a-zA-Z]+://)?([-\.\w]*)}.match(domain_name)[2]
|
76
|
-
assigned_routes = get("/v2/apps/#{app_guid}/routes").body
|
77
|
-
assigned_routes[:resources].each do |route|
|
78
|
-
route_domain = get(route[:entity][:domain_url]).body
|
79
|
-
return true if "#{route[:entity][:host]}.#{route_domain[:entity][:name]}" == domain_without_protocol
|
80
|
-
end
|
81
|
-
false
|
82
|
-
end
|
83
|
-
|
84
|
-
def route_to_nucleus_domain(route_resource)
|
85
|
-
route_entity = route_resource[:entity]
|
86
|
-
route_metadata = route_resource[:metadata]
|
87
|
-
assigned_domain = get(route_entity[:domain_url]).body
|
88
|
-
domain = { id: route_metadata[:guid], created_at: route_metadata[:created_at] }
|
89
|
-
if route_metadata[:updated_at].to_s == ''
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
if route_entity[:host].to_s == ''
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
domain
|
101
|
-
end
|
102
|
-
|
103
|
-
def cf_domain(domain_name)
|
104
|
-
%w(private shared).each do |domain_type|
|
105
|
-
response = get("/v2/#{domain_type}_domains").body
|
106
|
-
response[:resources].each do |domain|
|
107
|
-
return domain if domain[:entity][:name] == domain_name
|
108
|
-
end
|
109
|
-
end
|
110
|
-
nil
|
111
|
-
end
|
112
|
-
|
113
|
-
def cf_route(domain_guid, domain_host)
|
114
|
-
# There is no way to check if a root domain (empty hostname) is already taken.
|
115
|
-
# Therefore we must iterate through all routes and find matches...
|
116
|
-
all_routes = get('/v2/routes').body[:resources]
|
117
|
-
all_routes.each do |route|
|
118
|
-
return route if route[:entity][:domain_guid] == domain_guid && route[:entity][:host] == domain_host
|
119
|
-
end
|
120
|
-
nil
|
121
|
-
end
|
122
|
-
|
123
|
-
def create_cf_domain(app_guid, domain_name, domain_host)
|
124
|
-
created_domain = cf_domain(domain_name)
|
125
|
-
unless created_domain
|
126
|
-
# domain does not exist, create!
|
127
|
-
domain_request_body = { name: domain_name, owning_organization_guid: default_organization_guid }
|
128
|
-
created_domain = post('/v2/private_domains', body: domain_request_body).body
|
129
|
-
end
|
130
|
-
|
131
|
-
created_route = cf_route(created_domain[:metadata][:guid], domain_host)
|
132
|
-
unless created_route
|
133
|
-
# route does not exist, create!
|
134
|
-
route_request_body = { domain_guid: created_domain[:metadata][:guid],
|
135
|
-
host: domain_host, space_guid: user_space_guid }
|
136
|
-
created_route = post('/v2/routes', body: route_request_body).body
|
137
|
-
end
|
138
|
-
|
139
|
-
# assign the route to the application
|
140
|
-
put("/v2/apps/#{app_guid}/routes/#{created_route[:metadata][:guid]}").body
|
141
|
-
|
142
|
-
# return the actual route, not the association response
|
143
|
-
created_route
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
1
|
+
module Nucleus
|
2
|
+
module Adapters
|
3
|
+
module V1
|
4
|
+
class CloudFoundryV2 < Stub
|
5
|
+
# Application domain / route functionality to support the Cloud Foundry API.<br>
|
6
|
+
module Domains
|
7
|
+
# @see Stub#domains
|
8
|
+
def domains(domain_id)
|
9
|
+
app_guid = app_guid(domain_id)
|
10
|
+
assigned_routes = get("/v2/apps/#{app_guid}/routes").body
|
11
|
+
domains = []
|
12
|
+
assigned_routes[:resources].each do |assigned_route|
|
13
|
+
nucleus_domain = route_to_nucleus_domain(assigned_route)
|
14
|
+
domains.push(nucleus_domain) unless nucleus_domain[:name] == app_web_url(app_guid)
|
15
|
+
end
|
16
|
+
domains
|
17
|
+
end
|
18
|
+
|
19
|
+
# @see Stub#domain
|
20
|
+
def domain(application_name_or_id, domain_id)
|
21
|
+
app_guid = app_guid(application_name_or_id)
|
22
|
+
assigned_routes = get("/v2/apps/#{app_guid}/routes").body
|
23
|
+
assigned_routes[:resources].each do |assigned_route|
|
24
|
+
return route_to_nucleus_domain(assigned_route) if assigned_route[:metadata][:guid] == domain_id
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# @see Stub#create_domain
|
29
|
+
def create_domain(application_name_or_id, domain)
|
30
|
+
domains(application_name_or_id).each do |existing_domain|
|
31
|
+
if existing_domain[:name] == domain[:name]
|
32
|
+
fail Errors::SemanticAdapterRequestError,
|
33
|
+
"Domain '#{domain[:name]}' is already assigned to the application"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
app_guid = app_guid(application_name_or_id)
|
38
|
+
# extract the hostname and the domain name from the FQDN
|
39
|
+
/(?<domain_host>([-\w]+\.)*)(?<domain_name>([-\w]+\.[-\w]+))/ =~ domain[:name]
|
40
|
+
domain_host.chomp!('.') unless domain_host.nil?
|
41
|
+
|
42
|
+
# finally build the response
|
43
|
+
route_to_nucleus_domain(create_cf_domain(app_guid, domain_name, domain_host))
|
44
|
+
end
|
45
|
+
|
46
|
+
# @see Stub#delete_domain
|
47
|
+
def delete_domain(application_name_or_id, route_id)
|
48
|
+
app_guid = app_guid(application_name_or_id)
|
49
|
+
# remove route from the app
|
50
|
+
delete_response = delete("/v2/apps/#{app_guid}/routes/#{route_id}", expects: [201, 400])
|
51
|
+
if delete_response.status == 400
|
52
|
+
cf_error = delete_response.body[:code]
|
53
|
+
if cf_error == 1002
|
54
|
+
fail Errors::AdapterResourceNotFoundError, 'Domain not found. '\
|
55
|
+
'CF context specific: Route does not exist or is not assigned with this application'
|
56
|
+
else
|
57
|
+
# delete failed with 400, but not due to invalid domain
|
58
|
+
fail Errors::AdapterRequestError,
|
59
|
+
"#{delete_response.body[:description]} (#{cf_error} - #{delete_response.body[:error_code]})"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# check route usage
|
64
|
+
route_in_apps = get("/v2/routes/#{route_id}/apps").body
|
65
|
+
return unless route_in_apps[:total_results] == 0
|
66
|
+
|
67
|
+
# route is no longer needed, delete
|
68
|
+
delete("/v2/routes/#{route_id}")
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def domain?(application_name_or_id, domain_name)
|
74
|
+
app_guid = app_guid(application_name_or_id)
|
75
|
+
domain_without_protocol = %r{([a-zA-Z]+://)?([-\.\w]*)}.match(domain_name)[2]
|
76
|
+
assigned_routes = get("/v2/apps/#{app_guid}/routes").body
|
77
|
+
assigned_routes[:resources].each do |route|
|
78
|
+
route_domain = get(route[:entity][:domain_url]).body
|
79
|
+
return true if "#{route[:entity][:host]}.#{route_domain[:entity][:name]}" == domain_without_protocol
|
80
|
+
end
|
81
|
+
false
|
82
|
+
end
|
83
|
+
|
84
|
+
def route_to_nucleus_domain(route_resource)
|
85
|
+
route_entity = route_resource[:entity]
|
86
|
+
route_metadata = route_resource[:metadata]
|
87
|
+
assigned_domain = get(route_entity[:domain_url]).body
|
88
|
+
domain = { id: route_metadata[:guid], created_at: route_metadata[:created_at] }
|
89
|
+
domain[:updated_at] = if route_metadata[:updated_at].to_s == ''
|
90
|
+
route_metadata[:created_at]
|
91
|
+
else
|
92
|
+
route_metadata[:updated_at]
|
93
|
+
end
|
94
|
+
|
95
|
+
domain[:name] = if route_entity[:host].to_s == ''
|
96
|
+
assigned_domain[:entity][:name]
|
97
|
+
else
|
98
|
+
"#{route_entity[:host]}.#{assigned_domain[:entity][:name]}"
|
99
|
+
end
|
100
|
+
domain
|
101
|
+
end
|
102
|
+
|
103
|
+
def cf_domain(domain_name)
|
104
|
+
%w(private shared).each do |domain_type|
|
105
|
+
response = get("/v2/#{domain_type}_domains").body
|
106
|
+
response[:resources].each do |domain|
|
107
|
+
return domain if domain[:entity][:name] == domain_name
|
108
|
+
end
|
109
|
+
end
|
110
|
+
nil
|
111
|
+
end
|
112
|
+
|
113
|
+
def cf_route(domain_guid, domain_host)
|
114
|
+
# There is no way to check if a root domain (empty hostname) is already taken.
|
115
|
+
# Therefore we must iterate through all routes and find matches...
|
116
|
+
all_routes = get('/v2/routes').body[:resources]
|
117
|
+
all_routes.each do |route|
|
118
|
+
return route if route[:entity][:domain_guid] == domain_guid && route[:entity][:host] == domain_host
|
119
|
+
end
|
120
|
+
nil
|
121
|
+
end
|
122
|
+
|
123
|
+
def create_cf_domain(app_guid, domain_name, domain_host)
|
124
|
+
created_domain = cf_domain(domain_name)
|
125
|
+
unless created_domain
|
126
|
+
# domain does not exist, create!
|
127
|
+
domain_request_body = { name: domain_name, owning_organization_guid: default_organization_guid }
|
128
|
+
created_domain = post('/v2/private_domains', body: domain_request_body).body
|
129
|
+
end
|
130
|
+
|
131
|
+
created_route = cf_route(created_domain[:metadata][:guid], domain_host)
|
132
|
+
unless created_route
|
133
|
+
# route does not exist, create!
|
134
|
+
route_request_body = { domain_guid: created_domain[:metadata][:guid],
|
135
|
+
host: domain_host, space_guid: user_space_guid }
|
136
|
+
created_route = post('/v2/routes', body: route_request_body).body
|
137
|
+
end
|
138
|
+
|
139
|
+
# assign the route to the application
|
140
|
+
put("/v2/apps/#{app_guid}/routes/#{created_route[:metadata][:guid]}").body
|
141
|
+
|
142
|
+
# return the actual route, not the association response
|
143
|
+
created_route
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|