Browse Source

Report progress of multiple plugin installs (#51001)

When installing multiple plugins at once, this commit changes the
behavior to report installed plugins as we go. In the case of failure,
we emit a message that we are rolling back any plugins that were
installed successfully, and also that they were successfully rolled
back. In the case a plugin is not successfully rolled back, we report
this clearly too, alerting the user that there might still be state on
disk they would have to clean up.
Jason Tedor 5 years ago
parent
commit
514135d966

+ 27 - 11
distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/InstallPluginCommand.java

@@ -81,6 +81,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -224,32 +225,47 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
             }
         }
 
-        final List<Path> deleteOnFailure = new ArrayList<>();
-        final Set<PluginInfo> pluginInfos = new HashSet<>();
+        final Map<String, List<Path>> deleteOnFailures = new LinkedHashMap<>();
         for (final String pluginId : pluginIds) {
+            terminal.println("-> Installing " + pluginId);
             try {
                 if ("x-pack".equals(pluginId)) {
                     handleInstallXPack(buildFlavor());
                 }
 
+                final List<Path> deleteOnFailure = new ArrayList<>();
+                deleteOnFailures.put(pluginId, deleteOnFailure);
+
                 final Path pluginZip = download(terminal, pluginId, env.tmpFile(), isBatch);
                 final Path extractedZip = unzip(pluginZip, env.pluginsFile());
                 deleteOnFailure.add(extractedZip);
                 final PluginInfo pluginInfo = installPlugin(terminal, isBatch, extractedZip, env, deleteOnFailure);
-                pluginInfos.add(pluginInfo);
+                terminal.println("-> Installed " + pluginInfo.getName());
+                // swap the entry by plugin id for one with the installed plugin name, it gives a cleaner error message for URL installs
+                deleteOnFailures.remove(pluginId);
+                deleteOnFailures.put(pluginInfo.getName(), deleteOnFailure);
             } catch (final Exception installProblem) {
-                try {
-                    IOUtils.rm(deleteOnFailure.toArray(new Path[0]));
-                } catch (final IOException exceptionWhileRemovingFiles) {
-                    installProblem.addSuppressed(exceptionWhileRemovingFiles);
+                terminal.println("-> Failed installing " + pluginId);
+                for (final Map.Entry<String, List<Path>> deleteOnFailureEntry : deleteOnFailures.entrySet()) {
+                    terminal.println("-> Rolling back " + deleteOnFailureEntry.getKey());
+                    boolean success = false;
+                    try {
+                        IOUtils.rm(deleteOnFailureEntry.getValue().toArray(new Path[0]));
+                        success = true;
+                    } catch (final IOException exceptionWhileRemovingFiles) {
+                        final Exception exception = new Exception(
+                            "failed rolling back installation of [" + deleteOnFailureEntry.getKey() + "]",
+                            exceptionWhileRemovingFiles);
+                        installProblem.addSuppressed(exception);
+                        terminal.println("-> Failed rolling back " + deleteOnFailureEntry.getKey());
+                    }
+                    if (success) {
+                        terminal.println("-> Rolled back " + deleteOnFailureEntry.getKey());
+                    }
                 }
                 throw installProblem;
             }
         }
-
-        for (final PluginInfo pluginInfo : pluginInfos) {
-            terminal.println("-> Installed " + pluginInfo.getName());
-        }
     }
 
     Build.Flavor buildFlavor() {