From 21b17455c99f706ecd9efce275cf1a33be3aa24e Mon Sep 17 00:00:00 2001 From: crschnick Date: Wed, 1 Apr 2026 20:59:46 +0000 Subject: [PATCH] Fix incus project handling --- .../ext/system/incus/IncusCommandView.java | 228 ++++++++++-------- .../IncusContainerConsoleActionProvider.java | 5 +- ...ncusContainerEditConfigActionProvider.java | 5 +- .../ext/system/incus/IncusContainerStore.java | 26 +- 4 files changed, 149 insertions(+), 115 deletions(-) diff --git a/ext/system/src/main/java/io/xpipe/ext/system/incus/IncusCommandView.java b/ext/system/src/main/java/io/xpipe/ext/system/incus/IncusCommandView.java index a13ac7bf1..bf45433ac 100644 --- a/ext/system/src/main/java/io/xpipe/ext/system/incus/IncusCommandView.java +++ b/ext/system/src/main/java/io/xpipe/ext/system/incus/IncusCommandView.java @@ -22,6 +22,133 @@ public class IncusCommandView extends CommandViewBase { super(shellControl); } + public Project project(String project) { + return new Project(project); + } + + public class Project extends CommandView { + + private final String project; + + public Project(String project) { + this.project = project; + } + + @Override + protected CommandControl build(Consumer builder) { + var cmd = CommandBuilder.of().add("incus").add("--project", project != null ? project : "default"); + builder.accept(cmd); + return shellControl + .command(cmd) + .withErrorFormatter(IncusCommandView::formatErrorMessage) + .withExceptionConverter(IncusCommandView::convertException) + .elevated(requiresElevation()); + } + + @Override + protected ShellControl getShellControl() { + return IncusCommandView.this.getShellControl(); + } + + @Override + public Project start() throws Exception { + shellControl.start(); + return this; + } + + + public void start(String containerName) throws Exception { + build(commandBuilder -> commandBuilder + .add("start") + .addQuoted(containerName)) + .execute(); + } + + public void stop(String containerName) throws Exception { + build(commandBuilder -> commandBuilder + .add("stop") + .addQuoted(containerName)) + .execute(); + } + + public void pause(String containerName) throws Exception { + build(commandBuilder -> commandBuilder + .add("pause") + .addQuoted(containerName)) + .execute(); + } + + public CommandControl console(String containerName) { + return build(commandBuilder -> commandBuilder + .add("console").addQuoted(containerName)); + } + + public CommandControl configEdit(String containerName) { + return build(commandBuilder -> commandBuilder + .add("config", "edit").addQuoted(containerName)); + } + + + + public Optional queryContainerState(String containerName) throws Exception { + var l = listContainers(); + var found = l.stream() + .filter(containerEntry -> (containerEntry.getProject().equals(project) + || project == null + && containerEntry.getProject().equals("default")) + && containerEntry.getName().equals(containerName)) + .findFirst(); + return found; + } + + + public ShellControl exec(String container, String user, Supplier busybox) { + var sub = shellControl.subShell(); + sub.setDumbOpen(createOpenFunction(container, user, false, busybox)); + sub.setTerminalOpen(createOpenFunction(container, user, true, busybox)); + return sub.withExceptionConverter(IncusCommandView::convertException).elevated(requiresElevation()); + } + + private ShellOpenFunction createOpenFunction(String containerName, String user, boolean terminal, Supplier busybox) { + return new ShellOpenFunction() { + @Override + public CommandBuilder prepareWithoutInitCommand() { + var b = execCommand(containerName, terminal).add("su", "-l"); + if (user != null) { + b.addQuoted(user); + } + return b; + } + + @Override + public CommandBuilder prepareWithInitCommand(@NonNull String command) { + var b = execCommand(containerName, terminal).add("su", "-l"); + if (user != null) { + b.addQuoted(user); + } + return b.add(sc -> { + var suType = busybox.get(); + if (suType) { + return "-c"; + } else { + return "--session-command"; + } + }) + .addLiteral(command); + } + }; + } + + private CommandBuilder execCommand(String containerName, boolean terminal) { + var c = CommandBuilder.of() + .add("incus") + .add("--project", project != null ? project : "default") + .add("exec", terminal ? "-t" : "-T"); + return c.addQuoted(containerName) + .add("--"); + } + } + private static ElevationFunction requiresElevation() { return ElevationFunction.cached("incusRequiresElevation", new ElevationFunction() { @Override @@ -86,47 +213,6 @@ public class IncusCommandView extends CommandViewBase { return build(commandBuilder -> commandBuilder.add("version")).readStdoutOrThrow(); } - public void start(String projectName, String containerName) throws Exception { - build(commandBuilder -> commandBuilder - .add("start") - .addQuoted(containerName) - .add("--project") - .addQuoted(projectName)) - .execute(); - } - - public void stop(String projectName, String containerName) throws Exception { - build(commandBuilder -> commandBuilder - .add("stop") - .addQuoted(containerName) - .add("--project") - .addQuoted(projectName)) - .execute(); - } - - public void pause(String projectName, String containerName) throws Exception { - build(commandBuilder -> commandBuilder - .add("pause") - .addQuoted(containerName) - .add("--project") - .addQuoted(projectName)) - .execute(); - } - - public CommandControl console(String projectName, String containerName) { - return build(commandBuilder -> commandBuilder - .add("--project") - .addQuoted(projectName) - .add("console").addQuoted(containerName)); - } - - public CommandControl configEdit(String projectName, String containerName) { - return build(commandBuilder -> commandBuilder - .add("--project") - .addQuoted(projectName) - .add("config", "edit").addQuoted(containerName)); - } - public List> listContainers(DataStoreEntryRef store) throws Exception { return listContainers().stream() @@ -147,17 +233,6 @@ public class IncusCommandView extends CommandViewBase { .toList(); } - public Optional queryContainerState(String projectName, String containerName) throws Exception { - var l = listContainers(); - var found = l.stream() - .filter(containerEntry -> (containerEntry.getProject().equals(projectName) - || projectName == null - && containerEntry.getProject().equals("default")) - && containerEntry.getName().equals(containerName)) - .findFirst(); - return found; - } - @Value public static class ContainerEntry { String project; @@ -168,8 +243,7 @@ public class IncusCommandView extends CommandViewBase { } private List listContainers() throws Exception { - try (var c = build(commandBuilder -> commandBuilder.add("list", "--all-projects", "-f", "json")) - .start()) { + try (var c = build(commandBuilder -> commandBuilder.add("list", "--all-projects", "-f", "json")).start()) { var output = c.readStdoutOrThrow(); var json = JacksonMapper.getDefault().readTree(output); var l = new ArrayList(); @@ -214,50 +288,4 @@ public class IncusCommandView extends CommandViewBase { return l; } } - - public ShellControl exec(String projectName, String container, String user, Supplier busybox) { - var sub = shellControl.subShell(); - sub.setDumbOpen(createOpenFunction(projectName, container, user, false, busybox)); - sub.setTerminalOpen(createOpenFunction(projectName, container, user, true, busybox)); - return sub.withExceptionConverter(IncusCommandView::convertException).elevated(requiresElevation()); - } - - private ShellOpenFunction createOpenFunction( - String projectName, String containerName, String user, boolean terminal, Supplier busybox) { - return new ShellOpenFunction() { - @Override - public CommandBuilder prepareWithoutInitCommand() { - var b = execCommand(projectName, containerName, terminal).add("su", "-l"); - if (user != null) { - b.addQuoted(user); - } - return b; - } - - @Override - public CommandBuilder prepareWithInitCommand(@NonNull String command) { - var b = execCommand(projectName, containerName, terminal).add("su", "-l"); - if (user != null) { - b.addQuoted(user); - } - return b.add(sc -> { - var suType = busybox.get(); - if (suType) { - return "-c"; - } else { - return "--session-command"; - } - }) - .addLiteral(command); - } - }; - } - - public CommandBuilder execCommand(String projectName, String containerName, boolean terminal) { - var c = CommandBuilder.of().add("incus", "exec", terminal ? "-t" : "-T"); - return c.addQuoted(containerName) - .add("--project") - .addQuoted(projectName) - .add("--"); - } } diff --git a/ext/system/src/main/java/io/xpipe/ext/system/incus/IncusContainerConsoleActionProvider.java b/ext/system/src/main/java/io/xpipe/ext/system/incus/IncusContainerConsoleActionProvider.java index 80dd9aff0..036d60e85 100644 --- a/ext/system/src/main/java/io/xpipe/ext/system/incus/IncusContainerConsoleActionProvider.java +++ b/ext/system/src/main/java/io/xpipe/ext/system/incus/IncusContainerConsoleActionProvider.java @@ -52,12 +52,11 @@ public class IncusContainerConsoleActionProvider implements HubLeafProvider> getDependencies() { return DataStoreDependencies.of(install, identity != null ? identity.getDependencies() : null); @@ -93,7 +101,7 @@ public class IncusContainerStore getInstall().getStore().getHost().getStore().getOrStartSession()); var user = identity != null ? identity.unwrap().getUsername().retrieveUsername() : null; - var sc = new IncusCommandView(parent).exec(projectName, containerName, user, () -> { + var sc = view(parent).exec(containerName, user, () -> { var state = getState(); var alpine = state.getOsName() != null && state.getOsName().toLowerCase().contains("alpine"); @@ -130,8 +138,8 @@ public class IncusContainerStore private void refreshContainerState(ShellControl sc) throws Exception { var state = getState(); - var view = new IncusCommandView(sc); - var displayState = view.queryContainerState(projectName, containerName); + var view = view(sc); + var displayState = view.queryContainerState(containerName); if (displayState.isEmpty()) { return; } @@ -149,8 +157,8 @@ public class IncusContainerStore @Override public void start() throws Exception { var sc = getInstall().getStore().getHost().getStore().getOrStartSession(); - var view = new IncusCommandView(sc); - view.start(projectName, containerName); + var view = view(); + view.start(containerName); refreshContainerState(sc); } @@ -158,16 +166,16 @@ public class IncusContainerStore public void stop() throws Exception { stopSessionIfNeeded(); var sc = getInstall().getStore().getHost().getStore().getOrStartSession(); - var view = new IncusCommandView(sc); - view.stop(projectName, containerName); + var view = view(); + view.stop(containerName); refreshContainerState(sc); } @Override public void pause() throws Exception { var sc = getInstall().getStore().getHost().getStore().getOrStartSession(); - var view = new IncusCommandView(sc); - view.pause(projectName, containerName); + var view = view(); + view.pause(containerName); refreshContainerState(sc); }