aboutsummaryrefslogtreecommitdiffstats
path: root/node-repository
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2020-05-08 13:47:16 +0200
committerMartin Polden <mpolden@mpolden.no>2020-05-11 10:33:15 +0200
commit05b8c4bbe5e7887c3c447ad79c644ecacfc65831 (patch)
tree46be716d8f9b97e8aca1dce282a8c6e072b8b794 /node-repository
parent7d97b0955785e1a671e12b8468b55c24a7b6bc1c (diff)
Extract OS version change to support additional fields
Diffstat (limited to 'node-repository')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersionChange.java49
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersions.java65
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java14
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionChangeSerializer.java75
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionsSerializer.java62
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/UpgradeResponse.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java18
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionChangeSerializerTest.java51
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionsSerializerTest.java54
9 files changed, 231 insertions, 159 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersionChange.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersionChange.java
new file mode 100644
index 00000000000..12a86738f82
--- /dev/null
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersionChange.java
@@ -0,0 +1,49 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.provision.os;
+
+import com.google.common.collect.ImmutableSortedMap;
+import com.yahoo.component.Version;
+import com.yahoo.config.provision.NodeType;
+
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * The OS version change being deployed in a {@link com.yahoo.vespa.hosted.provision.NodeRepository}.
+ *
+ * @author mpolden
+ */
+public class OsVersionChange {
+
+ public static final OsVersionChange NONE = new OsVersionChange(Map.of());
+
+ private final Map<NodeType, Version> targets;
+
+ public OsVersionChange(Map<NodeType, Version> targets) {
+ this.targets = ImmutableSortedMap.copyOf(Objects.requireNonNull(targets));
+ }
+
+ /** Version targets for this */
+ public Map<NodeType, Version> targets() {
+ return targets;
+ }
+
+ /** Returns a copy of this with target versions set to given value */
+ public OsVersionChange with(Map<NodeType, Version> targets) {
+ return new OsVersionChange(targets);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ OsVersionChange that = (OsVersionChange) o;
+ return targets.equals(that.targets);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(targets);
+ }
+
+}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersions.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersions.java
index f45e6d86613..efe69953f27 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersions.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersions.java
@@ -7,12 +7,14 @@ import com.yahoo.vespa.curator.Lock;
import com.yahoo.vespa.hosted.provision.NodeRepository;
import com.yahoo.vespa.hosted.provision.persistence.CuratorDatabaseClient;
-import java.util.Map;
+import java.util.HashMap;
import java.util.Optional;
+import java.util.function.UnaryOperator;
import java.util.logging.Logger;
/**
- * Thread-safe class that manages target OS versions for nodes in this repository.
+ * Thread-safe class that manages an OS version change for nodes in this repository. An {@link Upgrader} decides how a
+ * {@link OsVersionChange} is applied to nodes.
*
* A version target is initially inactive. Activation decision is taken by
* {@link com.yahoo.vespa.hosted.provision.maintenance.OsUpgradeActivator}.
@@ -37,19 +39,29 @@ public class OsVersions {
this.upgrader = upgrader;
// Read and write all versions to make sure they are stored in the latest version of the serialized format
- try (var lock = db.lockOsVersions()) {
- db.writeOsVersions(db.readOsVersions());
+ try (var lock = db.lockOsVersionChange()) {
+ db.writeOsVersionChange(db.readOsVersionChange());
}
}
- /** Returns the current target versions for each node type */
- public Map<NodeType, Version> targets() {
- return db.readOsVersions();
+ /** Returns the current OS version change */
+ public OsVersionChange readChange() {
+ return db.readOsVersionChange();
+ }
+
+ /** Write the current OS version change with the result of the given operation applied */
+ public void writeChange(UnaryOperator<OsVersionChange> operation) {
+ try (var lock = db.lockOsVersionChange()) {
+ OsVersionChange change = readChange();
+ OsVersionChange newChange = operation.apply(change);
+ if (newChange.equals(change)) return; // Nothing changed
+ db.writeOsVersionChange(newChange);
+ }
}
/** Returns the current target version for given node type, if any */
public Optional<Version> targetFor(NodeType type) {
- return Optional.ofNullable(targets().get(type));
+ return Optional.ofNullable(readChange().targets().get(type));
}
/**
@@ -58,26 +70,26 @@ public class OsVersions {
*/
public void removeTarget(NodeType nodeType) {
require(nodeType);
- try (Lock lock = db.lockOsVersions()) {
- var osVersions = db.readOsVersions();
- osVersions.remove(nodeType);
+ writeChange((change) -> {
+ var targets = new HashMap<>(change.targets());
+ targets.remove(nodeType);
upgrader.disableUpgrade(nodeType);
- db.writeOsVersions(osVersions);
- }
+ return change.with(targets);
+ });
}
- /** Set the target OS version for nodes of given type */
+ /** Set the target OS version and upgrade budget for nodes of given type */
public void setTarget(NodeType nodeType, Version newTarget, boolean force) {
require(nodeType);
if (newTarget.isEmpty()) {
- throw new IllegalArgumentException("Invalid target version: " + newTarget.toFullString());
+ throw new IllegalArgumentException("Invalid target version: " + newTarget.toFullString());
}
- try (Lock lock = db.lockOsVersions()) {
- var osVersions = db.readOsVersions();
- var oldTarget = Optional.ofNullable(osVersions.get(nodeType));
+ writeChange((change) -> {
+ var targets = new HashMap<>(change.targets());
+ var oldTarget = Optional.ofNullable(targets.get(nodeType));
if (oldTarget.filter(v -> v.equals(newTarget)).isPresent()) {
- return; // Old target matches new target, nothing to do
+ return change; // Old target matches new target, nothing to do
}
if (!force && oldTarget.filter(v -> v.isAfter(newTarget)).isPresent()) {
@@ -86,21 +98,20 @@ public class OsVersions {
+ oldTarget.get());
}
- osVersions.put(nodeType, newTarget);
- db.writeOsVersions(osVersions);
+ targets.put(nodeType, newTarget);
log.info("Set OS target version for " + nodeType + " nodes to " + newTarget.toFullString());
- }
+ return change.with(targets);
+ });
}
/** Resume or halt upgrade of given node type */
public void resumeUpgradeOf(NodeType nodeType, boolean resume) {
require(nodeType);
- try (Lock lock = db.lockOsVersions()) {
- var osVersions = db.readOsVersions();
- var currentVersion = osVersions.get(nodeType);
- if (currentVersion == null) return; // No target version set for this type
+ try (Lock lock = db.lockOsVersionChange()) {
+ var targetVersion = readChange().targets().get(nodeType);
+ if (targetVersion == null) return; // No target version set for this type
if (resume) {
- upgrader.upgrade(nodeType, currentVersion);
+ upgrader.upgrade(nodeType, targetVersion);
} else {
upgrader.disableUpgrade(nodeType);
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java
index 4defbb55485..367271564ea 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java
@@ -1,4 +1,4 @@
-// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.provision.persistence;
import com.google.common.util.concurrent.UncheckedTimeoutException;
@@ -12,7 +12,6 @@ import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.Zone;
-import java.util.logging.Level;
import com.yahoo.path.Path;
import com.yahoo.transaction.NestedTransaction;
import com.yahoo.transaction.Transaction;
@@ -27,6 +26,7 @@ import com.yahoo.vespa.hosted.provision.lb.LoadBalancer;
import com.yahoo.vespa.hosted.provision.lb.LoadBalancerId;
import com.yahoo.vespa.hosted.provision.node.Agent;
import com.yahoo.vespa.hosted.provision.node.Status;
+import com.yahoo.vespa.hosted.provision.os.OsVersionChange;
import java.time.Clock;
import java.time.Duration;
@@ -488,19 +488,19 @@ public class CuratorDatabaseClient implements JobControl.Db {
// OS versions -----------------------------------------------------------
- public Map<NodeType, Version> readOsVersions() {
- return read(osVersionsPath, OsVersionsSerializer::fromJson).orElseGet(TreeMap::new);
+ public OsVersionChange readOsVersionChange() {
+ return read(osVersionsPath, OsVersionChangeSerializer::fromJson).orElse(OsVersionChange.NONE);
}
- public void writeOsVersions(Map<NodeType, Version> versions) {
+ public void writeOsVersionChange(OsVersionChange change) {
NestedTransaction transaction = new NestedTransaction();
CuratorTransaction curatorTransaction = db.newCuratorTransactionIn(transaction);
curatorTransaction.add(CuratorOperations.setData(osVersionsPath.getAbsolute(),
- OsVersionsSerializer.toJson(versions)));
+ OsVersionChangeSerializer.toJson(change)));
transaction.commit();
}
- public Lock lockOsVersions() {
+ public Lock lockOsVersionChange() {
return db.lock(lockPath.append("osVersionsLock"), defaultLockTimeout);
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionChangeSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionChangeSerializer.java
new file mode 100644
index 00000000000..b2b329725f5
--- /dev/null
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionChangeSerializer.java
@@ -0,0 +1,75 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.provision.persistence;
+
+import com.yahoo.component.Version;
+import com.yahoo.config.provision.NodeType;
+import com.yahoo.slime.ArrayTraverser;
+import com.yahoo.slime.ObjectTraverser;
+import com.yahoo.slime.Slime;
+import com.yahoo.slime.SlimeUtils;
+import com.yahoo.vespa.hosted.provision.os.OsVersionChange;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.HashMap;
+
+/**
+ * Serializer for {@link OsVersionChange}.
+ *
+ * @author mpolden
+ */
+public class OsVersionChangeSerializer {
+
+ private static final String TARGETS_FIELD = "targets";
+ private static final String NODE_TYPE_FIELD = "nodeType";
+ private static final String VERSION_FIELD = "version";
+
+ private OsVersionChangeSerializer() {}
+
+ public static byte[] toJson(OsVersionChange change) {
+ var slime = new Slime();
+ var object = slime.setObject();
+ var targetsObject = object.setArray(TARGETS_FIELD);
+ change.targets().forEach((nodeType, osVersion) -> {
+ var targetObject = targetsObject.addObject();
+ targetObject.setString(NODE_TYPE_FIELD, NodeSerializer.toString(nodeType));
+ targetObject.setString(VERSION_FIELD, osVersion.toFullString());
+ // TODO(mpolden): Stop writing old format after May 2020
+ var versionObject = object.setObject(NodeSerializer.toString(nodeType));
+ versionObject.setString(VERSION_FIELD, osVersion.toFullString());
+ });
+ try {
+ return SlimeUtils.toJsonBytes(slime);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ public static OsVersionChange fromJson(byte[] data) {
+ var targets = new HashMap<NodeType, Version>();
+ var inspector = SlimeUtils.jsonToSlime(data).get();
+ // TODO(mpolden): Remove reading of old format after May 2020
+ inspector.traverse((ObjectTraverser) (key, value) -> {
+ if (isNodeType(key)) {
+ var version = Version.fromString(value.field(VERSION_FIELD).asString());
+ targets.put(NodeSerializer.nodeTypeFromString(key), version);
+ }
+ });
+ inspector.field(TARGETS_FIELD).traverse((ArrayTraverser) (idx, arrayInspector) -> {
+ var version = Version.fromString(arrayInspector.field(VERSION_FIELD).asString());
+ var nodeType = NodeSerializer.nodeTypeFromString(arrayInspector.field(NODE_TYPE_FIELD).asString());
+ targets.put(nodeType, version);
+ });
+ return new OsVersionChange(targets);
+ }
+
+ private static boolean isNodeType(String name) {
+ try {
+ NodeType.valueOf(name);
+ return true;
+ } catch (IllegalArgumentException ignored) {
+ return false;
+ }
+ }
+
+}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionsSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionsSerializer.java
deleted file mode 100644
index fd430350b5c..00000000000
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionsSerializer.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.provision.persistence;
-
-import com.yahoo.component.Version;
-import com.yahoo.config.provision.NodeType;
-import com.yahoo.slime.ObjectTraverser;
-import com.yahoo.slime.Slime;
-import com.yahoo.slime.SlimeUtils;
-import com.yahoo.vespa.hosted.provision.node.OsVersion;
-
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * Serializer for a map of {@link NodeType} and {@link OsVersion}.
- *
- * @author mpolden
- */
-public class OsVersionsSerializer {
-
- private static final String VERSION_FIELD = "version";
-
- private OsVersionsSerializer() {}
-
- public static byte[] toJson(Map<NodeType, Version> versions) {
- var slime = new Slime();
- var object = slime.setObject();
- versions.forEach((nodeType, osVersion) -> {
- var versionObject = object.setObject(NodeSerializer.toString(nodeType));
- versionObject.setString(VERSION_FIELD, osVersion.toFullString());
- });
- try {
- return SlimeUtils.toJsonBytes(slime);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public static Map<NodeType, Version> fromJson(byte[] data) {
- var versions = new TreeMap<NodeType, Version>(); // Use TreeMap to sort by node type
- var inspector = SlimeUtils.jsonToSlime(data).get();
- inspector.traverse((ObjectTraverser) (key, value) -> {
- if (isNodeType(key)) {
- var version = Version.fromString(value.field(VERSION_FIELD).asString());
- versions.put(NodeSerializer.nodeTypeFromString(key), version);
- }
- });
- return versions;
- }
-
- private static boolean isNodeType(String name) {
- try {
- NodeType.valueOf(name);
- return true;
- } catch (IllegalArgumentException ignored) {
- return false;
- }
- }
-
-}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/UpgradeResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/UpgradeResponse.java
index 16858ec6963..be87a984941 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/UpgradeResponse.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/UpgradeResponse.java
@@ -39,7 +39,7 @@ public class UpgradeResponse extends HttpResponse {
infrastructureVersions.getTargetVersions().forEach((nodeType, version) -> versionsObject.setString(nodeType.name(), version.toFullString()));
Cursor osVersionsObject = root.setObject("osVersions");
- osVersions.targets().forEach((nodeType, osVersion) -> osVersionsObject.setString(nodeType.name(), osVersion.toFullString()));
+ osVersions.readChange().targets().forEach((nodeType, osVersion) -> osVersionsObject.setString(nodeType.name(), osVersion.toFullString()));
Cursor dockerImagesObject = root.setObject("dockerImages");
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java
index b8b09199ba2..e1d3eea58fd 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java
@@ -1,4 +1,4 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.provision.os;
import com.yahoo.component.Version;
@@ -36,12 +36,11 @@ public class OsVersionsTest {
@Test
public void test_versions() {
var versions = new OsVersions(tester.nodeRepository(), new DelegatingUpgrader(tester.nodeRepository(), Integer.MAX_VALUE));
- tester.makeReadyNodes(10, "default", NodeType.host);
- tester.prepareAndActivateInfraApplication(infraApplication, NodeType.host);
+ provisionInfraApplication(10);
Supplier<List<Node>> hostNodes = () -> tester.nodeRepository().getNodes(NodeType.host);
// Upgrade OS
- assertTrue("No versions set", versions.targets().isEmpty());
+ assertTrue("No versions set", versions.readChange().targets().isEmpty());
var version1 = Version.fromString("7.1");
versions.setTarget(NodeType.host, version1, false);
assertEquals(version1, versions.targetFor(NodeType.host).get());
@@ -81,9 +80,8 @@ public class OsVersionsTest {
int totalNodes = 20;
int maxActiveUpgrades = 5;
var versions = new OsVersions(tester.nodeRepository(), new DelegatingUpgrader(tester.nodeRepository(), maxActiveUpgrades));
- tester.makeReadyNodes(totalNodes, "default", NodeType.host);
+ provisionInfraApplication(totalNodes);
Supplier<NodeList> hostNodes = () -> tester.nodeRepository().list().state(Node.State.active).nodeType(NodeType.host);
- tester.prepareAndActivateInfraApplication(infraApplication, NodeType.host);
// 5 nodes have no version. The other 15 are spread across different versions
var hostNodesList = hostNodes.get().asList();
@@ -128,8 +126,7 @@ public class OsVersionsTest {
@Test
public void test_newer_upgrade_aborts_upgrade_to_stale_version() {
var versions = new OsVersions(tester.nodeRepository(), new DelegatingUpgrader(tester.nodeRepository(), Integer.MAX_VALUE));
- tester.makeReadyNodes(10, "default", NodeType.host);
- tester.prepareAndActivateInfraApplication(infraApplication, NodeType.host);
+ provisionInfraApplication(10);
Supplier<NodeList> hostNodes = () -> tester.nodeRepository().list().nodeType(NodeType.host);
// Some nodes are targeting an older version
@@ -145,6 +142,11 @@ public class OsVersionsTest {
assertEquals(version2, minVersion(hostNodes.get(), OsVersion::wanted));
}
+ private void provisionInfraApplication(int nodeCount) {
+ tester.makeReadyNodes(nodeCount, "default", NodeType.host);
+ tester.prepareAndActivateInfraApplication(infraApplication, NodeType.host);
+ }
+
private Version minVersion(NodeList nodes, Function<OsVersion, Optional<Version>> versionField) {
return nodes.asList().stream()
.map(Node::status)
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionChangeSerializerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionChangeSerializerTest.java
new file mode 100644
index 00000000000..b26c0f9055f
--- /dev/null
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionChangeSerializerTest.java
@@ -0,0 +1,51 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.provision.persistence;
+
+import com.yahoo.component.Version;
+import com.yahoo.config.provision.NodeType;
+import com.yahoo.vespa.hosted.provision.os.OsVersionChange;
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author mpolden
+ */
+public class OsVersionChangeSerializerTest {
+
+ @Test
+ public void serialization() {
+ var change = new OsVersionChange(Map.of(
+ NodeType.host, Version.fromString("1.2.3"),
+ NodeType.proxyhost, Version.fromString("4.5.6"),
+ NodeType.confighost, Version.fromString("7.8.9")
+ ));
+ var serialized = OsVersionChangeSerializer.fromJson(OsVersionChangeSerializer.toJson(change));
+ assertEquals(serialized, change);
+ }
+
+ @Test
+ public void legacy_serialization() {
+ // Read old format
+ var change = new OsVersionChange(Map.of(
+ NodeType.host, Version.fromString("1.2.3"),
+ NodeType.proxyhost, Version.fromString("4.5.6"),
+ NodeType.confighost, Version.fromString("7.8.9")
+ ));
+ var legacyFormat = "{\"host\":{\"version\":\"1.2.3\"},\"proxyhost\":{\"version\":\"4.5.6\"},\"confighost\":{\"version\":\"7.8.9\"}}";
+ assertEquals(change, OsVersionChangeSerializer.fromJson(legacyFormat.getBytes(StandardCharsets.UTF_8)));
+
+ // Write format supported by both old and new serializer
+ var oldFormat = "{\"targets\":[{\"nodeType\":\"host\",\"version\":\"1.2.3\"}," +
+ "{\"nodeType\":\"proxyhost\",\"version\":\"4.5.6\"}," +
+ "{\"nodeType\":\"confighost\",\"version\":\"7.8.9\"}]," +
+ "\"host\":{\"version\":\"1.2.3\"}," +
+ "\"proxyhost\":{\"version\":\"4.5.6\"}," +
+ "\"confighost\":{\"version\":\"7.8.9\"}}";
+ assertEquals(oldFormat, new String(OsVersionChangeSerializer.toJson(change), StandardCharsets.UTF_8));
+ }
+
+}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionsSerializerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionsSerializerTest.java
deleted file mode 100644
index 36dbf26c0d3..00000000000
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/OsVersionsSerializerTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.provision.persistence;
-
-import com.yahoo.component.Version;
-import com.yahoo.config.provision.NodeType;
-import org.junit.Test;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * @author mpolden
- */
-public class OsVersionsSerializerTest {
-
- @Test
- public void serialization() {
- var versions = Map.of(
- NodeType.host, Version.fromString("1.2.3"),
- NodeType.proxyhost, Version.fromString("4.5.6"),
- NodeType.confighost, Version.fromString("7.8.9")
- );
- var serialized = OsVersionsSerializer.fromJson(OsVersionsSerializer.toJson(versions));
- assertEquals(serialized, versions);
- }
-
- @Test
- public void ignores_unknown_keys() {
- var jsonWithUnknownKeys = "{\n" +
- " \"foo\": \"bar\",\n" +
- " " +
- "\"host\": {\n" +
- " \"version\": \"1.2.3\"\n" +
- " },\n" +
- " " +
- "\"proxyhost\": {\n" +
- " \"version\": \"4.5.6\"\n" +
- " },\n" +
- " " +
- "\"confighost\": {\n" +
- " \"version\": \"7.8.9\"\n" +
- " }\n" +
- "}";
- var versions = Map.of(
- NodeType.host, Version.fromString("1.2.3"),
- NodeType.proxyhost, Version.fromString("4.5.6"),
- NodeType.confighost, Version.fromString("7.8.9")
- );
- assertEquals(versions, OsVersionsSerializer.fromJson(jsonWithUnknownKeys.getBytes(StandardCharsets.UTF_8)));
- }
-
-}