feat(frontend): make container name configurable (#9433)

* feat(frontend): make container name configurable

Add an UIConfig param to specify the container name in a pod
where logs are retrieved. The default container name for
the Argo is `main`. However, in Tekton, the main container name
contains the `step-` prefix. Make this configurable to support
other orchestrations.

Signed-off-by: Yihong Wang <yh.wang@ibm.com>

* fix test case error

add `undefined` as the expected `logContainerName` param

Signed-off-by: Yihong Wang <yh.wang@ibm.com>

* address the comment

use default value `main` in `getPodLogsStreamFromK8s`
same as `getPodLogs`

Signed-off-by: Yihong Wang <yh.wang@ibm.com>

* only pass podLogContainerName

Signed-off-by: Yihong Wang <yh.wang@ibm.com>

---------

Signed-off-by: Yihong Wang <yh.wang@ibm.com>
This commit is contained in:
Yihong Wang 2023-05-17 16:37:06 -07:00 committed by GitHub
parent f915195446
commit bb9dc67572
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 36 additions and 8 deletions

View File

@ -193,7 +193,11 @@ function createUIServer(options: UIConfigs) {
}),
);
} else {
registerHandler(app.get, '/k8s/pod/logs', getPodLogsHandler(options.argo, options.artifacts));
registerHandler(
app.get,
'/k8s/pod/logs',
getPodLogsHandler(options.argo, options.artifacts, options.pod.logContainerName),
);
}
if (options.artifacts.streamLogsFromServerApi) {
@ -215,7 +219,11 @@ function createUIServer(options: UIConfigs) {
}),
);
} else {
registerHandler(app.get, '/k8s/pod/logs', getPodLogsHandler(options.argo, options.artifacts));
registerHandler(
app.get,
'/k8s/pod/logs',
getPodLogsHandler(options.argo, options.artifacts, options.pod.logContainerName),
);
}
/** Pod info */

View File

@ -92,6 +92,8 @@ export function loadConfigs(argv: string[], env: ProcessEnv): UIConfigs {
ARGO_ARCHIVE_PREFIX = 'logs',
/** Should use server API for log streaming? */
STREAM_LOGS_FROM_SERVER_API = 'false',
/** The main container name of a pod where logs are retrieved */
POD_LOG_CONTAINER_NAME = 'main',
/** Disables GKE metadata endpoint. */
DISABLE_GKE_METADATA = 'false',
/** Enable authorization checks for multi user mode. */
@ -124,6 +126,9 @@ export function loadConfigs(argv: string[], env: ProcessEnv): UIConfigs {
archiveLogs: asBool(ARGO_ARCHIVE_LOGS),
archivePrefix: ARGO_ARCHIVE_PREFIX,
},
pod: {
logContainerName: POD_LOG_CONTAINER_NAME,
},
artifacts: {
aws: {
accessKey: AWS_ACCESS_KEY_ID || '',
@ -270,6 +275,9 @@ export interface UIConfigs {
proxy: ArtifactsProxyConfig;
streamLogsFromServerApi: boolean;
};
pod: {
logContainerName: string;
};
argo: ArgoConfigs;
metadata: MetadataConfigs;
visualizations: VisualizationsConfigs;

View File

@ -37,6 +37,7 @@ export function getPodLogsHandler(
minio: MinioConfigs;
aws: AWSConfigs;
},
podLogContainerName: string,
): Handler {
const { archiveLogs, archiveArtifactory, archiveBucketName, archivePrefix = '' } = argoOptions;
@ -51,7 +52,9 @@ export function getPodLogsHandler(
// get the pod log stream (with fallbacks).
const getPodLogsStream = composePodLogsStreamHandler(
getPodLogsStreamFromK8s,
(podName: string, namespace?: string) => {
return getPodLogsStreamFromK8s(podName, namespace, podLogContainerName);
},
// if archive logs flag is set, then final attempt will try to retrieve the artifacts
// from the bucket and prefix provided in the config. Otherwise, only attempts
// to read from worflow status if the default handler fails.

View File

@ -240,14 +240,18 @@ export function waitForTensorboardInstance(
});
}
export function getPodLogs(podName: string, podNamespace?: string): Promise<string> {
export function getPodLogs(
podName: string,
podNamespace?: string,
containerName: string = 'main',
): Promise<string> {
podNamespace = podNamespace || serverNamespace;
if (!podNamespace) {
throw new Error(
`podNamespace is not specified and cannot get namespace from ${namespaceFilePath}.`,
);
}
return (k8sV1Client.readNamespacedPodLog(podName, podNamespace, 'main') as any).then(
return (k8sV1Client.readNamespacedPodLog(podName, podNamespace, containerName) as any).then(
(response: any) => (response && response.body ? response.body.toString() : ''),
(error: any) => {
throw new Error(JSON.stringify(error.body));

View File

@ -83,7 +83,7 @@ describe('workflow-helper', () => {
mockedGetPodLogs.mockResolvedValueOnce('pod logs');
const stream = await getPodLogsStreamFromK8s('podName', 'namespace');
expect(mockedGetPodLogs).toBeCalledWith('podName', 'namespace');
expect(mockedGetPodLogs).toBeCalledWith('podName', 'namespace', 'main');
expect(stream.read().toString()).toBe('pod logs');
});
});

View File

@ -81,10 +81,15 @@ export function composePodLogsStreamHandler<T = Stream>(
* Returns a stream containing the pod logs using kubernetes api.
* @param podName name of the pod.
* @param namespace namespace of the pod (uses the same namespace as the server if not provided).
* @param containerName container's name of the pod, the default value is 'main'.
*/
export async function getPodLogsStreamFromK8s(podName: string, namespace?: string) {
export async function getPodLogsStreamFromK8s(
podName: string,
namespace?: string,
containerName: string = 'main',
) {
const stream = new PassThrough();
stream.end(await getPodLogs(podName, namespace));
stream.end(await getPodLogs(podName, namespace, containerName));
console.log(`Getting logs for pod:${podName} in namespace ${namespace}.`);
return stream;
}