diff --git a/app/controllers/runtime/organizations_controller.rb b/app/controllers/runtime/organizations_controller.rb index b004a25615b..3d2ef17cfd9 100644 --- a/app/controllers/runtime/organizations_controller.rb +++ b/app/controllers/runtime/organizations_controller.rb @@ -73,6 +73,18 @@ def before_update(org) end end + if request_attrs['quota_definition_guid'] + quota = QuotaDefinition.first(guid: request_attrs['quota_definition_guid']) + if quota.log_rate_limit != QuotaDefinition::UNLIMITED + affected_processes = org.processes_dataset + unless affected_processes.where(log_rate_limit: ProcessModel::UNLIMITED_LOG_RATE).empty? + raise CloudController::Errors::ApiError.new_from_details( + 'UnprocessableEntity', + 'Current usage exceeds new quota values. This org currently contains apps running with an unlimited log rate limit.') + end + end + end + super(org) end diff --git a/app/controllers/runtime/space_quota_definitions_controller.rb b/app/controllers/runtime/space_quota_definitions_controller.rb index 306bb0ba604..90615174c63 100644 --- a/app/controllers/runtime/space_quota_definitions_controller.rb +++ b/app/controllers/runtime/space_quota_definitions_controller.rb @@ -25,6 +25,23 @@ def self.translate_validation_exception(e, attributes) end end + def before_update(quota) + if request_attrs['space'] && quota.log_rate_limit != QuotaDefinition::UNLIMITED + affected_processes = Space.dataset. + join(:apps, space_guid: :guid). + join(:processes, app_guid: :guid). + where(Sequel[:spaces][:guid] => request_attrs['space']) + + unless affected_processes.where(log_rate_limit: ProcessModel::UNLIMITED_LOG_RATE).empty? + raise CloudController::Errors::ApiError.new_from_details( + 'UnprocessableEntity', + 'Current usage exceeds new quota values. This space currently contains apps running with an unlimited log rate limit.') + end + end + + super(quota) + end + def delete(guid) do_delete(find_guid_and_validate_access(:delete, guid)) end diff --git a/spec/request/v2/organizations_spec.rb b/spec/request/v2/organizations_spec.rb index 4b296beb9ae..7822405b6af 100644 --- a/spec/request/v2/organizations_spec.rb +++ b/spec/request/v2/organizations_spec.rb @@ -99,4 +99,28 @@ ) end end + + describe 'PUT /v2/organizations/:guid' do + context 'when the quota has a finite log rate limit and there are apps with unlimited log rates' do + let(:admin_header) { headers_for(user, scopes: %w(cloud_controller.admin)) } + let(:org_quota) { VCAP::CloudController::QuotaDefinition.make(log_rate_limit: 100) } + + let(:params) do + { + quota_definition_guid: org_quota.guid + } + end + + let!(:space) { VCAP::CloudController::Space.make(organization: org) } + let!(:app_model) { VCAP::CloudController::AppModel.make(name: 'name1', space: space) } + let!(:process_model) { VCAP::CloudController::ProcessModel.make(app: app_model, log_rate_limit: -1) } + + it 'returns 422' do + put "/v2/organizations/#{org.guid}", params.to_json, admin_header + expect(last_response).to have_status_code(422) + expect(decoded_response['error_code']).to eq('CF-UnprocessableEntity') + expect(decoded_response['description']).to eq('Current usage exceeds new quota values. This org currently contains apps running with an unlimited log rate limit.') + end + end + end end diff --git a/spec/request/v2/space_quota_definitions_spec.rb b/spec/request/v2/space_quota_definitions_spec.rb new file mode 100644 index 00000000000..37ca5f1f85e --- /dev/null +++ b/spec/request/v2/space_quota_definitions_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +RSpec.describe 'SpaceQuotaDefinitions' do + let(:user) { VCAP::CloudController::User.make } + let(:org) { VCAP::CloudController::Organization.make } + + describe 'PUT /v2/space_quota_definitions/guid/spaces/space_guid' do + context 'when the quota has a finite log rate limit and there are apps with unlimited log rates' do + let(:admin_header) { headers_for(user, scopes: %w(cloud_controller.admin)) } + let(:space_quota) { VCAP::CloudController::SpaceQuotaDefinition.make(organization: org, log_rate_limit: 100) } + + let!(:space) { VCAP::CloudController::Space.make(organization: org) } + let!(:app_model) { VCAP::CloudController::AppModel.make(name: 'name1', space: space) } + let!(:process_model) { VCAP::CloudController::ProcessModel.make(app: app_model, log_rate_limit: -1) } + + it 'returns 422' do + put "/v2/space_quota_definitions/#{space_quota.guid}/spaces/#{space.guid}", nil, admin_header + expect(last_response).to have_status_code(422) + expect(decoded_response['error_code']).to eq('CF-UnprocessableEntity') + expect(decoded_response['description']).to eq('Current usage exceeds new quota values. This space currently contains apps running with an unlimited log rate limit.') + end + end + end +end