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

Commit 92284f2

Browse files
committed
V3 service plans - optionally include service offering in response
[#172309159](https://www.pivotaltracker.com/story/show/172309159)
1 parent 2b5a926 commit 92284f2

8 files changed

Lines changed: 93 additions & 10 deletions

File tree

app/controllers/v3/service_plans_controller.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
require 'messages/metadata_update_message'
88
require 'actions/transactional_metadata_update'
99
require 'decorators/include_service_plan_space_organization_decorator'
10+
require 'decorators/include_service_plan_service_offering_decorator'
1011

1112
class ServicePlansController < ApplicationController
1213
include ServicePermissions
@@ -42,6 +43,7 @@ def index
4243

4344
decorators = []
4445
decorators << IncludeServicePlanSpaceOrganizationDecorator if IncludeServicePlanSpaceOrganizationDecorator.match?(message.include)
46+
decorators << IncludeServicePlanServiceOfferingDecorator if IncludeServicePlanServiceOfferingDecorator.match?(message.include)
4547

4648
presenter = Presenters::V3::PaginatedListPresenter.new(
4749
presenter: Presenters::V3::ServicePlanPresenter,
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module VCAP::CloudController
2+
class IncludeServicePlanServiceOfferingDecorator
3+
class << self
4+
def match?(include)
5+
include&.include?('service_offering')
6+
end
7+
8+
def decorate(hash, service_plans)
9+
hash[:included] ||= {}
10+
service_offerings = service_plans.map(&:service).uniq
11+
12+
hash[:included][:service_offerings] = service_offerings.sort_by(&:created_at).map do |service_offering|
13+
Presenters::V3::ServiceOfferingPresenter.new(service_offering).to_hash
14+
end
15+
16+
hash
17+
end
18+
end
19+
end
20+
end

app/messages/service_plans_list_message.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class ServicePlansListMessage < MetadataListMessage
2222
register_allowed_keys(@single_keys + @array_keys)
2323

2424
validates_with NoAdditionalParamsValidator
25-
validates_with IncludeParamValidator, valid_values: ['space.organization']
25+
validates_with IncludeParamValidator, valid_values: %w(space.organization service_offering)
2626
validates :available, inclusion: { in: %w(true false), message: "only accepts values 'true' or 'false'" }, allow_nil: true
2727

2828
def self.from_params(params)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Resource | Allowed values
1818
**roles/[:guid]** | `user`, `space`, `organization`
1919
**routes** | `domain`
2020
**routes/[:guid]** | `domain`
21+
**service_plans** | `space.organization`, `service_offering`
2122
**spaces** | `organization`
2223
**spaces/[:guid]** | `organization`
2324

docs/v3/source/includes/experimental_resources/service_plans/_list.md.erb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ Name | Type | Description
4141
**service_offering_names** | _list of strings_ | Comma-delimited list of Service Offering names to filter by.
4242
**service_instance_guids** | _list of strings_ | Comma-delimited list of Service Instance GUIDs to filter by.
4343
**label_selector** | _string_ | **Experimental** - A query string containing a list of [label selector](#labels-and-selectors) requirements.
44+
**include** | _list of strings_ | Optionally include a list of unique related resources in the response. <br>Valid values are `space.organization` and `service_offering`.
45+
4446

4547
The **organization_guids** and **space_guids** filters do not filter plans that are public.
4648
They both act on plans that are restricted to certain Organizations, and to plans from Space-Scoped

spec/request/service_plans_spec.rb

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,9 @@
149149
space_guids: %w(hoge piyo),
150150
include: 'space.organization',
151151
available: true,
152-
per_page: '10',
152+
per_page: '10',
153153
page: 2,
154-
order_by: 'updated_at',
154+
order_by: 'updated_at',
155155
label_selector: 'foo==bar',
156156
}
157157
end
@@ -443,12 +443,12 @@
443443
end
444444

445445
describe 'includes' do
446-
let(:space_1) { VCAP::CloudController::Space.make }
447-
let(:space_2) { VCAP::CloudController::Space.make }
448-
let!(:space_scoped_plan_1) { generate_space_scoped_plan(space_1) }
449-
let!(:space_scoped_plan_2) { generate_space_scoped_plan(space_2) }
450-
451446
it 'can include `space.organization`' do
447+
space_1 = VCAP::CloudController::Space.make
448+
space_2 = VCAP::CloudController::Space.make
449+
generate_space_scoped_plan(space_1)
450+
generate_space_scoped_plan(space_2)
451+
452452
get '/v3/service_plans?include=space.organization', nil, admin_headers
453453
expect(last_response).to have_status_code(200)
454454

@@ -460,6 +460,21 @@
460460
expect(parsed_response['included']['organizations'][0]['guid']).to eq(space_1.organization.guid)
461461
expect(parsed_response['included']['organizations'][1]['guid']).to eq(space_2.organization.guid)
462462
end
463+
464+
it 'can include `service_offering`' do
465+
offering_1 = VCAP::CloudController::Service.make
466+
offering_2 = VCAP::CloudController::Service.make
467+
VCAP::CloudController::ServicePlan.make(service: offering_1)
468+
VCAP::CloudController::ServicePlan.make(service: offering_2)
469+
VCAP::CloudController::ServicePlan.make(service: offering_2)
470+
471+
get '/v3/service_plans?include=service_offering', nil, admin_headers
472+
expect(last_response).to have_status_code(200)
473+
474+
expect(parsed_response['included']['service_offerings']).to have(2).elements
475+
expect(parsed_response['included']['service_offerings'][0]['guid']).to eq(offering_1.guid)
476+
expect(parsed_response['included']['service_offerings'][1]['guid']).to eq(offering_2.guid)
477+
end
463478
end
464479
end
465480

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
require 'spec_helper'
2+
require 'decorators/include_service_plan_service_offering_decorator'
3+
4+
module VCAP::CloudController
5+
RSpec.describe IncludeServicePlanServiceOfferingDecorator do
6+
describe '.decorate' do
7+
let(:offering_1) { Service.make }
8+
let(:offering_2) { Service.make }
9+
let(:plan_1) { ServicePlan.make(service: offering_1) }
10+
let(:plan_2) { ServicePlan.make(service: offering_2) }
11+
let(:plan_3) { ServicePlan.make(service: offering_2) }
12+
13+
it 'decorates the given hash with service offerings from service plans' do
14+
undecorated_hash = { foo: 'bar', included: { monkeys: %w(zach greg) } }
15+
hash = described_class.decorate(undecorated_hash, [plan_1, plan_2, plan_3])
16+
17+
expect(hash[:foo]).to eq('bar')
18+
expect(hash[:included][:monkeys]).to contain_exactly('zach', 'greg')
19+
expect(hash[:included].keys).to have(2).keys
20+
21+
expect(hash[:included][:service_offerings]).to match_array([
22+
Presenters::V3::ServiceOfferingPresenter.new(offering_1).to_hash,
23+
Presenters::V3::ServiceOfferingPresenter.new(offering_2).to_hash
24+
])
25+
end
26+
27+
it 'only includes the service offerings from the specified service plans' do
28+
hash = described_class.decorate({}, [plan_1])
29+
expect(hash[:included][:service_offerings]).to have(1).element
30+
end
31+
end
32+
33+
describe '.match?' do
34+
it 'matches arrays containing "service_offering"' do
35+
expect(described_class.match?(['potato', 'service_offering', 'turnip'])).to be_truthy
36+
end
37+
38+
it 'does not match other arrays' do
39+
expect(described_class.match?(['potato', 'turnip'])).to be_falsey
40+
end
41+
end
42+
end
43+
end

spec/unit/messages/service_plans_list_message_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module VCAP::CloudController
88
{
99
'available' => 'true',
1010
'broker_catalog_ids' => 'broker_catalog_id_1,broker_catalog_id_2',
11-
'include' => 'space.organization',
11+
'include' => 'space.organization,service_offering',
1212
'names' => 'name_1,name_2',
1313
'organization_guids' => 'org_guid_1,org_guid_2',
1414
'service_broker_guids' => 'broker_guid_1,broker_guid_2',
@@ -27,7 +27,7 @@ module VCAP::CloudController
2727
expect(message).to be_a(ServicePlansListMessage)
2828
expect(message.available).to eq('true')
2929
expect(message.broker_catalog_ids).to contain_exactly('broker_catalog_id_1', 'broker_catalog_id_2')
30-
expect(message.include).to contain_exactly('space.organization')
30+
expect(message.include).to contain_exactly('space.organization', 'service_offering')
3131
expect(message.names).to contain_exactly('name_1', 'name_2')
3232
expect(message.organization_guids).to contain_exactly('org_guid_1', 'org_guid_2')
3333
expect(message.service_broker_guids).to contain_exactly('broker_guid_1', 'broker_guid_2')

0 commit comments

Comments
 (0)