async copyRetinaCaptureData()

in src/panels/RetinaCapturePanel.ts [116:210]


    async copyRetinaCaptureData(node: string, localCpPath: string) {
        if (!this.kubectl || !this.kubectlVersion) {
            vscode.window.showErrorMessage("Kubectl is not available");
            return;
        }

        const createPodYaml = `
apiVersion: v1
kind: Pod
metadata:
  name: node-explorer-${node}
  labels:
    app: node-explorer
spec:
  nodeName: ${node}
  tolerations:
    - key: CriticalAddonsOnly
      operator: Exists
    - effect: NoExecute
      operator: Exists
    - effect: NoSchedule
      operator: Exists
  volumes:
  - name: mnt-captures
    hostPath:
      path: /mnt/capture
  containers:
  - name: node-explorer
    image: alpine
    command: ["sleep", "9999999999"]
    volumeMounts:
    - name: mnt-captures
      mountPath: /mnt/capture
`;

        const applyResult = await longRunning(`Deploying pod to capture ${node} retina data.`, async () => {
            return await withOptionalTempFile(createPodYaml, "YAML", async (podSpecFile) => {
                const command = `apply -f ${podSpecFile}`;
                return await invokeKubectlCommand(this.kubectl!, this.kubeConfigFilePath, command);
            });
        });

        if (failed(applyResult)) {
            vscode.window.showErrorMessage(`Failed to apply Pod: ${applyResult.error}`);
            return;
        }
        const waitResult = await longRunning(`waiting for pod to get ready node-explorer-${node}.`, async () => {
            const command = `wait pod -n default --for=condition=ready --timeout=300s node-explorer-${node}`;
            return await invokeKubectlCommand(this.kubectl!, this.kubeConfigFilePath, command);
        });

        if (failed(waitResult)) {
            vscode.window.showErrorMessage(`Failed to wait for Pod to be ready: ${waitResult.error}`);
            return;
        }

        /* kubectl cp functionality is used to copy the data from the pod to the local host.
           `kubectl cp` can fail with an EOF error for large files, and there's currently no good workaround:
           See: https://github.com/kubernetes/kubernetes/issues/60140
           The best advice I can see is to use the 'retries' option if it is supported, and the
           'request-timeout' option otherwise. */
        const clientVersion = this.kubectlVersion!.clientVersion.gitVersion.replace(/^v/, "");
        const isRetriesOptionSupported = semver.parse(clientVersion) && semver.gte(clientVersion, "1.23.0");
        const cpEOFAvoidanceFlag = isRetriesOptionSupported ? "--retries 99" : "--request-timeout=10m";
        const captureHostFolderName = `${localCpPath}-${node}`;
        const nodeExplorerResult = await longRunning(
            `Copy captured data to local host location ${captureHostFolderName}.`,
            async () => {
                const cpcommand = `cp node-explorer-${node}:mnt/capture ${captureHostFolderName} ${cpEOFAvoidanceFlag}`;
                return await invokeKubectlCommand(this.kubectl!, this.kubeConfigFilePath, cpcommand);
            },
        );

        if (failed(nodeExplorerResult)) {
            vscode.window.showErrorMessage(`Failed to apply copy command: ${nodeExplorerResult.error}`);
            return;
        }

        const goToFolder = "Go to Folder";
        vscode.window
            .showInformationMessage(
                `Successfully copied the Retina Capture data to ${captureHostFolderName}`,
                goToFolder,
            )
            .then((selection) => {
                if (selection === goToFolder) {
                    if (env.remoteName === "wsl") {
                        commands.executeCommand("remote-wsl.revealInExplorer", Uri.file(captureHostFolderName));
                    } else {
                        // opening relative file path doesn't work in WSL
                        open(captureHostFolderName);
                    }
                }
            });
    }