Skip to content

Commit 02c07a2

Browse files
committed
fix: refactor informer handlers code to improve readability
Several big changes: - code branches less now and the cluster monitoring is separate from namespace monitoring - we ensure we track namespaces in the cluster so we have the annotations for namespace annotated import - informer configuration is in a separate file, because the object holding the config is now too big - move any workload-related functions to their respective handler file
1 parent 51246b1 commit 02c07a2

File tree

9 files changed

+689
-389
lines changed

9 files changed

+689
-389
lines changed

src/state.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { KubernetesObject, V1Namespace } from '@kubernetes/client-node';
22
import LruCache from 'lru-cache';
33

44
import { config } from './common/config';
5+
import { extractNamespaceName } from './supervisor/watchers';
56

67
const imagesLruCacheOptions: LruCache.Options<string, string> = {
78
// limit cache size so we don't exceed memory limit
@@ -113,6 +114,16 @@ export function kubernetesObjectToWorkloadAlreadyScanned(
113114
return undefined;
114115
}
115116

117+
export function storeNamespace(namespace: V1Namespace): void {
118+
const namespaceName = extractNamespaceName(namespace);
119+
state.watchedNamespaces[namespaceName] = namespace;
120+
}
121+
122+
export function deleteNamespace(namespace: V1Namespace): void {
123+
const namespaceName = extractNamespaceName(namespace);
124+
delete state.watchedNamespaces[namespaceName];
125+
}
126+
116127
export const state = {
117128
shutdownInProgress: false,
118129
imagesAlreadyScanned: new LruCache<string, string>(imagesLruCacheOptions),

src/supervisor/watchers/handlers/cron-job.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import {
33
V1CronJobList,
44
V1beta1CronJob,
55
V1beta1CronJobList,
6+
BatchV1Api,
7+
BatchV1beta1Api,
68
} from '@kubernetes/client-node';
79
import { deleteWorkload, trimWorkload } from './workload';
810
import { WorkloadKind } from '../../types';
@@ -15,6 +17,8 @@ import {
1517
deleteWorkloadImagesAlreadyScanned,
1618
kubernetesObjectToWorkloadAlreadyScanned,
1719
} from '../../../state';
20+
import { logger } from '../../../common/logger';
21+
import { retryKubernetesApiRequest } from '../../kuberenetes-api-wrappers';
1822

1923
export async function paginatedNamespacedCronJobList(
2024
namespace: string,
@@ -128,3 +132,91 @@ export async function cronJobWatchHandler(
128132
workloadName,
129133
);
130134
}
135+
136+
export async function isNamespacedCronJobSupported(
137+
workloadKind: WorkloadKind,
138+
namespace: string,
139+
client: BatchV1Api | BatchV1beta1Api,
140+
): Promise<boolean> {
141+
try {
142+
const pretty = undefined;
143+
const allowWatchBookmarks = undefined;
144+
const continueToken = undefined;
145+
const fieldSelector = undefined;
146+
const labelSelector = undefined;
147+
const limit = 1; // Try to grab only a single object
148+
const resourceVersion = undefined; // List anything in the cluster
149+
const resourceVersionMatch = undefined;
150+
const timeoutSeconds = 10; // Don't block the snyk-monitor indefinitely
151+
const attemptedApiCall = await retryKubernetesApiRequest(() =>
152+
client.listNamespacedCronJob(
153+
namespace,
154+
pretty,
155+
allowWatchBookmarks,
156+
continueToken,
157+
fieldSelector,
158+
labelSelector,
159+
limit,
160+
resourceVersion,
161+
resourceVersionMatch,
162+
timeoutSeconds,
163+
),
164+
);
165+
return (
166+
attemptedApiCall !== undefined &&
167+
attemptedApiCall.response !== undefined &&
168+
attemptedApiCall.response.statusCode !== undefined &&
169+
attemptedApiCall.response.statusCode >= 200 &&
170+
attemptedApiCall.response.statusCode < 300
171+
);
172+
} catch (error) {
173+
logger.debug(
174+
{ error, workloadKind: workloadKind },
175+
'Failed on Kubernetes API call to list CronJob or v1beta1 CronJob',
176+
);
177+
return false;
178+
}
179+
}
180+
181+
export async function isClusterCronJobSupported(
182+
workloadKind: WorkloadKind,
183+
client: BatchV1Api | BatchV1beta1Api,
184+
): Promise<boolean> {
185+
try {
186+
const pretty = undefined;
187+
const allowWatchBookmarks = undefined;
188+
const continueToken = undefined;
189+
const fieldSelector = undefined;
190+
const labelSelector = undefined;
191+
const limit = 1; // Try to grab only a single object
192+
const resourceVersion = undefined; // List anything in the cluster
193+
const resourceVersionMatch = undefined;
194+
const timeoutSeconds = 10; // Don't block the snyk-monitor indefinitely
195+
const attemptedApiCall = await retryKubernetesApiRequest(() =>
196+
client.listCronJobForAllNamespaces(
197+
allowWatchBookmarks,
198+
continueToken,
199+
fieldSelector,
200+
labelSelector,
201+
limit,
202+
pretty,
203+
resourceVersion,
204+
resourceVersionMatch,
205+
timeoutSeconds,
206+
),
207+
);
208+
return (
209+
attemptedApiCall !== undefined &&
210+
attemptedApiCall.response !== undefined &&
211+
attemptedApiCall.response.statusCode !== undefined &&
212+
attemptedApiCall.response.statusCode >= 200 &&
213+
attemptedApiCall.response.statusCode < 300
214+
);
215+
} catch (error) {
216+
logger.debug(
217+
{ error, workloadKind: workloadKind },
218+
'Failed on Kubernetes API call to list CronJob or v1beta1 CronJob',
219+
);
220+
return false;
221+
}
222+
}

src/supervisor/watchers/handlers/deployment-config.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
deleteWorkloadImagesAlreadyScanned,
1414
kubernetesObjectToWorkloadAlreadyScanned,
1515
} from '../../../state';
16+
import { retryKubernetesApiRequest } from '../../kuberenetes-api-wrappers';
17+
import { logger } from '../../../common/logger';
1618

1719
export async function paginatedNamespacedDeploymentConfigList(
1820
namespace: string,
@@ -47,6 +49,7 @@ export async function paginatedNamespacedDeploymentConfigList(
4749
fieldSelector,
4850
labelSelector,
4951
limit,
52+
// TODO: Why any?
5053
) as any,
5154
);
5255
}
@@ -127,3 +130,84 @@ export async function deploymentConfigWatchHandler(
127130
workloadName,
128131
);
129132
}
133+
134+
export async function isNamespacedDeploymentConfigSupported(
135+
namespace: string,
136+
): Promise<boolean> {
137+
try {
138+
const pretty = undefined;
139+
const continueToken = undefined;
140+
const fieldSelector = undefined;
141+
const labelSelector = undefined;
142+
const limit = 1; // Try to grab only a single object
143+
const resourceVersion = undefined; // List anything in the cluster
144+
const timeoutSeconds = 10; // Don't block the snyk-monitor indefinitely
145+
const attemptedApiCall = await retryKubernetesApiRequest(() =>
146+
k8sApi.customObjectsClient.listNamespacedCustomObject(
147+
'apps.openshift.io',
148+
'v1',
149+
namespace,
150+
'deploymentconfigs',
151+
pretty,
152+
continueToken,
153+
fieldSelector,
154+
labelSelector,
155+
limit,
156+
resourceVersion,
157+
timeoutSeconds,
158+
),
159+
);
160+
return (
161+
attemptedApiCall !== undefined &&
162+
attemptedApiCall.response !== undefined &&
163+
attemptedApiCall.response.statusCode !== undefined &&
164+
attemptedApiCall.response.statusCode >= 200 &&
165+
attemptedApiCall.response.statusCode < 300
166+
);
167+
} catch (error) {
168+
logger.debug(
169+
{ error, workloadKind: WorkloadKind.DeploymentConfig },
170+
'Failed on Kubernetes API call to list namespaced DeploymentConfig',
171+
);
172+
return false;
173+
}
174+
}
175+
176+
export async function isClusterDeploymentConfigSupported(): Promise<boolean> {
177+
try {
178+
const pretty = undefined;
179+
const continueToken = undefined;
180+
const fieldSelector = undefined;
181+
const labelSelector = undefined;
182+
const limit = 1; // Try to grab only a single object
183+
const resourceVersion = undefined; // List anything in the cluster
184+
const timeoutSeconds = 10; // Don't block the snyk-monitor indefinitely
185+
const attemptedApiCall = await retryKubernetesApiRequest(() =>
186+
k8sApi.customObjectsClient.listClusterCustomObject(
187+
'apps.openshift.io',
188+
'v1',
189+
'deploymentconfigs',
190+
pretty,
191+
continueToken,
192+
fieldSelector,
193+
labelSelector,
194+
limit,
195+
resourceVersion,
196+
timeoutSeconds,
197+
),
198+
);
199+
return (
200+
attemptedApiCall !== undefined &&
201+
attemptedApiCall.response !== undefined &&
202+
attemptedApiCall.response.statusCode !== undefined &&
203+
attemptedApiCall.response.statusCode >= 200 &&
204+
attemptedApiCall.response.statusCode < 300
205+
);
206+
} catch (error) {
207+
logger.debug(
208+
{ error, workloadKind: WorkloadKind.DeploymentConfig },
209+
'Failed on Kubernetes API call to list cluster DeploymentConfig',
210+
);
211+
return false;
212+
}
213+
}

0 commit comments

Comments
 (0)