Skip to content

Commit b915704

Browse files
committed
chore: validate both dep graphs are present in binaries tests
There is a possible race condition that can cause test flakiness when testing the binaries deployment with two dep graphs. The reason is as follows: A workload is available from Homebase when at least 1 dependency graph and its workload metadata are stored. Currently we don't do a check that asserts that both dependency graphs of a deployment are stored and the tests may fail. This fix ensures that both graphs are stored before proceeding with the tests.
1 parent 14f9560 commit b915704

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

test/helpers/kubernetes-upstream.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import {
44
IWorkloadLocator,
55
IWorkloadMetadata,
66
} from '../../src/transmitter/types';
7-
import { WorkloadLocatorValidator, WorkloadMetadataValidator } from './types';
7+
import {
8+
WorkloadLocatorValidator,
9+
WorkloadMetadataValidator,
10+
DepGraphsValidator,
11+
} from './types';
812
import config = require('../../src/common/config');
913

1014
const UPSTREAM_POLLING_CONFIGURATION = {
@@ -21,6 +25,25 @@ export async function getUpstreamResponseBody(
2125
return responseBody;
2226
}
2327

28+
export async function validateUpstreamStoredDepGraphs(
29+
validatorFn: DepGraphsValidator,
30+
relativeUrl: string,
31+
remainingChecks: number = UPSTREAM_POLLING_CONFIGURATION.MAXIMUM_REQUESTS,
32+
): Promise<boolean> {
33+
while (remainingChecks > 0) {
34+
console.log(`Pinging upstream for existing data (${remainingChecks} checks remaining)...`);
35+
const responseBody = await getUpstreamResponseBody(relativeUrl);
36+
const depGraphs = responseBody?.dependencyGraphResults;
37+
const result = validatorFn(depGraphs);
38+
if (result) {
39+
return true;
40+
}
41+
await sleep(UPSTREAM_POLLING_CONFIGURATION.WAIT_BETWEEN_REQUESTS_MS);
42+
remainingChecks--;
43+
}
44+
return false;
45+
}
46+
2447
export async function validateUpstreamStoredData(
2548
validatorFn: WorkloadLocatorValidator,
2649
relativeUrl: string,

test/helpers/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import {
33
IWorkloadMetadata,
44
} from '../../src/transmitter/types';
55

6+
export type DepGraphsValidator = (depGraphs?: {
7+
[name: string]: object;
8+
}) => boolean;
9+
610
export type WorkloadLocatorValidator = (
711
workloads: IWorkloadLocator[] | undefined,
812
) => boolean;

test/integration/kubernetes.test.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
validateUpstreamStoredData,
99
validateUpstreamStoredMetadata,
1010
getUpstreamResponseBody,
11+
validateUpstreamStoredDepGraphs,
1112
} from '../helpers/kubernetes-upstream';
1213
import {
1314
validateSecureConfiguration,
@@ -133,7 +134,7 @@ tap.test('snyk-monitor sends data to kubernetes-upstream', async (t) => {
133134
});
134135

135136
tap.test('snyk-monitor sends binary hashes to kubernetes-upstream after adding another deployment', async (t) => {
136-
t.plan(9);
137+
t.plan(10);
137138

138139
const deploymentName = 'binaries-deployment';
139140
const namespace = 'services';
@@ -143,16 +144,32 @@ tap.test('snyk-monitor sends binary hashes to kubernetes-upstream after adding a
143144
await kubectl.applyK8sYaml('./test/fixtures/binaries-deployment.yaml');
144145
console.log(`Begin polling kubernetes-upstream for the expected workloads with integration ID ${integrationId}...`);
145146

146-
const validatorFn: WorkloadLocatorValidator = (workloads) => {
147+
const workloadLocatorValidatorFn: WorkloadLocatorValidator = (workloads) => {
147148
return workloads !== undefined &&
148149
workloads.find((workload) => workload.name === deploymentName &&
149150
workload.type === WorkloadKind.Deployment) !== undefined;
150151
};
151152

153+
const depGraphsValidatorFn = (depGraphs?: {
154+
node?: object;
155+
openjdk?: object;
156+
}) => {
157+
return (
158+
depGraphs !== undefined &&
159+
depGraphs.node !== undefined &&
160+
depGraphs.openjdk !== undefined
161+
);
162+
};
163+
152164
const testResult = await validateUpstreamStoredData(
153-
validatorFn, `api/v2/workloads/${integrationId}/${clusterName}/${namespace}`);
165+
workloadLocatorValidatorFn, `api/v2/workloads/${integrationId}/${clusterName}/${namespace}`);
154166
t.ok(testResult, 'snyk-monitor sent expected data to kubernetes-upstream in the expected timeframe');
155167

168+
const depGraphsResult = await validateUpstreamStoredDepGraphs(
169+
depGraphsValidatorFn, `api/v1/dependency-graphs/${integrationId}/${clusterName}/${namespace}/${deploymentType}/${deploymentName}`
170+
);
171+
t.ok(depGraphsResult, 'snyk-monitor sent expected dependency graphs to kubernetes-upstream in the expected timeframe');
172+
156173
const depGraphResult = await getUpstreamResponseBody(
157174
`api/v1/dependency-graphs/${integrationId}/${clusterName}/${namespace}/${deploymentType}/${deploymentName}`);
158175
t.ok('dependencyGraphResults' in depGraphResult,

0 commit comments

Comments
 (0)