// // Images section, optionally grouped by repository. // const { Controller } = require("./Controller"); const { ImageTreeItem, RepositoryTreeItem } = require("../TreeItems/ImageTreeItem"); const { ContainerCLI } = require("../../Interfaces/ContainerCLI"); const { Terminal } = require("../../Interfaces/Terminal"); const images = require("../Models/Image"); const notify = require("../../Utilities/Notify"); const prompt = require("../../Utilities/Prompt"); class ImagesController extends Controller { constructor(sidebar) { super("apple_container.images"); this.sidebar = sidebar; this.registerCommands(); } async fetch() { let list = await ContainerCLI.listImages(); return images.build(list, { group: nova.config.get("apple_container.images.group", "boolean") !== false, registry: nova.config.get("apple_container.images.registry", "boolean") === true, infrastructure: nova.config.get("apple_container.images.infra", "boolean") === true }); } getTreeItem(element) { if (element instanceof images.RepositoryModel) { return new RepositoryTreeItem(element); } return new ImageTreeItem(element, { grouped: element.parent !== null }); } // References for the current selection, expanding repositories into tags. selectedReferences() { let selected = []; for (let element of this.selection) { if (element instanceof images.RepositoryModel) { selected = selected.concat(element.children.map((image) => image.reference)); } else { selected.push(element.reference); } } return selected; } registerCommands() { this.register("apple_container.images.reload", () => this.reload()); this.register("apple_container.images.run", async () => { let reference = this.selectedReferences()[0]; if (!reference) { return; } await runImage(reference); this.sidebar.reloadContainers(); }); this.register("apple_container.images.pull", async () => { for (let reference of this.selectedReferences()) { try { await ContainerCLI.pullImage(reference); } catch (error) { notify.failure(`Unable to pull ${reference}`, error, "apple-container-pull"); } } this.reload(); }); this.register("apple_container.images.push", async () => { for (let reference of this.selectedReferences()) { try { await ContainerCLI.pushImage(reference); notify.info("Push complete", reference, "apple-container-push"); } catch (error) { notify.failure(`Unable to push ${reference}`, error, "apple-container-push"); } } }); this.register("apple_container.images.tag", async () => { let reference = this.selectedReferences()[0]; if (!reference) { return; } let target = await prompt.input("New tag", { placeholder: reference, value: reference }); if (!target) { return; } try { await ContainerCLI.tagImage(reference, target); } catch (error) { notify.failure("Unable to tag image", error, "apple-container-tag"); } this.reload(); }); this.register("apple_container.images.inspect", async () => { for (let reference of this.selectedReferences()) { try { let output = await ContainerCLI.inspectImage(reference); nova.workspace.openNewTextDocument({ content: output, syntax: "json" }); } catch (error) { notify.failure("Unable to inspect image", error, "apple-container-inspect"); } } }); this.register("apple_container.images.copy", () => { let reference = this.selectedReferences()[0]; if (reference) { nova.clipboard.writeText(reference); } }); this.register("apple_container.images.delete", async () => { let references = this.selectedReferences(); if (references.length === 0) { return; } if (!(await prompt.confirm(`Delete ${references.join(", ")}?`))) { return; } try { await ContainerCLI.deleteImages(references); } catch (error) { notify.failure("Unable to delete image", error, "apple-container-delete-image"); } this.reload(); }); this.register("apple_container.images.prune", async () => { if (!(await prompt.confirm("Remove images not referenced by a container?", "Remove"))) { return; } try { await ContainerCLI.pruneImages(); } catch (error) { notify.failure("Unable to prune images", error, "apple-container-prune-image"); } this.reload(); }); for (let key of [ "apple_container.images.group", "apple_container.images.registry", "apple_container.images.infra" ]) { this.watch(key, () => this.reload()); } } } // Runs an image in the terminal, so its output is visible and an interactive // image still works. Arguments are offered because `container run` takes no // defaults worth guessing. async function runImage(reference) { let options = await prompt.input("Arguments for container run", { placeholder: "--detach --name my-container --publish 8080:80" }); if (options === null) { return null; } let parts = [ContainerCLI.path(), "run"]; if (options) { parts = parts.concat(options.split(/\s+/)); } parts.push(reference); return Terminal.run(Terminal.command(parts)); } module.exports = { ImagesController, runImage };