cf_light_api 1.7.0 → 2.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cf_light_api/worker.rb +212 -91
  3. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3067cac56cd133c9fc4fd246f29e0874335f2998
4
- data.tar.gz: 4fb42dd6f9e61ee969b6d966c15ac5bfc636cc6d
3
+ metadata.gz: bdbf36a622784f98ea2133973966ae40eb500572
4
+ data.tar.gz: 8b12c0cec0408a0f16d31392836eea9286f62fd7
5
5
  SHA512:
6
- metadata.gz: 348c46fd0ae464fb196b78598a713ed1b620a989757bdb1d8dcdf61d542df19b8d7edf5bd985e921b4cd5b61ad3c05ded7831c5f49ec6c4b458c85043ea4fbf9
7
- data.tar.gz: 64723974aad403fb3cff89385976ce7f7a8c2bb4214a3a5fd325f9ff65c8734a6fba658dde1496ca2f6c1e5e123c1ec3bdafa795ad208f5c54a9c2e1bc37ca97
6
+ metadata.gz: 6d65857061da6b5b87dd19928b5386ef2d339649bae6989cec2a981607cc09d28b3f8be72a2d2c97039517a5151e53ec9e50a55e290618e4c9e918bb27eaeb12
7
+ data.tar.gz: c5f6a83db24dbe514f9ce1272824274ac052f71b4f1296462793b4925ad290053273be7e60b21a6715e3555cca98b58823607b9679a2e1b880bc2451dd77f6e3
@@ -31,36 +31,151 @@ scheduler = Rufus::Scheduler.new
31
31
  @logger.info "Update timeout: '#{UPDATE_TIMEOUT}'"
32
32
  @logger.info "Graphite server: #{ENV['GRAPHITE']}" if ENV['GRAPHITE']
33
33
 
34
+ #@domains = {}
35
+ # @domains = cf_rest('/v2/domains?results-per-page=100') # We're retrieving this from the app instance 'uris' key instead.
36
+ # @routes = cf_rest('/v2/routes?results-per-page=100')
37
+
38
+ # def formatted_routes_for_app app
39
+ # routes = cf_rest(app['entity']['routes_url'])
40
+
41
+ # routes.collect do |route|
42
+ # domain = @domains.find{|a_domain| a_domain['metadata']['guid'] == route['entity']['domain_guid']}['entity']['name']
43
+ # # Suffix the hostname with a period for concatenation, unless it's blank (which can happen for apex routes).
44
+ # host = route['entity']['host'] != '' ? "#{route['entity']['host']}." : ''
45
+ # path = route['entity']['path']
46
+ # "#{host}#{domain}#{path}"
47
+ # end
48
+ # end
49
+
50
+ def formatted_instance_stats_for_app app
51
+ instances = cf_rest("/v2/apps/#{app['metadata']['guid']}/stats")[0]
52
+ raise "Unable to retrieve app instance stats: '#{instances['error_code']}'" if instances['error_code']
53
+ instances.map{|key,value|value}
54
+ end
55
+
56
+ def cf_rest(path, method='GET')
57
+ @logger.info "Making #{method} request for #{path}..."
58
+
59
+ resources = []
60
+ response = JSON.parse(@cf_client.base.rest_client.request(method, path)[1][:body])
61
+
62
+ # Some endpoints return a 'resources' array, others are flat, depending on the path.
63
+ if response['resources']
64
+ resources << response['resources']
65
+ else
66
+ resources << response
67
+ end
68
+
69
+ # Handle the pagination by recursing over myself until we get a response which doesn't contain a 'next_url'
70
+ # at which point all the resources are returned up the stack and flattened.
71
+ resources << cf_rest(response['next_url'], method) unless response['next_url'] == nil
72
+ resources.flatten
73
+ end
74
+
34
75
  scheduler.every UPDATE_INTERVAL, :first_in => '5s', :overlap => false, :timeout => UPDATE_TIMEOUT do
35
- cf_client = nil
36
- graphite = GraphiteAPI.new(graphite: ENV['GRAPHITE']) if ENV['GRAPHITE']
76
+ @cf_client = nil
77
+ # graphite = GraphiteAPI.new(graphite: ENV['GRAPHITE']) if ENV['GRAPHITE']
37
78
 
38
79
  begin
39
80
  lock_manager.lock("#{ENV['REDIS_KEY_PREFIX']}:lock", 5*60*1000) do |lock|
40
81
  if lock
41
82
  start_time = Time.now
42
83
 
43
- @logger.info "Updating data in parallel..."
84
+ @logger.info "Updating data..."
85
+
86
+ @cf_client = get_client() # Ensure we have a fresh auth token...
87
+
88
+ @apps = cf_rest('/v2/apps?results-per-page=100')
89
+ @orgs = cf_rest('/v2/organizations?results-per-page=100')
90
+ @quotas = cf_rest('/v2/quota_definitions?results-per-page=100')
91
+ @spaces = cf_rest('/v2/spaces?results-per-page=100')
92
+ @stacks = cf_rest('/v2/stacks?results-per-page=100')
93
+
94
+ # org_data = get_org_data(@cf_client)
95
+ # app_data = get_app_data(@cf_client, graphite)
96
+
97
+ formatted_orgs = @orgs.map do |org|
98
+ quota = @quotas.find{|a_quota| a_quota['metadata']['guid'] == org['entity']['quota_definition_guid']}
99
+
100
+ {
101
+ :guid => org['metadata']['guid'],
102
+ :name => org['entity']['name'],
103
+ :quota => {
104
+ :name => quota['entity']['name'],
105
+ :total_services => quota['entity']['total_services'],
106
+ :total_routes => quota['entity']['total_routes'],
107
+ :memory_limit => quota['entity']['memory_limit'] * 1024 * 1024
108
+ }
109
+ }
110
+ end
111
+
112
+ formatted_apps = @apps.map do |app|
113
+ # TODO: This is a bit repetative, could improve.
114
+ space = @spaces.find{|a_space| a_space['metadata']['guid'] == app['entity']['space_guid']}
115
+ org = @orgs.find{|an_org| an_org['metadata']['guid'] == space['entity']['organization_guid']}
116
+ stack = @stacks.find{|a_stack| a_stack['metadata']['guid'] == app['entity']['stack_guid']}
117
+
118
+ running = (app['entity']['state'] == "STARTED")
44
119
 
45
- cf_client = get_client()
120
+ base_data = {
121
+ :guid => app['metadata']['guid'],
122
+ :name => app['entity']['name'],
123
+ :org => org['entity']['name'],
124
+ :space => space['entity']['name'],
125
+ :stack => stack['entity']['name'],
126
+ :buildpack => app['entity']['buildpack'],
127
+ # This requires a call to /v2/apps/[guid]/routes for each app, or we can just use the 'uris' key from /v2/apps/[guid]/stats
128
+ # which we have to call anyway, to get app instance usage stats..
129
+ # :routes => running ? formatted_routes_for_app(app) : [],
130
+ :data_from => Time.now.to_i,
131
+ :last_uploaded => app['metadata']['updated_at'] ? DateTime.parse(app['metadata']['updated_at']).strftime('%Y-%m-%d %T %z') : nil
132
+ }
46
133
 
47
- org_data = get_org_data(cf_client)
48
- app_data = get_app_data(cf_client, graphite)
134
+ additional_data = {}
135
+ begin
136
+ instance_stats = []
137
+ routes = []
138
+ if running
139
+ instance_stats = formatted_instance_stats_for_app(app)
140
+ # Finds the first running app instance that has a set of routes, in case there are stopped/crashed app instances that don't have any.
141
+ running_instances = instance_stats.select{|instance| instance['stats']['uris'] if instance['state'] == 'RUNNING'}
142
+ raise "Unable to retrieve app routes - no app instances are running." if running_instances.empty?
143
+ routes = running_instances.first['stats']['uris']
144
+ end
49
145
 
50
- put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:orgs", org_data
51
- put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:apps", app_data
146
+ additional_data = {
147
+ :running => running,
148
+ :instances => instance_stats,
149
+ :routes => routes,
150
+ :error => nil
151
+ }
152
+ rescue => e
153
+ @logger.info " #{org['entity']['name']} #{space['entity']['name']}: '#{app['entity']['name']}' error: #{e.message}"
154
+ additional_data = {
155
+ :running => 'error',
156
+ :instances => [],
157
+ :routes => [],
158
+ :error => e.message
159
+ }
160
+ end
161
+
162
+ base_data.merge additional_data
163
+ end
164
+
165
+ put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:orgs", formatted_orgs
166
+ put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:apps", formatted_apps
52
167
  put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:last_updated", {:last_updated => Time.now}
53
168
 
54
169
  @logger.info "Update completed in #{format_duration(Time.now.to_f - start_time.to_f)}..."
55
170
  lock_manager.unlock(lock)
56
- cf_client.logout
171
+ @cf_client.logout
57
172
  else
58
173
  @logger.info "Update already running in another instance!"
59
174
  end
60
175
  end
61
176
  rescue Rufus::Scheduler::TimeoutError
62
177
  @logger.info 'Data update took too long and was aborted, waiting for the lock to expire before trying again...'
63
- cf_client.logout
178
+ @cf_client.logout
64
179
  end
65
180
  end
66
181
 
@@ -70,97 +185,103 @@ def get_client(cf_api=ENV['CF_API'], cf_user=ENV['CF_USER'], cf_password=ENV['CF
70
185
  client
71
186
  end
72
187
 
73
- def send_data_to_graphite(data, graphite)
74
- org = data[:org]
75
- space = data[:space]
76
- name = data[:name].sub ".", "_" # Some apps have dots in the app name
188
+ # def send_data_to_graphite(data, graphite)
189
+ # org = data[:org]
190
+ # space = data[:space]
191
+ # name = data[:name].sub ".", "_" # Some apps have dots in the app name
77
192
 
78
- data[:instances].each_with_index do |instance_data, index|
79
- graphite_base_key = "cf_apps.#{org}.#{space}.#{name}.#{index}"
193
+ # data[:instances].each_with_index do |instance_data, index|
194
+ # graphite_base_key = "cf_apps.#{org}.#{space}.#{name}.#{index}"
80
195
 
81
- # Quota data
82
- [:mem_quota, :disk_quota].each do |key|
83
- graphite.metrics "#{graphite_base_key}.#{key}" => instance_data[:stats][key]
84
- end
196
+ # # Quota data
197
+ # [:mem_quota, :disk_quota].each do |key|
198
+ # graphite.metrics "#{graphite_base_key}.#{key}" => instance_data[:stats][key]
199
+ # end
85
200
 
86
- # Usage data
87
- [:mem, :disk, :cpu].each do |key|
88
- graphite.metrics "#{graphite_base_key}.#{key}" => instance_data[:stats][:usage][key]
89
- end
90
- end
91
- end
201
+ # # Usage data
202
+ # [:mem, :disk, :cpu].each do |key|
203
+ # graphite.metrics "#{graphite_base_key}.#{key}" => instance_data[:stats][:usage][key]
204
+ # end
205
+ # end
206
+ # end
92
207
 
93
- def get_app_data(cf_client, graphite)
94
- Parallel.map(cf_client.organizations, :in_threads=> PARALLEL_MAPS) do |org|
95
- org_name = org.name
96
- Parallel.map(org.spaces, :in_threads => PARALLEL_MAPS) do |space|
97
- space_name = space.name
98
- @logger.info "Getting app data for apps in #{org_name}:#{space_name}..."
99
- Parallel.map(space.apps, :in_threads=> PARALLEL_MAPS) do |app|
100
- begin
101
- # It's possible for an app to have been terminated before this stage is reached.
102
- formatted_app_data = format_app_data(app, org_name, space_name)
103
- if graphite
104
- send_data_to_graphite(formatted_app_data, graphite)
105
- end
106
- formatted_app_data
107
- rescue CFoundry::AppNotFound
108
- next
109
- end
110
- end
111
- end
112
- end.flatten.compact
113
- end
208
+ # def get_app_data(cf_client, graphite)
209
+ # Parallel.map(cf_client.organizations, :in_threads=> PARALLEL_MAPS) do |org|
210
+ # org_name = org.name
211
+ # Parallel.map(org.spaces, :in_threads => PARALLEL_MAPS) do |space|
212
+ # space_name = space.name
213
+ # @logger.info "Getting app data for apps in #{org_name}:#{space_name}..."
214
+ # Parallel.map(space.apps, :in_threads=> PARALLEL_MAPS) do |app|
215
+ # begin
216
+ # # It's possible for an app to have been terminated before this stage is reached.
217
+ # formatted_app_data = format_app_data(app, org_name, space_name)
218
+ # if graphite
219
+ # send_data_to_graphite(formatted_app_data, graphite)
220
+ # end
221
+ # formatted_app_data
222
+ # rescue CFoundry::AppNotFound
223
+ # next
224
+ # end
225
+ # end
226
+ # end
227
+ # end.flatten.compact
228
+ # end
114
229
 
115
- def get_org_data(cf_client)
116
- Parallel.map( cf_client.organizations, :in_threads=> PARALLEL_MAPS) do |org|
117
- @logger.info "Getting org data for #{org.name}..."
118
- # The CFoundry client returns memory_limit in MB, so we need to normalise to bytes to match the Apps.
119
- {
120
- :guid => org.guid,
121
- :name => org.name,
122
- :quota => {
123
- :total_services => org.quota_definition.total_services,
124
- :memory_limit => org.quota_definition.memory_limit * 1024 * 1024
125
- }
126
- }
127
- end.flatten.compact
128
- end
230
+ # def get_org_data(cf_client)
231
+ # Parallel.map( cf_client.organizations, :in_threads=> PARALLEL_MAPS) do |org|
232
+ # @logger.info "Getting org data for #{org.name}..."
233
+ # # The CFoundry client returns memory_limit in MB, so we need to normalise to bytes to match the Apps.
234
+ # {
235
+ # :guid => org.guid,
236
+ # :name => org.name,
237
+ # :quota => {
238
+ # :total_services => org.quota_definition.total_services,
239
+ # :memory_limit => org.quota_definition.memory_limit * 1024 * 1024
240
+ # }
241
+ # }
242
+ # end.flatten.compact
243
+ # end
129
244
 
130
- def format_app_data(app, org_name, space_name)
245
+ # def format_app_data(app, org_name, space_name)
131
246
 
132
- last_uploaded = (app.manifest[:entity][:package_updated_at] ||= nil)
247
+ # last_uploaded = (app.manifest[:entity][:package_updated_at] ||= nil)
133
248
 
134
- base_data = {
135
- :guid => app.guid,
136
- :name => app.name,
137
- :org => org_name,
138
- :space => space_name,
139
- :stack => app.stack.name,
140
- :buildpack => app.buildpack,
141
- :routes => app.routes.map {|route| route.name},
142
- :data_from => Time.now.to_i,
143
- :last_uploaded => last_uploaded ? DateTime.parse(last_uploaded).strftime('%Y-%m-%d %T %z') : nil
144
- }
249
+ # base_data = {
250
+ # :guid => app.guid,
251
+ # :name => app.name,
252
+ # :org => org_name,
253
+ # :space => space_name,
254
+ # :stack => app.stack.name,
255
+ # :buildpack => app.buildpack,
256
+ # :routes => app.running? ? routes_for_app(app) : [],
257
+ # :data_from => Time.now.to_i,
258
+ # :last_uploaded => last_uploaded ? DateTime.parse(last_uploaded).strftime('%Y-%m-%d %T %z') : nil
259
+ # }
145
260
 
146
- additional_data = {}
147
- begin
148
- additional_data = {
149
- :running => app.running?,
150
- :instances => app.running? ? app.stats.map{|key, value| value} : [],
151
- :error => nil
152
- }
153
- rescue => e
154
- @logger.info " #{org_name} #{space_name}: '#{app.name}'' error: #{e.message}"
155
- additional_data = {
156
- :running => 'error',
157
- :instances => [],
158
- :error => e.message
159
- }
160
- end
261
+ # additional_data = {}
262
+ # begin
263
+ # additional_data = {
264
+ # :running => app.running?,
265
+ # :instances => app.running? ? app.stats.map{|key, value| value} : [],
266
+ # :error => nil
267
+ # }
268
+ # rescue => e
269
+ # @logger.info " #{org_name} #{space_name}: '#{app.name}'' error: #{e.message}"
270
+ # additional_data = {
271
+ # :running => 'error',
272
+ # :instances => [],
273
+ # :error => e.message
274
+ # }
275
+ # end
161
276
 
162
- base_data.merge additional_data
163
- end
277
+ # base_data.merge additional_data
278
+ # end
279
+
280
+ # def routes_for_app app
281
+ # guids = space.apps.first.routes.collect{|route| route.guid}
282
+ # guids.collect{|guid| @domains.select{|domain| domain[:guid] == guid}}
283
+ # @domains.collect
284
+ # end
164
285
 
165
286
  def put_in_redis(key, data)
166
287
  REDIS.set key, data.to_json
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: 1.7.0
4
+ version: 2.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: 2016-04-22 00:00:00.000000000 Z
11
+ date: 2016-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cfoundry
@@ -135,9 +135,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
135
135
  version: '0'
136
136
  required_rubygems_version: !ruby/object:Gem::Requirement
137
137
  requirements:
138
- - - '>='
138
+ - - '>'
139
139
  - !ruby/object:Gem::Version
140
- version: '0'
140
+ version: 1.3.1
141
141
  requirements: []
142
142
  rubyforge_project:
143
143
  rubygems_version: 2.0.14