Skip to content

Commit 4d04959

Browse files
committed
fix test issues
1 parent ee0025f commit 4d04959

File tree

5 files changed

+66
-51
lines changed

5 files changed

+66
-51
lines changed

db/migrations/20250731071027_allow_multiple_service_bindings.rb

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,62 @@
22
no_transaction # adding an index concurrently cannot be done within a transaction
33

44
up do
5-
transaction do
6-
alter_table :service_bindings do
7-
drop_constraint :unique_service_binding_service_instance_guid_app_guid if @db.indexes(:service_bindings).include?(:unique_service_binding_service_instance_guid_app_guid)
5+
db_type = database_type
6+
if indexes(:service_bindings)[:unique_service_binding_service_instance_guid_app_guid].present?
7+
alter_table(:service_bindings) do
8+
if db_type == :postgres
9+
drop_constraint(:unique_service_binding_service_instance_guid_app_guid)
10+
elsif db_type == :mysql
11+
drop_constraint(:unique_service_binding_service_instance_guid_app_guid, unique: true)
12+
end
813

9-
drop_constraint :unique_service_binding_app_guid_name if @db.indexes(:service_bindings).include?(:unique_service_binding_app_guid_name)
1014
end
1115
end
16+
alter_table(:service_bindings) { drop_constraint(:unique_service_binding_app_guid_name) } if indexes(:service_bindings)[:unique_service_binding_app_guid_name].present?
1217

13-
VCAP::Migration.with_concurrent_timeout(self) do
14-
add_index :service_bindings, %i[app_guid service_instance_guid], name: :service_bindings_app_guid_service_instance_guid_index, if_not_exists: true, concurrently: true
18+
if db_type == :postgres
19+
VCAP::Migration.with_concurrent_timeout(self) do
20+
add_index :service_bindings, %i[app_guid service_instance_guid], name: :service_bindings_app_guid_service_instance_guid_index, concurrently: true, if_not_exists: true
21+
add_index :service_bindings, %i[app_guid name], name: :service_bindings_app_guid_name_index, concurrently: true, if_not_exists: true
22+
end
23+
elsif db_type == :mysql
24+
alter_table(:service_bindings) do
25+
unless @db.indexes(:service_bindings).key?(:service_bindings_app_guid_service_instance_guid_index)
26+
add_index %i[app_guid service_instance_guid], name: :service_bindings_app_guid_service_instance_guid_index, concurrently: true
27+
end
28+
unless @db.indexes(:service_bindings).key?(:service_bindings_app_guid_name_index)
29+
add_index %i[app_guid name], name: :service_bindings_app_guid_name_index, concurrently: true
30+
end
31+
end
1532
end
1633
end
1734

1835
down do
19-
transaction do
20-
alter_table :service_bindings do
21-
unless @db.indexes(:service_bindings).include?(:unique_service_binding_service_instance_guid_app_guid)
22-
add_unique_constraint %i[service_instance_guid app_guid],
23-
name: :unique_service_binding_service_instance_guid_app_guid
24-
end
25-
add_unique_constraint %i[app_guid name], name: :unique_service_binding_app_guid_name unless @db.indexes(:service_bindings).include?(:unique_service_binding_app_guid_name)
36+
if indexes(:service_bindings)[:unique_service_binding_service_instance_guid_app_guid].blank?
37+
alter_table(:service_bindings) do
38+
add_unique_constraint %i[service_instance_guid app_guid],
39+
name: :unique_service_binding_service_instance_guid_app_guid
40+
end
41+
end
42+
if indexes(:service_bindings)[:unique_service_binding_app_guid_name].blank?
43+
alter_table(:service_bindings) do
44+
add_unique_constraint %i[app_guid name], name: :unique_service_binding_app_guid_name
2645
end
2746
end
2847

29-
VCAP::Migration.with_concurrent_timeout(self) do
30-
drop_index :service_bindings, %i[app_guid service_instance_guid], name: :service_bindings_app_guid_service_instance_guid_index, if_exists: true, concurrently: true
48+
if database_type == :postgres
49+
VCAP::Migration.with_concurrent_timeout(self) do
50+
drop_index :service_bindings, %i[app_guid service_instance_guid], name: :service_bindings_app_guid_service_instance_guid_index, concurrently: true, if_exists: true
51+
drop_index :service_bindings, %i[app_guid name], name: :service_bindings_app_guid_name_index, concurrently: true, if_exists: true
52+
end
53+
elsif database_type == :mysql
54+
alter_table(:service_bindings) do
55+
if @db.indexes(:service_bindings).key?(:service_bindings_app_guid_service_instance_guid_index)
56+
drop_index %i[app_guid service_instance_guid], name: :service_bindings_app_guid_service_instance_guid_index,
57+
concurrently: true
58+
end
59+
drop_index %i[app_guid name], name: :service_bindings_app_guid_name_index, concurrently: true if @db.indexes(:service_bindings).key?(:service_bindings_app_guid_name_index)
60+
end
3161
end
3262
end
3363
end

spec/migrations/20250731071027_allow_multiple_service_bindings_spec.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212
expect(db.indexes(:service_bindings)).to include(:unique_service_binding_service_instance_guid_app_guid)
1313
expect(db.indexes(:service_bindings)).to include(:unique_service_binding_app_guid_name)
1414
expect(db.indexes(:service_bindings)).not_to include(:service_bindings_app_guid_service_instance_guid_index)
15+
expect(db.indexes(:service_bindings)).not_to include(:service_bindings_app_guid_name_index)
1516
end
1617

1718
it 'migrates successfully' do
1819
expect { Sequel::Migrator.run(db, migrations_path, target: current_migration_index, allow_missing_migration_files: true) }.not_to raise_error
1920
expect(db.indexes(:service_bindings)).not_to include(:unique_service_binding_app_guid_name)
2021
expect(db.indexes(:service_bindings)).not_to include(:unique_service_binding_service_instance_guid_app_guid)
2122
expect(db.indexes(:service_bindings)).to include(:service_bindings_app_guid_service_instance_guid_index)
23+
expect(db.indexes(:service_bindings)).to include(:service_bindings_app_guid_name_index)
2224
end
2325

2426
it 'does not fail if indexes/constraints are already in desired state' do
@@ -27,6 +29,7 @@
2729
drop_constraint :unique_service_binding_app_guid_name
2830
end
2931
db.add_index :service_bindings, %i[app_guid service_instance_guid], name: :service_bindings_app_guid_service_instance_guid_index, if_not_exists: true, concurrently: true
32+
db.add_index :service_bindings, %i[app_guid name], name: :service_bindings_app_guid_name_index, if_not_exists: true, concurrently: true
3033

3134
expect { Sequel::Migrator.run(db, migrations_path, target: current_migration_index, allow_missing_migration_files: true) }.not_to raise_error
3235
end
@@ -38,6 +41,7 @@
3841
expect(db.indexes(:service_bindings)).to include(:unique_service_binding_service_instance_guid_app_guid)
3942
expect(db.indexes(:service_bindings)).to include(:unique_service_binding_app_guid_name)
4043
expect(db.indexes(:service_bindings)).not_to include(:service_bindings_app_guid_service_instance_guid_index)
44+
expect(db.indexes(:service_bindings)).not_to include(:service_bindings_app_guid_name_index)
4145
end
4246

4347
it 'does not fail if indexes/constraints are already in desired state' do
@@ -47,6 +51,7 @@
4751
add_unique_constraint %i[app_guid name], name: :unique_service_binding_app_guid_name
4852
end
4953
db.drop_index :service_bindings, %i[app_guid service_instance_guid], name: :service_bindings_app_guid_service_instance_guid_index, if_exists: true, concurrently: true
54+
db.drop_index :service_bindings, %i[app_guid name], name: :service_bindings_app_guid_name_index, if_exists: true, concurrently: true
5055

5156
expect { Sequel::Migrator.run(db, migrations_path, target: current_migration_index - 1, allow_missing_migration_files: true) }.not_to raise_error
5257
end

spec/request/service_credential_bindings_spec.rb

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,18 +1274,24 @@ def check_filtered_bindings(*bindings)
12741274
}))
12751275
end
12761276

1277-
it 'returns 422 when the binding already exists' do
1278-
api_call.call admin_headers
1279-
expect(last_response.status).to eq(201).or eq(202)
1277+
context 'when only one binding per app and service instance is allowed' do
1278+
before do
1279+
TestConfig.override(max_service_credential_bindings_per_app_service_instance: 1)
12801280

1281-
api_call.call admin_headers
1281+
it 'returns 422 when the binding already exists' do
1282+
api_call.call admin_headers
1283+
expect(last_response.status).to eq(201).or eq(202)
12821284

1283-
expect(last_response).to have_status_code(422)
1284-
expect(parsed_response['errors']).to include(include({
1285-
'detail' => include('The app is already bound to the service instance'),
1286-
'title' => 'CF-UnprocessableEntity',
1287-
'code' => 10_008
1288-
}))
1285+
api_call.call admin_headers
1286+
1287+
expect(last_response).to have_status_code(422)
1288+
expect(parsed_response['errors']).to include(include({
1289+
'detail' => include('The app is already bound to the service instance'),
1290+
'title' => 'CF-UnprocessableEntity',
1291+
'code' => 10_008
1292+
}))
1293+
end
1294+
end
12891295
end
12901296

12911297
context 'when the service instance does not exist' do

spec/unit/controllers/runtime/apps_controller_spec.rb

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2496,18 +2496,6 @@ def delete_app
24962496
ServiceBinding.make(service_instance: si2, app: process2.app, name: 'free')
24972497
end
24982498

2499-
it 'binding si2 to process1 with a name in use by process1 is not ok' do
2500-
expect do
2501-
ServiceBinding.make(service_instance: si2, app: process1.app, name: 'out')
2502-
end.to raise_error(Sequel::ValidationFailed, /App binding names must be unique\./)
2503-
end
2504-
2505-
it 'binding si1 to process1 with a new name is not ok' do
2506-
expect do
2507-
ServiceBinding.make(service_instance: si1, app: process1.app, name: 'gravy')
2508-
end.to raise_error(Sequel::ValidationFailed, 'The app is already bound to the service.')
2509-
end
2510-
25112499
it 'binding si2 to process1 with a name in use by process2 is ok' do
25122500
ServiceBinding.make(service_instance: si2, app: process1.app, name: 'free')
25132501
get "/v2/apps/#{process1.app.guid}/service_bindings?results-per-page=2&page=1&q=name:free"

spec/unit/models/services/service_binding_spec.rb

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ module VCAP::CloudController
2525
it { is_expected.to validate_presence :app }
2626
it { is_expected.to validate_presence :service_instance }
2727
it { is_expected.to validate_db_presence :credentials }
28-
it { is_expected.to validate_uniqueness %i[app_guid service_instance_guid], message: 'The app is already bound to the service.' }
2928
it { is_expected.to validate_presence [:type] }
3029

3130
it 'validates max length of name' do
@@ -80,19 +79,6 @@ module VCAP::CloudController
8079
let(:app) { AppModel.make }
8180
let(:service_instance) { ServiceInstance.make(space: app.space) }
8281

83-
context 'and the name is not null' do
84-
let(:existing_binding) do
85-
ServiceBinding.make(app: app, name: 'some-name', service_instance: service_instance, type: 'app')
86-
end
87-
88-
it 'adds a uniqueness error' do
89-
other_service_instance = ServiceInstance.make(space: existing_binding.space)
90-
conflict = ServiceBinding.new(app: existing_binding.app, name: existing_binding.name, service_instance: other_service_instance, type: 'app')
91-
expect(conflict.valid?).to be(false)
92-
expect(conflict.errors.full_messages).to eq(['The binding name is invalid. App binding names must be unique. The app already has a binding with name \'some-name\'.'])
93-
end
94-
end
95-
9682
context 'and the name is null' do
9783
let(:existing_binding) do
9884
ServiceBinding.make(app: app, name: nil, service_instance: service_instance, type: 'app')

0 commit comments

Comments
 (0)