summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/go/cmd/document.go2
-rw-r--r--client/go/vespa/document.go5
-rw-r--r--client/js/app/yarn.lock12
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java28
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java34
5 files changed, 65 insertions, 16 deletions
diff --git a/client/go/cmd/document.go b/client/go/cmd/document.go
index b2f71121d1a..9fe1492fed9 100644
--- a/client/go/cmd/document.go
+++ b/client/go/cmd/document.go
@@ -200,7 +200,7 @@ func printResult(cli *CLI, result util.OperationResult, payloadOnlyOnSuccess boo
if !result.Success {
fmt.Fprintln(out, color.RedString("Error:"), result.Message)
- } else if !(payloadOnlyOnSuccess && result.Payload != "") {
+ } else if !payloadOnlyOnSuccess || result.Payload == "" {
fmt.Fprintln(out, color.GreenString("Success:"), result.Message)
}
diff --git a/client/go/vespa/document.go b/client/go/vespa/document.go
index e08208eba6d..e8620c59033 100644
--- a/client/go/vespa/document.go
+++ b/client/go/vespa/document.go
@@ -7,6 +7,7 @@ package vespa
import (
"bytes"
"encoding/json"
+ "fmt"
"io"
"net/http"
"net/url"
@@ -70,7 +71,9 @@ func sendOperation(documentId string, jsonFile string, service *Service, operati
}
var doc map[string]interface{}
- json.Unmarshal(documentData, &doc)
+ if err := json.Unmarshal(documentData, &doc); err != nil {
+ return util.Failure(fmt.Sprintf("Document is not valid JSON: %s", err))
+ }
operationInFile := operationIn(doc)
if operation == anyOperation { // Operation is decided by file content
diff --git a/client/js/app/yarn.lock b/client/js/app/yarn.lock
index febfd8e32bd..c25724fdbc4 100644
--- a/client/js/app/yarn.lock
+++ b/client/js/app/yarn.lock
@@ -3512,9 +3512,9 @@ json-stable-stringify-without-jsonify@^1.0.1:
integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
json5@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
- integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593"
+ integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==
dependencies:
minimist "^1.2.0"
@@ -3692,9 +3692,9 @@ minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
brace-expansion "^1.1.7"
minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.6:
- version "1.2.6"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
- integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18"
+ integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==
mixin-deep@^1.2.0:
version "1.3.2"
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 37583f00547..a9e134f7db5 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
@@ -62,6 +62,7 @@ public class CuratorDatabaseClient {
private static final Path root = Path.fromString("/provision/v1");
private static final Path lockPath = root.append("locks");
+ private static final Path nodesPath = root.append("nodes");
private static final Path loadBalancersPath = root.append("loadBalancers");
private static final Path applicationsPath = root.append("applications");
private static final Path inactiveJobsPath = root.append("inactiveJobs");
@@ -91,6 +92,8 @@ public class CuratorDatabaseClient {
private void initZK() {
db.create(root);
+ db.create(nodesPath);
+ // TODO(mpolden): Remove state paths after migration to nodesPath
for (Node.State state : Node.State.values())
db.create(toPath(state));
db.create(applicationsPath);
@@ -225,14 +228,21 @@ public class CuratorDatabaseClient {
private void writeNode(Node.State toState, CuratorTransaction curatorTransaction, Node node, Node newNode) {
byte[] nodeData = nodeSerializer.toJson(newNode);
- String currentNodePath = toPath(node).getAbsolute();
- String newNodePath = toPath(toState, newNode.hostname()).getAbsolute();
- if (newNodePath.equals(currentNodePath)) {
- curatorTransaction.add(CuratorOperations.setData(currentNodePath, nodeData));
- } else {
- curatorTransaction.add(CuratorOperations.delete(currentNodePath))
- .add(CuratorOperations.create(newNodePath, nodeData));
+ { // TODO(mpolden): Remove this after migration to nodesPath
+ String currentNodePath = toPath(node).getAbsolute();
+ String newNodePath = toPath(toState, newNode.hostname()).getAbsolute();
+ if (newNodePath.equals(currentNodePath)) {
+ curatorTransaction.add(CuratorOperations.setData(currentNodePath, nodeData));
+ } else {
+ curatorTransaction.add(CuratorOperations.delete(currentNodePath))
+ .add(CuratorOperations.create(newNodePath, nodeData));
+ }
+ }
+ Path nodePath = nodePath(newNode);
+ if (db.exists(nodePath)) {
+ curatorTransaction.add(CuratorOperations.delete(nodePath.getAbsolute()));
}
+ curatorTransaction.add(CuratorOperations.create(nodePath.getAbsolute(), nodeData));
}
private Status newNodeStatus(Node node, Node.State toState) {
@@ -294,6 +304,10 @@ public class CuratorDatabaseClient {
return root.append(toDir(nodeState)).append(nodeName);
}
+ private Path nodePath(Node node) {
+ return nodesPath.append(node.hostname());
+ }
+
/** Creates and returns the path to the lock for this application */
private Path lockPath(ApplicationId application) {
Path lockPath = CuratorDatabaseClient.lockPath.append(application.tenant().value())
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 94707f7f429..f448266b94b 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
@@ -48,7 +48,6 @@ import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutionException;
-import java.util.stream.Collectors;
/**
* Serializes a node to/from JSON.
@@ -69,6 +68,7 @@ public class NodeSerializer {
private final NodeFlavors flavors;
// Node fields
+ private static final String stateKey = "state";
private static final String hostnameKey = "hostname";
private static final String ipAddressesKey = "ipAddresses";
private static final String ipAddressPoolKey = "additionalIpAddresses";
@@ -166,6 +166,7 @@ public class NodeSerializer {
private void toSlime(Node node, Cursor object) {
object.setString(hostnameKey, node.hostname());
+ object.setString(stateKey, toString(node.state()));
toSlime(node.ipConfig().primary(), object.setArray(ipAddressesKey));
toSlime(node.ipConfig().pool().ipSet(), object.setArray(ipAddressPoolKey));
toSlime(node.ipConfig().pool().getAddressList(), object);
@@ -539,4 +540,35 @@ public class NodeSerializer {
};
}
+ static Node.State nodeStateFromString(String state) {
+ return switch (state) {
+ case "active" -> Node.State.active;
+ case "dirty" -> Node.State.dirty;
+ case "failed" -> Node.State.failed;
+ case "inactive" -> Node.State.inactive;
+ case "parked" -> Node.State.parked;
+ case "provisioned" -> Node.State.provisioned;
+ case "ready" -> Node.State.ready;
+ case "reserved" -> Node.State.reserved;
+ case "deprovisioned" -> Node.State.deprovisioned;
+ case "breakfixed" -> Node.State.breakfixed;
+ default -> throw new IllegalArgumentException("Unknown node state '" + state + "'");
+ };
+ }
+
+ static String toString(Node.State state) {
+ return switch (state) {
+ case active -> "active";
+ case dirty -> "dirty";
+ case failed -> "failed";
+ case inactive -> "inactive";
+ case parked -> "parked";
+ case provisioned -> "provisioned";
+ case ready -> "ready";
+ case reserved -> "reserved";
+ case deprovisioned -> "deprovisioned";
+ case breakfixed -> "breakfixed";
+ };
+ }
+
}