Skip to content

Commit

Permalink
[#1211] graceful handling of empty project list for gcp filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
4upz committed Jan 31, 2024
1 parent 6bcf920 commit 0801c4d
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 0 deletions.
78 changes: 78 additions & 0 deletions packages/gcp/src/__tests__/BillingExportTable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import {
mockQueryResultsCloudSQLSSDComputeEngineDataFlowHDD,
mockQueryResultsComputeEngineRam,
mockQueryResultsForProjectFilter,
mockQueryResultsForProjectFilterEmpty,
mockQueryResultsForProjectFilterError,
mockQueryResultsGPUMachineTypes,
mockQueryResultsUnknownAndCloudSQLCompute,
mockQueryResultsUnknownUsages,
Expand Down Expand Up @@ -1582,6 +1584,82 @@ describe('GCP BillingExportTable Service', () => {
expect(result).toEqual(expectedResult)
})

it('ignores empty project filters', async () => {
setConfig({
GCP: {
projects: [],
},
})

mockJob.getQueryResults.mockResolvedValue(
mockQueryResultsForProjectFilterEmpty,
)

const billingExportTableService = new BillingExportTable(
new ComputeEstimator(),
new StorageEstimator(GCP_CLOUD_CONSTANTS.SSDCOEFFICIENT),
new StorageEstimator(GCP_CLOUD_CONSTANTS.HDDCOEFFICIENT),
new NetworkingEstimator(GCP_CLOUD_CONSTANTS.NETWORKING_COEFFICIENT),
new MemoryEstimator(GCP_CLOUD_CONSTANTS.MEMORY_COEFFICIENT),
new UnknownEstimator(GCP_CLOUD_CONSTANTS.ESTIMATE_UNKNOWN_USAGE_BY),
new EmbodiedEmissionsEstimator(
GCP_CLOUD_CONSTANTS.SERVER_EXPECTED_LIFESPAN,
),
new BigQuery(),
)

await billingExportTableService.getEstimates(startDate, endDate, grouping)

const expectedWhereFilter = `AND project.id IN`

expect(mockCreateQueryJob).toHaveBeenCalledWith(
expect.objectContaining({
query: expect.not.stringContaining(expectedWhereFilter),
}),
)
})

it('logs warning and ignores incorrectly formatted projects', async () => {
setConfig({
GCP: {
projects: undefined,
},
})

mockJob.getQueryResults.mockResolvedValue(
mockQueryResultsForProjectFilterError,
)

const loggerSpy = jest.spyOn(Logger.prototype, 'warn')

const billingExportTableService = new BillingExportTable(
new ComputeEstimator(),
new StorageEstimator(GCP_CLOUD_CONSTANTS.SSDCOEFFICIENT),
new StorageEstimator(GCP_CLOUD_CONSTANTS.HDDCOEFFICIENT),
new NetworkingEstimator(GCP_CLOUD_CONSTANTS.NETWORKING_COEFFICIENT),
new MemoryEstimator(GCP_CLOUD_CONSTANTS.MEMORY_COEFFICIENT),
new UnknownEstimator(GCP_CLOUD_CONSTANTS.ESTIMATE_UNKNOWN_USAGE_BY),
new EmbodiedEmissionsEstimator(
GCP_CLOUD_CONSTANTS.SERVER_EXPECTED_LIFESPAN,
),
new BigQuery(),
)

await billingExportTableService.getEstimates(startDate, endDate, grouping)

const expectedWhereFilter = `AND project.id IN`

expect(mockCreateQueryJob).toHaveBeenCalledWith(
expect.objectContaining({
query: expect.not.stringContaining(expectedWhereFilter),
}),
)

expect(loggerSpy).toHaveBeenCalledWith(
'Configured list of projects is invalid. Projects must be a list of objects containing project IDs. Ignoring project filter...',
)
})

it('logs warning and ignores tags with incorrect prefix', async () => {
// given
const badTagName = 'beetlejuice:environment'
Expand Down
52 changes: 52 additions & 0 deletions packages/gcp/src/__tests__/fixtures/bigQuery.fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1005,3 +1005,55 @@ export const mockQueryResultsForProjectFilter: any[][] = [
},
],
]

export const mockQueryResultsForProjectFilterError: any[][] = [
[
{
timestamp: bigQueryDateOne,
accountId: accountId,
accountName: accountName,
region: 'us-east1',
serviceName: 'App Engine',
usageType: 'Cloud Datastore Storage',
usageUnit: 'byte-seconds',
usageAmount: 2.83e16,
cost: 5,
machineType: null,
tags: 'environment: dev',
labels: 'project: ccf',
},
{
timestamp: bigQueryDateOne,
accountId: accountId,
accountName: accountName,
region: 'us-east1',
serviceName: 'Compute Engine',
usageType: 'Compute optimized Core running in Americas',
usageUnit: 'seconds',
usageAmount: 80000,
cost: 7,
machineType: null,
tags: 'environment: prod',
projectLabels: 'team: thoughtworks',
},
],
]

export const mockQueryResultsForProjectFilterEmpty: any[][] = [
[
{
timestamp: bigQueryDateOne,
accountId: accountId,
accountName: accountName,
region: 'us-east1',
serviceName: 'App Engine',
usageType: 'Cloud Datastore Storage',
usageUnit: 'byte-seconds',
usageAmount: 2.83e16,
cost: 5,
machineType: null,
tags: 'environment: dev',
labels: 'project: ccf',
},
],
]
3 changes: 3 additions & 0 deletions packages/gcp/src/lib/BillingExportTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,9 @@ export default class BillingExportTable {
)
return ''
}

if (!projects.length) return ''

const projectIdList = projects
.map((project) => `'${project.id}'`)
.join(', ')
Expand Down

0 comments on commit 0801c4d

Please sign in to comment.