diff options
author | gjoranv <gjoranv@gmail.com> | 2023-09-05 13:17:10 +0200 |
---|---|---|
committer | gjoranv <gjoranv@gmail.com> | 2023-09-11 18:25:56 +0200 |
commit | 1f55e759b1830bc8f2386d7bc5db71e524327620 (patch) | |
tree | 26bb44c172fc3812dc52b10d74c7086d418425b0 /node-repository | |
parent | 0a383addced96943dd7e94ed50ec7006b3e282e1 (diff) |
Add wireguard key timestamp to node repo.
Diffstat (limited to 'node-repository')
10 files changed, 91 insertions, 36 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java index 864566f119e..8db8e7c2cf8 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java @@ -65,6 +65,7 @@ public final class Node implements Nodelike { /** Only set for configservers and exclave nodes */ private final Optional<WireguardKey> wireguardPubKey; + private final Optional<Instant> wireguardKeyTimestamp; /** Record of the last event of each type happening to this node */ private final History history; @@ -95,7 +96,8 @@ public final class Node implements Nodelike { NodeType type, Reports reports, Optional<String> modelName, Optional<TenantName> reservedTo, Optional<ApplicationId> exclusiveToApplicationId, Optional<Duration> hostTTL, Optional<Instant> hostEmptyAt, Optional<ClusterSpec.Type> exclusiveToClusterType, Optional<String> switchHostname, - List<TrustStoreItem> trustStoreItems, CloudAccount cloudAccount, Optional<WireguardKey> wireguardPubKey) { + List<TrustStoreItem> trustStoreItems, CloudAccount cloudAccount, Optional<WireguardKey> wireguardPubKey, + Optional<Instant> wireguardKeyTimestamp) { this.id = Objects.requireNonNull(id, "A node must have an ID"); this.extraId = Objects.requireNonNull(extraId, "Extra ID cannot be null"); this.hostname = requireNonEmptyString(hostname, "A node must have a hostname"); @@ -118,6 +120,7 @@ public final class Node implements Nodelike { this.trustStoreItems = Objects.requireNonNull(trustStoreItems).stream().distinct().toList(); this.cloudAccount = Objects.requireNonNull(cloudAccount); this.wireguardPubKey = Objects.requireNonNull(wireguardPubKey); + this.wireguardKeyTimestamp = Objects.requireNonNull(wireguardKeyTimestamp); if (state == State.active) requireNonEmpty(ipConfig.primary(), "Active node " + hostname + " must have at least one valid IP address"); @@ -265,6 +268,11 @@ public final class Node implements Nodelike { return wireguardPubKey; } + /** Returns the timestamp of the wireguard key of this node. Only relevant for enclave nodes. */ + public Optional<Instant> wireguardKeyTimestamp() { + return wireguardKeyTimestamp; + } + /** * Returns a copy of this where wantToFail is set to true and history is updated to reflect this. */ @@ -359,14 +367,16 @@ public final class Node implements Nodelike { public Node with(Status status) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } /** Returns a node with the type assigned to the given value */ public Node with(NodeType type) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } /** Returns a node with the flavor assigned to the given value */ @@ -375,35 +385,40 @@ public final class Node implements Nodelike { History updateHistory = history.with(new History.Event(History.Event.Type.resized, agent, instant)); return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, updateHistory, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } /** Returns a copy of this with the reboot generation set to generation */ public Node withReboot(Generation generation) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status.withReboot(generation), state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } /** Returns a copy of this with given id set */ public Node withId(String id) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } /** Returns a copy of this with model name set to given value */ public Node withModelName(String modelName) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, Optional.of(modelName), reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } /** Returns a copy of this with model name cleared */ public Node withoutModelName() { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, Optional.empty(), reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } /** Returns a copy of this with a history record saying it was detected to be down at this instant */ @@ -445,21 +460,24 @@ public final class Node implements Nodelike { public Node with(Allocation allocation) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, Optional.of(allocation), history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } /** Returns a copy of this node with IP config set to the given value. */ public Node with(IP.Config ipConfig) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } /** Returns a copy of this node with the parent hostname assigned to the given value. */ public Node withParentHostname(String parentHostname) { return new Node(id, extraId, ipConfig, hostname, Optional.of(parentHostname), flavor, status, state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } public Node withReservedTo(TenantName tenant) { @@ -467,57 +485,73 @@ public final class Node implements Nodelike { throw new IllegalArgumentException("Only host nodes can be reserved, " + hostname + " has type " + type); return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, Optional.of(tenant), exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } /** Returns a copy of this node which is not reserved to a tenant */ public Node withoutReservedTo() { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, Optional.empty(), exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } public Node withExclusiveToApplicationId(ApplicationId exclusiveTo) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, reservedTo, Optional.ofNullable(exclusiveTo), hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } public Node withExtraId(Optional<String> extraId) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } public Node withHostTTL(Duration hostTTL) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, Optional.ofNullable(hostTTL), hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } public Node withHostEmptyAt(Instant hostEmptyAt) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, Optional.ofNullable(hostEmptyAt), - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } public Node withExclusiveToClusterType(ClusterSpec.Type exclusiveTo) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - Optional.ofNullable(exclusiveTo), switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + Optional.ofNullable(exclusiveTo), switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } public Node withWireguardPubkey(WireguardKey wireguardPubkey) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, Optional.ofNullable(wireguardPubkey)); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, Optional.ofNullable(wireguardPubkey), + wireguardKeyTimestamp); + } + + public Node withWireguardKeyTimestamp(Instant wireguardKeyTimestamp) { + return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, + type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + Optional.ofNullable(wireguardKeyTimestamp)); } /** Returns a copy of this node with switch hostname set to given value */ public Node withSwitchHostname(String switchHostname) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, Optional.ofNullable(switchHostname), trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, Optional.ofNullable(switchHostname), trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } /** Returns a copy of this node with switch hostname unset */ @@ -570,19 +604,22 @@ public final class Node implements Nodelike { public Node with(History history) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } public Node with(Reports reports) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } public Node with(List<TrustStoreItem> trustStoreItems) { return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt, - exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey); + exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey, + wireguardKeyTimestamp); } private static Optional<String> requireNonEmptyString(Optional<String> value, String message) { @@ -731,6 +768,7 @@ public final class Node implements Nodelike { private List<TrustStoreItem> trustStoreItems; private CloudAccount cloudAccount = CloudAccount.empty; private WireguardKey wireguardPubKey; + private Instant wireguardKeyTimestamp; private Builder(String id, String hostname, Flavor flavor, State state, NodeType type) { this.id = id; @@ -825,6 +863,11 @@ public final class Node implements Nodelike { return this; } + public Builder wireguardKeyTimestamp(Instant wireguardKeyTimestamp) { + this.wireguardKeyTimestamp = wireguardKeyTimestamp; + return this; + } + public Node build() { return new Node(id, Optional.empty(), Optional.ofNullable(ipConfig).orElse(IP.Config.EMPTY), hostname, Optional.ofNullable(parentHostname), flavor, Optional.ofNullable(status).orElseGet(Status::initial), state, Optional.ofNullable(allocation), @@ -832,7 +875,7 @@ public final class Node implements Nodelike { Optional.ofNullable(modelName), Optional.ofNullable(reservedTo), Optional.ofNullable(exclusiveToApplicationId), Optional.ofNullable(hostTTL), Optional.ofNullable(hostEmptyAt), Optional.ofNullable(exclusiveToClusterType), Optional.ofNullable(switchHostname), Optional.ofNullable(trustStoreItems).orElseGet(List::of), cloudAccount, - Optional.ofNullable(wireguardPubKey)); + Optional.ofNullable(wireguardPubKey), Optional.ofNullable(wireguardKeyTimestamp)); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java index 43a135a7e04..3c3868bfeb8 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java @@ -4,7 +4,6 @@ package com.yahoo.vespa.hosted.provision.persistence; import ai.vespa.http.DomainName; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import com.google.common.util.concurrent.UncheckedExecutionException; import com.yahoo.collections.Pair; import com.yahoo.component.Version; import com.yahoo.concurrent.UncheckedTimeoutException; @@ -42,7 +41,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.TreeMap; -import java.util.concurrent.ExecutionException; import java.util.function.Function; import java.util.function.Predicate; import java.util.logging.Level; @@ -222,8 +220,9 @@ public class CuratorDb { toState.isAllocated() ? node.allocation() : Optional.empty(), node.history().recordStateTransition(node.state(), toState, agent, clock.instant()), node.type(), node.reports(), node.modelName(), node.reservedTo(), - node.exclusiveToApplicationId(), node.hostTTL(), node.hostEmptyAt(), node.exclusiveToClusterType(), - node.switchHostname(), node.trustedCertificates(), node.cloudAccount(), node.wireguardPubKey()); + node.exclusiveToApplicationId(), node.hostTTL(), node.hostEmptyAt(), + node.exclusiveToClusterType(), node.switchHostname(), node.trustedCertificates(), + node.cloudAccount(), node.wireguardPubKey(), node.wireguardKeyTimestamp()); curatorTransaction.add(createOrSet(nodePath(newNode), nodeSerializer.toJson(newNode))); writtenNodes.add(newNode); } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java index df39a0230b6..358c94895d1 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java @@ -100,6 +100,7 @@ public class NodeSerializer { private static final String trustedCertificatesKey = "trustedCertificates"; private static final String cloudAccountKey = "cloudAccount"; private static final String wireguardPubKeyKey = "wireguardPubkey"; + private static final String wireguardKeyTimestampKey = "wireguardKeyTimestamp"; // Node resource fields private static final String flavorKey = "flavor"; @@ -190,6 +191,7 @@ public class NodeSerializer { object.setString(cloudAccountKey, node.cloudAccount().value()); } node.wireguardPubKey().ifPresent(pubKey -> object.setString(wireguardPubKeyKey, pubKey.value())); + node.wireguardKeyTimestamp().ifPresent(timestamp -> object.setLong(wireguardKeyTimestampKey, timestamp.toEpochMilli())); } private void toSlime(Flavor flavor, Cursor object) { @@ -284,7 +286,8 @@ public class NodeSerializer { SlimeUtils.optionalString(object.field(switchHostnameKey)), trustedCertificatesFromSlime(object), SlimeUtils.optionalString(object.field(cloudAccountKey)).map(CloudAccount::from).orElse(CloudAccount.empty), - SlimeUtils.optionalString(object.field(wireguardPubKeyKey)).map(WireguardKey::from)); + SlimeUtils.optionalString(object.field(wireguardPubKeyKey)).map(WireguardKey::from), + SlimeUtils.optionalInstant(object.field(wireguardKeyTimestampKey))); } private Status statusFromSlime(Inspector object) { diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodePatcher.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodePatcher.java index d88cade0022..45d6f13513a 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodePatcher.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodePatcher.java @@ -109,7 +109,8 @@ public class NodePatcher { "reports", "trustStore", "vespaVersion", - "wireguardPubkey")); + "wireguardPubkey", + "wireguardKeyTimestamp")); if (!disallowedFields.isEmpty()) { throw new IllegalArgumentException("Patching fields not supported: " + disallowedFields); } @@ -274,6 +275,8 @@ public class NodePatcher { return nodeWithTrustStore(node, value); case "wireguardPubkey": return node.withWireguardPubkey(SlimeUtils.optionalString(value).map(WireguardKey::new).orElse(null)); + case "wireguardKeyTimestamp": + return node.withWireguardKeyTimestamp(SlimeUtils.optionalInstant(value).orElse(null)); default : throw new IllegalArgumentException("Could not apply field '" + name + "' on a node: No such modifiable field"); } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java index 5221fa8875b..e3960cc5db5 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java @@ -193,6 +193,7 @@ class NodesResponse extends SlimeJsonResponse { object.setString("cloudAccount", node.cloudAccount().value()); } node.wireguardPubKey().ifPresent(key -> object.setString("wireguardPubkey", key.value())); + node.wireguardKeyTimestamp().ifPresent(timestamp -> object.setLong("wireguardKeyTimestamp", timestamp.toEpochMilli())); } private Version resolveVersionFlag(StringFlag flag, Node node, Allocation allocation) { diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java index 90cf37aa876..086639d7276 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java @@ -163,6 +163,7 @@ public class MockNodeRepository extends NodeRepository { nodes.add(Node.create("dockerhost2", ipConfig(101, 1, 3), "dockerhost2.yahoo.com", flavors.getFlavorOrThrow("large"), NodeType.host) .wireguardPubKey(WireguardKey.from("000011112222333344445555666677778888999900c=")) + .wireguardKeyTimestamp(Instant.ofEpochMilli(123L)) .cloudAccount(tenantAccount).build()); nodes.add(Node.create("dockerhost3", ipConfig(102, 1, 3), "dockerhost3.yahoo.com", flavors.getFlavorOrThrow("large"), NodeType.host).cloudAccount(defaultCloudAccount).build()); @@ -176,7 +177,9 @@ public class MockNodeRepository extends NodeRepository { // Config servers nodes.add(Node.create("cfg1", ipConfig(201), "cfg1.yahoo.com", flavors.getFlavorOrThrow("default"), NodeType.config) .cloudAccount(defaultCloudAccount) - .wireguardPubKey(WireguardKey.from("lololololololololololololololololololololoo=")).build()); + .wireguardPubKey(WireguardKey.from("lololololololololololololololololololololoo=")) + .wireguardKeyTimestamp(Instant.ofEpochMilli(456L)) + .build()); nodes.add(Node.create("cfg2", ipConfig(202), "cfg2.yahoo.com", flavors.getFlavorOrThrow("default"), NodeType.config) .cloudAccount(defaultCloudAccount) .build()); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiTest.java index 7769523f3d6..5f0a70ab420 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiTest.java @@ -399,13 +399,13 @@ public class NodesV2ApiTest { "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Could not set field 'wireguardPubkey': Wireguard key must match '^[A-Za-z0-9+/]{42}[AEIMQUYcgkosw480]=$', but got: 'not a wg key'\"}"); assertResponse(new Request("http://localhost:8080/nodes/v2/node/host4.yahoo.com", - Utf8.toBytes("{\"wireguardPubkey\": \"lololololololololololololololololololololoo=\"}"), Request.Method.PATCH), + Utf8.toBytes("{\"wireguardPubkey\": \"lololololololololololololololololololololoo=\",\"wireguardKeyTimestamp\" : 789}"), Request.Method.PATCH), "{\"message\":\"Updated host4.yahoo.com\"}"); assertFile(new Request("http://localhost:8080/nodes/v2/node/host4.yahoo.com"), "node4-wg.json"); } - @Test + @Test public void post_controller_node() throws Exception { String data = "[{\"hostname\":\"controller1.yahoo.com\", \"id\":\"fake-controller1.yahoo.com\"," + createIpAddresses("127.0.0.1") + diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/cfg1.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/cfg1.json index fc72d9e08cc..928e91861a2 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/cfg1.json +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/cfg1.json @@ -119,5 +119,6 @@ ], "additionalIpAddresses": [], "cloudAccount": "aws:111222333444", - "wireguardPubkey":"lololololololololololololololololololololoo=" + "wireguardPubkey":"lololololololololololololololololololololoo=", + "wireguardKeyTimestamp": 456 } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/docker-node2.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/docker-node2.json index c1c1ba0cae8..72b5483d849 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/docker-node2.json +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/docker-node2.json @@ -117,5 +117,6 @@ "ipAddresses": ["127.0.101.1", "::101:1"], "additionalIpAddresses": ["::101:2", "::101:3", "::101:4"], "cloudAccount": "aws:777888999000", - "wireguardPubkey": "000011112222333344445555666677778888999900c=" + "wireguardPubkey": "000011112222333344445555666677778888999900c=", + "wireguardKeyTimestamp": 123 } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/node4-wg.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/node4-wg.json index a385a319bfe..7911c0eff3d 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/node4-wg.json +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/node4-wg.json @@ -118,5 +118,6 @@ "ipAddresses": ["127.0.4.1", "::4:1"], "additionalIpAddresses": [], "cloudAccount": "aws:111222333444", - "wireguardPubkey": "lololololololololololololololololololololoo=" + "wireguardPubkey": "lololololololololololololololololololololoo=", + "wireguardKeyTimestamp": 789 } |