diff options
author | Harald Musum <musum@yahooinc.com> | 2022-03-14 21:02:06 +0100 |
---|---|---|
committer | Harald Musum <musum@yahooinc.com> | 2022-03-14 21:02:06 +0100 |
commit | be72c65016403794c439cdfb74921d37c7a419e9 (patch) | |
tree | fc66bab2b76afc660c0c527145385b7076863ee9 /node-admin/src | |
parent | a64cf6d0da6bf48442906417023586a2d80fd426 (diff) |
Add command for deleting version lock
Diffstat (limited to 'node-admin/src')
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(); + }); + } + } |