Jian Li
Committed by Gerrit Code Review

Revise Mastership REST API to use synchronous methods

- Add missing swagger docs
- Add missing unit tests

Change-Id: I21a20410ea322e7893c5c0c48f5d9fd0f2f9dfe1
...@@ -37,8 +37,6 @@ import javax.ws.rs.core.Response; ...@@ -37,8 +37,6 @@ import javax.ws.rs.core.Response;
37 import java.io.IOException; 37 import java.io.IOException;
38 import java.io.InputStream; 38 import java.io.InputStream;
39 import java.util.Set; 39 import java.util.Set;
40 -import java.util.concurrent.CompletableFuture;
41 -import java.util.concurrent.ExecutionException;
42 40
43 import static org.onlab.util.Tools.nullIsNotFound; 41 import static org.onlab.util.Tools.nullIsNotFound;
44 42
...@@ -48,8 +46,7 @@ import static org.onlab.util.Tools.nullIsNotFound; ...@@ -48,8 +46,7 @@ import static org.onlab.util.Tools.nullIsNotFound;
48 @Path("mastership") 46 @Path("mastership")
49 public final class MastershipWebResource extends AbstractWebResource { 47 public final class MastershipWebResource extends AbstractWebResource {
50 48
51 - private static final String NODE = "node"; 49 + private static final String DEVICE_IDS = "deviceIds";
52 - private static final String DEVICES = "devices";
53 private static final String DEVICE_ID = "deviceId"; 50 private static final String DEVICE_ID = "deviceId";
54 private static final String NODE_ID = "nodeId"; 51 private static final String NODE_ID = "nodeId";
55 52
...@@ -59,7 +56,6 @@ public final class MastershipWebResource extends AbstractWebResource { ...@@ -59,7 +56,6 @@ public final class MastershipWebResource extends AbstractWebResource {
59 private static final String NODE_ID_NOT_FOUND = "Node id is not found"; 56 private static final String NODE_ID_NOT_FOUND = "Node id is not found";
60 private static final String ROLE_INFO_NOT_FOUND = "Role info is not found"; 57 private static final String ROLE_INFO_NOT_FOUND = "Role info is not found";
61 private static final String MASTERSHIP_ROLE_NOT_FOUND = "Mastership role is not found"; 58 private static final String MASTERSHIP_ROLE_NOT_FOUND = "Mastership role is not found";
62 - private static final String RESULT_NOT_FOUND = "Result is not found";
63 59
64 private final MastershipService mastershipService = get(MastershipService.class); 60 private final MastershipService mastershipService = get(MastershipService.class);
65 private final MastershipAdminService mastershipAdminService = 61 private final MastershipAdminService mastershipAdminService =
...@@ -86,7 +82,7 @@ public final class MastershipWebResource extends AbstractWebResource { ...@@ -86,7 +82,7 @@ public final class MastershipWebResource extends AbstractWebResource {
86 * 82 *
87 * @param deviceId device identifier 83 * @param deviceId device identifier
88 * @return the identifier of the master controller for the device 84 * @return the identifier of the master controller for the device
89 - * // TODO: add swagger doc 85 + * @onos.rsModel NodeId
90 */ 86 */
91 @GET 87 @GET
92 @Produces(MediaType.APPLICATION_JSON) 88 @Produces(MediaType.APPLICATION_JSON)
...@@ -96,7 +92,7 @@ public final class MastershipWebResource extends AbstractWebResource { ...@@ -96,7 +92,7 @@ public final class MastershipWebResource extends AbstractWebResource {
96 DeviceId.deviceId(deviceId)), NODE_ID_NOT_FOUND); 92 DeviceId.deviceId(deviceId)), NODE_ID_NOT_FOUND);
97 93
98 ObjectNode root = mapper().createObjectNode(); 94 ObjectNode root = mapper().createObjectNode();
99 - root.put(NODE, id.id()); 95 + root.put(NODE_ID, id.id());
100 return ok(root).build(); 96 return ok(root).build();
101 } 97 }
102 98
...@@ -123,14 +119,14 @@ public final class MastershipWebResource extends AbstractWebResource { ...@@ -123,14 +119,14 @@ public final class MastershipWebResource extends AbstractWebResource {
123 * 119 *
124 * @param nodeId controller identifier 120 * @param nodeId controller identifier
125 * @return a set of device identifiers 121 * @return a set of device identifiers
126 - * // TODO: add swagger doc 122 + * @onos.rsModel DeviceIds
127 */ 123 */
128 @GET 124 @GET
129 @Produces(MediaType.APPLICATION_JSON) 125 @Produces(MediaType.APPLICATION_JSON)
130 @Path("{nodeId}/device") 126 @Path("{nodeId}/device")
131 public Response getDeviceOf(@PathParam("nodeId") String nodeId) { 127 public Response getDeviceOf(@PathParam("nodeId") String nodeId) {
132 ObjectNode root = mapper().createObjectNode(); 128 ObjectNode root = mapper().createObjectNode();
133 - ArrayNode devicesNode = root.putArray(DEVICES); 129 + ArrayNode devicesNode = root.putArray(DEVICE_IDS);
134 130
135 Set<DeviceId> devices = mastershipService.getDevicesOf(NodeId.nodeId(nodeId)); 131 Set<DeviceId> devices = mastershipService.getDevicesOf(NodeId.nodeId(nodeId));
136 if (devices != null) { 132 if (devices != null) {
...@@ -152,20 +148,10 @@ public final class MastershipWebResource extends AbstractWebResource { ...@@ -152,20 +148,10 @@ public final class MastershipWebResource extends AbstractWebResource {
152 @Produces(MediaType.APPLICATION_JSON) 148 @Produces(MediaType.APPLICATION_JSON)
153 @Path("{deviceId}/request") 149 @Path("{deviceId}/request")
154 public Response requestRoleFor(@PathParam("deviceId") String deviceId) { 150 public Response requestRoleFor(@PathParam("deviceId") String deviceId) {
155 - 151 + MastershipRole role = nullIsNotFound(mastershipService.requestRoleForSync(
156 - // TODO: will not use CompletableFuture when MastershipService
157 - // provides a non CompletableFuture object as an output
158 - CompletableFuture<MastershipRole> result =
159 - nullIsNotFound(mastershipService.requestRoleFor(
160 DeviceId.deviceId(deviceId)), MASTERSHIP_ROLE_NOT_FOUND); 152 DeviceId.deviceId(deviceId)), MASTERSHIP_ROLE_NOT_FOUND);
161 -
162 - try {
163 - MastershipRole role = result.get();
164 ObjectNode root = codec(MastershipRole.class).encode(role, this); 153 ObjectNode root = codec(MastershipRole.class).encode(role, this);
165 return ok(root).build(); 154 return ok(root).build();
166 - } catch (InterruptedException | ExecutionException e) {
167 - throw new IllegalArgumentException(e);
168 - }
169 } 155 }
170 156
171 /** 157 /**
...@@ -181,18 +167,8 @@ public final class MastershipWebResource extends AbstractWebResource { ...@@ -181,18 +167,8 @@ public final class MastershipWebResource extends AbstractWebResource {
181 @Path("{deviceId}/relinquish") 167 @Path("{deviceId}/relinquish")
182 public Response relinquishMastership(@PathParam("deviceId") String deviceId) { 168 public Response relinquishMastership(@PathParam("deviceId") String deviceId) {
183 DeviceId id = DeviceId.deviceId(deviceId); 169 DeviceId id = DeviceId.deviceId(deviceId);
184 - 170 + mastershipService.relinquishMastershipSync(id);
185 - // TODO: will not use CompletableFuture when MastershipService
186 - // provides a non CompletableFuture object as an output
187 - CompletableFuture<Void> result =
188 - nullIsNotFound(mastershipService.relinquishMastership(id), RESULT_NOT_FOUND);
189 -
190 - try {
191 - result.get();
192 return Response.created(id.uri()).build(); 171 return Response.created(id.uri()).build();
193 - } catch (InterruptedException | ExecutionException e) {
194 - throw new IllegalArgumentException(e);
195 - }
196 } 172 }
197 173
198 /** 174 /**
...@@ -222,15 +198,11 @@ public final class MastershipWebResource extends AbstractWebResource { ...@@ -222,15 +198,11 @@ public final class MastershipWebResource extends AbstractWebResource {
222 throw new IllegalArgumentException(NODE_ID_INVALID); 198 throw new IllegalArgumentException(NODE_ID_INVALID);
223 } 199 }
224 200
225 - // TODO: will not use CompletableFuture when MastershipAdminService 201 + mastershipAdminService.setRoleSync(NodeId.nodeId(nodeIdJson.asText()),
226 - // provides a non CompletableFuture object as an output 202 + DeviceId.deviceId(deviceIdJson.asText()), role);
227 - CompletableFuture<Void> result =
228 - nullIsNotFound(mastershipAdminService.setRole(NodeId.nodeId(nodeIdJson.asText()),
229 - DeviceId.deviceId(deviceIdJson.asText()), role), RESULT_NOT_FOUND);
230 - result.get();
231 203
232 return Response.ok().build(); 204 return Response.ok().build();
233 - } catch (InterruptedException | ExecutionException | IOException e) { 205 + } catch (IOException e) {
234 throw new IllegalArgumentException(e); 206 throw new IllegalArgumentException(e);
235 } 207 }
236 } 208 }
......
1 +{
2 + "type": "object",
3 + "title": "deviceIds",
4 + "required": [
5 + "deviceIds"
6 + ],
7 + "properties": {
8 + "deviceIds": {
9 + "type": "array",
10 + "xml": {
11 + "name": "deviceId",
12 + "wrapped": true
13 + },
14 + "items": {
15 + "type": "string",
16 + "example": "of:0000000000000001"
17 + }
18 + }
19 + }
20 +}
1 +{
2 + "type": "object",
3 + "title": "nodeId",
4 + "required": [
5 + "nodeId"
6 + ],
7 + "properties": {
8 + "nodeId": {
9 + "type": "string",
10 + "example": "1"
11 + }
12 + }
13 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableList; ...@@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableList;
22 import com.google.common.collect.ImmutableSet; 22 import com.google.common.collect.ImmutableSet;
23 import org.apache.commons.lang3.StringUtils; 23 import org.apache.commons.lang3.StringUtils;
24 import org.hamcrest.Description; 24 import org.hamcrest.Description;
25 +import org.hamcrest.Matchers;
25 import org.hamcrest.TypeSafeMatcher; 26 import org.hamcrest.TypeSafeMatcher;
26 import org.junit.Before; 27 import org.junit.Before;
27 import org.junit.Test; 28 import org.junit.Test;
...@@ -37,8 +38,10 @@ import org.onosproject.mastership.MastershipService; ...@@ -37,8 +38,10 @@ import org.onosproject.mastership.MastershipService;
37 import org.onosproject.net.DeviceId; 38 import org.onosproject.net.DeviceId;
38 import org.onosproject.net.MastershipRole; 39 import org.onosproject.net.MastershipRole;
39 40
41 +import javax.ws.rs.client.Entity;
40 import javax.ws.rs.client.WebTarget; 42 import javax.ws.rs.client.WebTarget;
41 import javax.ws.rs.core.Response; 43 import javax.ws.rs.core.Response;
44 +import java.io.InputStream;
42 import java.net.HttpURLConnection; 45 import java.net.HttpURLConnection;
43 import java.util.List; 46 import java.util.List;
44 import java.util.Set; 47 import java.util.Set;
...@@ -214,9 +217,9 @@ public final class MastershipResourceTest extends ResourceTest { ...@@ -214,9 +217,9 @@ public final class MastershipResourceTest extends ResourceTest {
214 assertThat(result, notNullValue()); 217 assertThat(result, notNullValue());
215 218
216 assertThat(result.names(), hasSize(1)); 219 assertThat(result.names(), hasSize(1));
217 - assertThat(result.names().get(0), is("node")); 220 + assertThat(result.names().get(0), is("nodeId"));
218 221
219 - final String node = result.get("node").asString(); 222 + final String node = result.get("nodeId").asString();
220 assertThat(node, notNullValue()); 223 assertThat(node, notNullValue());
221 assertThat(node, is("node:1")); 224 assertThat(node, is("node:1"));
222 } 225 }
...@@ -269,9 +272,9 @@ public final class MastershipResourceTest extends ResourceTest { ...@@ -269,9 +272,9 @@ public final class MastershipResourceTest extends ResourceTest {
269 assertThat(result, notNullValue()); 272 assertThat(result, notNullValue());
270 273
271 assertThat(result.names(), hasSize(1)); 274 assertThat(result.names(), hasSize(1));
272 - assertThat(result.names().get(0), is("devices")); 275 + assertThat(result.names().get(0), is("deviceIds"));
273 276
274 - final JsonArray jsonDevices = result.get("devices").asArray(); 277 + final JsonArray jsonDevices = result.get("deviceIds").asArray();
275 assertThat(jsonDevices, notNullValue()); 278 assertThat(jsonDevices, notNullValue());
276 assertThat(jsonDevices.size(), is(3)); 279 assertThat(jsonDevices.size(), is(3));
277 } 280 }
...@@ -281,7 +284,21 @@ public final class MastershipResourceTest extends ResourceTest { ...@@ -281,7 +284,21 @@ public final class MastershipResourceTest extends ResourceTest {
281 */ 284 */
282 @Test 285 @Test
283 public void testRequestRoleFor() { 286 public void testRequestRoleFor() {
284 - // TODO: will be added when CompletableFuture is removed 287 + expect(mockService.requestRoleForSync(anyObject())).andReturn(role1).anyTimes();
288 + replay(mockService);
289 +
290 + final WebTarget wt = target();
291 + final String response = wt.path("mastership/" + deviceId1.toString() +
292 + "/request").request().get(String.class);
293 + final JsonObject result = Json.parse(response).asObject();
294 + assertThat(result, notNullValue());
295 +
296 + assertThat(result.names(), hasSize(1));
297 + assertThat(result.names().get(0), is("role"));
298 +
299 + final String role = result.get("role").asString();
300 + assertThat(role, notNullValue());
301 + assertThat(role, is("MASTER"));
285 } 302 }
286 303
287 /** 304 /**
...@@ -289,7 +306,16 @@ public final class MastershipResourceTest extends ResourceTest { ...@@ -289,7 +306,16 @@ public final class MastershipResourceTest extends ResourceTest {
289 */ 306 */
290 @Test 307 @Test
291 public void testRelinquishMastership() { 308 public void testRelinquishMastership() {
292 - // TODO: will be added when CompletableFuture is removed 309 + mockService.relinquishMastershipSync(anyObject());
310 + expectLastCall();
311 + replay(mockService);
312 +
313 + final WebTarget wt = target();
314 + final Response response = wt.path("mastership/" + deviceId1.toString() +
315 + "/relinquish").request().get();
316 + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
317 + String location = response.getLocation().toString();
318 + assertThat(location, Matchers.startsWith(deviceId1.toString()));
293 } 319 }
294 320
295 /** 321 /**
...@@ -297,7 +323,16 @@ public final class MastershipResourceTest extends ResourceTest { ...@@ -297,7 +323,16 @@ public final class MastershipResourceTest extends ResourceTest {
297 */ 323 */
298 @Test 324 @Test
299 public void testSetRole() { 325 public void testSetRole() {
300 - // TODO: will be added when CompletableFuture is removed 326 + mockAdminService.setRoleSync(anyObject(), anyObject(), anyObject());
327 + expectLastCall();
328 + replay(mockAdminService);
329 +
330 + final WebTarget wt = target();
331 + final InputStream jsonStream = MetersResourceTest.class
332 + .getResourceAsStream("put-set-roles.json");
333 + final Response response = wt.path("mastership")
334 + .request().put(Entity.json(jsonStream));
335 + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
301 } 336 }
302 337
303 /** 338 /**
......