Skip to content

Commit b34b1c0

Browse files
authored
Merge pull request #779 from snyk/feat/send_cluster_metadata_on_startup
[RUN-1560] Send cluster metadata on start up
2 parents 4a21511 + 288d88f commit b34b1c0

File tree

5 files changed

+91
-9
lines changed

5 files changed

+91
-9
lines changed

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { logger } from './common/logger';
88
import { currentClusterName } from './supervisor/cluster';
99
import { beginWatchingWorkloads } from './supervisor/watchers';
1010
import { loadAndSendWorkloadEventsPolicy } from './common/policy';
11+
import { sendClusterMetadata } from './transmitter';
1112

1213
process.on('uncaughtException', (err) => {
1314
if (state.shutdownInProgress) {
@@ -62,6 +63,7 @@ cleanUpTempStorage();
6263

6364
// Allow running in an async context
6465
setImmediate(async function setUpAndMonitor(): Promise<void> {
66+
await sendClusterMetadata();
6567
await loadAndSendWorkloadEventsPolicy();
6668
await monitor();
6769
});

src/transmitter/index.ts

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import {
1515
IRequestError,
1616
ScanResultsPayload,
1717
IDependencyGraphPayload,
18-
WorkloadEventsPolicyPayload,
18+
IWorkloadEventsPolicyPayload,
19+
IClusterMetadataPayload,
1920
} from './types';
2021
import { getProxyAgent } from './proxy';
2122

@@ -85,8 +86,7 @@ export async function sendScanResults(
8586
): Promise<boolean> {
8687
for (const payload of payloads) {
8788
// Intentionally removing scan results as they would be too big to log
88-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
89-
const { scanResults, ...payloadWithoutScanResults } = payload;
89+
const payloadWithoutScanResults = { ...payload, scanResults: undefined };
9090
try {
9191
const request: HomebaseRequest = {
9292
method: 'post',
@@ -148,7 +148,7 @@ export async function sendWorkloadMetadata(
148148
}
149149

150150
export async function sendWorkloadEventsPolicy(
151-
payload: WorkloadEventsPolicyPayload,
151+
payload: IWorkloadEventsPolicyPayload,
152152
): Promise<void> {
153153
try {
154154
logger.info(
@@ -296,3 +296,53 @@ function shouldRetryRequest(
296296

297297
return false;
298298
}
299+
300+
export async function sendClusterMetadata(): Promise<void> {
301+
const payload: IClusterMetadataPayload = {
302+
userLocator: config.INTEGRATION_ID,
303+
cluster: config.CLUSTER_NAME,
304+
agentId: config.AGENT_ID,
305+
version: config.MONITOR_VERSION,
306+
namespace: config.NAMESPACE,
307+
};
308+
309+
try {
310+
logger.info(
311+
{
312+
userLocator: payload.userLocator,
313+
cluster: payload.cluster,
314+
agentId: payload.agentId,
315+
},
316+
'attempting to send cluster metadata',
317+
);
318+
319+
const { response, attempt } = await retryRequest(
320+
'post',
321+
`${upstreamUrl}/api/v1/cluster`,
322+
payload,
323+
);
324+
if (!isSuccessStatusCode(response.statusCode)) {
325+
throw new Error(`${response.statusCode} ${response.statusMessage}`);
326+
}
327+
328+
logger.info(
329+
{
330+
userLocator: payload.userLocator,
331+
cluster: payload.cluster,
332+
agentId: payload.agentId,
333+
attempt,
334+
},
335+
'cluster metadata sent upstream successfully',
336+
);
337+
} catch (error) {
338+
logger.error(
339+
{
340+
error,
341+
userLocator: payload.userLocator,
342+
cluster: payload.cluster,
343+
agentId: payload.agentId,
344+
},
345+
'could not send cluster metadata',
346+
);
347+
}
348+
}

src/transmitter/payload.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
IKubernetesMonitorMetadata,
1313
ScanResultsPayload,
1414
IDependencyGraphPayload,
15-
WorkloadEventsPolicyPayload,
15+
IWorkloadEventsPolicyPayload,
1616
} from './types';
1717

1818
export function constructDepGraph(
@@ -135,7 +135,7 @@ export function constructDeleteWorkload(
135135

136136
export function constructWorkloadEventsPolicy(
137137
policy: string,
138-
): WorkloadEventsPolicyPayload {
138+
): IWorkloadEventsPolicyPayload {
139139
return {
140140
policy,
141141
userLocator: config.INTEGRATION_ID,

src/transmitter/types.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,21 @@ export interface IDeleteWorkloadPayload {
6363
agentId: string;
6464
}
6565

66-
export interface WorkloadEventsPolicyPayload {
66+
export interface IWorkloadEventsPolicyPayload {
6767
userLocator: string;
6868
cluster: string;
6969
agentId: string;
7070
policy: string;
7171
}
7272

73+
export interface IClusterMetadataPayload {
74+
userLocator: string;
75+
cluster: string;
76+
agentId: string;
77+
version: string;
78+
namespace?: string;
79+
}
80+
7381
export interface IWorkload {
7482
type: string;
7583
name: string;

test/system/kind.spec.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,11 @@ test('Kubernetes-Monitor with KinD', async (jestDoneCallback) => {
9797
.times(1)
9898
.reply(
9999
200,
100-
(uri, requestBody: transmitterTypes.WorkloadEventsPolicyPayload) => {
100+
(uri, requestBody: transmitterTypes.IWorkloadEventsPolicyPayload) => {
101101
try {
102102
expect(
103103
requestBody,
104-
).toEqual<transmitterTypes.WorkloadEventsPolicyPayload>({
104+
).toEqual<transmitterTypes.IWorkloadEventsPolicyPayload>({
105105
agentId: expect.any(String),
106106
cluster: expect.any(String),
107107
userLocator: expect.any(String),
@@ -113,6 +113,28 @@ test('Kubernetes-Monitor with KinD', async (jestDoneCallback) => {
113113
},
114114
);
115115

116+
nock('https://kubernetes-upstream.snyk.io')
117+
.post('/api/v1/cluster')
118+
.times(1)
119+
.reply(
120+
200,
121+
(uri, requestBody: transmitterTypes.IClusterMetadataPayload) => {
122+
try {
123+
expect(requestBody).toEqual<
124+
Partial<transmitterTypes.IClusterMetadataPayload>
125+
>({
126+
agentId: expect.any(String),
127+
cluster: expect.any(String),
128+
userLocator: expect.any(String),
129+
// also should have version here but due to test limitation it is undefined
130+
// as it is injected as an environment variable via the Helm chart
131+
});
132+
} catch (error) {
133+
jestDoneCallback(error);
134+
}
135+
},
136+
);
137+
116138
// Setup nocks
117139
nock(/https\:\/\/127\.0\.0\.1\:\d+/, { allowUnmocked: true })
118140
.get('/api/v1/namespaces')

0 commit comments

Comments
 (0)