diff --git a/src/extension.ts b/src/extension.ts index e006479e..3273bada 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -20,6 +20,8 @@ import type { ContainerCreateOptions, ExtensionContext } from '@podman-desktop/a import * as extensionApi from '@podman-desktop/api'; import { BootC } from './bootc'; import * as os from 'node:os'; +import * as fs from 'node:fs'; +import { resolve } from 'node:path'; let bootc: BootC | undefined; const bootcImageBuilderContainerName = '-bootc-image-builder'; @@ -27,7 +29,6 @@ const bootcImageBuilderName = 'quay.io/centos-bootc/bootc-image-builder'; let diskImageBuildingName: string; export async function activate(extensionContext: ExtensionContext): Promise { - bootc = new BootC(extensionContext); await bootc?.activate(); @@ -36,65 +37,75 @@ export async function activate(extensionContext: ExtensionContext): Promise { - // ignore everything before last / // we will use this as the "build" container name - diskImageBuildingName = image.name.split('/').pop() + bootcImageBuilderContainerName, + diskImageBuildingName = image.name.split('/').pop() + bootcImageBuilderContainerName; // TODO: Make sure that 'image' has been pushed to registry before building it.. // or else it will fail. // for demo right now, don't bother checking - await pullBootcImageBuilderImage(); - progress.report({ increment: 10 }); - await removePreviousBuildImage(image); - progress.report({ increment: 15 }); - let containerId = await createImage(image, selectedType, selectedFolder); - - logContainer(image, containerId, progress); + try { + await pullBootcImageBuilderImage(); + progress.report({ increment: 10 }); + await removePreviousBuildImage(image); + progress.report({ increment: 15 }); - // list containers using extensionApi.containerEngine.listContainers - // and filter + const containerId = await createImage(image, selectedType, selectedFolder); + progress.report({ increment: 16 }); - // List containers and filter by the name 'diskImageBuildingName' + await logContainer(image, containerId, progress); - let containerRunning = true; - while (containerRunning) { - extensionApi.containerEngine.listContainers().then((containers) => { - console.log(containers); - containers.forEach((container) => { - if (container.Id === containerId) { + // Wait for container to exit so that the task doesn't end and we can monitor progress + let containerRunning = true; + while (containerRunning) { + await extensionApi.containerEngine.listContainers().then(containers => { + containers.forEach(container => { // check if container is stopped - if (container.State === 'exited') { + if (container.Id === containerId && container.State === 'exited') { // remove the container // Cant do this until we extract the logs //extensionApi.containerEngine.deleteContainer(image.engineId, container.Id); containerRunning = false; } - } - } - ); - }); - await new Promise(r => setTimeout(r, 2000)); - } - + }); + }); + await new Promise(r => setTimeout(r, 1000)); + } + } catch (error) { + console.error(error); + await extensionApi.window.showErrorMessage(`Unable to build disk image: ${error}`); + } // Mark the task as completed progress.report({ increment: -1 }); }, @@ -104,7 +115,7 @@ export async function activate(extensionContext: ExtensionContext): Promise providerConnection.connection.type === 'podman', - ); + // keep only the podman engine + // TODO: match by engineId from `image.engineId` instead of just looking for the first podman + const podmanConnection = providerConnections.filter( + providerConnection => providerConnection.connection.type === 'podman', + ); - // engine running - if (podmanConnection.length < 1) { - throw new Error('No podman engine running. Cannot preload images'); - } + // engine running + if (podmanConnection.length < 1) { + throw new Error('No podman engine running. Cannot preload images'); + } - // get the podman engine - let containerConnection = podmanConnection[0].connection; + // get the podman engine + const containerConnection = podmanConnection[0].connection; console.log('Pulling ' + bootcImageBuilderName); - - try { - await extensionApi.containerEngine.pullImage(containerConnection, bootcImageBuilderName, () => - console.log("Bootc builder image pulled"), - ); - } catch (e) { - console.log(e); - } + await extensionApi.containerEngine.pullImage(containerConnection, bootcImageBuilderName, () => {}); } async function createImage(image, type, folder: string) { - console.log('Building ' + diskImageBuildingName + ' to ' + type); -/* + /* // The "raw" CLI command for the below container create @@ -160,53 +162,44 @@ quay.io/centos-bootc/bootc-image-builder:latest \ $IMAGE */ -// Update options with the above values -let options: ContainerCreateOptions = { - name: diskImageBuildingName, - Image: bootcImageBuilderName, - Tty: true, - HostConfig: { - Privileged: true, - SecurityOpt: ['label=type:unconfined_t'], - Binds: [folder + ':/tmp/' + type] - }, - // Outputs to: - // /disk. - // in the directory provided - Cmd: [image.name,"--type", type, "--output","/tmp/" + type], -}; -try { - let result = await extensionApi.containerEngine.createContainer(image.engineId, options); + // Update options with the above values + const options: ContainerCreateOptions = { + name: diskImageBuildingName, + Image: bootcImageBuilderName, + Tty: true, + HostConfig: { + Privileged: true, + SecurityOpt: ['label=type:unconfined_t'], + Binds: [folder + ':/tmp/' + type], + }, + // Outputs to: + // /disk. + // in the directory provided + Cmd: [image.name, '--type', type, '--output', '/tmp/' + type], + }; + + const result = await extensionApi.containerEngine.createContainer(image.engineId, options); + + // return the created container id return result.id; -} catch (e) { - console.log(e); -} } async function logContainer(image, containerId: string, progress): Promise { - try { - await extensionApi.containerEngine.logsContainer( - image.engineId, - containerId, - (_name: string, data: string) => { - if (data) { - if (data.includes('org.osbuild.rpm')) - progress.report({ increment: 40 }); - else if (data.includes('org.osbuild.selinux')) - progress.report({ increment: 60 }); - else if (data.includes('org.osbuild.deploy.container')) - progress.report({ increment: 80 }); - else if (data.includes('org.osbuild.copy')) - progress.report({ increment: 90 }); - } - } - ); - } catch (err) { - console.error(err); - // propagate the error - // throw err; - } + await extensionApi.containerEngine.logsContainer(image.engineId, containerId, (_name: string, data: string) => { + if (data) { + if (data.includes('org.osbuild.rpm')) { + progress.report({ increment: 40 }); + } else if (data.includes('org.osbuild.selinux')) { + progress.report({ increment: 60 }); + } else if (data.includes('org.osbuild.deploy.container')) { + progress.report({ increment: 80 }); + } else if (data.includes('org.osbuild.copy')) { + progress.report({ increment: 90 }); + } + } + }); } + export async function deactivate(): Promise { await bootc?.deactivate(); }