cf_light_api 2.6.0 → 3.0.0.pre1
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/bin/cf_light_api +1 -0
- data/lib/cf_light_api/cf_response_error.rb +2 -0
- data/lib/cf_light_api/worker.rb +220 -119
- data/lib/sinatra/cf_light_api.rb +11 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d374bcb2bda0fd2db6302a99752f4ffe46438ad
|
4
|
+
data.tar.gz: 02301b70a44ba3d2376828040f407f8c46597a0f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5535e198e1e5531135cb259529079a91c1c5f91aeafa93a4ef65b8a8f7fbbbf4da142d4a0c755d6fdcda221841666d1425561f64d2b230c89ba60542e9ce97f2
|
7
|
+
data.tar.gz: 79e6852453c97727dba30d4877aa2503757e95b467a94ad7bc2562324aec5e29519119d02c522704898acac4620cdc199c84d5211361016fa7e5d842f5d353ad
|
data/bin/cf_light_api
CHANGED
data/lib/cf_light_api/worker.rb
CHANGED
@@ -18,6 +18,13 @@ class CFLightAPIWorker
|
|
18
18
|
|
19
19
|
def initialize
|
20
20
|
@logger = Logger.new(STDOUT)
|
21
|
+
|
22
|
+
if ENV['DEBUG']
|
23
|
+
@logger.level = Logger::DEBUG
|
24
|
+
else
|
25
|
+
@logger.level = Logger::INFO
|
26
|
+
end
|
27
|
+
|
21
28
|
@logger.formatter = proc do |severity, datetime, progname, msg|
|
22
29
|
"#{datetime} [cf_light_api:worker]: #{msg}\n"
|
23
30
|
end
|
@@ -34,7 +41,7 @@ class CFLightAPIWorker
|
|
34
41
|
if ENV['GRAPHITE_HOST'] or ENV['GRAPHITE_PORT']
|
35
42
|
['GRAPHITE_HOST', 'GRAPHITE_PORT', 'CF_ENV_NAME'].each do |env|
|
36
43
|
unless ENV[env]
|
37
|
-
@logger.info "Error: please set the '#{env}' environment variable to enable exporting to Graphite."
|
44
|
+
@logger.info "Error: please also set the '#{env}' environment variable to enable exporting to Graphite."
|
38
45
|
exit 1
|
39
46
|
end
|
40
47
|
end
|
@@ -61,30 +68,43 @@ class CFLightAPIWorker
|
|
61
68
|
@scheduler.every update_interval, :first_in => '5s', :overlap => false, :timeout => update_timeout do
|
62
69
|
update_cf_data
|
63
70
|
end
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
def formatted_instance_stats_for_app app
|
68
|
-
instances = cf_rest("/v2/apps/#{app['metadata']['guid']}/stats")[0]
|
69
|
-
raise "Unable to retrieve app instance stats: '#{instances['error_code']}'" if instances['error_code']
|
70
|
-
instances.map{|key,value|value}
|
71
71
|
end
|
72
72
|
|
73
73
|
def cf_rest(path, method='GET')
|
74
|
-
@logger.
|
74
|
+
@logger.debug "Making #{method} request for #{path}..."
|
75
75
|
|
76
76
|
resources = []
|
77
|
-
options
|
78
|
-
response
|
77
|
+
options = {:accept => :json}
|
78
|
+
response = @cf_client.base.rest_client.request(method, path, options)[1][:body]
|
79
79
|
|
80
80
|
begin
|
81
81
|
response = JSON.parse(response)
|
82
|
+
if response['error_code']
|
83
|
+
raise CFResponseError.new("Code #{response['code']}, #{response['error_code']} - #{response['description']}")
|
84
|
+
end
|
85
|
+
|
82
86
|
rescue Rufus::Scheduler::TimeoutError => e
|
83
87
|
raise e
|
88
|
+
rescue JSON::ParserError => e
|
89
|
+
@logger.error "Error parsing JSON response from #{method} #{path}: #{e.message}"
|
90
|
+
@logger.trace e.backtrace
|
91
|
+
@logger.trace response
|
92
|
+
raise e
|
93
|
+
rescue CFoundry => e
|
94
|
+
@logger.error "CFoundry error making #{method} #{path}: #{e.message}"
|
95
|
+
@logger.trace e.backtrace
|
96
|
+
@logger.trace response
|
97
|
+
raise e
|
98
|
+
rescue CFResponseError => e
|
99
|
+
@logger.error "CF API returned a response with an error document for #{method} #{path}: #{e.message}"
|
100
|
+
@logger.trace e.backtrace
|
101
|
+
@logger.trace response
|
102
|
+
raise e
|
84
103
|
rescue StandardError => e
|
85
|
-
@logger.
|
86
|
-
@logger.
|
87
|
-
|
104
|
+
@logger.error "General error making #{method} #{path}: #{e.message}"
|
105
|
+
@logger.trace e.backtrace
|
106
|
+
@logger.trace response
|
107
|
+
raise e
|
88
108
|
end
|
89
109
|
|
90
110
|
# Some endpoints return a 'resources' array, others are flat, depending on the path.
|
@@ -111,33 +131,36 @@ class CFLightAPIWorker
|
|
111
131
|
|
112
132
|
instance_stats.each_with_index do |instance_data, index|
|
113
133
|
graphite_base_key = "cf_apps.#{ENV['CF_ENV_NAME']}.#{org}.#{space}.#{sanitised_app_name}.#{index}"
|
114
|
-
@logger.
|
134
|
+
@logger.debug " Exporting app instance \##{index} usage statistics to Graphite, path '#{graphite_base_key}'"
|
115
135
|
|
116
136
|
# Quota data
|
117
137
|
['mem_quota', 'disk_quota'].each do |key|
|
118
|
-
@
|
138
|
+
@logger.trace "#{graphite_base_key}.#{key} => #{instance_data['stats'][key]}"
|
139
|
+
# @graphite.metrics "#{graphite_base_key}.#{key}" => instance_data['stats'][key]
|
119
140
|
end
|
120
141
|
|
121
142
|
# Usage data
|
122
143
|
['mem', 'disk', 'cpu'].each do |key|
|
123
|
-
@
|
144
|
+
@logger.trace "#{graphite_base_key}.#{key} => #{instance_data['stats']['usage'][key]}"
|
145
|
+
# @graphite.metrics "#{graphite_base_key}.#{key}" => instance_data['stats']['usage'][key]
|
124
146
|
end
|
125
147
|
end
|
126
148
|
end
|
127
149
|
|
128
150
|
def send_org_quota_data_to_graphite(org_name, quota)
|
129
151
|
graphite_base_key = "cf_orgs.#{ENV['CF_ENV_NAME']}.#{org_name}"
|
130
|
-
@logger.
|
152
|
+
@logger.debug " Exporting org quota statistics to Graphite, path '#{graphite_base_key}'"
|
131
153
|
|
132
154
|
quota.keys.each do |key|
|
133
|
-
@
|
155
|
+
@logger.trace "#{graphite_base_key}.quota.#{key} => #{quota[key]}"
|
156
|
+
# @graphite.metrics "#{graphite_base_key}.quota.#{key}" => quota[key]
|
134
157
|
end
|
135
158
|
end
|
136
159
|
|
137
160
|
def send_cf_light_api_update_time_to_graphite seconds
|
138
161
|
graphite_key = "cf_light_api.#{ENV['CF_ENV_NAME']}.update_duration"
|
139
|
-
@logger.info "Exporting CF Light API update time to Graphite, path
|
140
|
-
@graphite.metrics "#{graphite_key}" => seconds.round
|
162
|
+
@logger.info "Exporting CF Light API update time to Graphite, path #{graphite_key} => #{seconds.round}"
|
163
|
+
# @graphite.metrics "#{graphite_key}" => seconds.round
|
141
164
|
end
|
142
165
|
|
143
166
|
def put_in_redis(key, data)
|
@@ -151,28 +174,62 @@ class CFLightAPIWorker
|
|
151
174
|
format("%02d hrs, %02d mins, %02d secs", hours, minutes, seconds)
|
152
175
|
end
|
153
176
|
|
177
|
+
def update_domains
|
178
|
+
@domains = cf_rest('/v2/domains?results-per-page=100')
|
179
|
+
end
|
180
|
+
|
181
|
+
def find_domain_for_route route
|
182
|
+
return @domains.find{|a_domain| a_domain['metadata']['guid'] == route['entity']['domain_guid']}
|
183
|
+
end
|
184
|
+
|
154
185
|
def format_routes_for_app app
|
155
|
-
routes
|
186
|
+
# The app object passed in here should contain a "routes" attribute, fetched as part of the original request to CF (with inline-relation gathering enabled)
|
187
|
+
# and it will look something like this:
|
188
|
+
# "routes"=>
|
189
|
+
# [{"metadata"=>{"guid"=>"afea5690-fb93-451a-9610-2d524d36e35f", "url"=>"/v2/routes/afea5690-fb93-451a-9610-2d524d36e35f", "created_at"=>"2015-03-11T12:20:22Z", "updated_at"=>"2015-03-11T12:20:22Z"},
|
190
|
+
# "entity"=>
|
191
|
+
# {"host"=>"hostname_here",
|
192
|
+
# "path"=>"",
|
193
|
+
# "domain_guid"=>"f13e6864-537e-41bb-b46c-f3810dbf7c84",
|
194
|
+
# "space_guid"=>"c0af44b8-8b51-4db5-927e-ccad2e6dab54",
|
195
|
+
# "service_instance_guid"=>nil,
|
196
|
+
# "port"=>nil,
|
197
|
+
# "domain_url"=>"/v2/shared_domains/f13e6864-537e-41bb-b46c-f3810dbf7c84",
|
198
|
+
# "space_url"=>"/v2/spaces/c0af44b8-8b51-4db5-927e-ccad2e6dab54",
|
199
|
+
# "apps_url"=>"/v2/routes/afea5690-fb93-451a-9610-2d524d36e35f/apps",
|
200
|
+
# "route_mappings_url"=>"/v2/routes/afea5690-fb93-451a-9610-2d524d36e35f/route_mappings"}},
|
201
|
+
# If we don't receive that child attribute, (perhaps the app was being staged or didn't have any routes yet) we make another request to CF to try
|
202
|
+
# and fetch them before giving up and just returning an empty array.
|
203
|
+
|
204
|
+
routes = []
|
205
|
+
if app['entity']['routes'] == nil
|
206
|
+
# We have no routes data inlined with the app entity, so let's try to retrieve them directly from CF
|
207
|
+
routes = cf_rest(app['entity']['routes_url'])
|
208
|
+
else
|
209
|
+
# Routes were already retrieved as an inline-relation, so just use those...
|
210
|
+
routes = app['entity']['routes']
|
211
|
+
end
|
212
|
+
|
156
213
|
routes.collect do |route|
|
157
214
|
host = route['entity']['host']
|
158
215
|
path = route['entity']['path']
|
159
216
|
|
160
|
-
domain =
|
161
|
-
|
162
|
-
domain
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
217
|
+
domain = find_domain_for_route(route)
|
218
|
+
if domain == nil
|
219
|
+
# The domain doesn't exist, this could be due to a race condition, so let's update the list and try again
|
220
|
+
update_domains()
|
221
|
+
domain = find_domain_for_route(route)
|
222
|
+
if domain == nil
|
223
|
+
# If we can't determine the domain associated with this route, raise an error as we can't guarantee the state is correct here,
|
224
|
+
# it shouldn't be possible to get a route back from CF with a domain GUID that doesn't exist, as that route would be invalid.
|
225
|
+
raise "Unable to find domain #{route['entity']['domain_guid']} for route #{route['metadata']['guid']}."
|
226
|
+
end
|
168
227
|
end
|
169
|
-
|
170
|
-
"#{host}.#{domain}#{path}"
|
228
|
+
"#{host}.#{domain['entity']['name']}#{path}"
|
171
229
|
end
|
172
230
|
end
|
173
231
|
|
174
232
|
def filtered_environment_variables env_vars
|
175
|
-
|
176
233
|
if ENVIRONMENT_VARIABLES_WHITELIST.any?
|
177
234
|
return ENVIRONMENT_VARIABLES_WHITELIST.inject({}) do |filtered, key|
|
178
235
|
filtered[key] = env_vars[key] if env_vars[key]
|
@@ -182,7 +239,49 @@ class CFLightAPIWorker
|
|
182
239
|
else
|
183
240
|
return env_vars
|
184
241
|
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def format_orgs orgs
|
245
|
+
return orgs.map do |org|
|
246
|
+
quota = @quotas.find{|a_quota| a_quota['metadata']['guid'] == org['entity']['quota_definition_guid']}
|
185
247
|
|
248
|
+
quota = {
|
249
|
+
:total_services => quota['entity']['total_services'],
|
250
|
+
:total_routes => quota['entity']['total_routes'],
|
251
|
+
:memory_limit => quota['entity']['memory_limit'] * 1024 * 1024
|
252
|
+
}
|
253
|
+
|
254
|
+
send_org_quota_data_to_graphite(org['entity']['name'], quota) if @graphite
|
255
|
+
|
256
|
+
{
|
257
|
+
:guid => org['metadata']['guid'],
|
258
|
+
:name => org['entity']['name'],
|
259
|
+
:quota => quota
|
260
|
+
}
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
def get_v1_base_data app
|
265
|
+
# Format the app data in the expected format for the /v1/apps endpoint, to remain compatible.
|
266
|
+
|
267
|
+
# Find the org for this app, using the org GUID from the space. Relationship: Apps belong to spaces, and spaces belong to orgs.
|
268
|
+
space = @spaces.find{|a_space| a_space['metadata']['guid'] == app['entity']['space_guid']}
|
269
|
+
org = @orgs.find{|an_org| an_org['metadata']['guid'] == space['entity']['organization_guid']}
|
270
|
+
|
271
|
+
{
|
272
|
+
:buildpack => app['entity']['buildpack'],
|
273
|
+
:data_from => Time.now.to_i,
|
274
|
+
:diego => app['entity']['diego'],
|
275
|
+
:docker => app['entity']['docker_image'] ? true : false,
|
276
|
+
:docker_image => app['entity']['docker_image'],
|
277
|
+
:guid => app['metadata']['guid'],
|
278
|
+
:last_uploaded => app['metadata']['updated_at'] ? DateTime.parse(app['metadata']['updated_at']).strftime('%Y-%m-%d %T %z') : nil,
|
279
|
+
:name => app['entity']['name'],
|
280
|
+
:org => org['entity']['name'],
|
281
|
+
:space => space['entity']['name'],
|
282
|
+
:stack => app['entity']['stack']['entity']['name'],
|
283
|
+
:state => app['entity']['state']
|
284
|
+
}
|
186
285
|
end
|
187
286
|
|
188
287
|
def update_cf_data
|
@@ -193,115 +292,113 @@ class CFLightAPIWorker
|
|
193
292
|
@lock_manager.lock("#{ENV['REDIS_KEY_PREFIX']}:lock", 5*60*1000) do |lock|
|
194
293
|
if lock
|
195
294
|
start_time = Time.now
|
196
|
-
|
197
295
|
@logger.info "Updating data..."
|
198
|
-
|
199
296
|
@cf_client = get_client() # Ensure we have a fresh auth token...
|
200
297
|
|
201
|
-
@
|
202
|
-
|
203
|
-
@
|
298
|
+
@cf_info = cf_rest('/v2/info').first
|
299
|
+
|
300
|
+
@apps = cf_rest('/v2/apps?results-per-page=100&inline-relations-depth=1&include-relations=routes,stack')
|
204
301
|
@spaces = cf_rest('/v2/spaces?results-per-page=100')
|
205
|
-
@stacks = cf_rest('/v2/stacks?results-per-page=100')
|
206
|
-
@domains = cf_rest('/v2/domains?results-per-page=100')
|
207
|
-
cf_info = cf_rest('/v2/info').first
|
208
|
-
|
209
|
-
formatted_orgs = @orgs.map do |org|
|
210
|
-
quota = @quotas.find{|a_quota| a_quota['metadata']['guid'] == org['entity']['quota_definition_guid']}
|
211
|
-
|
212
|
-
quota = {
|
213
|
-
:total_services => quota['entity']['total_services'],
|
214
|
-
:total_routes => quota['entity']['total_routes'],
|
215
|
-
:memory_limit => quota['entity']['memory_limit'] * 1024 * 1024
|
216
|
-
}
|
217
|
-
|
218
|
-
send_org_quota_data_to_graphite(org['entity']['name'], quota) if @graphite
|
219
|
-
|
220
|
-
{
|
221
|
-
:guid => org['metadata']['guid'],
|
222
|
-
:name => org['entity']['name'],
|
223
|
-
:quota => quota
|
224
|
-
}
|
225
|
-
end
|
226
302
|
|
227
|
-
|
228
|
-
# TODO: This is a bit repetative, could maybe improve?
|
229
|
-
space = @spaces.find{|a_space| a_space['metadata']['guid'] == app['entity']['space_guid']}
|
230
|
-
org = @orgs.find{|an_org| an_org['metadata']['guid'] == space['entity']['organization_guid']}
|
231
|
-
stack = @stacks.find{|a_stack| a_stack['metadata']['guid'] == app['entity']['stack_guid']}
|
232
|
-
|
233
|
-
running = (app['entity']['state'] == "STARTED")
|
234
|
-
|
235
|
-
base_data = {
|
236
|
-
:buildpack => app['entity']['buildpack'],
|
237
|
-
:data_from => Time.now.to_i,
|
238
|
-
:diego => app['entity']['diego'],
|
239
|
-
:docker => app['entity']['docker_image'] ? true : false,
|
240
|
-
:docker_image => app['entity']['docker_image'],
|
241
|
-
:guid => app['metadata']['guid'],
|
242
|
-
:last_uploaded => app['metadata']['updated_at'] ? DateTime.parse(app['metadata']['updated_at']).strftime('%Y-%m-%d %T %z') : nil,
|
243
|
-
:name => app['entity']['name'],
|
244
|
-
:org => org['entity']['name'],
|
245
|
-
:space => space['entity']['name'],
|
246
|
-
:stack => stack['entity']['name'],
|
247
|
-
:state => app['entity']['state']
|
248
|
-
}
|
249
|
-
|
250
|
-
if ENV['EXPOSE_ENVIRONMENT_VARIABLES'] == 'true' then
|
251
|
-
base_data[:environment_variables] = filtered_environment_variables( app['entity']['environment_json'] )
|
252
|
-
end
|
303
|
+
update_domains() # Sets @domain by hitting the CF API
|
253
304
|
|
254
|
-
|
255
|
-
|
305
|
+
# Orgs
|
306
|
+
@orgs = cf_rest('/v2/organizations?results-per-page=100')
|
307
|
+
@quotas = cf_rest('/v2/quota_definitions?results-per-page=100')
|
308
|
+
formatted_orgs = format_orgs @orgs
|
256
309
|
|
310
|
+
v1_data = []
|
311
|
+
v2_data = []
|
312
|
+
|
313
|
+
Parallel.each(@apps, :in_threads => @update_threads) do |app|
|
257
314
|
begin
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
315
|
+
# Formats the base data compatible with the v1 endpoint
|
316
|
+
v1_document = get_v1_base_data(app)
|
317
|
+
|
318
|
+
# New format base data for the v2 endpoint
|
319
|
+
v2_document = app['entity'].dup
|
320
|
+
v2_document['environment_json'] = {} # The environment JSON will have been duplicated from the app entity, so we need to blank it here, as it will be re-populated later if EXPOSE_ENVIRONMENT_VARIABLES is true.
|
321
|
+
v2_document['created_at'] = app['metadata']['created_at']
|
322
|
+
v2_document['updated_at'] = app['metadata']['updated_at']
|
323
|
+
v2_document['guid'] = app['metadata']['guid']
|
324
|
+
v2_document['instances'] = []
|
325
|
+
v2_document['routes'] = []
|
326
|
+
v2_document['meta'] = { 'error' => false }
|
327
|
+
|
328
|
+
# Add space, stack and org names as a top level string attribute for ease of use:
|
329
|
+
v2_document['stack'] = app['entity']['stack']['entity']['name']
|
330
|
+
|
331
|
+
# Get the org name from the app's space - relationship: an app belongs to a space, and a space belongs to an org.
|
332
|
+
space = @spaces.find{|a_space| a_space['metadata']['guid'] == app['entity']['space_guid']}
|
333
|
+
org = @orgs.find{|an_org| an_org['metadata']['guid'] == space['entity']['organization_guid']}
|
334
|
+
|
335
|
+
v2_document['space'] = space['entity']['name']
|
336
|
+
v1_document['org'] = org['entity']['name']
|
337
|
+
v2_document['org'] = org['entity']['name']
|
338
|
+
|
339
|
+
# Gather and filter environment variable JSON if the feature is enabled:
|
340
|
+
if ENV['EXPOSE_ENVIRONMENT_VARIABLES'] == 'true' then
|
341
|
+
env_vars = filtered_environment_variables( app['entity']['environment_json'] )
|
342
|
+
v1_document['environment_variables'] = env_vars
|
343
|
+
v2_document['environment_json'] = env_vars
|
267
344
|
end
|
268
345
|
|
269
346
|
routes = format_routes_for_app(app)
|
347
|
+
v1_document['routes'] = routes
|
348
|
+
v2_document['routes'] = routes
|
349
|
+
|
350
|
+
response = cf_rest("/v2/apps/#{app['metadata']['guid']}/stats")
|
351
|
+
instances = response.first.map{|key,value|value}
|
352
|
+
v1_document['instances'] = instances
|
353
|
+
v2_document['instances'] = instances
|
354
|
+
|
355
|
+
running = false
|
356
|
+
if instances.any?
|
357
|
+
if instances.select{|instance| instance['state'] == 'RUNNING'}.any?
|
358
|
+
running = true
|
359
|
+
end
|
360
|
+
end
|
361
|
+
v1_document['running'] = running
|
362
|
+
v2_document['running'] = running
|
270
363
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
:routes => routes,
|
275
|
-
:error => nil
|
276
|
-
}
|
364
|
+
if @graphite
|
365
|
+
send_instance_usage_data_to_graphite(instances, org['entity']['name'], app['entity']['space']['entity']['name'], app['entity']['name'])
|
366
|
+
end
|
277
367
|
|
278
368
|
rescue Rufus::Scheduler::TimeoutError => e
|
279
369
|
raise e
|
280
|
-
rescue StandardError => e
|
281
|
-
|
282
|
-
#
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
:routes => [],
|
290
|
-
:error => e.message
|
291
|
-
}
|
370
|
+
rescue CFoundry, CFResponseError, StandardError => e
|
371
|
+
v1_document['running'] = "error"
|
372
|
+
v1_document['error'] = "#{e.message}"
|
373
|
+
|
374
|
+
v2_document['meta'] = {}
|
375
|
+
v2_document['meta']['error'] = true
|
376
|
+
v2_document['meta']['type'] = e.class
|
377
|
+
v2_document['meta']['message'] = e.message
|
378
|
+
v2_document['meta']['backtrace'] = e.backtrace
|
292
379
|
end
|
293
380
|
|
294
|
-
|
381
|
+
v1_data << v1_document
|
382
|
+
v2_data << v2_document
|
383
|
+
end
|
384
|
+
|
385
|
+
# Sanity check - do we have the expected quantity of data? This shouldn't happen as the `parallel` gem should handle
|
386
|
+
# sharing and modifying variables for us when using threads.
|
387
|
+
if @apps.count != v1_data.count or @apps.count != v2_data.count
|
388
|
+
raise "V1 and V2 app counts don't match after processing!"
|
295
389
|
end
|
296
390
|
|
297
|
-
put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:info", cf_info
|
391
|
+
put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:info", @cf_info
|
298
392
|
put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:orgs", formatted_orgs
|
299
|
-
put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:apps",
|
393
|
+
put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:apps", v1_data
|
394
|
+
put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:apps:v2", v2_data
|
395
|
+
|
300
396
|
put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:last_updated", {:last_updated => Time.now}
|
301
397
|
|
302
398
|
elapsed_seconds = Time.now.to_f - start_time.to_f
|
303
|
-
|
399
|
+
|
304
400
|
send_cf_light_api_update_time_to_graphite(elapsed_seconds) if @graphite
|
401
|
+
@logger.info "Update completed in #{format_duration(elapsed_seconds)}..."
|
305
402
|
|
306
403
|
@lock_manager.unlock(lock)
|
307
404
|
@cf_client.logout
|
@@ -310,9 +407,13 @@ class CFLightAPIWorker
|
|
310
407
|
end
|
311
408
|
end
|
312
409
|
rescue Rufus::Scheduler::TimeoutError
|
410
|
+
Parallel::Kill
|
411
|
+
@cf_client.logout
|
313
412
|
@logger.info 'Data update took too long and was aborted, waiting for the lock to expire before trying again...'
|
314
413
|
send_cf_light_api_update_time_to_graphite(0) if @graphite
|
315
|
-
|
414
|
+
rescue StandardError => e
|
415
|
+
@logger.info "Unable to complete update due to #{e.class}: #{e.message}"
|
416
|
+
@logger.error e.backtrace
|
316
417
|
end
|
317
418
|
end
|
318
419
|
|
data/lib/sinatra/cf_light_api.rb
CHANGED
@@ -21,6 +21,17 @@ module Sinatra
|
|
21
21
|
return all_apps.to_json
|
22
22
|
end
|
23
23
|
|
24
|
+
app.get '/v2/apps/?:org?' do
|
25
|
+
content_type :json
|
26
|
+
all_apps = JSON.parse(REDIS.get("#{ENV['REDIS_KEY_PREFIX']}:apps:v2"))
|
27
|
+
|
28
|
+
if params[:org]
|
29
|
+
return all_apps.select{|an_app| an_app['org'] == params[:org]}.to_json
|
30
|
+
end
|
31
|
+
|
32
|
+
return all_apps.to_json
|
33
|
+
end
|
34
|
+
|
24
35
|
app.get '/v1/orgs/?:guid?' do
|
25
36
|
content_type :json
|
26
37
|
all_orgs = JSON.parse(REDIS.get("#{ENV['REDIS_KEY_PREFIX']}:orgs"))
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cf_light_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0.pre1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Springer Platform Engineering
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cfoundry
|
@@ -130,6 +130,7 @@ executables:
|
|
130
130
|
extensions: []
|
131
131
|
extra_rdoc_files: []
|
132
132
|
files:
|
133
|
+
- "./lib/cf_light_api/cf_response_error.rb"
|
133
134
|
- "./lib/cf_light_api/redis.rb"
|
134
135
|
- "./lib/cf_light_api/worker.rb"
|
135
136
|
- "./lib/sinatra/cf_light_api.rb"
|
@@ -149,9 +150,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
149
150
|
version: '0'
|
150
151
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
152
|
requirements:
|
152
|
-
- - "
|
153
|
+
- - ">"
|
153
154
|
- !ruby/object:Gem::Version
|
154
|
-
version:
|
155
|
+
version: 1.3.1
|
155
156
|
requirements: []
|
156
157
|
rubyforge_project:
|
157
158
|
rubygems_version: 2.5.1
|