Skip to content
This repository was archived by the owner on Jun 2, 2021. It is now read-only.

Commit f186ac4

Browse files
Brian CunnieTeal Stannard
andcommitted
**V3**: GET /v3/routes filters by app GUIDs
Typical usage: `GET /v3/routes?app_guids=guid1,guid2` Previously, in order to show the routes mapped to each app, we had to go through each app and fetch the routes that were mapped to it with `GET /v3/apps/:guid/routes`. This commit allows us to `GET /v3/routes?app_guids=1,2,3,...` to get all relevant routes in a *single* request. This is a little unusual for the v3 API, since routes and apps are not directly associated—they are associated "through" destinations. But we've already added a convenience endpoint in the form of `GET /v3/apps/:guid/routes`. We removed `RoutesListMessage::for_app_guid`. It's no longer necessary now that filtering by an app's GUID is available. Docs: we sorted the query parameters for a better user experience. [finishes #172625783] Co-authored-by: Brian Cunnie <bcunnie@pivotal.io> Co-authored-by: Teal Stannard <tstannard@pivotal.io>
1 parent 4cd6bd2 commit f186ac4

7 files changed

Lines changed: 47 additions & 24 deletions

File tree

app/controllers/v3/routes_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def destroy_destination
181181
end
182182

183183
def index_by_app
184-
message = RoutesListMessage.from_params(query_params).for_app_guid(hashed_params['guid'])
184+
message = RoutesListMessage.from_params(query_params.merge({ app_guids: hashed_params['guid'] }))
185185
invalid_param!(message.errors.full_messages) unless message.valid?
186186

187187
app, space, org = AppFetcher.new.fetch(hashed_params['guid'])

app/fetchers/route_fetcher.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@ def fetch(message, readable_route_guids, eager_loaded_associations: [])
99
private
1010

1111
def filter(message, dataset)
12-
if message.app_guid
13-
destinations_route_guids = RouteMappingModel.where(app_guid: message.app_guid).select(:route_guid)
14-
dataset = dataset.where(guid: destinations_route_guids)
15-
end
16-
1712
if message.requested?(:hosts)
1813
dataset = dataset.where(host: message.hosts)
1914
end
@@ -35,6 +30,11 @@ def filter(message, dataset)
3530
dataset = dataset.where(domain_id: Domain.where(guid: message.domain_guids).select(:id))
3631
end
3732

33+
if message.requested?(:app_guids)
34+
destinations_route_guids = RouteMappingModel.where(app_guid: message.app_guids).select(:route_guid)
35+
dataset = dataset.where(guid: destinations_route_guids)
36+
end
37+
3838
if message.requested?(:label_selector)
3939
dataset = LabelSelectorQueryGenerator.add_selector_queries(
4040
label_klass: RouteLabelModel,

app/messages/routes_list_message.rb

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class RoutesListMessage < ListMessage
88
:organization_guids,
99
:domain_guids,
1010
:paths,
11+
:app_guids,
1112
:include,
1213
:label_selector,
1314
]
@@ -17,19 +18,13 @@ class RoutesListMessage < ListMessage
1718

1819
validates :hosts, allow_nil: true, array: true
1920
validates :paths, allow_nil: true, array: true
21+
validates :app_guids, allow_nil: true, array: true
2022
validates :space_guids, allow_nil: true, array: true
2123
validates :organization_guids, allow_nil: true, array: true
2224
validates :domain_guids, allow_nil: true, array: true
2325

24-
attr_reader :app_guid
25-
2626
def self.from_params(params)
27-
super(params, %w(hosts space_guids organization_guids domain_guids paths include))
28-
end
29-
30-
def for_app_guid(app_guid)
31-
@app_guid = app_guid
32-
self
27+
super(params, %w(hosts space_guids organization_guids domain_guids app_guids paths include))
3328
end
3429
end
3530
end

docs/v3/source/includes/resources/routes/_list.md.erb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ Retrieve all routes the user has access to.
3030

3131
Name | Type | Description
3232
---- | ---- | ------------
33+
**app_guids** | _list of strings_ | Comma-delimited list of app guids to filter by.
34+
**domain_guids** | _list of strings_ | Comma-delimited list of domain guids to filter by.
3335
**hosts** | _list of strings_ | Comma-delimited list of hostnames to filter by.
36+
**organization_guids** | _list of strings_ | Comma-delimited list of organization guids to filter by.
3437
**paths** | _list of strings_ | Comma-delimited list of paths to filter by (e.g. `/path1,/path2`).
35-
**domain_guids** | _list of strings_ | Comma-delimited list of domain guids to filter by.
3638
**space_guids** | _list of strings_ | Comma-delimited list of space guids to filter by.
37-
**organization_guids** | _list of strings_ | Comma-delimited list of organization guids to filter by.
3839
**page** | _integer_ | Page to display. Valid values are integers >= 1.
3940
**per_page** | _integer_ | Number of results per page. <br>Valid values are 1 through 5000.
4041
**order_by** | _string_ | Value to sort by. Defaults to ascending. Prepend with `-` to sort descending. <br>Valid values are `created_at`, `updated_at`.

spec/request/routes_spec.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@
121121
space_guids: ['foo', 'bar'],
122122
organization_guids: ['foo', 'bar'],
123123
domain_guids: ['foo', 'bar'],
124+
app_guids: ['foo', 'bar'],
124125
paths: ['foo', 'bar'],
125126
hosts: 'foo',
126127
include: 'domain',
@@ -464,6 +465,18 @@
464465
})
465466
end
466467
end
468+
469+
context 'app_guids filter' do
470+
it 'returns routes filtered by app_guid' do
471+
get "/v3/routes?app_guids=#{app_model.guid}", nil, admin_header
472+
expect(last_response.status).to eq(200)
473+
expect(parsed_response['resources'].size).to eq(1)
474+
expect(parsed_response['resources'].first['destinations'].size).to eq(2)
475+
expect(
476+
parsed_response['resources'].first['destinations'].map { |destination| destination['app']['guid'] }.uniq
477+
).to eq([app_model.guid])
478+
end
479+
end
467480
end
468481

469482
describe 'labels' do

spec/unit/fetchers/route_fetcher_spec.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,24 @@ module VCAP::CloudController
177177
end
178178
end
179179

180+
context 'when fetching routes for several apps' do
181+
let(:app_model) { AppModel.make(space: space1) }
182+
let(:app_model2) { AppModel.make(space: space1) }
183+
let!(:destination1) { RouteMappingModel.make(app: app_model, route: route1, process_type: 'web') }
184+
let!(:destination2) { RouteMappingModel.make(app: app_model2, route: route2, process_type: 'worker') }
185+
let(:routes_filter) { { app_guids: [app_model.guid, app_model2.guid] } }
186+
187+
it 'only returns routes that are mapped to the app' do
188+
results = RouteFetcher.fetch(message, Route.all.map(&:guid)).all
189+
expect(results).to contain_exactly(route1, route2)
190+
end
191+
end
192+
180193
context 'when fetching routes for an app' do
181194
let(:app_model) { AppModel.make(space: space1) }
182195
let!(:destination1) { RouteMappingModel.make(app: app_model, route: route1, process_type: 'web') }
183196
let!(:destination2) { RouteMappingModel.make(app: app_model, route: route2, process_type: 'worker') }
184-
let(:message) { RoutesListMessage.from_params({}).for_app_guid(app_model.guid) }
197+
let(:routes_filter) { { app_guids: [app_model.guid] } }
185198

186199
it 'only returns routes that are mapped to the app' do
187200
results = RouteFetcher.fetch(message, Route.all.map(&:guid)).all

spec/unit/messages/routes_list_message_spec.rb

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,6 @@ module VCAP::CloudController
1616
end
1717
end
1818

19-
describe '#for_app_guid' do
20-
it 'sets app_guid on message' do
21-
message = RoutesListMessage.from_params({}).for_app_guid('some-app-guid')
22-
expect(message.app_guid).to eq('some-app-guid')
23-
end
24-
end
25-
2619
describe 'fields' do
2720
it 'accepts an empty set' do
2821
message = RoutesListMessage.from_params({})
@@ -105,6 +98,14 @@ module VCAP::CloudController
10598
expect(message.errors[:base].length).to eq 1
10699
expect(message.errors[:base][0]).to match(/Duplicate included resource: 'domain'/)
107100
end
101+
102+
context 'when app guids param is provided' do
103+
it 'accepts it' do
104+
message = RoutesListMessage.from_params({ 'app_guids' => 'guid1,guid2' })
105+
expect(message).to be_valid
106+
expect(message.app_guids).to eq(['guid1', 'guid2'])
107+
end
108+
end
108109
end
109110
end
110111
end

0 commit comments

Comments
 (0)