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

Commit 5c99e81

Browse files
belinda-liuBrian Cunnie
andcommitted
V3: GET /v3/routes?ports=xxxx (filter routes by port)
- Includes `GET /v3/apps/:guid/routes?ports=xxxx` - The test for TCP routes are non-trivial: - make sure to disable k8s - a `before do` block enables the setup of the `let`s in a subsequent context; don't be tempted to optimize this, it won't work. (applies to _request_ and _fetcher_ specs) [#172664949] Co-authored-by: Belinda Liu <bliu@pivotal.io> Co-authored-by: Brian Cunnie <bcunnie@pivotal.io>
1 parent 17402a4 commit 5c99e81

7 files changed

Lines changed: 125 additions & 7 deletions

File tree

app/fetchers/route_fetcher.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ def filter(message, dataset)
1717
dataset = dataset.where(path: message.paths)
1818
end
1919

20+
if message.requested?(:ports)
21+
dataset = dataset.where(port: message.ports)
22+
end
23+
2024
if message.requested?(:organization_guids)
2125
space_ids = Organization.where(guid: message.organization_guids).map(&:spaces).flatten.map(&:id)
2226
dataset = dataset.where(space_id: space_ids)

app/messages/routes_list_message.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class RoutesListMessage < ListMessage
1111
:app_guids,
1212
:include,
1313
:label_selector,
14+
:ports,
1415
]
1516

1617
validates_with NoAdditionalParamsValidator
@@ -22,9 +23,10 @@ class RoutesListMessage < ListMessage
2223
validates :space_guids, allow_nil: true, array: true
2324
validates :organization_guids, allow_nil: true, array: true
2425
validates :domain_guids, allow_nil: true, array: true
26+
validates :ports, allow_nil: true, array: true
2527

2628
def self.from_params(params)
27-
super(params, %w(hosts space_guids organization_guids domain_guids app_guids paths include))
29+
super(params, %w(hosts space_guids organization_guids domain_guids app_guids paths ports include))
2830
end
2931
end
3032
end

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Name | Type | Description
3535
**hosts** | _list of strings_ | Comma-delimited list of hostnames to filter by.
3636
**organization_guids** | _list of strings_ | Comma-delimited list of organization guids to filter by.
3737
**paths** | _list of strings_ | Comma-delimited list of paths to filter by (e.g. `/path1,/path2`).
38+
**ports** | _list of integers_ | Comma-delimited list of ports to filter by (e.g. `3306,5432`).
3839
**space_guids** | _list of strings_ | Comma-delimited list of space guids to filter by.
3940
**page** | _integer_ | Page to display. Valid values are integers >= 1.
4041
**per_page** | _integer_ | Number of results per page. <br>Valid values are 1 through 5000.

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ Retrieve all routes that have [destinations](#the-destination-object) that point
3030

3131
Name | Type | Description
3232
---- | ---- | ------------
33+
**domain_guids** | _list of strings_ | Comma-delimited list of domain guids to filter by.
3334
**hosts** | _list of strings_ | Comma-delimited list of hostnames to filter by.
35+
**organization_guids** | _list of strings_ | Comma-delimited list of organization guids to filter by.
3436
**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.
37+
**ports** | _list of integers_ | Comma-delimited list of ports to filter by (e.g. `3306,5432`).
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: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,17 +119,18 @@
119119

120120
let(:params) do
121121
{
122-
page: '2',
123-
per_page: '10',
124-
order_by: 'updated_at',
122+
page: '2',
123+
per_page: '10',
124+
order_by: 'updated_at',
125125
space_guids: ['foo', 'bar'],
126126
organization_guids: ['foo', 'bar'],
127127
domain_guids: ['foo', 'bar'],
128128
app_guids: ['foo', 'bar'],
129129
paths: ['foo', 'bar'],
130130
hosts: 'foo',
131+
ports: 636,
131132
include: 'domain',
132-
label_selector: 'foo,bar',
133+
label_selector: 'foo,bar',
133134
}
134135
end
135136
end
@@ -522,6 +523,39 @@
522523
).to eq([app_model.guid])
523524
end
524525
end
526+
527+
context 'ports filter' do
528+
# Don't even think of converting the following hash to symbols ('type' => 'tcp' NOT type: 'tcp'), and you need to set the GUID
529+
let(:router_group) { VCAP::CloudController::RoutingApi::RouterGroup.new({ 'type' => 'tcp', 'reservable_ports' => '7777,8888,9999', 'guid' => 'some-guid' }) }
530+
let(:routing_api_client) { instance_double(VCAP::CloudController::RoutingApi::Client) }
531+
532+
before do
533+
allow_any_instance_of(CloudController::DependencyLocator).to receive(:routing_api_client).and_return(routing_api_client)
534+
allow(routing_api_client).to receive(:enabled?).and_return(true)
535+
allow(routing_api_client).to receive(:router_group).and_return(router_group)
536+
end
537+
538+
context 'when there are multiple TCP routes with different ports' do
539+
# The following `let`s depend on the above `before do`
540+
let(:domain_tcp) { VCAP::CloudController::SharedDomain.make(router_group_guid: router_group.guid, name: 'my.domain') }
541+
let!(:route_with_ports_0) do
542+
VCAP::CloudController::Route.make(host: '', space: space, domain: domain_tcp, guid: 'route-with-port-0', port: 7777)
543+
end
544+
let!(:route_with_ports_1) do
545+
VCAP::CloudController::Route.make(host: '', space: space, domain: domain_tcp, guid: 'route-with-port-1', port: 8888)
546+
end
547+
let!(:route_with_ports_2) do
548+
VCAP::CloudController::Route.make(host: '', space: space, domain: domain_tcp, guid: 'route-with-port-2', port: 9999)
549+
end
550+
551+
it 'returns routes filtered by ports' do
552+
get '/v3/routes?ports=7777,8888', nil, admin_header
553+
expect(last_response).to have_status_code(200)
554+
expect(parsed_response['resources'].size).to eq(2)
555+
expect(parsed_response['resources'].map { |resource| resource['port'] }).to contain_exactly(route_with_ports_0.port, route_with_ports_1.port)
556+
end
557+
end
558+
end
525559
end
526560

527561
describe 'labels' do
@@ -2448,6 +2482,41 @@
24482482
it_behaves_like 'permissions for list endpoint', ALL_PERMISSIONS
24492483
end
24502484

2485+
context 'ports filter' do
2486+
# Don't even think of converting the following hash to symbols ('type' => 'tcp' NOT type: 'tcp'), and you need to set the GUID
2487+
let(:router_group) { VCAP::CloudController::RoutingApi::RouterGroup.new({ 'type' => 'tcp', 'reservable_ports' => '7777,8888,9999', 'guid' => 'some-guid' }) }
2488+
let(:routing_api_client) { instance_double(VCAP::CloudController::RoutingApi::Client) }
2489+
2490+
before do
2491+
allow_any_instance_of(CloudController::DependencyLocator).to receive(:routing_api_client).and_return(routing_api_client)
2492+
allow(routing_api_client).to receive(:enabled?).and_return(true)
2493+
allow(routing_api_client).to receive(:router_group).and_return(router_group)
2494+
end
2495+
2496+
context 'when there are multiple TCP routes with different ports' do
2497+
# The following `let`s depend on the above `before do`
2498+
let(:domain_tcp) { VCAP::CloudController::SharedDomain.make(router_group_guid: router_group.guid, name: 'my.domain') }
2499+
let!(:route_with_ports_0) do
2500+
VCAP::CloudController::Route.make(host: '', space: space, domain: domain_tcp, guid: 'route-with-port-0', port: 7777)
2501+
end
2502+
let!(:route_with_ports_1) do
2503+
VCAP::CloudController::Route.make(host: '', space: space, domain: domain_tcp, guid: 'route-with-port-1', port: 8888)
2504+
end
2505+
let!(:route_with_ports_2) do
2506+
VCAP::CloudController::Route.make(host: '', space: space, domain: domain_tcp, guid: 'route-with-port-2', port: 9999)
2507+
end
2508+
let!(:route_mapping_1) { VCAP::CloudController::RouteMappingModel.make(app: app_model, route: route_with_ports_1, process_type: 'web') }
2509+
let!(:route_mapping_2) { VCAP::CloudController::RouteMappingModel.make(app: app_model, route: route_with_ports_2, process_type: 'web') }
2510+
2511+
it 'returns routes filtered by ports' do
2512+
get "/v3/apps/#{app_model.guid}/routes?ports=7777,8888", nil, admin_header
2513+
expect(last_response).to have_status_code(200)
2514+
expect(parsed_response['resources'].size).to eq(1)
2515+
expect(parsed_response['resources'].first['port']).to eq(route_with_ports_1.port)
2516+
end
2517+
end
2518+
end
2519+
24512520
describe 'eager loading' do
24522521
it 'eager loads associated resources that the presenter specifies' do
24532522
expect(VCAP::CloudController::RouteFetcher).to receive(:fetch).with(

spec/unit/fetchers/route_fetcher_spec.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,41 @@ module VCAP::CloudController
138138
end
139139
end
140140

141+
context 'when fetching routes by ports' do
142+
let!(:router_group) { VCAP::CloudController::RoutingApi::RouterGroup.new({ 'type' => 'tcp', 'reservable_ports' => '8888,9999', 'guid' => 'some-guid' }) }
143+
let(:routing_api_client) { instance_double(VCAP::CloudController::RoutingApi::Client) }
144+
145+
before do
146+
TestConfig.override(kubernetes: {})
147+
allow_any_instance_of(CloudController::DependencyLocator).to receive(:routing_api_client).and_return(routing_api_client)
148+
allow(routing_api_client).to receive(:enabled?).and_return(true)
149+
allow(routing_api_client).to receive(:router_group).and_return(router_group)
150+
end
151+
152+
context 'when there is a matching route' do
153+
let(:domain_tcp) { VCAP::CloudController::SharedDomain.make(router_group_guid: router_group.guid, name: 'my.domain') }
154+
let!(:route_with_ports) do
155+
VCAP::CloudController::Route.make(host: '', space: space1, domain: domain_tcp, guid: 'route-with-port', port: 8888)
156+
end
157+
let(:routes_filter) { { ports: '8888' } }
158+
159+
it 'only returns the matching route' do
160+
results = RouteFetcher.fetch(message, [route2.guid, route3.guid, route_with_ports.guid]).all
161+
expect(results.length).to eq(1)
162+
expect(results[0].guid).to eq(route_with_ports.guid)
163+
end
164+
end
165+
166+
context 'when there is no matching route' do
167+
let(:routes_filter) { { ports: '123' } }
168+
169+
it 'returns no routes' do
170+
results = RouteFetcher.fetch(message, [route2.guid, route3.guid]).all
171+
expect(results.length).to eq(0)
172+
end
173+
end
174+
end
175+
141176
context 'when fetching routes by label selector' do
142177
let!(:route_label) do
143178
VCAP::CloudController::RouteLabelModel.make(resource_guid: route1.guid, key_name: 'dog', value: 'scooby-doo')

spec/unit/messages/routes_list_message_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ module VCAP::CloudController
7676
expect(message.domain_guids).to eq(['guid1', 'guid2'])
7777
end
7878

79+
it 'accepts a ports param' do
80+
message = RoutesListMessage.from_params({ 'ports' => '5900,6000,7000' })
81+
expect(message).to be_valid
82+
expect(message.ports).to eq(['5900', '6000', '7000'])
83+
end
84+
7985
it 'does not accept any other params' do
8086
message = RoutesListMessage.from_params({ 'app_guid' => 'pants' })
8187

0 commit comments

Comments
 (0)