From c41a3dfe49faed6d741747c8ec1d9f8ddc3877ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serdar=20=C3=96zer?= Date: Mon, 16 Mar 2026 15:01:35 +0100 Subject: [PATCH 01/13] feat: validate_unique removed - Model's that already has uniqueness constraint on db level are refactored. sequel validate_unique method removed from list. --- app/models/runtime/app_model.rb | 3 +-- app/models/runtime/domain.rb | 1 - .../runtime/helpers/organization_role_mixin.rb | 1 - app/models/runtime/helpers/space_role_mixin.rb | 1 - app/models/runtime/isolation_segment_model.rb | 4 +--- app/models/runtime/organization.rb | 1 - app/models/runtime/space.rb | 1 - app/models/runtime/space_quota_definition.rb | 1 - app/models/runtime/stack.rb | 1 - app/models/runtime/user.rb | 1 - app/models/services/service_broker.rb | 1 - app/models/services/service_key.rb | 1 - .../shared_examples/models/domain_validation.rb | 7 +++---- spec/unit/actions/app_create_spec.rb | 16 ---------------- spec/unit/actions/organization_create_spec.rb | 2 -- spec/unit/actions/service_broker_create_spec.rb | 2 -- spec/unit/actions/space_create_spec.rb | 2 -- spec/unit/actions/space_quotas_create_spec.rb | 2 -- spec/unit/actions/stack_create_spec.rb | 2 -- spec/unit/actions/user_create_spec.rb | 2 -- spec/unit/isolation_segment_create_spec.rb | 4 +--- spec/unit/models/runtime/domain_spec.rb | 1 - .../runtime/isolation_segment_model_spec.rb | 16 ---------------- .../models/runtime/organization_auditor_spec.rb | 10 +++++++++- .../runtime/organization_billing_manager_spec.rb | 10 +++++++++- .../models/runtime/organization_manager_spec.rb | 10 +++++++++- spec/unit/models/runtime/organization_spec.rb | 1 - .../models/runtime/organization_user_spec.rb | 10 +++++++++- spec/unit/models/runtime/shared_domain_spec.rb | 2 +- spec/unit/models/runtime/space_auditor_spec.rb | 10 +++++++++- spec/unit/models/runtime/space_developer_spec.rb | 9 ++++++++- spec/unit/models/runtime/space_manager_spec.rb | 9 ++++++++- .../runtime/space_quota_definition_spec.rb | 1 - spec/unit/models/runtime/space_spec.rb | 1 - spec/unit/models/runtime/space_supporter_spec.rb | 9 ++++++++- spec/unit/models/runtime/stack_spec.rb | 1 - spec/unit/models/runtime/user_spec.rb | 1 - spec/unit/models/services/service_broker_spec.rb | 1 - spec/unit/models/services/service_key_spec.rb | 10 +++++++++- 39 files changed, 85 insertions(+), 83 deletions(-) diff --git a/app/models/runtime/app_model.rb b/app/models/runtime/app_model.rb index b47733f7fb3..d4e14ecc54a 100644 --- a/app/models/runtime/app_model.rb +++ b/app/models/runtime/app_model.rb @@ -84,7 +84,7 @@ def around_save rescue Sequel::UniqueConstraintViolation => e raise e unless e.message.include?('apps_v3_space_guid_name_index') - errors.add(%i[space_guid name], :unique) + errors.add(%i[space_guid name], Sequel.lit("App with the name '#{name}' already exists.")) raise validation_failed_error rescue Sequel::ForeignKeyConstraintViolation => e raise e unless e.message.include?('fk_apps_droplet_guid') @@ -100,7 +100,6 @@ def validate validate_environment_variables validate_droplet_is_staged - validates_unique %i[space_guid name], message: Sequel.lit("App with the name '#{name}' already exists.") end def lifecycle_type diff --git a/app/models/runtime/domain.rb b/app/models/runtime/domain.rb index 56839444059..12b9288d397 100644 --- a/app/models/runtime/domain.rb +++ b/app/models/runtime/domain.rb @@ -97,7 +97,6 @@ def around_save def validate validates_presence :name - validates_unique :name, dataset: Domain.dataset validates_format CloudController::DomainDecorator::DOMAIN_REGEX, :name, message: 'can contain multiple subdomains, each having only alphanumeric characters and hyphens of up to 63 characters, see RFC 1035.' diff --git a/app/models/runtime/helpers/organization_role_mixin.rb b/app/models/runtime/helpers/organization_role_mixin.rb index 95a824c53e6..ef6942a4297 100644 --- a/app/models/runtime/helpers/organization_role_mixin.rb +++ b/app/models/runtime/helpers/organization_role_mixin.rb @@ -24,7 +24,6 @@ def around_save end def validate - validates_unique %i[organization_id user_id] validates_presence :organization_id validates_presence :user_id end diff --git a/app/models/runtime/helpers/space_role_mixin.rb b/app/models/runtime/helpers/space_role_mixin.rb index a220803ab3b..9c4d24139c0 100644 --- a/app/models/runtime/helpers/space_role_mixin.rb +++ b/app/models/runtime/helpers/space_role_mixin.rb @@ -26,7 +26,6 @@ def around_save def validate validates_presence :space_id validates_presence :user_id - validates_unique %i[space_id user_id] end end end diff --git a/app/models/runtime/isolation_segment_model.rb b/app/models/runtime/isolation_segment_model.rb index b66447b2c4e..e91b66e135a 100644 --- a/app/models/runtime/isolation_segment_model.rb +++ b/app/models/runtime/isolation_segment_model.rb @@ -25,14 +25,12 @@ def around_save rescue Sequel::UniqueConstraintViolation => e raise e unless e.message.include?('isolation_segment_name_unique_constraint') - errors.add(:name, :unique) + errors.add(:name, Sequel.lit('Isolation Segment names are case insensitive and must be unique')) raise validation_failed_error end def validate validates_format ISOLATION_SEGMENT_MODEL_REGEX, :name, message: Sequel.lit('Isolation Segment names can only contain non-blank unicode characters') - - validates_unique [:name], message: Sequel.lit('Isolation Segment names are case insensitive and must be unique') end def is_shared_segment? diff --git a/app/models/runtime/organization.rb b/app/models/runtime/organization.rb index 226d7dda885..c5701b8c633 100644 --- a/app/models/runtime/organization.rb +++ b/app/models/runtime/organization.rb @@ -218,7 +218,6 @@ def around_save def validate validates_presence :name - validates_unique :name validates_format ORG_NAME_REGEX, :name validates_includes ORG_STATUS_VALUES, :status, allow_missing: true diff --git a/app/models/runtime/space.rb b/app/models/runtime/space.rb index 18324a8be81..507260fb856 100644 --- a/app/models/runtime/space.rb +++ b/app/models/runtime/space.rb @@ -229,7 +229,6 @@ def around_save def validate validates_presence :name validates_presence :organization - validates_unique %i[organization_id name] validates_format SPACE_NAME_REGEX, :name errors.add(:space_quota_definition, :invalid_organization) if space_quota_definition && space_quota_definition.organization_id != organization.id diff --git a/app/models/runtime/space_quota_definition.rb b/app/models/runtime/space_quota_definition.rb index dd8681e3fed..cceebadc46b 100644 --- a/app/models/runtime/space_quota_definition.rb +++ b/app/models/runtime/space_quota_definition.rb @@ -41,7 +41,6 @@ def validate validates_presence :total_routes validates_presence :memory_limit validates_presence :organization - validates_unique %i[organization_id name] validates_limit(:memory_limit, memory_limit) validates_limit(:instance_memory_limit, instance_memory_limit) diff --git a/app/models/runtime/stack.rb b/app/models/runtime/stack.rb index c2fb2d81222..730695ee9db 100644 --- a/app/models/runtime/stack.rb +++ b/app/models/runtime/stack.rb @@ -43,7 +43,6 @@ def around_save def validate validates_presence :name - validates_unique :name validates_includes StackStates::VALID_STATES, :state, allow_missing: true end diff --git a/app/models/runtime/user.rb b/app/models/runtime/user.rb index 212ce236089..2ef4adcfdac 100644 --- a/app/models/runtime/user.rb +++ b/app/models/runtime/user.rb @@ -87,7 +87,6 @@ def around_save def validate validates_presence :guid - validates_unique :guid end def validate_organization(org) diff --git a/app/models/services/service_broker.rb b/app/models/services/service_broker.rb index 90b56eb41c9..7cba05219c8 100644 --- a/app/models/services/service_broker.rb +++ b/app/models/services/service_broker.rb @@ -34,7 +34,6 @@ def validate validates_presence :broker_url validates_presence :auth_username validates_presence :auth_password - validates_unique :name, message: Sequel.lit('Name must be unique') validates_url :broker_url validates_url_no_basic_auth end diff --git a/app/models/services/service_key.rb b/app/models/services/service_key.rb index 0cc8545b3f1..cd33e12034f 100644 --- a/app/models/services/service_key.rb +++ b/app/models/services/service_key.rb @@ -49,7 +49,6 @@ def around_save def validate validates_presence :name validates_presence :service_instance - validates_unique %i[name service_instance_id] return unless service_instance diff --git a/spec/support/shared_examples/models/domain_validation.rb b/spec/support/shared_examples/models/domain_validation.rb index 55d08f1d757..a38ad243de0 100644 --- a/spec/support/shared_examples/models/domain_validation.rb +++ b/spec/support/shared_examples/models/domain_validation.rb @@ -13,10 +13,9 @@ module VCAP::CloudController context "when there's another domain with the same name" do it 'fails to validate' do - other_domain = described_class.make - other_domain.name = subject.name - expect(other_domain).not_to be_valid - expect(other_domain.errors[:name]).to include(:unique) + expect { + described_class.make(name: subject.name) + }.to raise_error(Sequel::ValidationFailed, /already reserved by another domain|unique/) end end diff --git a/spec/unit/actions/app_create_spec.rb b/spec/unit/actions/app_create_spec.rb index da951d624ce..2b31125426c 100644 --- a/spec/unit/actions/app_create_spec.rb +++ b/spec/unit/actions/app_create_spec.rb @@ -200,22 +200,6 @@ module VCAP::CloudController end end - context 'when creating apps concurrently' do - it 'ensures one creation is successful and the other fails due to name conflict' do - # First request, should succeed - expect do - app_create.create(message, lifecycle) - end.not_to raise_error - - # Mock the validation for the second request to simulate the race condition and trigger a unique constraint violation - allow_any_instance_of(AppModel).to receive(:validate).and_return(true) - - # Second request, should fail with correct error - expect do - app_create.create(message, lifecycle) - end.to raise_error(CloudController::Errors::V3::ApiError) - end - end describe 'stack state validation' do let(:test_stack) { Stack.make(name: 'test-stack-for-validation') } diff --git a/spec/unit/actions/organization_create_spec.rb b/spec/unit/actions/organization_create_spec.rb index 7efbe430aaa..569eb1e371b 100644 --- a/spec/unit/actions/organization_create_spec.rb +++ b/spec/unit/actions/organization_create_spec.rb @@ -121,8 +121,6 @@ module VCAP::CloudController org_create.create(message) end.not_to raise_error - # Mock the validation for the second request to simulate the race condition and trigger a unique constraint violation - allow_any_instance_of(Organization).to receive(:validate).and_return(true) # Second request, should fail with correct error expect do diff --git a/spec/unit/actions/service_broker_create_spec.rb b/spec/unit/actions/service_broker_create_spec.rb index 973405df6d6..49ff4efb50d 100644 --- a/spec/unit/actions/service_broker_create_spec.rb +++ b/spec/unit/actions/service_broker_create_spec.rb @@ -140,8 +140,6 @@ module CloudController action.create(message) end.not_to raise_error - # Mock the validation for the second request to simulate the race condition and trigger a unique constraint violation - allow_any_instance_of(ServiceBroker).to receive(:validate).and_return(true) # Second request, should fail with correct error expect do diff --git a/spec/unit/actions/space_create_spec.rb b/spec/unit/actions/space_create_spec.rb index 6d356167753..2d43674bdf8 100644 --- a/spec/unit/actions/space_create_spec.rb +++ b/spec/unit/actions/space_create_spec.rb @@ -90,8 +90,6 @@ module VCAP::CloudController SpaceCreate.new(user_audit_info:).create(org, message) end.not_to raise_error - # Mock the validation for the second request to simulate the race condition and trigger a unique constraint violation - allow_any_instance_of(Space).to receive(:validate).and_return(true) # Second request, should fail with correct error expect do diff --git a/spec/unit/actions/space_quotas_create_spec.rb b/spec/unit/actions/space_quotas_create_spec.rb index e3573fb9a0f..08c6f7d5dfd 100644 --- a/spec/unit/actions/space_quotas_create_spec.rb +++ b/spec/unit/actions/space_quotas_create_spec.rb @@ -210,8 +210,6 @@ module VCAP::CloudController space_quotas_create.create(message, organization: org) end.not_to raise_error - # Mock the validation for the second request to simulate the race condition and trigger a unique constraint violation - allow_any_instance_of(SpaceQuotaDefinition).to receive(:validate).and_return(true) # Second request, should fail with correct error expect do diff --git a/spec/unit/actions/stack_create_spec.rb b/spec/unit/actions/stack_create_spec.rb index 156019fd567..c661bd9db45 100644 --- a/spec/unit/actions/stack_create_spec.rb +++ b/spec/unit/actions/stack_create_spec.rb @@ -130,8 +130,6 @@ module VCAP::CloudController stack_create.create(message) end.not_to raise_error - # Mock the validation for the second request to simulate the race condition and trigger a unique constraint violation - allow_any_instance_of(Stack).to receive(:validate).and_return(true) # Second request, should fail with correct error expect do diff --git a/spec/unit/actions/user_create_spec.rb b/spec/unit/actions/user_create_spec.rb index 6d182d97549..37a785f9f28 100644 --- a/spec/unit/actions/user_create_spec.rb +++ b/spec/unit/actions/user_create_spec.rb @@ -44,8 +44,6 @@ module VCAP::CloudController subject.create(message:) end.not_to raise_error - # Mock the validation for the second request to simulate the race condition and trigger a unique constraint violation - allow_any_instance_of(User).to receive(:validate).and_return(true) # Second request, should fail with correct error expect do diff --git a/spec/unit/isolation_segment_create_spec.rb b/spec/unit/isolation_segment_create_spec.rb index a79655e3628..2aac7938bee 100644 --- a/spec/unit/isolation_segment_create_spec.rb +++ b/spec/unit/isolation_segment_create_spec.rb @@ -53,13 +53,11 @@ module VCAP::CloudController IsolationSegmentCreate.create(message) end.not_to raise_error - # Mock the validation for the second request to simulate the race condition and trigger a unique constraint violation - allow_any_instance_of(IsolationSegmentModel).to receive(:validate).and_return(true) # Second request, should fail with correct error expect do IsolationSegmentCreate.create(message) - end.to raise_error(IsolationSegmentCreate::Error, 'name unique') + end.to raise_error(IsolationSegmentCreate::Error, 'Isolation Segment names are case insensitive and must be unique') end end end diff --git a/spec/unit/models/runtime/domain_spec.rb b/spec/unit/models/runtime/domain_spec.rb index e3e94564e8b..5c7c3c7ccf0 100644 --- a/spec/unit/models/runtime/domain_spec.rb +++ b/spec/unit/models/runtime/domain_spec.rb @@ -105,7 +105,6 @@ module VCAP::CloudController describe 'Validations' do it { is_expected.to validate_presence :name } - it { is_expected.to validate_uniqueness :name } describe 'route collisions' do let!(:existing_domain) { SharedDomain.make(name: 'base.domain') } diff --git a/spec/unit/models/runtime/isolation_segment_model_spec.rb b/spec/unit/models/runtime/isolation_segment_model_spec.rb index 6b76de2d616..2b0268a279a 100644 --- a/spec/unit/models/runtime/isolation_segment_model_spec.rb +++ b/spec/unit/models/runtime/isolation_segment_model_spec.rb @@ -124,22 +124,6 @@ module VCAP::CloudController end.to raise_error(Sequel::ValidationFailed, 'Isolation Segment names can only contain non-blank unicode characters') end - it 'requires a unique name' do - IsolationSegmentModel.make(name: 'segment1') - - expect do - IsolationSegmentModel.make(name: 'segment1') - end.to raise_error(Sequel::ValidationFailed, 'Isolation Segment names are case insensitive and must be unique') - end - - it 'uniqueness is case insensitive' do - IsolationSegmentModel.make(name: 'lowercase') - - expect do - IsolationSegmentModel.make(name: 'lowerCase') - end.to raise_error(Sequel::ValidationFailed, 'Isolation Segment names are case insensitive and must be unique') - end - it 'allows standard ascii characters' do expect do IsolationSegmentModel.make(name: "A -_- word 2!?()'\"&+.") diff --git a/spec/unit/models/runtime/organization_auditor_spec.rb b/spec/unit/models/runtime/organization_auditor_spec.rb index 8737b8d4bfc..7675657ffd5 100644 --- a/spec/unit/models/runtime/organization_auditor_spec.rb +++ b/spec/unit/models/runtime/organization_auditor_spec.rb @@ -5,8 +5,16 @@ module VCAP::CloudController let(:organization) { Organization.make } let(:user) { User.make } + describe "uniquiness" do + it "prevend dublicate organization_id and user_id combination" do + OrganizationAuditor.create(organization_id: organization.id, user_id: user.id) + expect { + OrganizationAuditor.create(organization_id: organization.id, user_id: user.id) + }.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do - it { is_expected.to validate_uniqueness %i[organization_id user_id] } it { is_expected.to validate_presence :organization_id } it { is_expected.to validate_presence :user_id } diff --git a/spec/unit/models/runtime/organization_billing_manager_spec.rb b/spec/unit/models/runtime/organization_billing_manager_spec.rb index b981cd596c2..4ed8c2dd8de 100644 --- a/spec/unit/models/runtime/organization_billing_manager_spec.rb +++ b/spec/unit/models/runtime/organization_billing_manager_spec.rb @@ -5,8 +5,16 @@ module VCAP::CloudController let(:organization) { Organization.make } let(:user) { User.make } + describe "uniquiness" do + it "prevend dublicate organization_id and user_id combination" do + OrganizationBillingManager.create(organization_id: organization.id, user_id: user.id) + expect { + OrganizationBillingManager.create(organization_id: organization.id, user_id: user.id) + }.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do - it { is_expected.to validate_uniqueness %i[organization_id user_id] } it { is_expected.to validate_presence :organization_id } it { is_expected.to validate_presence :user_id } diff --git a/spec/unit/models/runtime/organization_manager_spec.rb b/spec/unit/models/runtime/organization_manager_spec.rb index 8f7bd4f41a3..e5c3993576b 100644 --- a/spec/unit/models/runtime/organization_manager_spec.rb +++ b/spec/unit/models/runtime/organization_manager_spec.rb @@ -5,8 +5,16 @@ module VCAP::CloudController let(:organization) { Organization.make } let(:user) { User.make } + describe "uniquiness" do + it "prevend dublicate organization_id and user_id combination" do + OrganizationManager.create(organization_id: organization.id, user_id: user.id) + expect { + OrganizationManager.create(organization_id: organization.id, user_id: user.id) + }.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do - it { is_expected.to validate_uniqueness %i[organization_id user_id] } it { is_expected.to validate_presence :organization_id } it { is_expected.to validate_presence :user_id } diff --git a/spec/unit/models/runtime/organization_spec.rb b/spec/unit/models/runtime/organization_spec.rb index de1f8c930f8..8ad2510d9dd 100644 --- a/spec/unit/models/runtime/organization_spec.rb +++ b/spec/unit/models/runtime/organization_spec.rb @@ -125,7 +125,6 @@ module VCAP::CloudController let(:org) { Organization.make } it { is_expected.to validate_presence :name } - it { is_expected.to validate_uniqueness :name } it { is_expected.to strip_whitespace :name } describe 'name' do diff --git a/spec/unit/models/runtime/organization_user_spec.rb b/spec/unit/models/runtime/organization_user_spec.rb index c0c896fa43c..bb72b1a4cfa 100644 --- a/spec/unit/models/runtime/organization_user_spec.rb +++ b/spec/unit/models/runtime/organization_user_spec.rb @@ -5,8 +5,16 @@ module VCAP::CloudController let(:organization) { Organization.make } let(:user) { User.make } + describe "uniquiness" do + it "prevend dublicate organization_id and user_id combination" do + OrganizationUser.create(organization_id: organization.id, user_id: user.id) + expect { + OrganizationUser.create(organization_id: organization.id, user_id: user.id) + }.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do - it { is_expected.to validate_uniqueness %i[organization_id user_id] } it { is_expected.to validate_presence :organization_id } it { is_expected.to validate_presence :user_id } diff --git a/spec/unit/models/runtime/shared_domain_spec.rb b/spec/unit/models/runtime/shared_domain_spec.rb index 6b587cfb922..342447a6178 100644 --- a/spec/unit/models/runtime/shared_domain_spec.rb +++ b/spec/unit/models/runtime/shared_domain_spec.rb @@ -67,7 +67,7 @@ module VCAP::CloudController it 'denies shared foo.com when private foo.com exists' do PrivateDomain.make name: 'foo.com' - expect { SharedDomain.make name: 'foo.com' }.to raise_error(Sequel::ValidationFailed, /name unique/) + expect { SharedDomain.make name: 'foo.com' }.to raise_error(Sequel::ValidationFailed, /already reserved by another domain|unique/) end context 'when the domain is internal' do diff --git a/spec/unit/models/runtime/space_auditor_spec.rb b/spec/unit/models/runtime/space_auditor_spec.rb index 6203084ae93..3101fa61384 100644 --- a/spec/unit/models/runtime/space_auditor_spec.rb +++ b/spec/unit/models/runtime/space_auditor_spec.rb @@ -5,8 +5,16 @@ module VCAP::CloudController let(:space) { Space.make } let(:user) { User.make } + describe "uniquiness" do + it "prevend dublicate space_id and user_id combination" do + SpaceAuditor.create(space_id: space.id, user_id: user.id) + expect{ + SpaceAuditor.create(space_id: space.id, user_id: user.id) + }.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do - it { is_expected.to validate_uniqueness %i[space_id user_id] } it { is_expected.to validate_presence :space_id } it { is_expected.to validate_presence :user_id } diff --git a/spec/unit/models/runtime/space_developer_spec.rb b/spec/unit/models/runtime/space_developer_spec.rb index 60e2a0cbb43..8b7a61ae22f 100644 --- a/spec/unit/models/runtime/space_developer_spec.rb +++ b/spec/unit/models/runtime/space_developer_spec.rb @@ -5,8 +5,15 @@ module VCAP::CloudController let(:space) { Space.make } let(:user) { User.make } + describe "uniquiness" do + it "prevend dublicate space_id and user_id combination" do + SpaceDeveloper.create(space_id: space.id, user_id: user.id) + expect{ + SpaceDeveloper.create(space_id: space.id, user_id: user.id) + }.to raise_error(Sequel::ValidationFailed, /unique/) + end + end describe 'Validations' do - it { is_expected.to validate_uniqueness %i[space_id user_id] } it { is_expected.to validate_presence :space_id } it { is_expected.to validate_presence :user_id } diff --git a/spec/unit/models/runtime/space_manager_spec.rb b/spec/unit/models/runtime/space_manager_spec.rb index 45a5e2ded30..de46d51ece0 100644 --- a/spec/unit/models/runtime/space_manager_spec.rb +++ b/spec/unit/models/runtime/space_manager_spec.rb @@ -5,8 +5,15 @@ module VCAP::CloudController let(:space) { Space.make } let(:user) { User.make } + describe "uniquiness" do + it "prevend dublicate space_id and user_id combination" do + SpaceManager.create(space_id: space.id, user_id: user.id) + expect{ + SpaceManager.create(space_id: space.id, user_id: user.id) + }.to raise_error(Sequel::ValidationFailed, /unique/) + end + end describe 'Validations' do - it { is_expected.to validate_uniqueness %i[space_id user_id] } it { is_expected.to validate_presence :space_id } it { is_expected.to validate_presence :user_id } diff --git a/spec/unit/models/runtime/space_quota_definition_spec.rb b/spec/unit/models/runtime/space_quota_definition_spec.rb index 07b64ebdbac..c7599170634 100644 --- a/spec/unit/models/runtime/space_quota_definition_spec.rb +++ b/spec/unit/models/runtime/space_quota_definition_spec.rb @@ -24,7 +24,6 @@ module VCAP::CloudController it { is_expected.to validate_presence :total_routes } it { is_expected.to validate_presence :memory_limit } it { is_expected.to validate_presence :organization } - it { is_expected.to validate_uniqueness %i[organization_id name] } describe 'memory_limits' do it 'total memory_limit cannot be less than zero' do diff --git a/spec/unit/models/runtime/space_spec.rb b/spec/unit/models/runtime/space_spec.rb index b4c4711c648..67dadd913fc 100644 --- a/spec/unit/models/runtime/space_spec.rb +++ b/spec/unit/models/runtime/space_spec.rb @@ -7,7 +7,6 @@ module VCAP::CloudController describe 'Validations' do it { is_expected.to validate_presence :name } it { is_expected.to validate_presence :organization } - it { is_expected.to validate_uniqueness %i[organization_id name] } it { is_expected.to strip_whitespace :name } context 'name' do diff --git a/spec/unit/models/runtime/space_supporter_spec.rb b/spec/unit/models/runtime/space_supporter_spec.rb index dfb037ba594..6df94437f86 100644 --- a/spec/unit/models/runtime/space_supporter_spec.rb +++ b/spec/unit/models/runtime/space_supporter_spec.rb @@ -6,8 +6,15 @@ module VCAP::CloudController let(:space) { Space.make } let(:user) { User.make } + describe "uniquiness" do + it "prevend dublicate space_id and user_id combination" do + SpaceSupporter.create(space_id: space.id, user_id: user.id) + expect{ + SpaceSupporter.create(space_id: space.id, user_id: user.id) + }.to raise_error(Sequel::ValidationFailed, /unique/) + end + end describe 'Validations' do - it { is_expected.to validate_uniqueness %i[space_id user_id] } it { is_expected.to validate_presence :space_id } it { is_expected.to validate_presence :user_id } diff --git a/spec/unit/models/runtime/stack_spec.rb b/spec/unit/models/runtime/stack_spec.rb index ec3fe336ee6..dafc0bdb851 100644 --- a/spec/unit/models/runtime/stack_spec.rb +++ b/spec/unit/models/runtime/stack_spec.rb @@ -24,7 +24,6 @@ module VCAP::CloudController describe 'Validations' do it { is_expected.to validate_presence :name } - it { is_expected.to validate_uniqueness :name } it { is_expected.to strip_whitespace :name } describe 'state validation' do diff --git a/spec/unit/models/runtime/user_spec.rb b/spec/unit/models/runtime/user_spec.rb index ad10cdcf0d2..2b7d15655e2 100644 --- a/spec/unit/models/runtime/user_spec.rb +++ b/spec/unit/models/runtime/user_spec.rb @@ -63,7 +63,6 @@ module VCAP::CloudController describe 'Validations' do it { is_expected.to validate_presence :guid } - it { is_expected.to validate_uniqueness :guid } end describe 'Serialization' do diff --git a/spec/unit/models/services/service_broker_spec.rb b/spec/unit/models/services/service_broker_spec.rb index fd2c8641541..a5bbea8e1b1 100644 --- a/spec/unit/models/services/service_broker_spec.rb +++ b/spec/unit/models/services/service_broker_spec.rb @@ -33,7 +33,6 @@ module VCAP::CloudController it { is_expected.to validate_presence :broker_url } it { is_expected.to validate_presence :auth_username } it { is_expected.to validate_presence :auth_password } - it { is_expected.to validate_uniqueness :name, message: Sequel.lit('Name must be unique') } it 'validates the url is a valid http/https url' do expect(broker).to be_valid diff --git a/spec/unit/models/services/service_key_spec.rb b/spec/unit/models/services/service_key_spec.rb index f4a224bbf60..a267ab21abe 100644 --- a/spec/unit/models/services/service_key_spec.rb +++ b/spec/unit/models/services/service_key_spec.rb @@ -19,12 +19,20 @@ module VCAP::CloudController it { is_expected.to have_associated :service_instance, associated_instance: ->(service_key) { ServiceInstance.make(space: service_key.space) } } end + describe 'uniqueness' do + it 'enforces uniqueness of name and service_instance_id' do + existing = ServiceKey.make + expect { + ServiceKey.make(name: existing.name, service_instance: existing.service_instance) + }.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do it { is_expected.to validate_presence :service_instance } it { is_expected.to validate_presence :name } it { is_expected.to validate_db_presence :service_instance_id } it { is_expected.to validate_db_presence :credentials } - it { is_expected.to validate_uniqueness %i[name service_instance_id] } context 'MaxServiceKeysPolicy' do let(:service_key) { ServiceKey.make } From 66dc1f505a4b6fad91d9113bf18e9c458ddddf87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serdar=20=C3=96zer?= Date: Mon, 16 Mar 2026 15:53:36 +0100 Subject: [PATCH 02/13] feat: around_save added for existing unique index for service_plan --- app/models/services/service_plan.rb | 11 ++++++++++- spec/unit/models/services/service_plan_spec.rb | 9 +++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/app/models/services/service_plan.rb b/app/models/services/service_plan.rb index f713352828b..8a655d95e86 100644 --- a/app/models/services/service_plan.rb +++ b/app/models/services/service_plan.rb @@ -75,13 +75,22 @@ def active? alias_method :broker_provided_id, :unique_id + def around_save + yield + rescue Sequel::UniqueConstraintViolation => e + raise e unless e.message.include?('svc_plan_svc_id_name_index') + + errors.add(%i[name service_id], Sequel.lit("Plan names must be unique within a service. Service #{service.try(:label)} already has a plan named #{name}")) + raise validation_failed_error + end + + def validate validates_presence :name, message: 'is required' validates_presence :description, message: 'is required' validates_presence :free, message: 'is required' validates_presence :service, message: 'is required' validates_presence :unique_id, message: 'is required' - validates_unique %i[service_id name], message: Sequel.lit("Plan names must be unique within a service. Service #{service.try(:label)} already has a plan named #{name}") validate_private_broker_plan_not_public end diff --git a/spec/unit/models/services/service_plan_spec.rb b/spec/unit/models/services/service_plan_spec.rb index 6a0310cffef..583bf577dde 100644 --- a/spec/unit/models/services/service_plan_spec.rb +++ b/spec/unit/models/services/service_plan_spec.rb @@ -12,6 +12,15 @@ module VCAP::CloudController it { is_expected.to have_associated :annotations, class: ServicePlanAnnotationModel } end + describe 'uniqueness' do + it 'enforces uniqueness of name within a service' do + existing = ServicePlan.make + expect { + ServicePlan.make(name: existing.name, service: existing.service) + }.to raise_error(Sequel::ValidationFailed, /already has a plan named/) + end + end + describe 'Validations' do it { is_expected.to validate_presence :name, message: 'is required' } it { is_expected.to validate_presence :free, message: 'is required' } From 156e48a9a98f9803212f0a8e2bf5482160f8caf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serdar=20=C3=96zer?= Date: Mon, 16 Mar 2026 16:06:52 +0100 Subject: [PATCH 03/13] feat: around_save added for existing unique index for service_plan_visibility --- app/models/services/service_plan_visibility.rb | 10 +++++++++- .../models/services/service_plan_visibility_spec.rb | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/models/services/service_plan_visibility.rb b/app/models/services/service_plan_visibility.rb index ec7d399f510..f728b1c9b46 100644 --- a/app/models/services/service_plan_visibility.rb +++ b/app/models/services/service_plan_visibility.rb @@ -6,10 +6,18 @@ class ServicePlanVisibility < Sequel::Model import_attributes :service_plan_guid, :organization_guid export_attributes :service_plan_guid, :organization_guid + def around_save + yield + rescue Sequel::UniqueConstraintViolation => e + raise e unless e.message.include?('spv_org_id_sp_id_index') + + errors.add(%i[organization_id service_plan_id], :unique) + raise validation_failed_error + end + def validate validates_presence :service_plan validates_presence :organization - validates_unique %i[organization_id service_plan_id] validate_plan_is_not_private validate_plan_is_not_public end diff --git a/spec/unit/models/services/service_plan_visibility_spec.rb b/spec/unit/models/services/service_plan_visibility_spec.rb index f8708027578..7e14c181623 100644 --- a/spec/unit/models/services/service_plan_visibility_spec.rb +++ b/spec/unit/models/services/service_plan_visibility_spec.rb @@ -9,10 +9,18 @@ module VCAP::CloudController it { is_expected.to have_associated :organization } end + describe 'uniqueness' do + it 'enforces uniqueness of organization and service plan combination' do + existing = ServicePlanVisibility.make + expect { + ServicePlanVisibility.create(service_plan: existing.service_plan, organization: existing.organization) + }.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do it { is_expected.to validate_presence :service_plan } it { is_expected.to validate_presence :organization } - it { is_expected.to validate_uniqueness %i[organization_id service_plan_id] } context 'when the service plan visibility is for a private broker' do it 'returns a validation error' do From 41ca8806956e14afbf86543764b29a2a4eff67a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serdar=20=C3=96zer?= Date: Mon, 16 Mar 2026 16:38:11 +0100 Subject: [PATCH 04/13] feat: around_save added for existing unique index for service_dashboard_client model --- app/models/services/service_dashboard_client.rb | 10 +++++++++- .../models/services/service_dashboard_client_spec.rb | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/models/services/service_dashboard_client.rb b/app/models/services/service_dashboard_client.rb index 175df575e41..c608a2a6d42 100644 --- a/app/models/services/service_dashboard_client.rb +++ b/app/models/services/service_dashboard_client.rb @@ -2,9 +2,17 @@ module VCAP::CloudController class ServiceDashboardClient < Sequel::Model many_to_one :service_broker + def around_save + yield + rescue Sequel::UniqueConstraintViolation => e + raise e unless e.message.include?('s_d_clients_uaa_id_unique') + + errors.add(:uaa_id, :unique) + raise validation_failed_error + end + def validate validates_presence :uaa_id - validates_unique :uaa_id end class << self diff --git a/spec/unit/models/services/service_dashboard_client_spec.rb b/spec/unit/models/services/service_dashboard_client_spec.rb index 342e85c84dc..8b1ffee0042 100644 --- a/spec/unit/models/services/service_dashboard_client_spec.rb +++ b/spec/unit/models/services/service_dashboard_client_spec.rb @@ -12,9 +12,17 @@ module VCAP::CloudController it { is_expected.to have_associated :service_broker } end + describe 'uniqueness' do + it 'enforces uniqueness of uaa_id' do + existing = ServiceDashboardClient.make(service_broker:) + expect { + ServiceDashboardClient.create(uaa_id: existing.uaa_id, service_broker: other_broker) + }.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do it { is_expected.to validate_presence :uaa_id } - it { is_expected.to validate_uniqueness :uaa_id } context 'when all fields are valid' do let(:client) { ServiceDashboardClient.make_unsaved(service_broker:) } From bca2128b0d37e0951d93d16b60aed29d001ea113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serdar=20=C3=96zer?= Date: Mon, 16 Mar 2026 16:51:47 +0100 Subject: [PATCH 05/13] feat: around_save added for existing unique index for feature_flag model --- app/models/runtime/feature_flag.rb | 10 +++++++++- spec/unit/models/runtime/feature_flag_spec.rb | 16 +++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/app/models/runtime/feature_flag.rb b/app/models/runtime/feature_flag.rb index df991d89f7e..e64b7d60e7b 100644 --- a/app/models/runtime/feature_flag.rb +++ b/app/models/runtime/feature_flag.rb @@ -43,9 +43,17 @@ class UndefinedFeatureFlagError < StandardError export_attributes :name, :enabled, :error_message import_attributes :name, :enabled, :error_message + def around_save + yield + rescue Sequel::UniqueConstraintViolation => e + raise e unless e.message.include?('feature_flags_name_index') + + errors.add(:name, :unique) + raise validation_failed_error + end + def validate validates_presence :name - validates_unique :name validates_presence :enabled validates_includes DEFAULT_FLAGS.keys.map(&:to_s), :name diff --git a/spec/unit/models/runtime/feature_flag_spec.rb b/spec/unit/models/runtime/feature_flag_spec.rb index 458f93c4cdd..99febd580d6 100644 --- a/spec/unit/models/runtime/feature_flag_spec.rb +++ b/spec/unit/models/runtime/feature_flag_spec.rb @@ -6,17 +6,19 @@ module VCAP::CloudController it { is_expected.to have_timestamp_columns } + describe 'uniqueness' do + it 'enforces uniqueness of name' do + existing_flag = FeatureFlag.make + expect { + FeatureFlag.create(name: existing_flag.name, enabled: true) + }.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do it { is_expected.to validate_presence :name } it { is_expected.to validate_presence :enabled } - it 'validates name is unique' do - existing_flag = FeatureFlag.make - duplicate_flag = FeatureFlag.new - duplicate_flag.name = existing_flag.name - expect { duplicate_flag.save }.to raise_error(Sequel::ValidationFailed, /name unique/) - end - context 'name validation' do context 'with a valid name' do it 'allows creation of a feature flag that has a corresponding default' do From 84cd8d4e65e86a4cd280f6836d901d218eb4ef0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serdar=20=C3=96zer?= Date: Tue, 17 Mar 2026 10:23:21 +0100 Subject: [PATCH 06/13] feat: around_save added for existing unique index for qutoa_definition model --- app/models/runtime/quota_definition.rb | 1 - spec/unit/models/runtime/quota_definition_spec.rb | 10 +++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/models/runtime/quota_definition.rb b/app/models/runtime/quota_definition.rb index 738570d1bc3..ba9a61357ba 100644 --- a/app/models/runtime/quota_definition.rb +++ b/app/models/runtime/quota_definition.rb @@ -30,7 +30,6 @@ def around_save def validate validates_presence :name - validates_unique :name validates_presence :non_basic_services_allowed validates_presence :total_services validates_presence :total_routes diff --git a/spec/unit/models/runtime/quota_definition_spec.rb b/spec/unit/models/runtime/quota_definition_spec.rb index 21d67e7f60c..5868d3c6452 100644 --- a/spec/unit/models/runtime/quota_definition_spec.rb +++ b/spec/unit/models/runtime/quota_definition_spec.rb @@ -14,13 +14,21 @@ module VCAP::CloudController it { is_expected.to have_associated :organizations } end + describe 'uniqueness' do + it 'enforces uniqueness of name' do + existing = QuotaDefinition.make + expect { + QuotaDefinition.create(name: existing.name, non_basic_services_allowed: true, total_services: 0, total_routes: 0, memory_limit: 0) + }.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do it { is_expected.to validate_presence :name } it { is_expected.to validate_presence :non_basic_services_allowed } it { is_expected.to validate_presence :total_services } it { is_expected.to validate_presence :total_routes } it { is_expected.to validate_presence :memory_limit } - it { is_expected.to validate_uniqueness :name } describe 'memory_limits' do it 'total memory_limit cannot be less than -1 ("unlimited")' do From bb30c9894c45db6f0bce313518491ef2858bc84b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serdar=20=C3=96zer?= Date: Tue, 17 Mar 2026 10:25:03 +0100 Subject: [PATCH 07/13] fix: rubocop errors are fixed --- app/models/runtime/app_model.rb | 1 - app/models/services/service_plan.rb | 1 - spec/support/shared_examples/models/domain_validation.rb | 4 ++-- spec/unit/actions/app_create_spec.rb | 1 - spec/unit/actions/organization_create_spec.rb | 1 - spec/unit/actions/service_broker_create_spec.rb | 1 - spec/unit/actions/space_create_spec.rb | 1 - spec/unit/actions/space_quotas_create_spec.rb | 1 - spec/unit/actions/stack_create_spec.rb | 1 - spec/unit/actions/user_create_spec.rb | 1 - spec/unit/isolation_segment_create_spec.rb | 1 - spec/unit/models/runtime/feature_flag_spec.rb | 4 ++-- spec/unit/models/runtime/organization_auditor_spec.rb | 8 ++++---- .../models/runtime/organization_billing_manager_spec.rb | 8 ++++---- spec/unit/models/runtime/organization_manager_spec.rb | 8 ++++---- spec/unit/models/runtime/organization_user_spec.rb | 8 ++++---- spec/unit/models/runtime/quota_definition_spec.rb | 4 ++-- spec/unit/models/runtime/space_auditor_spec.rb | 8 ++++---- spec/unit/models/runtime/space_developer_spec.rb | 9 +++++---- spec/unit/models/runtime/space_manager_spec.rb | 9 +++++---- spec/unit/models/runtime/space_supporter_spec.rb | 9 +++++---- .../models/services/service_dashboard_client_spec.rb | 4 ++-- spec/unit/models/services/service_key_spec.rb | 4 ++-- spec/unit/models/services/service_plan_spec.rb | 4 ++-- .../unit/models/services/service_plan_visibility_spec.rb | 4 ++-- 25 files changed, 49 insertions(+), 56 deletions(-) diff --git a/app/models/runtime/app_model.rb b/app/models/runtime/app_model.rb index d4e14ecc54a..b02e1550c56 100644 --- a/app/models/runtime/app_model.rb +++ b/app/models/runtime/app_model.rb @@ -99,7 +99,6 @@ def validate validates_format APP_NAME_REGEX, :name validate_environment_variables validate_droplet_is_staged - end def lifecycle_type diff --git a/app/models/services/service_plan.rb b/app/models/services/service_plan.rb index 8a655d95e86..50fbe006bdc 100644 --- a/app/models/services/service_plan.rb +++ b/app/models/services/service_plan.rb @@ -84,7 +84,6 @@ def around_save raise validation_failed_error end - def validate validates_presence :name, message: 'is required' validates_presence :description, message: 'is required' diff --git a/spec/support/shared_examples/models/domain_validation.rb b/spec/support/shared_examples/models/domain_validation.rb index a38ad243de0..cedbdbca8b8 100644 --- a/spec/support/shared_examples/models/domain_validation.rb +++ b/spec/support/shared_examples/models/domain_validation.rb @@ -13,9 +13,9 @@ module VCAP::CloudController context "when there's another domain with the same name" do it 'fails to validate' do - expect { + expect do described_class.make(name: subject.name) - }.to raise_error(Sequel::ValidationFailed, /already reserved by another domain|unique/) + end.to raise_error(Sequel::ValidationFailed, /already reserved by another domain|unique/) end end diff --git a/spec/unit/actions/app_create_spec.rb b/spec/unit/actions/app_create_spec.rb index 2b31125426c..8730f187d4a 100644 --- a/spec/unit/actions/app_create_spec.rb +++ b/spec/unit/actions/app_create_spec.rb @@ -200,7 +200,6 @@ module VCAP::CloudController end end - describe 'stack state validation' do let(:test_stack) { Stack.make(name: 'test-stack-for-validation') } let(:lifecycle_request) { { type: 'buildpack', data: { buildpacks: [buildpack_identifier], stack: test_stack.name } } } diff --git a/spec/unit/actions/organization_create_spec.rb b/spec/unit/actions/organization_create_spec.rb index 569eb1e371b..47d63f4b6f2 100644 --- a/spec/unit/actions/organization_create_spec.rb +++ b/spec/unit/actions/organization_create_spec.rb @@ -121,7 +121,6 @@ module VCAP::CloudController org_create.create(message) end.not_to raise_error - # Second request, should fail with correct error expect do org_create.create(message) diff --git a/spec/unit/actions/service_broker_create_spec.rb b/spec/unit/actions/service_broker_create_spec.rb index 49ff4efb50d..9cfa2aecf65 100644 --- a/spec/unit/actions/service_broker_create_spec.rb +++ b/spec/unit/actions/service_broker_create_spec.rb @@ -140,7 +140,6 @@ module CloudController action.create(message) end.not_to raise_error - # Second request, should fail with correct error expect do action.create(message) diff --git a/spec/unit/actions/space_create_spec.rb b/spec/unit/actions/space_create_spec.rb index 2d43674bdf8..dd06f2e60c5 100644 --- a/spec/unit/actions/space_create_spec.rb +++ b/spec/unit/actions/space_create_spec.rb @@ -90,7 +90,6 @@ module VCAP::CloudController SpaceCreate.new(user_audit_info:).create(org, message) end.not_to raise_error - # Second request, should fail with correct error expect do SpaceCreate.new(user_audit_info:).create(org, message) diff --git a/spec/unit/actions/space_quotas_create_spec.rb b/spec/unit/actions/space_quotas_create_spec.rb index 08c6f7d5dfd..f5f8723ea95 100644 --- a/spec/unit/actions/space_quotas_create_spec.rb +++ b/spec/unit/actions/space_quotas_create_spec.rb @@ -210,7 +210,6 @@ module VCAP::CloudController space_quotas_create.create(message, organization: org) end.not_to raise_error - # Second request, should fail with correct error expect do space_quotas_create.create(message, organization: org) diff --git a/spec/unit/actions/stack_create_spec.rb b/spec/unit/actions/stack_create_spec.rb index c661bd9db45..bf088a7395d 100644 --- a/spec/unit/actions/stack_create_spec.rb +++ b/spec/unit/actions/stack_create_spec.rb @@ -130,7 +130,6 @@ module VCAP::CloudController stack_create.create(message) end.not_to raise_error - # Second request, should fail with correct error expect do stack_create.create(message) diff --git a/spec/unit/actions/user_create_spec.rb b/spec/unit/actions/user_create_spec.rb index 37a785f9f28..838b88a4bc3 100644 --- a/spec/unit/actions/user_create_spec.rb +++ b/spec/unit/actions/user_create_spec.rb @@ -44,7 +44,6 @@ module VCAP::CloudController subject.create(message:) end.not_to raise_error - # Second request, should fail with correct error expect do subject.create(message:) diff --git a/spec/unit/isolation_segment_create_spec.rb b/spec/unit/isolation_segment_create_spec.rb index 2aac7938bee..ef2659cf274 100644 --- a/spec/unit/isolation_segment_create_spec.rb +++ b/spec/unit/isolation_segment_create_spec.rb @@ -53,7 +53,6 @@ module VCAP::CloudController IsolationSegmentCreate.create(message) end.not_to raise_error - # Second request, should fail with correct error expect do IsolationSegmentCreate.create(message) diff --git a/spec/unit/models/runtime/feature_flag_spec.rb b/spec/unit/models/runtime/feature_flag_spec.rb index 99febd580d6..88b41fd0e93 100644 --- a/spec/unit/models/runtime/feature_flag_spec.rb +++ b/spec/unit/models/runtime/feature_flag_spec.rb @@ -9,9 +9,9 @@ module VCAP::CloudController describe 'uniqueness' do it 'enforces uniqueness of name' do existing_flag = FeatureFlag.make - expect { + expect do FeatureFlag.create(name: existing_flag.name, enabled: true) - }.to raise_error(Sequel::ValidationFailed, /unique/) + end.to raise_error(Sequel::ValidationFailed, /unique/) end end diff --git a/spec/unit/models/runtime/organization_auditor_spec.rb b/spec/unit/models/runtime/organization_auditor_spec.rb index 7675657ffd5..66aea240981 100644 --- a/spec/unit/models/runtime/organization_auditor_spec.rb +++ b/spec/unit/models/runtime/organization_auditor_spec.rb @@ -5,12 +5,12 @@ module VCAP::CloudController let(:organization) { Organization.make } let(:user) { User.make } - describe "uniquiness" do - it "prevend dublicate organization_id and user_id combination" do + describe 'uniquiness' do + it 'prevend dublicate organization_id and user_id combination' do OrganizationAuditor.create(organization_id: organization.id, user_id: user.id) - expect { + expect do OrganizationAuditor.create(organization_id: organization.id, user_id: user.id) - }.to raise_error(Sequel::ValidationFailed, /unique/) + end.to raise_error(Sequel::ValidationFailed, /unique/) end end diff --git a/spec/unit/models/runtime/organization_billing_manager_spec.rb b/spec/unit/models/runtime/organization_billing_manager_spec.rb index 4ed8c2dd8de..b6b07a8286c 100644 --- a/spec/unit/models/runtime/organization_billing_manager_spec.rb +++ b/spec/unit/models/runtime/organization_billing_manager_spec.rb @@ -5,12 +5,12 @@ module VCAP::CloudController let(:organization) { Organization.make } let(:user) { User.make } - describe "uniquiness" do - it "prevend dublicate organization_id and user_id combination" do + describe 'uniquiness' do + it 'prevend dublicate organization_id and user_id combination' do OrganizationBillingManager.create(organization_id: organization.id, user_id: user.id) - expect { + expect do OrganizationBillingManager.create(organization_id: organization.id, user_id: user.id) - }.to raise_error(Sequel::ValidationFailed, /unique/) + end.to raise_error(Sequel::ValidationFailed, /unique/) end end diff --git a/spec/unit/models/runtime/organization_manager_spec.rb b/spec/unit/models/runtime/organization_manager_spec.rb index e5c3993576b..ff563ae2a9d 100644 --- a/spec/unit/models/runtime/organization_manager_spec.rb +++ b/spec/unit/models/runtime/organization_manager_spec.rb @@ -5,12 +5,12 @@ module VCAP::CloudController let(:organization) { Organization.make } let(:user) { User.make } - describe "uniquiness" do - it "prevend dublicate organization_id and user_id combination" do + describe 'uniquiness' do + it 'prevend dublicate organization_id and user_id combination' do OrganizationManager.create(organization_id: organization.id, user_id: user.id) - expect { + expect do OrganizationManager.create(organization_id: organization.id, user_id: user.id) - }.to raise_error(Sequel::ValidationFailed, /unique/) + end.to raise_error(Sequel::ValidationFailed, /unique/) end end diff --git a/spec/unit/models/runtime/organization_user_spec.rb b/spec/unit/models/runtime/organization_user_spec.rb index bb72b1a4cfa..97f84111df3 100644 --- a/spec/unit/models/runtime/organization_user_spec.rb +++ b/spec/unit/models/runtime/organization_user_spec.rb @@ -5,12 +5,12 @@ module VCAP::CloudController let(:organization) { Organization.make } let(:user) { User.make } - describe "uniquiness" do - it "prevend dublicate organization_id and user_id combination" do + describe 'uniquiness' do + it 'prevend dublicate organization_id and user_id combination' do OrganizationUser.create(organization_id: organization.id, user_id: user.id) - expect { + expect do OrganizationUser.create(organization_id: organization.id, user_id: user.id) - }.to raise_error(Sequel::ValidationFailed, /unique/) + end.to raise_error(Sequel::ValidationFailed, /unique/) end end diff --git a/spec/unit/models/runtime/quota_definition_spec.rb b/spec/unit/models/runtime/quota_definition_spec.rb index 5868d3c6452..47bce2377ad 100644 --- a/spec/unit/models/runtime/quota_definition_spec.rb +++ b/spec/unit/models/runtime/quota_definition_spec.rb @@ -17,9 +17,9 @@ module VCAP::CloudController describe 'uniqueness' do it 'enforces uniqueness of name' do existing = QuotaDefinition.make - expect { + expect do QuotaDefinition.create(name: existing.name, non_basic_services_allowed: true, total_services: 0, total_routes: 0, memory_limit: 0) - }.to raise_error(Sequel::ValidationFailed, /unique/) + end.to raise_error(Sequel::ValidationFailed, /unique/) end end diff --git a/spec/unit/models/runtime/space_auditor_spec.rb b/spec/unit/models/runtime/space_auditor_spec.rb index 3101fa61384..440320255ff 100644 --- a/spec/unit/models/runtime/space_auditor_spec.rb +++ b/spec/unit/models/runtime/space_auditor_spec.rb @@ -5,12 +5,12 @@ module VCAP::CloudController let(:space) { Space.make } let(:user) { User.make } - describe "uniquiness" do - it "prevend dublicate space_id and user_id combination" do + describe 'uniquiness' do + it 'prevend dublicate space_id and user_id combination' do SpaceAuditor.create(space_id: space.id, user_id: user.id) - expect{ + expect do SpaceAuditor.create(space_id: space.id, user_id: user.id) - }.to raise_error(Sequel::ValidationFailed, /unique/) + end.to raise_error(Sequel::ValidationFailed, /unique/) end end diff --git a/spec/unit/models/runtime/space_developer_spec.rb b/spec/unit/models/runtime/space_developer_spec.rb index 8b7a61ae22f..8e0922c8d58 100644 --- a/spec/unit/models/runtime/space_developer_spec.rb +++ b/spec/unit/models/runtime/space_developer_spec.rb @@ -5,14 +5,15 @@ module VCAP::CloudController let(:space) { Space.make } let(:user) { User.make } - describe "uniquiness" do - it "prevend dublicate space_id and user_id combination" do + describe 'uniquiness' do + it 'prevend dublicate space_id and user_id combination' do SpaceDeveloper.create(space_id: space.id, user_id: user.id) - expect{ + expect do SpaceDeveloper.create(space_id: space.id, user_id: user.id) - }.to raise_error(Sequel::ValidationFailed, /unique/) + end.to raise_error(Sequel::ValidationFailed, /unique/) end end + describe 'Validations' do it { is_expected.to validate_presence :space_id } it { is_expected.to validate_presence :user_id } diff --git a/spec/unit/models/runtime/space_manager_spec.rb b/spec/unit/models/runtime/space_manager_spec.rb index de46d51ece0..36a8c94038d 100644 --- a/spec/unit/models/runtime/space_manager_spec.rb +++ b/spec/unit/models/runtime/space_manager_spec.rb @@ -5,14 +5,15 @@ module VCAP::CloudController let(:space) { Space.make } let(:user) { User.make } - describe "uniquiness" do - it "prevend dublicate space_id and user_id combination" do + describe 'uniquiness' do + it 'prevend dublicate space_id and user_id combination' do SpaceManager.create(space_id: space.id, user_id: user.id) - expect{ + expect do SpaceManager.create(space_id: space.id, user_id: user.id) - }.to raise_error(Sequel::ValidationFailed, /unique/) + end.to raise_error(Sequel::ValidationFailed, /unique/) end end + describe 'Validations' do it { is_expected.to validate_presence :space_id } it { is_expected.to validate_presence :user_id } diff --git a/spec/unit/models/runtime/space_supporter_spec.rb b/spec/unit/models/runtime/space_supporter_spec.rb index 6df94437f86..cba0eee62a6 100644 --- a/spec/unit/models/runtime/space_supporter_spec.rb +++ b/spec/unit/models/runtime/space_supporter_spec.rb @@ -6,14 +6,15 @@ module VCAP::CloudController let(:space) { Space.make } let(:user) { User.make } - describe "uniquiness" do - it "prevend dublicate space_id and user_id combination" do + describe 'uniquiness' do + it 'prevend dublicate space_id and user_id combination' do SpaceSupporter.create(space_id: space.id, user_id: user.id) - expect{ + expect do SpaceSupporter.create(space_id: space.id, user_id: user.id) - }.to raise_error(Sequel::ValidationFailed, /unique/) + end.to raise_error(Sequel::ValidationFailed, /unique/) end end + describe 'Validations' do it { is_expected.to validate_presence :space_id } it { is_expected.to validate_presence :user_id } diff --git a/spec/unit/models/services/service_dashboard_client_spec.rb b/spec/unit/models/services/service_dashboard_client_spec.rb index 8b1ffee0042..35ed4ee8867 100644 --- a/spec/unit/models/services/service_dashboard_client_spec.rb +++ b/spec/unit/models/services/service_dashboard_client_spec.rb @@ -15,9 +15,9 @@ module VCAP::CloudController describe 'uniqueness' do it 'enforces uniqueness of uaa_id' do existing = ServiceDashboardClient.make(service_broker:) - expect { + expect do ServiceDashboardClient.create(uaa_id: existing.uaa_id, service_broker: other_broker) - }.to raise_error(Sequel::ValidationFailed, /unique/) + end.to raise_error(Sequel::ValidationFailed, /unique/) end end diff --git a/spec/unit/models/services/service_key_spec.rb b/spec/unit/models/services/service_key_spec.rb index a267ab21abe..4ddf0c50d0c 100644 --- a/spec/unit/models/services/service_key_spec.rb +++ b/spec/unit/models/services/service_key_spec.rb @@ -22,9 +22,9 @@ module VCAP::CloudController describe 'uniqueness' do it 'enforces uniqueness of name and service_instance_id' do existing = ServiceKey.make - expect { + expect do ServiceKey.make(name: existing.name, service_instance: existing.service_instance) - }.to raise_error(Sequel::ValidationFailed, /unique/) + end.to raise_error(Sequel::ValidationFailed, /unique/) end end diff --git a/spec/unit/models/services/service_plan_spec.rb b/spec/unit/models/services/service_plan_spec.rb index 583bf577dde..f9e49c3dfa8 100644 --- a/spec/unit/models/services/service_plan_spec.rb +++ b/spec/unit/models/services/service_plan_spec.rb @@ -15,9 +15,9 @@ module VCAP::CloudController describe 'uniqueness' do it 'enforces uniqueness of name within a service' do existing = ServicePlan.make - expect { + expect do ServicePlan.make(name: existing.name, service: existing.service) - }.to raise_error(Sequel::ValidationFailed, /already has a plan named/) + end.to raise_error(Sequel::ValidationFailed, /already has a plan named/) end end diff --git a/spec/unit/models/services/service_plan_visibility_spec.rb b/spec/unit/models/services/service_plan_visibility_spec.rb index 7e14c181623..1b0d81b5df9 100644 --- a/spec/unit/models/services/service_plan_visibility_spec.rb +++ b/spec/unit/models/services/service_plan_visibility_spec.rb @@ -12,9 +12,9 @@ module VCAP::CloudController describe 'uniqueness' do it 'enforces uniqueness of organization and service plan combination' do existing = ServicePlanVisibility.make - expect { + expect do ServicePlanVisibility.create(service_plan: existing.service_plan, organization: existing.organization) - }.to raise_error(Sequel::ValidationFailed, /unique/) + end.to raise_error(Sequel::ValidationFailed, /unique/) end end From c496a362385da85f934d3127017610095561f586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serdar=20=C3=96zer?= Date: Tue, 17 Mar 2026 11:46:25 +0100 Subject: [PATCH 08/13] fix: error message fixed for service_broker model --- app/models/services/service_broker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/services/service_broker.rb b/app/models/services/service_broker.rb index 7cba05219c8..0769f5e7320 100644 --- a/app/models/services/service_broker.rb +++ b/app/models/services/service_broker.rb @@ -25,7 +25,7 @@ def around_save rescue Sequel::UniqueConstraintViolation => e raise e unless e.message.include?('service_brokers_name_index') - errors.add(:name, :unique) + errors.add(:name, Sequel.lit('Name must be unique')) raise validation_failed_error end From be178e28c1c6a62a83b07ddc6e7511817f1d7a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serdar=20=C3=96zer?= Date: Tue, 17 Mar 2026 12:23:01 +0100 Subject: [PATCH 09/13] fix: service_broker validate_unique reintroduced because, it uses this validation in service_broker_registraion service to refraing http call invalid brokers --- app/models/services/service_broker.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/services/service_broker.rb b/app/models/services/service_broker.rb index 0769f5e7320..0d85ba6005e 100644 --- a/app/models/services/service_broker.rb +++ b/app/models/services/service_broker.rb @@ -34,6 +34,7 @@ def validate validates_presence :broker_url validates_presence :auth_username validates_presence :auth_password + validates_unique :name, message: Sequel.lit('Name must be unique') validates_url :broker_url validates_url_no_basic_auth end From 0b73ef979f77c1ea296a1edf0f076410f1620a1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serdar=20=C3=96zer?= Date: Tue, 17 Mar 2026 13:01:56 +0100 Subject: [PATCH 10/13] fix: service_broker validate_unique reintroduced because, it uses this validation in service_key_manager to refraing http call in service_key_create --- app/models/services/service_key.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/services/service_key.rb b/app/models/services/service_key.rb index cd33e12034f..0cc8545b3f1 100644 --- a/app/models/services/service_key.rb +++ b/app/models/services/service_key.rb @@ -49,6 +49,7 @@ def around_save def validate validates_presence :name validates_presence :service_instance + validates_unique %i[name service_instance_id] return unless service_instance From 240dd21ad77b7bab7c9672d3c7a560cfa208605e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serdar=20=C3=96zer?= Date: Wed, 18 Mar 2026 08:30:07 +0100 Subject: [PATCH 11/13] fix: service_broker validation_unique is removed --- app/models/services/service_broker.rb | 1 - lib/services/service_brokers/service_broker_registration.rb | 4 ++++ .../controllers/services/service_brokers_controller_spec.rb | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/models/services/service_broker.rb b/app/models/services/service_broker.rb index 0d85ba6005e..0769f5e7320 100644 --- a/app/models/services/service_broker.rb +++ b/app/models/services/service_broker.rb @@ -34,7 +34,6 @@ def validate validates_presence :broker_url validates_presence :auth_username validates_presence :auth_password - validates_unique :name, message: Sequel.lit('Name must be unique') validates_url :broker_url validates_url_no_basic_auth end diff --git a/lib/services/service_brokers/service_broker_registration.rb b/lib/services/service_brokers/service_broker_registration.rb index 3cc4e8ab42d..4c4e6f4322d 100644 --- a/lib/services/service_brokers/service_broker_registration.rb +++ b/lib/services/service_brokers/service_broker_registration.rb @@ -30,6 +30,8 @@ def create raise e end self + rescue Sequel::ValidationFailed + nil end def update @@ -50,6 +52,8 @@ def update synchronize_services_and_plans! end self + rescue Sequel::ValidationFailed + nil end delegate :errors, to: :broker diff --git a/spec/unit/controllers/services/service_brokers_controller_spec.rb b/spec/unit/controllers/services/service_brokers_controller_spec.rb index eff7192f8de..9c4ead91998 100644 --- a/spec/unit/controllers/services/service_brokers_controller_spec.rb +++ b/spec/unit/controllers/services/service_brokers_controller_spec.rb @@ -291,6 +291,7 @@ def stub_catalog(broker_url: nil, username: nil, password: nil) post '/v2/service_brokers', public_body expect(last_response).to have_status_code(201) + stub_catalog post '/v2/service_brokers', body expect(last_response).to have_status_code(400) end From 8c7d5ed8d51bddf968799f9a5f928d0055928c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serdar=20=C3=96zer?= Date: Wed, 18 Mar 2026 16:25:27 +0100 Subject: [PATCH 12/13] fix: typos are fixed --- spec/unit/models/runtime/organization_auditor_spec.rb | 4 ++-- spec/unit/models/runtime/organization_billing_manager_spec.rb | 4 ++-- spec/unit/models/runtime/organization_manager_spec.rb | 4 ++-- spec/unit/models/runtime/organization_user_spec.rb | 4 ++-- spec/unit/models/runtime/space_auditor_spec.rb | 4 ++-- spec/unit/models/runtime/space_developer_spec.rb | 4 ++-- spec/unit/models/runtime/space_manager_spec.rb | 4 ++-- spec/unit/models/runtime/space_supporter_spec.rb | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/spec/unit/models/runtime/organization_auditor_spec.rb b/spec/unit/models/runtime/organization_auditor_spec.rb index 66aea240981..e7c12080c85 100644 --- a/spec/unit/models/runtime/organization_auditor_spec.rb +++ b/spec/unit/models/runtime/organization_auditor_spec.rb @@ -5,8 +5,8 @@ module VCAP::CloudController let(:organization) { Organization.make } let(:user) { User.make } - describe 'uniquiness' do - it 'prevend dublicate organization_id and user_id combination' do + describe 'uniqueness' do + it 'prevents duplicate organization_id and user_id combination' do OrganizationAuditor.create(organization_id: organization.id, user_id: user.id) expect do OrganizationAuditor.create(organization_id: organization.id, user_id: user.id) diff --git a/spec/unit/models/runtime/organization_billing_manager_spec.rb b/spec/unit/models/runtime/organization_billing_manager_spec.rb index b6b07a8286c..8c101550d79 100644 --- a/spec/unit/models/runtime/organization_billing_manager_spec.rb +++ b/spec/unit/models/runtime/organization_billing_manager_spec.rb @@ -5,8 +5,8 @@ module VCAP::CloudController let(:organization) { Organization.make } let(:user) { User.make } - describe 'uniquiness' do - it 'prevend dublicate organization_id and user_id combination' do + describe 'uniqueness' do + it 'prevents duplicate organization_id and user_id combination' do OrganizationBillingManager.create(organization_id: organization.id, user_id: user.id) expect do OrganizationBillingManager.create(organization_id: organization.id, user_id: user.id) diff --git a/spec/unit/models/runtime/organization_manager_spec.rb b/spec/unit/models/runtime/organization_manager_spec.rb index ff563ae2a9d..c26d026ead5 100644 --- a/spec/unit/models/runtime/organization_manager_spec.rb +++ b/spec/unit/models/runtime/organization_manager_spec.rb @@ -5,8 +5,8 @@ module VCAP::CloudController let(:organization) { Organization.make } let(:user) { User.make } - describe 'uniquiness' do - it 'prevend dublicate organization_id and user_id combination' do + describe 'uniqueness' do + it 'prevents duplicate organization_id and user_id combination' do OrganizationManager.create(organization_id: organization.id, user_id: user.id) expect do OrganizationManager.create(organization_id: organization.id, user_id: user.id) diff --git a/spec/unit/models/runtime/organization_user_spec.rb b/spec/unit/models/runtime/organization_user_spec.rb index 97f84111df3..1217f66b431 100644 --- a/spec/unit/models/runtime/organization_user_spec.rb +++ b/spec/unit/models/runtime/organization_user_spec.rb @@ -5,8 +5,8 @@ module VCAP::CloudController let(:organization) { Organization.make } let(:user) { User.make } - describe 'uniquiness' do - it 'prevend dublicate organization_id and user_id combination' do + describe 'uniqueness' do + it 'prevents duplicate organization_id and user_id combination' do OrganizationUser.create(organization_id: organization.id, user_id: user.id) expect do OrganizationUser.create(organization_id: organization.id, user_id: user.id) diff --git a/spec/unit/models/runtime/space_auditor_spec.rb b/spec/unit/models/runtime/space_auditor_spec.rb index 440320255ff..1383c8ae302 100644 --- a/spec/unit/models/runtime/space_auditor_spec.rb +++ b/spec/unit/models/runtime/space_auditor_spec.rb @@ -5,8 +5,8 @@ module VCAP::CloudController let(:space) { Space.make } let(:user) { User.make } - describe 'uniquiness' do - it 'prevend dublicate space_id and user_id combination' do + describe 'uniqueness' do + it 'prevents duplicate space_id and user_id combination' do SpaceAuditor.create(space_id: space.id, user_id: user.id) expect do SpaceAuditor.create(space_id: space.id, user_id: user.id) diff --git a/spec/unit/models/runtime/space_developer_spec.rb b/spec/unit/models/runtime/space_developer_spec.rb index 8e0922c8d58..97c04e82215 100644 --- a/spec/unit/models/runtime/space_developer_spec.rb +++ b/spec/unit/models/runtime/space_developer_spec.rb @@ -5,8 +5,8 @@ module VCAP::CloudController let(:space) { Space.make } let(:user) { User.make } - describe 'uniquiness' do - it 'prevend dublicate space_id and user_id combination' do + describe 'uniqueness' do + it 'prevents duplicate space_id and user_id combination' do SpaceDeveloper.create(space_id: space.id, user_id: user.id) expect do SpaceDeveloper.create(space_id: space.id, user_id: user.id) diff --git a/spec/unit/models/runtime/space_manager_spec.rb b/spec/unit/models/runtime/space_manager_spec.rb index 36a8c94038d..5d832f2c576 100644 --- a/spec/unit/models/runtime/space_manager_spec.rb +++ b/spec/unit/models/runtime/space_manager_spec.rb @@ -5,8 +5,8 @@ module VCAP::CloudController let(:space) { Space.make } let(:user) { User.make } - describe 'uniquiness' do - it 'prevend dublicate space_id and user_id combination' do + describe 'uniqueness' do + it 'prevents duplicate space_id and user_id combination' do SpaceManager.create(space_id: space.id, user_id: user.id) expect do SpaceManager.create(space_id: space.id, user_id: user.id) diff --git a/spec/unit/models/runtime/space_supporter_spec.rb b/spec/unit/models/runtime/space_supporter_spec.rb index cba0eee62a6..1581c17fc76 100644 --- a/spec/unit/models/runtime/space_supporter_spec.rb +++ b/spec/unit/models/runtime/space_supporter_spec.rb @@ -6,8 +6,8 @@ module VCAP::CloudController let(:space) { Space.make } let(:user) { User.make } - describe 'uniquiness' do - it 'prevend dublicate space_id and user_id combination' do + describe 'uniqueness' do + it 'prevents duplicate space_id and user_id combination' do SpaceSupporter.create(space_id: space.id, user_id: user.id) expect do SpaceSupporter.create(space_id: space.id, user_id: user.id) From 3e6166d8aa8e336163115e6849cfde60d101d608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serdar=20=C3=96zer?= Date: Wed, 18 Mar 2026 17:46:03 +0100 Subject: [PATCH 13/13] fix: concurrent context tests are removed in unit/actions. Uniqueness tests are reintroduced in unit/models. --- spec/unit/actions/organization_create_spec.rb | 17 ----------------- spec/unit/actions/service_broker_create_spec.rb | 14 -------------- spec/unit/actions/space_create_spec.rb | 17 ----------------- spec/unit/actions/space_quotas_create_spec.rb | 14 -------------- spec/unit/actions/stack_create_spec.rb | 17 ----------------- spec/unit/actions/user_create_spec.rb | 16 ---------------- spec/unit/isolation_segment_create_spec.rb | 15 --------------- .../runtime/isolation_segment_model_spec.rb | 16 ++++++++++++++++ spec/unit/models/runtime/organization_spec.rb | 9 +++++++++ .../runtime/space_quota_definition_spec.rb | 9 +++++++++ spec/unit/models/runtime/space_spec.rb | 9 +++++++++ spec/unit/models/runtime/stack_spec.rb | 9 +++++++++ spec/unit/models/runtime/user_spec.rb | 9 +++++++++ .../unit/models/services/service_broker_spec.rb | 9 +++++++++ 14 files changed, 70 insertions(+), 110 deletions(-) diff --git a/spec/unit/actions/organization_create_spec.rb b/spec/unit/actions/organization_create_spec.rb index 47d63f4b6f2..77e810e1d0e 100644 --- a/spec/unit/actions/organization_create_spec.rb +++ b/spec/unit/actions/organization_create_spec.rb @@ -110,23 +110,6 @@ module VCAP::CloudController end.to raise_error(OrganizationCreate::Error, "Organization '#{name}' already exists.") end end - - context 'when creating organizations concurrently' do - let(:name) { 'Alfredo' } - - it 'ensures one creation is successful and the other fails due to name conflict' do - # First request, should succeed - message = VCAP::CloudController::OrganizationUpdateMessage.new(name:) - expect do - org_create.create(message) - end.not_to raise_error - - # Second request, should fail with correct error - expect do - org_create.create(message) - end.to raise_error(OrganizationCreate::Error, "Organization 'Alfredo' already exists.") - end - end end end end diff --git a/spec/unit/actions/service_broker_create_spec.rb b/spec/unit/actions/service_broker_create_spec.rb index 9cfa2aecf65..22caa6b50e8 100644 --- a/spec/unit/actions/service_broker_create_spec.rb +++ b/spec/unit/actions/service_broker_create_spec.rb @@ -132,20 +132,6 @@ module CloudController end end end - - describe 'when creating a service broker with the same name concurrently' do - it 'ensures one creation is successful and the other fails due to name conflict' do - # First request, should succeed - expect do - action.create(message) - end.not_to raise_error - - # Second request, should fail with correct error - expect do - action.create(message) - end.to raise_error(V3::ServiceBrokerCreate::InvalidServiceBroker) - end - end end end end diff --git a/spec/unit/actions/space_create_spec.rb b/spec/unit/actions/space_create_spec.rb index dd06f2e60c5..c1547d30001 100644 --- a/spec/unit/actions/space_create_spec.rb +++ b/spec/unit/actions/space_create_spec.rb @@ -79,23 +79,6 @@ module VCAP::CloudController end.to raise_error(SpaceCreate::Error, 'Name must be unique per organization') end end - - context 'when creating spaces concurrently' do - let(:name) { 'Rose' } - - it 'ensures one creation is successful and the other fails due to name conflict' do - # First request, should succeed - message = VCAP::CloudController::SpaceCreateMessage.new(name:) - expect do - SpaceCreate.new(user_audit_info:).create(org, message) - end.not_to raise_error - - # Second request, should fail with correct error - expect do - SpaceCreate.new(user_audit_info:).create(org, message) - end.to raise_error(SpaceCreate::Error, 'Name must be unique per organization') - end - end end end end diff --git a/spec/unit/actions/space_quotas_create_spec.rb b/spec/unit/actions/space_quotas_create_spec.rb index f5f8723ea95..79ee409f9d5 100644 --- a/spec/unit/actions/space_quotas_create_spec.rb +++ b/spec/unit/actions/space_quotas_create_spec.rb @@ -202,20 +202,6 @@ module VCAP::CloudController end end end - - context 'when creating space quota with the same name concurrently' do - it 'ensures one creation is successful and the other fails due to name conflict' do - # First request, should succeed - expect do - space_quotas_create.create(message, organization: org) - end.not_to raise_error - - # Second request, should fail with correct error - expect do - space_quotas_create.create(message, organization: org) - end.to raise_error(SpaceQuotasCreate::Error, "Space Quota 'my-name' already exists.") - end - end end end end diff --git a/spec/unit/actions/stack_create_spec.rb b/spec/unit/actions/stack_create_spec.rb index bf088a7395d..1bc21fd2280 100644 --- a/spec/unit/actions/stack_create_spec.rb +++ b/spec/unit/actions/stack_create_spec.rb @@ -119,23 +119,6 @@ module VCAP::CloudController end.to raise_error(StackCreate::Error, 'Name must be unique') end end - - context 'when creating stack with the same name concurrently' do - let(:name) { 'Gaby' } - - it 'ensures one creation is successful and the other fails due to name conflict' do - message = VCAP::CloudController::StackCreateMessage.new(name:) - # First request, should succeed - expect do - stack_create.create(message) - end.not_to raise_error - - # Second request, should fail with correct error - expect do - stack_create.create(message) - end.to raise_error(StackCreate::Error, 'Name must be unique') - end - end end end end diff --git a/spec/unit/actions/user_create_spec.rb b/spec/unit/actions/user_create_spec.rb index 838b88a4bc3..9d215ad10ee 100644 --- a/spec/unit/actions/user_create_spec.rb +++ b/spec/unit/actions/user_create_spec.rb @@ -35,22 +35,6 @@ module VCAP::CloudController end end - context 'when creating users concurrently' do - let(:message) { UserCreateMessage.new({ guid: 'some-nice-user-gu-id' }) } - - it 'ensures one creation is successful and the other fails due to name conflict' do - # First request, should succeed - expect do - subject.create(message:) - end.not_to raise_error - - # Second request, should fail with correct error - expect do - subject.create(message:) - end.to raise_error(UserCreate::Error, "User with guid 'some-nice-user-gu-id' already exists.") - end - end - describe 'creating users' do before do allow(User).to receive_messages(create_uaa_shadow_user: { 'id' => guid }, get_user_id_by_username_and_origin: nil) diff --git a/spec/unit/isolation_segment_create_spec.rb b/spec/unit/isolation_segment_create_spec.rb index ef2659cf274..ccc67da435a 100644 --- a/spec/unit/isolation_segment_create_spec.rb +++ b/spec/unit/isolation_segment_create_spec.rb @@ -44,21 +44,6 @@ module VCAP::CloudController end.to raise_error(IsolationSegmentCreate::Error, 'blork is busted') end end - - context 'when creating isolation segments concurrently' do - it 'ensures one creation is successful and the other fails due to name conflict' do - # First request, should succeed - message = VCAP::CloudController::IsolationSegmentCreateMessage.new(name: 'foobar') - expect do - IsolationSegmentCreate.create(message) - end.not_to raise_error - - # Second request, should fail with correct error - expect do - IsolationSegmentCreate.create(message) - end.to raise_error(IsolationSegmentCreate::Error, 'Isolation Segment names are case insensitive and must be unique') - end - end end end end diff --git a/spec/unit/models/runtime/isolation_segment_model_spec.rb b/spec/unit/models/runtime/isolation_segment_model_spec.rb index 2b0268a279a..6b76de2d616 100644 --- a/spec/unit/models/runtime/isolation_segment_model_spec.rb +++ b/spec/unit/models/runtime/isolation_segment_model_spec.rb @@ -124,6 +124,22 @@ module VCAP::CloudController end.to raise_error(Sequel::ValidationFailed, 'Isolation Segment names can only contain non-blank unicode characters') end + it 'requires a unique name' do + IsolationSegmentModel.make(name: 'segment1') + + expect do + IsolationSegmentModel.make(name: 'segment1') + end.to raise_error(Sequel::ValidationFailed, 'Isolation Segment names are case insensitive and must be unique') + end + + it 'uniqueness is case insensitive' do + IsolationSegmentModel.make(name: 'lowercase') + + expect do + IsolationSegmentModel.make(name: 'lowerCase') + end.to raise_error(Sequel::ValidationFailed, 'Isolation Segment names are case insensitive and must be unique') + end + it 'allows standard ascii characters' do expect do IsolationSegmentModel.make(name: "A -_- word 2!?()'\"&+.") diff --git a/spec/unit/models/runtime/organization_spec.rb b/spec/unit/models/runtime/organization_spec.rb index 8ad2510d9dd..52945ecadb1 100644 --- a/spec/unit/models/runtime/organization_spec.rb +++ b/spec/unit/models/runtime/organization_spec.rb @@ -121,6 +121,15 @@ module VCAP::CloudController end end + describe 'uniqueness' do + it 'enforces uniqueness of name' do + existing_org = Organization.make + expect do + Organization.create(name: existing_org.name) + end.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do let(:org) { Organization.make } diff --git a/spec/unit/models/runtime/space_quota_definition_spec.rb b/spec/unit/models/runtime/space_quota_definition_spec.rb index c7599170634..e248390e660 100644 --- a/spec/unit/models/runtime/space_quota_definition_spec.rb +++ b/spec/unit/models/runtime/space_quota_definition_spec.rb @@ -17,6 +17,15 @@ module VCAP::CloudController end end + describe 'uniqueness' do + it 'enforces uniqueness of name within an organization' do + existing_quota = SpaceQuotaDefinition.make + expect do + SpaceQuotaDefinition.make(name: existing_quota.name, organization: existing_quota.organization) + end.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do it { is_expected.to validate_presence :name } it { is_expected.to validate_presence :non_basic_services_allowed } diff --git a/spec/unit/models/runtime/space_spec.rb b/spec/unit/models/runtime/space_spec.rb index 67dadd913fc..c22df7313aa 100644 --- a/spec/unit/models/runtime/space_spec.rb +++ b/spec/unit/models/runtime/space_spec.rb @@ -4,6 +4,15 @@ module VCAP::CloudController RSpec.describe VCAP::CloudController::Space, type: :model do it { is_expected.to have_timestamp_columns } + describe 'uniqueness' do + it 'enforces uniqueness of name within an organization' do + existing_space = Space.make + expect do + Space.create(name: existing_space.name, organization: existing_space.organization) + end.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do it { is_expected.to validate_presence :name } it { is_expected.to validate_presence :organization } diff --git a/spec/unit/models/runtime/stack_spec.rb b/spec/unit/models/runtime/stack_spec.rb index dafc0bdb851..cb17e7c8064 100644 --- a/spec/unit/models/runtime/stack_spec.rb +++ b/spec/unit/models/runtime/stack_spec.rb @@ -22,6 +22,15 @@ module VCAP::CloudController end end + describe 'uniqueness' do + it 'enforces uniqueness of name' do + existing_stack = Stack.make + expect do + Stack.create(name: existing_stack.name) + end.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do it { is_expected.to validate_presence :name } it { is_expected.to strip_whitespace :name } diff --git a/spec/unit/models/runtime/user_spec.rb b/spec/unit/models/runtime/user_spec.rb index 2b7d15655e2..17451d91581 100644 --- a/spec/unit/models/runtime/user_spec.rb +++ b/spec/unit/models/runtime/user_spec.rb @@ -61,6 +61,15 @@ module VCAP::CloudController end end + describe 'uniqueness' do + it 'enforces uniqueness of guid' do + existing_user = User.make + expect do + User.create(guid: existing_user.guid) + end.to raise_error(Sequel::ValidationFailed, /unique/) + end + end + describe 'Validations' do it { is_expected.to validate_presence :guid } end diff --git a/spec/unit/models/services/service_broker_spec.rb b/spec/unit/models/services/service_broker_spec.rb index a5bbea8e1b1..a02e0f7ee22 100644 --- a/spec/unit/models/services/service_broker_spec.rb +++ b/spec/unit/models/services/service_broker_spec.rb @@ -28,6 +28,15 @@ module VCAP::CloudController end end + describe 'uniqueness' do + it 'enforces uniqueness of name' do + existing_broker = ServiceBroker.make + expect do + ServiceBroker.create(name: existing_broker.name, broker_url: 'http://example.com', auth_username: 'user', auth_password: 'pass') + end.to raise_error(Sequel::ValidationFailed, 'Name must be unique') + end + end + describe 'Validations' do it { is_expected.to validate_presence :name } it { is_expected.to validate_presence :broker_url }