Skip to content

Commit

Permalink
Ensure we pass the right action name for delete object APIs
Browse files Browse the repository at this point in the history
From backbeat routes, all APIs will use a name we only need for
monitoring, but the action name is actually used during the
quota evalutation (and possibly bucket policy as well).

Issue: CLDSRV-590
  • Loading branch information
williamlardier committed Dec 6, 2024
1 parent 5d1b31e commit 597ea26
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
7 changes: 7 additions & 0 deletions lib/api/objectDelete.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ function objectDeleteInternal(authInfo, request, log, isExpiration, cb) {
const reqVersionId = decodedVidResult;
const hasGovernanceBypass = hasGovernanceBypassHeader(request.headers);

// Reassign a specific apiMethod, as monitoring can rely on the
// type of cloudserver instance to determine it comes from Backbeat routes.
// This is also needed for quota evaluation, where "routeBackbeat" cannot
// be used for different operations, such as putObject
// eslint-disable-next-line no-param-reassign
request.apiMethod = reqVersionId ? 'objectDeleteVersion' : 'deleteObject';

const valParams = {
authInfo,
bucketName,
Expand Down
52 changes: 52 additions & 0 deletions tests/unit/api/apiUtils/quotas/quotaUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,32 @@ describe('validateQuotas (buckets)', () => {
});
});

it('should not return QuotaExceeded if quotas are exceeded but operation is creating a delete marker', done => {
const result1 = {
bytesTotal: 150,
};
const result2 = {
bytesTotal: 120,
};
QuotaService._getLatestMetricsCallback.yields(null, result1);
QuotaService._getLatestMetricsCallback.onCall(1).yields(null, result2);

validateQuotas(request, mockBucket, {}, ['objectDelete'], 'objectDelete', 0, false, mockLog, err => {
assert.ifError(err);
assert.strictEqual(QuotaService._getLatestMetricsCallback.calledOnce, true);
assert.strictEqual(QuotaService._getLatestMetricsCallback.calledWith(
'bucket',
'bucketName_1640995200000',
null,
{
action: 'objectDelete',
inflight: 0,
}
), true);
done();
});
});

it('should not return QuotaExceeded if the quotas are exceeded but operation is a delete', done => {
const result1 = {
bytesTotal: 150,
Expand All @@ -140,6 +166,32 @@ describe('validateQuotas (buckets)', () => {
});
});

it('should not return QuotaExceeded if the quotas are exceeded but operation is a delete with version', done => {
const result1 = {
bytesTotal: 150,
};
const result2 = {
bytesTotal: 120,
};
QuotaService._getLatestMetricsCallback.yields(null, result1);
QuotaService._getLatestMetricsCallback.onCall(1).yields(null, result2);

validateQuotas(request, mockBucket, {}, ['objectDelete'], 'objectDeleteVersion', -50, false, mockLog, err => {
assert.ifError(err);
assert.strictEqual(QuotaService._getLatestMetricsCallback.calledOnce, true);
assert.strictEqual(QuotaService._getLatestMetricsCallback.calledWith(
'bucket',
'bucketName_1640995200000',
null,
{
action: 'objectDelete',
inflight: -50,
}
), true);
done();
});
});

it('should decrease the inflights by deleting data, and go below 0 to unblock operations', done => {
const result1 = {
bytesTotal: 150,
Expand Down

0 comments on commit 597ea26

Please sign in to comment.