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