1- import { parse } from 'url' ;
21import { queue } from 'async' ;
32import needle from 'needle' ;
43import sleep from 'sleep-promise' ;
@@ -17,6 +16,7 @@ import {
1716 IDependencyGraphPayload ,
1817 IWorkloadEventsPolicyPayload ,
1918 IClusterMetadataPayload ,
19+ IRuntimeDataPayload ,
2020} from './types' ;
2121import { getProxyAgent } from './proxy' ;
2222
@@ -27,24 +27,29 @@ interface KubernetesUpstreamRequest {
2727 | IDependencyGraphPayload
2828 | ScanResultsPayload
2929 | IWorkloadMetadataPayload
30- | IDeleteWorkloadPayload ;
30+ | IDeleteWorkloadPayload
31+ | IClusterMetadataPayload
32+ | IRuntimeDataPayload ;
3133}
3234
3335const upstreamUrl =
3436 config . INTEGRATION_API || config . DEFAULT_KUBERNETES_UPSTREAM_URL ;
3537
36- let agent = new HttpAgent ( {
38+ let httpAgent = new HttpAgent ( {
3739 keepAlive : true ,
3840} ) ;
3941
40- if ( parse ( upstreamUrl ) . protocol ?. startsWith ( 'https' ) ) {
41- agent = new HttpsAgent ( {
42- keepAlive : true ,
43- } ) ;
42+ let httpsAgent = new HttpsAgent ( {
43+ keepAlive : true ,
44+ } ) ;
45+
46+ function getAgent ( u : string ) : HttpAgent {
47+ const url = new URL ( u ) ;
48+ return url . protocol === 'https:' ? httpsAgent : httpAgent ;
4449}
4550
4651// Async queue wraps around the call to retryRequest in order to limit
47- // the number of requests in flight to Homebase at any one time.
52+ // the number of requests in flight to kubernetes upstream at any one time.
4853const reqQueue = queue ( async function ( req : KubernetesUpstreamRequest ) {
4954 return await retryRequest ( req . method , req . url , req . payload ) ;
5055} , config . REQUEST_QUEUE_LENGTH ) ;
@@ -60,7 +65,7 @@ export async function sendDepGraph(
6065 const request : KubernetesUpstreamRequest = {
6166 method : 'post' ,
6267 url : `${ upstreamUrl } /api/v1/dependency-graph` ,
63- payload : payload ,
68+ payload,
6469 } ;
6570
6671 const { response, attempt } = await reqQueue . pushAsync ( request ) ;
@@ -91,7 +96,7 @@ export async function sendScanResults(
9196 const request : KubernetesUpstreamRequest = {
9297 method : 'post' ,
9398 url : `${ upstreamUrl } /api/v1/scan-results` ,
94- payload : payload ,
99+ payload,
95100 } ;
96101
97102 const { response, attempt } = await reqQueue . pushAsync ( request ) ;
@@ -127,7 +132,7 @@ export async function sendWorkloadMetadata(
127132 const request : KubernetesUpstreamRequest = {
128133 method : 'post' ,
129134 url : `${ upstreamUrl } /api/v1/workload` ,
130- payload : payload ,
135+ payload,
131136 } ;
132137
133138 const { response, attempt } = await reqQueue . pushAsync ( request ) ;
@@ -198,7 +203,7 @@ export async function deleteWorkload(
198203 const request : KubernetesUpstreamRequest = {
199204 method : 'delete' ,
200205 url : `${ upstreamUrl } /api/v1/workload` ,
201- payload : payload ,
206+ payload,
202207 } ;
203208
204209 const { response, attempt } = await reqQueue . pushAsync ( request ) ;
@@ -229,10 +234,11 @@ function isSuccessStatusCode(statusCode: number | undefined): boolean {
229234 return statusCode !== undefined && statusCode > 100 && statusCode < 400 ;
230235}
231236
232- async function retryRequest (
237+ export async function retryRequest (
233238 verb : NeedleHttpVerbs ,
234239 url : string ,
235240 payload : object ,
241+ reqOptions : NeedleOptions = { } ,
236242) : Promise < IResponseWithAttempts > {
237243 const retry = {
238244 attempts : 3 ,
@@ -241,7 +247,8 @@ async function retryRequest(
241247 const options : NeedleOptions = {
242248 json : true ,
243249 compressed : true ,
244- agent,
250+ agent : getAgent ( url ) ,
251+ ...reqOptions ,
245252 } ;
246253
247254 if ( config . HTTP_PROXY || config . HTTPS_PROXY ) {
@@ -317,11 +324,13 @@ export async function sendClusterMetadata(): Promise<void> {
317324 'attempting to send cluster metadata' ,
318325 ) ;
319326
320- const { response , attempt } = await retryRequest (
321- 'post' ,
322- `${ upstreamUrl } /api/v1/cluster` ,
327+ const request : KubernetesUpstreamRequest = {
328+ method : 'post' ,
329+ url : `${ upstreamUrl } /api/v1/cluster` ,
323330 payload,
324- ) ;
331+ } ;
332+
333+ const { response, attempt } = await reqQueue . pushAsync ( request ) ;
325334 if ( ! isSuccessStatusCode ( response . statusCode ) ) {
326335 throw new Error ( `${ response . statusCode } ${ response . statusMessage } ` ) ;
327336 }
@@ -347,3 +356,46 @@ export async function sendClusterMetadata(): Promise<void> {
347356 ) ;
348357 }
349358}
359+
360+ export async function sendRuntimeData (
361+ payload : IRuntimeDataPayload ,
362+ ) : Promise < void > {
363+ const logContext = {
364+ userLocator : payload . target . userLocator ,
365+ cluster : payload . target . cluster ,
366+ agentId : payload . target . agentId ,
367+ identity : payload . identity ,
368+ } ;
369+
370+ try {
371+ logger . info ( logContext , 'attempting to send runtime data' ) ;
372+
373+ const request : KubernetesUpstreamRequest = {
374+ method : 'post' ,
375+ url : `${ upstreamUrl } /api/v1/runtime-results` ,
376+ payload,
377+ } ;
378+
379+ const { response, attempt } = await reqQueue . pushAsync ( request ) ;
380+
381+ if ( ! isSuccessStatusCode ( response . statusCode ) ) {
382+ throw new Error ( `${ response . statusCode } ${ response . statusMessage } ` ) ;
383+ }
384+
385+ logger . info (
386+ {
387+ attempt,
388+ ...logContext ,
389+ } ,
390+ 'runtime data sent upstream successfully' ,
391+ ) ;
392+ } catch ( error ) {
393+ logger . error (
394+ {
395+ error,
396+ ...logContext ,
397+ } ,
398+ 'could not send runtime data' ,
399+ ) ;
400+ }
401+ }
0 commit comments