ONOS-3379: Config REST 500 errors on GET operations if keys don't exist
Change-Id: Ie32bdb70693c5571421840265b4be71d0706d797
diff --git a/utils/misc/src/main/java/org/onlab/util/Tools.java b/utils/misc/src/main/java/org/onlab/util/Tools.java
index 1b78814..ffefbfd 100644
--- a/utils/misc/src/main/java/org/onlab/util/Tools.java
+++ b/utils/misc/src/main/java/org/onlab/util/Tools.java
@@ -40,6 +40,7 @@
import java.util.Dictionary;
import java.util.List;
import java.util.Random;
+import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@@ -144,6 +145,23 @@
}
/**
+ * Returns the specified set if the set is not null and not empty;
+ * otherwise throws a not found exception.
+ *
+ * @param item set to check
+ * @param message not found message
+ * @param <T> Set item type
+ * @return item if not null and not empty
+ * @throws org.onlab.util.ItemNotFoundException if set is null or empty
+ */
+ public static <T> Set<T> emptyIsNotFound(Set<T> item, String message) {
+ if (item == null || item.isEmpty()) {
+ throw new ItemNotFoundException(message);
+ }
+ return item;
+ }
+
+ /**
* Returns the specified item if that item is not null; otherwise throws
* bad argument exception.
*
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/NetworkConfigWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/NetworkConfigWebResource.java
index 954b25a..69c0b6a 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/NetworkConfigWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/NetworkConfigWebResource.java
@@ -15,10 +15,9 @@
*/
package org.onosproject.rest.resources;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.config.SubjectFactory;
-import org.onosproject.rest.AbstractWebResource;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -29,8 +28,16 @@
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.io.InputStream;
+
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.SubjectFactory;
+import org.onosproject.rest.AbstractWebResource;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import static org.onlab.util.Tools.emptyIsNotFound;
+import static org.onlab.util.Tools.nullIsNotFound;
/**
* Manage network configurations.
@@ -38,8 +45,29 @@
@Path("network/configuration")
public class NetworkConfigWebResource extends AbstractWebResource {
+
+ private String subjectClassNotFoundErrorString(String subjectClassKey) {
+ return "Config for '" + subjectClassKey + "' not found";
+ }
+
+ private String subjectNotFoundErrorString(String subjectClassKey,
+ String subjectKey) {
+ return "Config for '"
+ + subjectClassKey + "/" + subjectKey
+ + "' not found";
+ }
+
+ private String configKeyNotFoundErrorString(String subjectClassKey,
+ String subjectKey,
+ String configKey) {
+ return "Config for '"
+ + subjectClassKey + "/" + subjectKey + "/" + configKey
+ + "' not found";
+ }
+
/**
* Get entire network configuration base.
+ *
* @rsModel NetCfgGet
* @return network configuration JSON
*/
@@ -70,7 +98,9 @@
public Response download(@PathParam("subjectClassKey") String subjectClassKey) {
NetworkConfigService service = get(NetworkConfigService.class);
ObjectNode root = mapper().createObjectNode();
- SubjectFactory subjectFactory = service.getSubjectFactory(subjectClassKey);
+ SubjectFactory subjectFactory =
+ nullIsNotFound(service.getSubjectFactory(subjectClassKey),
+ subjectClassNotFoundErrorString(subjectClassKey));
produceJson(service, root, subjectFactory, subjectFactory.subjectClass());
return ok(root).build();
}
@@ -90,8 +120,12 @@
@PathParam("subjectKey") String subjectKey) {
NetworkConfigService service = get(NetworkConfigService.class);
ObjectNode root = mapper().createObjectNode();
- SubjectFactory subjectFactory = service.getSubjectFactory(subjectClassKey);
- produceSubjectJson(service, root, subjectFactory.createSubject(subjectKey));
+ SubjectFactory subjectFactory =
+ nullIsNotFound(service.getSubjectFactory(subjectClassKey),
+ subjectClassNotFoundErrorString(subjectClassKey));
+ produceSubjectJson(service, root, subjectFactory.createSubject(subjectKey),
+ true,
+ subjectNotFoundErrorString(subjectClassKey, subjectKey));
return ok(root).build();
}
@@ -111,20 +145,40 @@
@PathParam("subjectKey") String subjectKey,
@PathParam("configKey") String configKey) {
NetworkConfigService service = get(NetworkConfigService.class);
- return ok(service.getConfig(service.getSubjectFactory(subjectClassKey).createSubject(subjectKey),
- service.getConfigClass(subjectClassKey, configKey)).node()).build();
+
+ Object subject =
+ nullIsNotFound(service.getSubjectFactory(subjectClassKey)
+ .createSubject(subjectKey),
+ subjectNotFoundErrorString(subjectClassKey, subjectKey));
+
+ Class configClass =
+ nullIsNotFound(service.getConfigClass(subjectClassKey, configKey),
+ configKeyNotFoundErrorString(subjectClassKey, subjectKey, configKey));
+ Config config =
+ nullIsNotFound(service.getConfig(subject, configClass),
+ configKeyNotFoundErrorString(subjectClassKey,
+ subjectKey,
+ configKey));
+ return ok(config.node()).build();
}
@SuppressWarnings("unchecked")
private void produceJson(NetworkConfigService service, ObjectNode node,
SubjectFactory subjectFactory, Class subjectClass) {
service.getSubjects(subjectClass).forEach(s ->
- produceSubjectJson(service, newObject(node, subjectFactory.subjectKey(s)), s));
+ produceSubjectJson(service, newObject(node, subjectFactory.subjectKey(s)), s, false, ""));
}
private void produceSubjectJson(NetworkConfigService service, ObjectNode node,
- Object subject) {
- service.getConfigs(subject).forEach(c -> node.set(c.key(), c.node()));
+ Object subject,
+ boolean emptyIsError,
+ String emptyErrorMessage) {
+ Set<? extends Config<Object>> configs = service.getConfigs(subject);
+ if (emptyIsError) {
+ // caller wants an empty set to be a 404
+ configs = emptyIsNotFound(configs, emptyErrorMessage);
+ }
+ configs.forEach(c -> node.set(c.key(), c.node()));
}