Skip to content

Commit 54a4227

Browse files
committed
Deprecated Syslog Binding URL API removal
Code clean up after the deprecation of the `/v4` API for the Syslog Binding URL.
1 parent 2fc86b8 commit 54a4227

File tree

3 files changed

+2
-330
lines changed

3 files changed

+2
-330
lines changed

app/controllers/internal/syslog_drain_urls_controller.rb

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,53 +3,10 @@ class SyslogDrainUrlsInternalController < RestController::BaseController
33
# Endpoint uses mutual tls for auth, handled by nginx
44
allow_unauthenticated_access
55

6-
get '/internal/v4/syslog_drain_urls', :list
6+
get '/internal/v5/syslog_drain_urls', :list
77

88
def list
99
prepare_aggregate_function
10-
guid_to_drain_maps = AppModel.
11-
join(ServiceBinding.table_name, app_guid: :guid).
12-
join(Space.table_name, guid: :apps__space_guid).
13-
join(Organization.table_name, id: :spaces__organization_id).
14-
where(Sequel.lit('syslog_drain_url IS NOT NULL')).
15-
where(Sequel.lit("syslog_drain_url != ''")).
16-
group(
17-
"#{AppModel.table_name}__guid".to_sym,
18-
"#{AppModel.table_name}__name".to_sym,
19-
"#{Space.table_name}__name".to_sym,
20-
"#{Organization.table_name}__name".to_sym
21-
).
22-
select(
23-
"#{AppModel.table_name}__guid".to_sym,
24-
"#{AppModel.table_name}__name".to_sym,
25-
aggregate_function("#{ServiceBinding.table_name}__syslog_drain_url".to_sym).as(:syslog_drain_urls)
26-
).
27-
select_append("#{Space.table_name}__name___space_name".to_sym).
28-
select_append("#{Organization.table_name}__name___organization_name".to_sym).
29-
order(:guid).
30-
limit(batch_size).
31-
offset(last_id).
32-
all
33-
34-
next_page_token = nil
35-
drain_urls = {}
36-
37-
guid_to_drain_maps.each do |guid_and_drains|
38-
drain_urls[guid_and_drains[:guid]] = {
39-
drains: guid_and_drains[:syslog_drain_urls].split(','),
40-
hostname: hostname_from_app_name(guid_and_drains[:organization_name], guid_and_drains[:space_name], guid_and_drains[:name])
41-
}
42-
end
43-
44-
next_page_token = last_id + batch_size unless guid_to_drain_maps.empty?
45-
46-
[HTTP::OK, MultiJson.dump({ results: drain_urls, next_id: next_page_token, v5_available: true }, pretty: true)]
47-
end
48-
49-
get '/internal/v5/syslog_drain_urls', :listv5
50-
51-
def listv5
52-
prepare_aggregate_function
5310

5411
bindings = ServiceBinding.
5512
join(:apps, guid: :app_guid).

docs/internal/README.md

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,8 @@ We do not recommend using internal API endpoints for anything other than their i
9191

9292
**Auth Mechanism:** mTLS
9393

94-
### GET /internal/v4/syslog_drain_urls
95-
**Description:** Return list of syslog drain urls from logging services
96-
97-
**Intended Consumer:** Loggregator
98-
99-
**Auth Mechanism:** mTLS
100-
10194
### GET /internal/v5/syslog_drain_urls
102-
**Description:** Return list of syslog drain urls from logging services. Intends to replace v4 version.
95+
**Description:** Return list of syslog drain urls from logging services.
10396

10497
**Intended Consumer:** Loggregator
10598

spec/unit/controllers/internal/syslog_drain_urls_controller_spec.rb

Lines changed: 0 additions & 278 deletions
Original file line numberDiff line numberDiff line change
@@ -12,280 +12,6 @@ module VCAP::CloudController
1212
let!(:binding_with_drain1) { ServiceBinding.make(syslog_drain_url: 'fish,finger', app: app_obj, service_instance: instance1) }
1313
let!(:binding_with_drain2) { ServiceBinding.make(syslog_drain_url: 'foobar', app: app_obj, service_instance: instance2) }
1414

15-
describe 'GET /internal/v4/syslog_drain_urls' do
16-
it 'returns a list of syslog drain urls' do
17-
get '/internal/v4/syslog_drain_urls', '{}'
18-
expect(last_response).to be_successful
19-
expect(decoded_results.count).to eq(1)
20-
expect(decoded_v5_available).to be(true)
21-
expect(decoded_results).to include(
22-
{
23-
app_obj.guid => { 'drains' => contain_exactly('fish%2cfinger', 'foobar'),
24-
'hostname' => 'org-1.space-1.app-1' }
25-
}
26-
)
27-
end
28-
29-
context 'rfc-1034-compliance: whitespace converted to hyphens' do
30-
let(:org) { Organization.make(name: 'org 2') }
31-
let(:space) { Space.make(name: 'space 2', organization: org) }
32-
let(:app_obj) { AppModel.make(name: 'app 2', space: space) }
33-
34-
it 'truncates trailing hyphens' do
35-
get '/internal/v4/syslog_drain_urls', '{}'
36-
expect(last_response).to be_successful
37-
expect(decoded_results.count).to eq(1)
38-
expect(decoded_v5_available).to be(true)
39-
expect(decoded_results).to include(
40-
{
41-
app_obj.guid => { 'drains' => contain_exactly('fish%2cfinger', 'foobar'),
42-
'hostname' => 'org-2.space-2.app-2' }
43-
}
44-
)
45-
end
46-
end
47-
48-
context 'rfc-1034-compliance: named end with hyphens' do
49-
let(:org) { Organization.make(name: 'org-3-') }
50-
let(:space) { Space.make(name: 'space-3--', organization: org) }
51-
let(:app_obj) { AppModel.make(name: 'app-3---', space: space) }
52-
53-
it 'truncates trailing hyphens' do
54-
get '/internal/v4/syslog_drain_urls', '{}'
55-
expect(last_response).to be_successful
56-
expect(decoded_results.count).to eq(1)
57-
expect(decoded_v5_available).to be(true)
58-
expect(decoded_results).to include(
59-
{
60-
app_obj.guid => { 'drains' => contain_exactly('fish%2cfinger', 'foobar'),
61-
'hostname' => 'org-3.space-3.app-3' }
62-
}
63-
)
64-
end
65-
end
66-
67-
context 'rfc-1034-compliance: remove disallowed characters' do
68-
let(:org) { Organization.make(name: '!org@-4#' + [233].pack('U')) }
69-
let(:space) { Space.make(name: '$space%-^4--&', organization: org) }
70-
let(:app_obj) { AppModel.make(name: '";*app(-)4_-=-+-[]{}\\|;:,.<>/?`~', space: space) }
71-
72-
it 'truncates trailing hyphens' do
73-
get '/internal/v4/syslog_drain_urls', '{}'
74-
expect(last_response).to be_successful
75-
expect(decoded_results.count).to eq(1)
76-
expect(decoded_v5_available).to be(true)
77-
expect(decoded_results).to include(
78-
{
79-
app_obj.guid => { 'drains' => contain_exactly('fish%2cfinger', 'foobar'),
80-
'hostname' => 'org-4.space-4.app-4' }
81-
}
82-
)
83-
end
84-
end
85-
86-
context 'rfc-1034-compliance: truncate overlong name components to first 63' do
87-
let(:orgName) { 'org-5-' + ('x' * (63 - 6)) }
88-
let(:orgNamePlus) { orgName + 'y' }
89-
let(:org) { Organization.make(name: orgNamePlus) }
90-
let(:spaceName) { 'space-5-' + ('x' * (63 - 8)) }
91-
let(:spaceNamePlus) { spaceName + 'y' }
92-
let(:space) { Space.make(name: spaceNamePlus, organization: org) }
93-
let(:appName) { 'app-5-' + ('x' * (63 - 6)) }
94-
let(:appNamePlus) { appName + 'y' }
95-
let(:app_obj) { AppModel.make(name: appNamePlus, space: space) }
96-
97-
it 'truncates trailing hyphens' do
98-
get '/internal/v4/syslog_drain_urls', '{}'
99-
expect(last_response).to be_successful
100-
expect(decoded_results.count).to eq(1)
101-
expect(decoded_v5_available).to be(true)
102-
expect(decoded_results).to include(
103-
{
104-
app_obj.guid => { 'drains' => contain_exactly('fish%2cfinger', 'foobar'),
105-
'hostname' => "#{orgName}.#{spaceName}.#{appName}" }
106-
}
107-
)
108-
end
109-
end
110-
111-
context 'rfc-1034-compliance: keep 63-char names' do
112-
let(:orgName) { 'org-5-' + ('x' * (63 - 6)) }
113-
let(:org) { Organization.make(name: orgName) }
114-
let(:spaceName) { 'space-5-' + ('x' * (63 - 8)) }
115-
let(:space) { Space.make(name: spaceName, organization: org) }
116-
let(:appName) { 'app-5-' + ('x' * (63 - 6)) }
117-
let(:app_obj) { AppModel.make(name: appName, space: space) }
118-
119-
it 'retains length-compliant names' do
120-
get '/internal/v4/syslog_drain_urls', '{}'
121-
expect(last_response).to be_successful
122-
expect(decoded_results.count).to eq(1)
123-
expect(decoded_v5_available).to be(true)
124-
expect(decoded_results).to include(
125-
{
126-
app_obj.guid => { 'drains' => contain_exactly('fish%2cfinger', 'foobar'),
127-
'hostname' => "#{orgName}.#{spaceName}.#{appName}" }
128-
}
129-
)
130-
end
131-
end
132-
133-
context 'when an app has no service binding' do
134-
let!(:app_no_binding) { AppModel.make }
135-
136-
it 'does not include that app' do
137-
get '/internal/v4/syslog_drain_urls', '{}'
138-
expect(last_response).to be_successful
139-
expect(decoded_v5_available).to be(true)
140-
expect(decoded_results).not_to have_key(app_no_binding.guid)
141-
end
142-
end
143-
144-
context "when an app's bindings have no syslog_drain_url" do
145-
let!(:app_no_drain) { ServiceBinding.make.app }
146-
147-
it 'does not include that app' do
148-
get '/internal/v4/syslog_drain_urls', '{}'
149-
expect(last_response).to be_successful
150-
expect(decoded_v5_available).to be(true)
151-
expect(decoded_results).not_to have_key(app_no_drain.guid)
152-
end
153-
end
154-
155-
context "when an app's binding has blank syslog_drain_urls" do
156-
let!(:app_empty_drain) { ServiceBinding.make(syslog_drain_url: '').app }
157-
158-
it 'includes the app without the empty syslog_drain_urls' do
159-
get '/internal/v4/syslog_drain_urls', '{}'
160-
expect(last_response).to be_successful
161-
expect(decoded_v5_available).to be(true)
162-
expect(decoded_results).not_to have_key(app_empty_drain.guid)
163-
end
164-
end
165-
166-
context 'when there are many service bindings on a single app' do
167-
before do
168-
50.times do |i|
169-
ServiceBinding.make(
170-
app: app_obj,
171-
syslog_drain_url: "syslog://example.com/#{i}",
172-
service_instance: UserProvidedServiceInstance.make(space: app_obj.space)
173-
)
174-
end
175-
end
176-
177-
it 'includes all of the syslog_drain_urls for that app' do
178-
get '/internal/v4/syslog_drain_urls', '{}'
179-
expect(last_response).to be_successful
180-
expect(decoded_v5_available).to be(true)
181-
expect(decoded_results[app_obj.guid]['drains'].length).to eq(52)
182-
end
183-
end
184-
185-
describe 'paging' do
186-
before do
187-
3.times do
188-
app_obj = AppModel.make
189-
instance = UserProvidedServiceInstance.make(space: app_obj.space)
190-
ServiceBinding.make(syslog_drain_url: 'fish,finger', app: app_obj, service_instance: instance)
191-
end
192-
end
193-
194-
it 'respects the batch_size parameter' do
195-
[1, 3].each do |size|
196-
get '/internal/v4/syslog_drain_urls', { 'batch_size' => size }
197-
expect(last_response).to be_successful
198-
expect(decoded_v5_available).to be(true)
199-
expect(decoded_results.size).to eq(size)
200-
end
201-
end
202-
203-
it 'returns non-intersecting results when token is supplied' do
204-
get '/internal/v4/syslog_drain_urls', {
205-
'batch_size' => 2,
206-
'next_id' => 0
207-
}
208-
209-
saved_results = decoded_results.dup
210-
expect(saved_results.size).to eq(2)
211-
212-
get '/internal/v4/syslog_drain_urls', {
213-
'batch_size' => 2,
214-
'next_id' => decoded_response['next_id']
215-
}
216-
217-
new_results = decoded_results.dup
218-
219-
expect(new_results.size).to eq(2)
220-
saved_results.each_key do |guid|
221-
expect(new_results).not_to have_key(guid)
222-
end
223-
end
224-
225-
it 'eventuallies return entire collection, batch after batch' do
226-
apps = {}
227-
total_size = AppModel.count
228-
229-
token = 0
230-
while apps.size < total_size
231-
get '/internal/v4/syslog_drain_urls', {
232-
'batch_size' => 2,
233-
'next_id' => token
234-
}
235-
236-
expect(last_response.status).to eq(200)
237-
token = decoded_response['next_id']
238-
apps.merge!(decoded_results)
239-
end
240-
241-
expect(apps.size).to eq(total_size)
242-
get '/internal/v4/syslog_drain_urls', {
243-
'batch_size' => 2,
244-
'next_id' => token
245-
}
246-
expect(decoded_results.size).to eq(0)
247-
expect(decoded_v5_available).to be(true)
248-
expect(decoded_response['next_id']).to be_nil
249-
end
250-
251-
context 'when an app has no service_bindings' do
252-
before do
253-
AppModel.make(guid: '00000')
254-
end
255-
256-
it 'does not affect the paging results' do
257-
get '/internal/v4/syslog_drain_urls', {
258-
'batch_size' => 2,
259-
'next_id' => 0
260-
}
261-
262-
saved_results = decoded_results.dup
263-
expect(saved_results.size).to eq(2)
264-
expect(decoded_v5_available).to be(true)
265-
end
266-
end
267-
268-
context 'when an app has no syslog_drain_urls' do
269-
let(:app_with_first_ordered_guid) { AppModel.make(guid: '000', space: instance1.space) }
270-
271-
before do
272-
ServiceBinding.make(syslog_drain_url: nil, app: app_with_first_ordered_guid, service_instance: instance1)
273-
end
274-
275-
it 'does not affect the paging results' do
276-
get '/internal/v4/syslog_drain_urls', {
277-
'batch_size' => 2,
278-
'next_id' => 0
279-
}
280-
281-
saved_results = decoded_results.dup
282-
expect(saved_results.size).to eq(2)
283-
expect(decoded_v5_available).to be(true)
284-
end
285-
end
286-
end
287-
end
288-
28915
describe 'GET /internal/v5/syslog_drain_urls' do
29016
let(:app_obj2) { AppModel.make(name: 'app-2', space: space) }
29117
let(:app_obj3) { AppModel.make(name: 'app-3', space: space) }
@@ -540,9 +266,5 @@ def decoded_results
540266
def decoded_next_id
541267
decoded_response.fetch('next_id')
542268
end
543-
544-
def decoded_v5_available
545-
decoded_response.fetch('v5_available')
546-
end
547269
end
548270
end

0 commit comments

Comments
 (0)