-
Notifications
You must be signed in to change notification settings - Fork 361
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Apply log rate limit to staging tasks
- The log rate limit from the application web process is applied to the staging task - The staging log rate limit can be customized when creating a build, for consistency with memory and disk limits [#182311441](https://www.pivotaltracker.com/story/show/182311441) Co-authored-by: Rebecca Roberts <[email protected]>
- Loading branch information
1 parent
fc22209
commit 6d3e2e8
Showing
14 changed files
with
188 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
db/migrations/20220718211322_add_staging_log_rate_limit_to_builds.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Sequel.migration do | ||
change do | ||
alter_table :builds do | ||
add_column :staging_log_rate_limit, :Bignum, null: false, default: -1 | ||
end | ||
end | ||
end |
28 changes: 28 additions & 0 deletions
28
lib/cloud_controller/backends/quota_validating_staging_log_rate_limit_calculator.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
module VCAP::CloudController | ||
class QuotaValidatingStagingLogRateLimitCalculator | ||
class SpaceQuotaExceeded < StandardError; end | ||
class OrgQuotaExceeded < StandardError; end | ||
|
||
def get_limit(requested_limit, space, org) | ||
if requested_limit.nil? | ||
requested_limit = -1 | ||
end | ||
|
||
requested_limit = requested_limit.to_i | ||
|
||
space_quota_exceeded!(requested_limit) unless space.has_remaining_log_rate_limit(requested_limit) | ||
org_quota_exceeded!(requested_limit) unless org.has_remaining_log_rate_limit(requested_limit) | ||
requested_limit | ||
end | ||
|
||
private | ||
|
||
def org_quota_exceeded!(staging_log_rate_limit) | ||
raise OrgQuotaExceeded.new("staging requires #{staging_log_rate_limit} bytes per second") | ||
end | ||
|
||
def space_quota_exceeded!(staging_log_rate_limit) | ||
raise SpaceQuotaExceeded.new("staging requires #{staging_log_rate_limit} bytes per second") | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1778,6 +1778,7 @@ | |
app: app_model, | ||
staging_memory_in_mb: 123, | ||
staging_disk_in_mb: 456, | ||
staging_log_rate_limit: 789, | ||
created_by_user_name: 'bob the builder', | ||
created_by_user_guid: user.guid, | ||
created_by_user_email: '[email protected]' | ||
|
@@ -1789,6 +1790,7 @@ | |
app: app_model, | ||
staging_memory_in_mb: 123, | ||
staging_disk_in_mb: 456, | ||
staging_log_rate_limit: 789, | ||
created_at: build.created_at - 1.day, | ||
created_by_user_name: 'bob the builder', | ||
created_by_user_guid: user.guid, | ||
|
@@ -1874,6 +1876,7 @@ | |
'error' => nil, | ||
'staging_memory_in_mb' => 123, | ||
'staging_disk_in_mb' => 456, | ||
'staging_log_rate_limit_bytes_per_second' => 789, | ||
'lifecycle' => { | ||
'type' => 'buildpack', | ||
'data' => { | ||
|
@@ -1902,6 +1905,7 @@ | |
'error' => nil, | ||
'staging_memory_in_mb' => 123, | ||
'staging_disk_in_mb' => 456, | ||
'staging_log_rate_limit_bytes_per_second' => 789, | ||
'lifecycle' => { | ||
'type' => 'buildpack', | ||
'data' => { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,6 +78,7 @@ | |
'state' => 'STAGING', | ||
'staging_memory_in_mb' => 42, | ||
'staging_disk_in_mb' => 42, | ||
'staging_log_rate_limit_bytes_per_second' => -1, | ||
'metadata' => { 'labels' => { 'release' => 'stable', 'seriouseats.com/potato' => 'mashed' }, 'annotations' => { 'potato' => 'idaho' } }, | ||
'error' => nil, | ||
'lifecycle' => { | ||
|
@@ -347,6 +348,7 @@ | |
created_by_user_email: '[email protected]', | ||
staging_memory_in_mb: 123, | ||
staging_disk_in_mb: 456, | ||
staging_log_rate_limit: 234 | ||
) | ||
end | ||
let!(:second_build) do | ||
|
@@ -358,7 +360,8 @@ | |
created_by_user_guid: developer.guid, | ||
created_by_user_email: '[email protected]', | ||
staging_memory_in_mb: 789, | ||
staging_disk_in_mb: 12 | ||
staging_disk_in_mb: 12, | ||
staging_log_rate_limit: 345 | ||
) | ||
end | ||
let(:package) { VCAP::CloudController::PackageModel.make(app_guid: app_model.guid) } | ||
|
@@ -468,6 +471,7 @@ | |
'state' => 'STAGED', | ||
'staging_memory_in_mb' => 123, | ||
'staging_disk_in_mb' => 456, | ||
'staging_log_rate_limit_bytes_per_second' => 234, | ||
'error' => nil, | ||
'lifecycle' => { | ||
'type' => 'buildpack', | ||
|
@@ -496,6 +500,7 @@ | |
'state' => 'STAGED', | ||
'staging_memory_in_mb' => 789, | ||
'staging_disk_in_mb' => 12, | ||
'staging_log_rate_limit_bytes_per_second' => 345, | ||
'error' => nil, | ||
'lifecycle' => { | ||
'type' => 'buildpack', | ||
|
@@ -557,6 +562,7 @@ | |
app: app_model, | ||
staging_memory_in_mb: 123, | ||
staging_disk_in_mb: 456, | ||
staging_log_rate_limit: 789, | ||
created_by_user_name: 'bob the builder', | ||
created_by_user_guid: developer.guid, | ||
created_by_user_email: '[email protected]' | ||
|
@@ -593,6 +599,7 @@ | |
'state' => 'STAGED', | ||
'staging_memory_in_mb' => 123, | ||
'staging_disk_in_mb' => 456, | ||
'staging_log_rate_limit_bytes_per_second' => 789, | ||
'error' => nil, | ||
'lifecycle' => { | ||
'type' => 'buildpack', | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,12 +10,14 @@ module VCAP::CloudController | |
user_audit_info: user_audit_info, | ||
memory_limit_calculator: memory_limit_calculator, | ||
disk_limit_calculator: disk_limit_calculator, | ||
log_rate_limit_calculator: log_rate_limit_calculator, | ||
environment_presenter: environment_builder | ||
) | ||
end | ||
|
||
let(:memory_limit_calculator) { double(:memory_limit_calculator) } | ||
let(:disk_limit_calculator) { double(:disk_limit_calculator) } | ||
let(:log_rate_limit_calculator) { double(:log_rate_limit_calculator) } | ||
let(:environment_builder) { double(:environment_builder) } | ||
let(:user_audit_info) { UserAuditInfo.new(user_email: '[email protected]', user_guid: '1234', user_name: 'charles') } | ||
|
||
|
@@ -24,6 +26,7 @@ module VCAP::CloudController | |
{ | ||
staging_memory_in_mb: staging_memory_in_mb, | ||
staging_disk_in_mb: staging_disk_in_mb, | ||
staging_log_rate_limit_bytes_per_second: staging_log_rate_limit_bytes_per_second, | ||
lifecycle: request_lifecycle, | ||
}.deep_stringify_keys | ||
end | ||
|
@@ -50,7 +53,7 @@ module VCAP::CloudController | |
let(:space) { Space.make } | ||
let(:org) { space.organization } | ||
let(:app) { AppModel.make(space: space) } | ||
let!(:process) { ProcessModel.make(app: app, memory: 8192, disk_quota: 512) } | ||
let!(:process) { ProcessModel.make(app: app, memory: 8192, disk_quota: 512, log_rate_limit: 7168) } | ||
|
||
let(:buildpack_git_url) { 'http://example.com/repo.git' } | ||
let(:stack) { Stack.default } | ||
|
@@ -65,9 +68,11 @@ module VCAP::CloudController | |
let(:stager) { instance_double(Diego::Stager) } | ||
let(:calculated_mem_limit) { 32 } | ||
let(:calculated_staging_disk_in_mb) { 64 } | ||
let(:calculated_staging_log_rate_limit) { 96 } | ||
|
||
let(:staging_memory_in_mb) { 1024 } | ||
let(:staging_disk_in_mb) { 2048 } | ||
let(:staging_log_rate_limit_bytes_per_second) { 3072 } | ||
let(:environment_variables) { 'random string' } | ||
|
||
before do | ||
|
@@ -76,6 +81,7 @@ module VCAP::CloudController | |
allow(stager).to receive(:stage) | ||
allow(memory_limit_calculator).to receive(:get_limit).with(staging_memory_in_mb, space, org).and_return(calculated_mem_limit) | ||
allow(disk_limit_calculator).to receive(:get_limit).with(staging_disk_in_mb).and_return(calculated_staging_disk_in_mb) | ||
allow(log_rate_limit_calculator).to receive(:get_limit).with(staging_log_rate_limit_bytes_per_second, space, org).and_return(calculated_staging_log_rate_limit) | ||
allow(environment_builder).to receive(:build).and_return(environment_variables) | ||
end | ||
|
||
|
@@ -93,6 +99,7 @@ module VCAP::CloudController | |
expect(build.package_guid).to eq(package.guid) | ||
expect(build.staging_memory_in_mb).to eq(calculated_mem_limit) | ||
expect(build.staging_disk_in_mb).to eq(calculated_staging_disk_in_mb) | ||
expect(build.staging_log_rate_limit).to eq(calculated_staging_log_rate_limit) | ||
expect(build.lifecycle_data.to_hash).to eq(lifecycle_data) | ||
expect(build.created_by_user_guid).to eq('1234') | ||
expect(build.created_by_user_name).to eq('charles') | ||
|
@@ -174,6 +181,7 @@ module VCAP::CloudController | |
expect(staging_details.staging_guid).to eq(build.guid) | ||
expect(staging_details.staging_memory_in_mb).to eq(calculated_mem_limit) | ||
expect(staging_details.staging_disk_in_mb).to eq(calculated_staging_disk_in_mb) | ||
expect(staging_details.staging_log_rate_limit_bytes_per_second).to eq(calculated_staging_log_rate_limit) | ||
expect(staging_details.environment_variables).to eq(environment_variables) | ||
expect(staging_details.lifecycle).to eq(lifecycle) | ||
expect(staging_details.isolation_segment).to be_nil | ||
|
@@ -210,6 +218,20 @@ module VCAP::CloudController | |
end | ||
end | ||
|
||
context 'when staging log rate limit is not specified in the message' do | ||
before do | ||
allow(log_rate_limit_calculator).to receive(:get_limit).with(process.log_rate_limit, space, org).and_return(process.log_rate_limit) | ||
end | ||
let(:staging_log_rate_limit_bytes_per_second) { nil } | ||
|
||
it 'uses the app web process log rate limit for staging log rate limit' do | ||
expect(log_rate_limit_calculator).to receive(:get_limit).with(process.log_rate_limit, space, org) | ||
|
||
build = action.create_and_stage(package: package, lifecycle: lifecycle) | ||
expect(build.staging_log_rate_limit).to eq(process.log_rate_limit) | ||
end | ||
end | ||
|
||
describe 'isolation segments' do | ||
let(:assigner) { VCAP::CloudController::IsolationSegmentAssign.new } | ||
let(:isolation_segment_model) { VCAP::CloudController::IsolationSegmentModel.make } | ||
|
68 changes: 68 additions & 0 deletions
68
.../lib/cloud_controller/backends/quota_validating_staging_log_rate_limit_calculator_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
require 'spec_helper' | ||
require 'cloud_controller/backends/quota_validating_staging_log_rate_limit_calculator' | ||
|
||
module VCAP::CloudController | ||
RSpec.describe QuotaValidatingStagingLogRateLimitCalculator do | ||
let(:calculator) { QuotaValidatingStagingLogRateLimitCalculator.new } | ||
|
||
describe '#get_limit' do | ||
let(:space_quota_limit) { 200 } | ||
let(:org_quota_limit) { 200 } | ||
let(:requested_limit) { 100 } | ||
let(:space) { Space.make } | ||
let(:org) { space.organization } | ||
let(:space_quota_definition) { SpaceQuotaDefinition.make(organization: org, log_rate_limit: space_quota_limit) } | ||
let(:quota_definition) { QuotaDefinition.make(log_rate_limit: org_quota_limit) } | ||
|
||
before do | ||
space.space_quota_definition = space_quota_definition | ||
org.quota_definition = quota_definition | ||
space.save | ||
org.save | ||
end | ||
|
||
it 'uses the requested_limit' do | ||
limit = calculator.get_limit(requested_limit, space, org) | ||
expect(limit).to eq(requested_limit) | ||
end | ||
|
||
context 'when the requested_limit is passed as an integer string' do | ||
let(:requested_limit) { '100' } | ||
|
||
it 'uses the requested_limit' do | ||
limit = calculator.get_limit(requested_limit, space, org) | ||
expect(limit).to eq(100) | ||
end | ||
end | ||
|
||
context 'when the requested_limit exceeds the space quota' do | ||
let(:space_quota_limit) { requested_limit - 1 } | ||
|
||
it 'raises a SpaceQuotaExceeded error' do | ||
expect { | ||
calculator.get_limit(requested_limit, space, org) | ||
}.to raise_error(QuotaValidatingStagingLogRateLimitCalculator::SpaceQuotaExceeded, /staging requires 100 bytes per second/) | ||
end | ||
end | ||
|
||
context 'when the requested_limit exceeds the org quota' do | ||
let(:org_quota_limit) { requested_limit - 1 } | ||
|
||
it 'raises a OrgQuotaExceeded error' do | ||
expect { | ||
calculator.get_limit(requested_limit, space, org) | ||
}.to raise_error(QuotaValidatingStagingLogRateLimitCalculator::OrgQuotaExceeded, /staging requires 100 bytes per second/) | ||
end | ||
end | ||
|
||
context 'when the requested_limit is nil' do | ||
let(:requested_limit) { nil } | ||
|
||
it 'uses no limit' do | ||
limit = calculator.get_limit(requested_limit, space, org) | ||
expect(limit).to eq(-1) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.