summaryrefslogtreecommitdiffstats
path: root/node-admin
diff options
context:
space:
mode:
authorHarald Musum <musum@yahooinc.com>2022-03-14 21:02:06 +0100
committerHarald Musum <musum@yahooinc.com>2022-03-14 21:02:06 +0100
commitbe72c65016403794c439cdfb74921d37c7a419e9 (patch)
treefc66bab2b76afc660c0c527145385b7076863ee9 /node-admin
parenta64cf6d0da6bf48442906417023586a2d80fd426 (diff)
Add command for deleting version lock
Diffstat (limited to 'node-admin')
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/Yum.java5
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumCommand.java90
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTester.java22
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTest.java13
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTesterTest.java16
5 files changed, 112 insertions, 34 deletions
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/Yum.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/Yum.java
index 191b81e2263..8806ec217db 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/Yum.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/Yum.java
@@ -7,6 +7,7 @@ import com.yahoo.vespa.hosted.node.admin.task.util.process.Terminal;
import java.util.List;
import java.util.Optional;
+import static com.yahoo.vespa.hosted.node.admin.task.util.yum.YumCommand.DeleteVersionLockYumCommand;
import static com.yahoo.vespa.hosted.node.admin.task.util.yum.YumCommand.GenericYumCommand;
import static com.yahoo.vespa.hosted.node.admin.task.util.yum.YumCommand.InstallFixedYumCommand;
@@ -68,6 +69,10 @@ public class Yum {
return remove(packages.stream().map(YumPackageName::fromString).toArray(YumPackageName[]::new));
}
+ public YumCommand.DeleteVersionLockYumCommand deleteVersionLock(YumPackageName yumPackage) {
+ return new DeleteVersionLockYumCommand(terminal, yumPackage);
+ }
+
static YumPackageName[] toYumPackageNameArray(String package1, String... packages) {
YumPackageName[] array = new YumPackageName[1 + packages.length];
array[0] = YumPackageName.fromString(package1);
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumCommand.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumCommand.java
index e5cc43dc196..070bac3dfc9 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumCommand.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumCommand.java
@@ -158,36 +158,15 @@ public abstract class YumCommand<T extends YumCommand<T>> {
public boolean converge(TaskContext context) {
String targetVersionLockName = yumPackage.toVersionLockName();
- List<String> command = new ArrayList<>(4);
- command.add("yum");
- command.add("versionlock");
- command.add("list");
-
- boolean alreadyLocked = terminal
- .newCommandLine(context)
- .add(command)
- .executeSilently()
- .getOutputLinesStream()
- .map(YumPackageName::parseString)
- .filter(Optional::isPresent) // removes garbage first lines, even with --quiet
- .map(Optional::get)
- .anyMatch(packageName -> {
- // Ignore lines for other packages
- if (packageName.getName().equals(yumPackage.getName())) {
- // If existing lock doesn't exactly match the full package name,
- // it means it's locked to another version and we must remove that lock.
- String versionLockName = packageName.toVersionLockName();
- if (versionLockName.equals(targetVersionLockName)) {
- return true;
- } else {
- terminal.newCommandLine(context)
- .add("yum", "versionlock", "delete", versionLockName)
- .execute();
- }
- }
-
- return false;
- });
+ boolean alreadyLocked = false;
+ Optional<String> versionLock = versionLockExists(context, terminal, yumPackage);
+ if (versionLock.isPresent()) {
+ if (versionLock.get().equals(targetVersionLockName)) {
+ alreadyLocked = true;
+ } else {
+ YumCommand.deleteVersionLock(context, terminal, versionLock.get());
+ }
+ }
boolean modified = false;
@@ -240,6 +219,24 @@ public abstract class YumCommand<T extends YumCommand<T>> {
protected InstallFixedYumCommand getThis() { return this; }
}
+ public static class DeleteVersionLockYumCommand extends YumCommand<DeleteVersionLockYumCommand> {
+ private final Terminal terminal;
+ private final YumPackageName yumPackage;
+
+ DeleteVersionLockYumCommand(Terminal terminal, YumPackageName yumPackage) {
+ super(terminal);
+ this.terminal = terminal;
+ this.yumPackage = yumPackage;
+ }
+
+ @Override
+ public boolean converge(TaskContext context) {
+ return deleteVersionLock(context, terminal, yumPackage.toName());
+ }
+
+ protected DeleteVersionLockYumCommand getThis() { return this; }
+ }
+
protected boolean isInstalled(TaskContext context, YumPackageName yumPackage) {
return queryInstalled(terminal, context, yumPackage).map(yumPackage::isSubsetOf).orElse(false);
}
@@ -264,4 +261,37 @@ public abstract class YumCommand<T extends YumCommand<T>> {
return Optional.of(builder.build());
}
+
+ private static Optional<String> versionLockExists(TaskContext context, Terminal terminal, YumPackageName yumPackage) {
+
+ List<String> command = new ArrayList<>(4);
+ command.add("yum");
+ command.add("versionlock");
+ command.add("list");
+
+ return terminal
+ .newCommandLine(context)
+ .add(command)
+ .executeSilently()
+ .getOutputLinesStream()
+ .map(YumPackageName::parseString)
+ .filter(Optional::isPresent) // removes garbage first lines, even with --quiet
+ .map(Optional::get)
+ // Ignore lines for other packages
+ .filter(packageName -> packageName.getName().equals(yumPackage.getName()))
+ // If existing lock doesn't exactly match the full package name,
+ // it means it's locked to another version and we must remove that lock.
+ .map(YumPackageName::toVersionLockName)
+ .findFirst();
+ }
+
+ private static boolean deleteVersionLock(TaskContext context, Terminal terminal, String wildcardEntry) {
+ // Idempotent command, gives exit code 0 also when versionlock does not exist
+ terminal.newCommandLine(context)
+ .add("yum", "versionlock", "delete", wildcardEntry)
+ .execute()
+ .getOutputLinesStream();
+ return true;
+ }
+
}
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTester.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTester.java
index c56740f778b..3052cd0d292 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTester.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTester.java
@@ -38,6 +38,10 @@ public class YumTester extends Yum {
return new InstallFixedCommandExpectation(yumPackage);
}
+ public DeleteVersionLockCommandExpectation expectDeleteVersionLock(String yumPackage) {
+ return new DeleteVersionLockCommandExpectation(yumPackage);
+ }
+
public QueryInstalledExpectation expectQueryInstalled(String packageName) {
return new QueryInstalledExpectation(packageName);
}
@@ -62,6 +66,7 @@ public class YumTester extends Yum {
public YumTester andReturn(boolean value) {
if (value) return execute("Success");
switch (commandType) {
+ case deleteVersionLock:
case installFixed:
case install: return execute("Nothing to do");
case upgrade: return execute("No packages marked for update");
@@ -84,8 +89,11 @@ public class YumTester extends Yum {
}
StringBuilder cmd = new StringBuilder();
- cmd.append("yum ").append(commandType.command).append(" --assumeyes");
- enableRepos.forEach(repo -> cmd.append(" --enablerepo=").append(repo));
+ cmd.append("yum ").append(commandType.command);
+ if (commandType != CommandType.deleteVersionLock) {
+ cmd.append(" --assumeyes");
+ enableRepos.forEach(repo -> cmd.append(" --enablerepo=").append(repo));
+ }
if (commandType == CommandType.install && packages.size() > 1)
cmd.append(" --setopt skip_missing_names_on_install=False");
if (commandType == CommandType.upgrade && packages.size() > 1)
@@ -118,6 +126,14 @@ public class YumTester extends Yum {
}
+ public class DeleteVersionLockCommandExpectation extends GenericYumCommandExpectation {
+
+ private DeleteVersionLockCommandExpectation(String yumPackage) {
+ super(CommandType.deleteVersionLock, yumPackage);
+ }
+
+ }
+
public class QueryInstalledExpectation {
private final String packageName;
@@ -142,7 +158,7 @@ public class YumTester extends Yum {
}
private enum CommandType {
- install("install"), upgrade("upgrade"), remove("remove"), installFixed("install");
+ install("install"), upgrade("upgrade"), remove("remove"), installFixed("install"), deleteVersionLock("versionlock delete");
private final String command;
CommandType(String command) {
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTest.java
index feafb2a9a31..3376ba70500 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTest.java
@@ -301,6 +301,19 @@ public class YumTest {
yum.upgrade().converge(taskContext);
}
+ @Test
+ public void testDeleteVersionLock() {
+ terminal.expectCommand("yum versionlock delete openssh-0:8.0p1-4.el8_1.x86_64 2>&1");
+
+ YumPackageName pkg = new YumPackageName
+ .Builder("openssh")
+ .setVersion("8.0p1")
+ .setRelease("4.el8_1")
+ .setArchitecture("x86_64")
+ .build();
+ assertTrue(yum.deleteVersionLock(pkg).converge(taskContext));
+ }
+
private void mockRpmQuery(String packageName, YumPackageName installedOrNull) {
new YumTester(terminal).expectQueryInstalled(packageName).andReturn(installedOrNull);
}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTesterTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTesterTest.java
index 6d1049cfa6c..f5cb188d07a 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTesterTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTesterTest.java
@@ -38,6 +38,11 @@ public class YumTesterTest {
assertYumMethod(yum -> yum.expectInstallFixedVersion(minimalPackage.toName()).withEnableRepo(repos),
yum -> yum.installFixedVersion(minimalPackage).enableRepo(repos).converge(context));
+
+ // versionlock always returns success
+ assertYumMethodAlwaysSuccess(yum -> yum.expectDeleteVersionLock(minimalPackage.toName()),
+ yum -> yum.deleteVersionLock(minimalPackage).converge(context));
+
}
@Test
@@ -48,7 +53,7 @@ public class YumTesterTest {
}
private void assertYumMethod(Function<YumTester, YumTester.GenericYumCommandExpectation> yumTesterExpectationFunction,
- Function<Yum, Boolean> yumFunction) {
+ Function<Yum, Boolean> yumFunction) {
List.of(true, false).forEach(wantedReturnValue -> {
yumTesterExpectationFunction.apply(yum).andReturn(wantedReturnValue);
assertEquals(wantedReturnValue, yumFunction.apply(yum));
@@ -56,4 +61,13 @@ public class YumTesterTest {
});
}
+ private void assertYumMethodAlwaysSuccess(Function<YumTester, YumTester.GenericYumCommandExpectation> yumTesterExpectationFunction,
+ Function<Yum, Boolean> yumFunction) {
+ List.of(true, false).forEach(wantedReturnValue -> {
+ yumTesterExpectationFunction.apply(yum).andReturn(wantedReturnValue);
+ assertEquals(true, yumFunction.apply(yum));
+ terminal.verifyAllCommandsExecuted();
+ });
+ }
+
}