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

Commit 99c02e4

Browse files
committed
v3: Support advanced filters on stacks, tasks, space quotas
Now, the list endpoints for these resources support filtering on `created_ats` and `updated_ats`, including relational operators on these filters. [#173719526] Authored-by: Reid Mitchell <rmitchell@pivotal.io>
1 parent 0afcf83 commit 99c02e4

15 files changed

Lines changed: 124 additions & 87 deletions

File tree

app/controllers/v3/stacks_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def index
1313
message = StacksListMessage.from_params(query_params)
1414
invalid_param!(message.errors.full_messages) unless message.valid?
1515

16-
dataset = StackListFetcher.new.fetch_all(message)
16+
dataset = StackListFetcher.fetch_all(message)
1717

1818
render status: :ok, json: Presenters::V3::PaginatedListPresenter.new(
1919
presenter: Presenters::V3::StackPresenter,

app/controllers/v3/tasks_controller.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ def index
2121
show_secrets = false
2222

2323
if app_nested?
24-
app, dataset = TaskListFetcher.new.fetch_for_app(message: message)
24+
app, dataset = TaskListFetcher.fetch_for_app(message: message)
2525
app_not_found! unless app && permission_queryer.can_read_from_space?(app.space.guid, app.organization.guid)
2626
show_secrets = can_read_secrets?(app.organization, app.space)
2727
else
2828
dataset = if permission_queryer.can_read_globally?
29-
TaskListFetcher.new.fetch_all(message: message)
29+
TaskListFetcher.fetch_all(message: message)
3030
else
31-
TaskListFetcher.new.fetch_for_spaces(message: message, space_guids: readable_space_guids)
31+
TaskListFetcher.fetch_for_spaces(message: message, space_guids: readable_space_guids)
3232
end
3333
end
3434

app/fetchers/space_quota_list_fetcher.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
require 'cloud_controller/paging/sequel_paginator'
22
require 'cloud_controller/paging/paginated_result'
3+
require 'fetchers/base_list_fetcher'
34

45
module VCAP::CloudController
5-
class SpaceQuotaListFetcher
6+
class SpaceQuotaListFetcher < BaseListFetcher
67
class << self
78
def fetch(message:, readable_space_quota_guids:)
89
dataset = SpaceQuotaDefinition.dataset
@@ -34,7 +35,7 @@ def filter(message, dataset, readable_space_quota_guids)
3435
qualify(:space_quota_definitions)
3536
end
3637

37-
dataset
38+
super(message, dataset, SpaceQuotaDefinition)
3839
end
3940
end
4041
end

app/fetchers/stack_list_fetcher.rb

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,31 @@
11
require 'cloud_controller/paging/sequel_paginator'
22
require 'cloud_controller/paging/paginated_result'
3+
require 'fetchers/base_list_fetcher'
34

45
module VCAP::CloudController
5-
class StackListFetcher
6-
def fetch_all(message)
7-
dataset = Stack.dataset
8-
filter(message, dataset)
9-
end
10-
11-
def filter(message, dataset)
12-
if message.requested?(:names)
13-
dataset = dataset.where(name: message.names)
6+
class StackListFetcher < BaseListFetcher
7+
class << self
8+
def fetch_all(message)
9+
dataset = Stack.dataset
10+
filter(message, dataset)
1411
end
1512

16-
if message.requested?(:label_selector)
17-
dataset = LabelSelectorQueryGenerator.add_selector_queries(
18-
label_klass: StackLabelModel,
19-
resource_dataset: dataset,
20-
requirements: message.requirements,
21-
resource_klass: Stack,
22-
)
13+
def filter(message, dataset)
14+
if message.requested?(:names)
15+
dataset = dataset.where(name: message.names)
16+
end
17+
18+
if message.requested?(:label_selector)
19+
dataset = LabelSelectorQueryGenerator.add_selector_queries(
20+
label_klass: StackLabelModel,
21+
resource_dataset: dataset,
22+
requirements: message.requirements,
23+
resource_klass: Stack,
24+
)
25+
end
26+
27+
super(message, dataset, Stack)
2328
end
24-
dataset
2529
end
2630
end
2731
end

app/fetchers/task_list_fetcher.rb

Lines changed: 61 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,80 @@
1+
require 'fetchers/base_list_fetcher'
2+
13
module VCAP::CloudController
2-
class TaskListFetcher
3-
def fetch_for_spaces(message:, space_guids:)
4-
app_dataset = AppModel.select(:id).where(space_guid: space_guids)
5-
filter(message, app_dataset)
6-
end
4+
class TaskListFetcher < BaseListFetcher
5+
class << self
6+
def fetch_for_spaces(message:, space_guids:)
7+
app_dataset = AppModel.select(:id).where(space_guid: space_guids)
8+
filter(message).where(app: filter_app_dataset(message, app_dataset))
9+
end
710

8-
def fetch_all(message:)
9-
app_dataset = AppModel.select(:id)
10-
filter(message, app_dataset)
11-
end
11+
def fetch_all(message:)
12+
app_dataset = AppModel.select(:id)
13+
filter(message).where(app: filter_app_dataset(message, app_dataset))
14+
end
1215

13-
def fetch_for_app(message:)
14-
app_dataset = AppModel.where(guid: message.app_guid).eager(:space, space: :organization)
15-
app = app_dataset.first
16-
return nil unless app
16+
def fetch_for_app(message:)
17+
app_dataset = AppModel.where(guid: message.app_guid).eager(:space, space: :organization)
18+
app = app_dataset.first
19+
return nil unless app
1720

18-
if message.requested?(:organization_guids) || message.requested?(:space_guids) || message.requested?(:app_guids)
19-
[app, filter(message, app_dataset)]
20-
else
21-
[app, filter_task_dataset(message, TaskModel.dataset).where(app_guid: message.app_guid).qualify]
21+
if message.requested?(:organization_guids) || message.requested?(:space_guids) || message.requested?(:app_guids)
22+
[app, filter(message).where(app: filter_app_dataset(message, app_dataset))]
23+
else
24+
[app, filter_task_dataset(message, TaskModel.dataset).where(app_guid: message.app_guid).qualify]
25+
end
2226
end
23-
end
2427

25-
private
28+
private
2629

27-
def filter(message, app_dataset)
28-
task_dataset = TaskModel.dataset
29-
filter_task_dataset(message, task_dataset).where(app: filter_app_dataset(message, app_dataset))
30-
end
30+
def filter(message)
31+
task_dataset = TaskModel.dataset
32+
task_dataset = filter_task_dataset(message, task_dataset)
3133

32-
def filter_app_dataset(message, app_dataset)
33-
if message.requested?(:space_guids)
34-
app_dataset = app_dataset.where(space_guid: message.space_guids)
35-
end
36-
if message.requested?(:organization_guids)
37-
app_dataset = app_dataset.where(space_guid: Organization.where(guid: message.organization_guids).map(&:spaces).flatten.map(&:guid))
34+
super(message, task_dataset, TaskModel)
3835
end
39-
if message.requested?(:app_guids)
40-
app_dataset = app_dataset.where(guid: message.app_guids)
41-
end
42-
app_dataset
43-
end
4436

45-
def filter_task_dataset(message, task_dataset)
46-
if message.requested?(:names)
47-
task_dataset = task_dataset.where(name: message.names)
37+
def filter_app_dataset(message, app_dataset)
38+
if message.requested?(:space_guids)
39+
app_dataset = app_dataset.where(space_guid: message.space_guids)
40+
end
41+
if message.requested?(:organization_guids)
42+
app_dataset = app_dataset.where(space_guid: Organization.where(guid: message.organization_guids).map(&:spaces).flatten.map(&:guid))
43+
end
44+
if message.requested?(:app_guids)
45+
app_dataset = app_dataset.where(guid: message.app_guids)
46+
end
47+
app_dataset
4848
end
4949

50-
if message.requested?(:states)
51-
task_dataset = task_dataset.where(state: message.states)
52-
end
50+
def filter_task_dataset(message, task_dataset)
51+
if message.requested?(:names)
52+
task_dataset = task_dataset.where(name: message.names)
53+
end
5354

54-
if message.requested?(:guids)
55-
task_dataset = task_dataset.where(guid: message.guids)
56-
end
55+
if message.requested?(:states)
56+
task_dataset = task_dataset.where(state: message.states)
57+
end
5758

58-
if message.requested?(:sequence_ids)
59-
task_dataset = task_dataset.where(sequence_id: message.sequence_ids)
60-
end
59+
if message.requested?(:guids)
60+
task_dataset = task_dataset.where(guid: message.guids)
61+
end
6162

62-
if message.requested?(:label_selector)
63-
task_dataset = LabelSelectorQueryGenerator.add_selector_queries(
64-
label_klass: TaskLabelModel,
65-
resource_dataset: task_dataset,
66-
requirements: message.requirements,
67-
resource_klass: TaskModel
68-
)
69-
end
63+
if message.requested?(:sequence_ids)
64+
task_dataset = task_dataset.where(sequence_id: message.sequence_ids)
65+
end
7066

71-
task_dataset
67+
if message.requested?(:label_selector)
68+
task_dataset = LabelSelectorQueryGenerator.add_selector_queries(
69+
label_klass: TaskLabelModel,
70+
resource_dataset: task_dataset,
71+
requirements: message.requirements,
72+
resource_klass: TaskModel
73+
)
74+
end
75+
76+
task_dataset
77+
end
7278
end
7379
end
7480
end

docs/v3/source/includes/concepts/_filters.md.erb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ This will return all routes with hostname `"hostname1"`, `""` OR `"hostname2"`.
4848

4949
#### Relational Operators (Experimental)
5050

51-
Fields can be filtered using relational operators when listing resources.
51+
Some fields (e.g. `created_at` and `updated_at`) can be filtered using relational operators when listing resources.
5252

5353
For example, a response to `/v3/audit_events?created_ats[lt]=2020-06-30T12:34:56Z` will contain
5454
audit events with a `created_at` timestamp strictly earlier than `2020-06-30T12:34:56Z`.
@@ -67,9 +67,3 @@ Timestamps must be in [standard timestamp format](#timestamps).
6767
**lte** | Return resources less than or equal to the given value for the filtered attribute
6868
**gt** | Return resources strictly greater than the given value for the filtered attribute
6969
**gte** | Return resources greater than or equal to the given value for the filtered attribute
70-
71-
##### Resources with relational operators
72-
73-
The following resources can filter using relational operators:
74-
75-
- **[audit_events](#list-audit-events)**

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ Name | Type | Description
3737
**page** | _integer_ | Page to display; valid values are integers >= 1
3838
**per_page** | _integer_ | Number of results per page; <br>valid values are 1 through 5000
3939
**order_by** | _string_ | Value to sort by. Defaults to ascending; prepend with `-` to sort descending. <br>Valid values are `created_at`, `updated_at`
40+
**created_ats** (*experimental*)| _[timestamp](#timestamps)_ | Timestamp to filter by. When filtering on equality, several comma-delimited timestamps may be passed. Also supports filtering with [relational operators](#relational-operators-experimental)
41+
**updated_ats** (*experimental*)| _[timestamp](#timestamps)_ | Timestamp to filter by. When filtering on equality, several comma-delimited timestamps may be passed. Also supports filtering with [relational operators](#relational-operators-experimental)
4042

4143
#### Permitted roles
4244

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ Name | Type | Description
3535
**per_page** | _integer_ | Number of results per page; <br>valid values are 1 through 5000
3636
**order_by** | _string_ | Value to sort by. Defaults to ascending; prepend with `-` to sort descending<br>Valid values are `created_at`, `updated_at`, and `name`
3737
**label_selector** (*experimental*)| _string_ | A query string containing a list of [label selector](#labels-and-selectors) requirements
38+
**created_ats** (*experimental*)| _[timestamp](#timestamps)_ | Timestamp to filter by. When filtering on equality, several comma-delimited timestamps may be passed. Also supports filtering with [relational operators](#relational-operators-experimental)
39+
**updated_ats** (*experimental*)| _[timestamp](#timestamps)_ | Timestamp to filter by. When filtering on equality, several comma-delimited timestamps may be passed. Also supports filtering with [relational operators](#relational-operators-experimental)
3840

3941
#### Permitted roles
4042
|

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ Name | Type | Description
4040
**per_page** | _integer_ | Number of results per page; <br>valid values are 1 through 5000
4141
**order_by** | _string_ | Value to sort by. Defaults to ascending; prepend with `-` to sort descending. <br>Valid values are `created_at`, `updated_at`
4242
**label_selector** (*experimental*)| _string_ | A query string containing a list of [label selector](#labels-and-selectors) requirements
43+
**created_ats** (*experimental*)| _[timestamp](#timestamps)_ | Timestamp to filter by. When filtering on equality, several comma-delimited timestamps may be passed. Also supports filtering with [relational operators](#relational-operators-experimental)
44+
**updated_ats** (*experimental*)| _[timestamp](#timestamps)_ | Timestamp to filter by. When filtering on equality, several comma-delimited timestamps may be passed. Also supports filtering with [relational operators](#relational-operators-experimental)
4345

4446
#### Permitted roles
4547
|

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ Name | Type | Description
3939
**per_page** | _integer_ | Number of results per page; <br>valid values are 1 through 5000
4040
**order_by** | _string_ | Value to sort by. Defaults to ascending; prepend with `-` to sort descending. <br>Valid values are `created_at`, `updated_at`
4141
**label_selector** (*experimental*)| _string_ | A query string containing a list of [label selector](#labels-and-selectors) requirements
42+
**created_ats** (*experimental*)| _[timestamp](#timestamps)_ | Timestamp to filter by. When filtering on equality, several comma-delimited timestamps may be passed. Also supports filtering with [relational operators](#relational-operators-experimental)
43+
**updated_ats** (*experimental*)| _[timestamp](#timestamps)_ | Timestamp to filter by. When filtering on equality, several comma-delimited timestamps may be passed. Also supports filtering with [relational operators](#relational-operators-experimental)
4244

4345
#### Permitted roles
4446
|

0 commit comments

Comments
 (0)