Bug 8533: Not possible to invoke RPC on mount points with new Restconf 85/57685/3
authorIvan Hrasko <ivan.hrasko@pantheon.tech>
Tue, 23 May 2017 12:27:04 +0000 (14:27 +0200)
committerIvan Hrasko <ivan.hrasko@pantheon.tech>
Tue, 23 May 2017 13:22:50 +0000 (13:22 +0000)
- put identifer of RPC into InstanceIdentiferContext
instead of mount point identifer which leads to fail
in unit test

- when working with mount point use mount point's
schema context to find RPC module, previously used
controller's schema context leads to NPE

- repaired imports in RestconfApplication to use
new implementation

Change-Id: Ieb46b050e881c89ea58bb9f521be69554733d575
Signed-off-by: Ivan Hrasko <ivan.hrasko@pantheon.tech>
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/RestconfApplication.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/parser/ParserIdentifier.java
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/jersey/providers/XmlBodyReaderMountPointTest.java
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/utils/parser/ParserIdentifierTest.java
restconf/sal-rest-connector/src/test/resources/parser-identifier/invoke-rpc-module.yang [new file with mode: 0644]

index 5f47fcbc4609a2d8f12cc1a637eda85632b2c571..6b4b85db629ebba7b45d9ebc18a1801029420a48 100644 (file)
@@ -13,15 +13,15 @@ import java.util.Set;
 import javax.ws.rs.core.Application;
 import org.opendaylight.netconf.md.sal.rest.schema.SchemaExportContentYangBodyWriter;
 import org.opendaylight.netconf.md.sal.rest.schema.SchemaExportContentYinBodyWriter;
-import org.opendaylight.netconf.sal.rest.impl.JsonNormalizedNodeBodyReader;
 import org.opendaylight.netconf.sal.rest.impl.PATCHJsonBodyWriter;
 import org.opendaylight.netconf.sal.rest.impl.PATCHXmlBodyWriter;
 import org.opendaylight.netconf.sal.rest.impl.RestconfDocumentedExceptionMapper;
-import org.opendaylight.netconf.sal.rest.impl.XmlNormalizedNodeBodyReader;
 import org.opendaylight.restconf.common.wrapper.services.ServicesWrapperImpl;
+import org.opendaylight.restconf.jersey.providers.JsonNormalizedNodeBodyReader;
 import org.opendaylight.restconf.jersey.providers.JsonToPATCHBodyReader;
 import org.opendaylight.restconf.jersey.providers.NormalizedNodeJsonBodyWriter;
 import org.opendaylight.restconf.jersey.providers.NormalizedNodeXmlBodyWriter;
+import org.opendaylight.restconf.jersey.providers.XmlNormalizedNodeBodyReader;
 import org.opendaylight.restconf.jersey.providers.XmlToPATCHBodyReader;
 
 public class RestconfApplication extends Application {
index f0aab31b63db760b52d323751395527ecd194428..8fe65f274ba8c2ed0feb138123d847cbf4da9592 100644 (file)
@@ -71,7 +71,7 @@ public final class ParserIdentifier {
             final String identifier,
             final SchemaContext schemaContext,
             final Optional<DOMMountPointService> mountPointService) {
-        if ((identifier != null) && identifier.contains(RestconfConstants.MOUNT)) {
+        if (identifier != null && identifier.contains(RestconfConstants.MOUNT)) {
             if (!mountPointService.isPresent()) {
                 throw new RestconfDocumentedException("Mount point service is not available");
             }
@@ -88,27 +88,29 @@ public final class ParserIdentifier {
                         "Mount point does not exist.", ErrorType.PROTOCOL, ErrorTag.DATA_MISSING);
             }
 
+            final DOMMountPoint domMountPoint = mountPoint.get();
+            final SchemaContext mountSchemaContext = domMountPoint.getSchemaContext();
+
             final String pathId = pathsIt.next().replaceFirst("/", "");
             final YangInstanceIdentifier pathYangInstanceIdentifier = IdentifierCodec.deserialize(
-                    pathId, mountPoint.get().getSchemaContext());
+                    pathId, mountSchemaContext);
 
-            final DataSchemaContextNode<?> child = DataSchemaContextTree.from(
-                    mountPoint.get().getSchemaContext()).getChild(pathYangInstanceIdentifier);
+            final DataSchemaContextNode<?> child = DataSchemaContextTree.from(mountSchemaContext)
+                .getChild(pathYangInstanceIdentifier);
             if (child != null) {
                 return new InstanceIdentifierContext<SchemaNode>(pathYangInstanceIdentifier, child.getDataSchemaNode(),
-                        mountPoint.get(), mountPoint.get().getSchemaContext());
+                        domMountPoint, mountSchemaContext);
             }
-            final QName rpcQName = mountYangInstanceIdentifier.getLastPathArgument().getNodeType();
+            final QName rpcQName = pathYangInstanceIdentifier.getLastPathArgument().getNodeType();
             RpcDefinition def = null;
-            for (final RpcDefinition rpcDefinition : schemaContext
+            for (final RpcDefinition rpcDefinition : mountSchemaContext
                     .findModuleByNamespaceAndRevision(rpcQName.getNamespace(), rpcQName.getRevision()).getRpcs()) {
                 if (rpcDefinition.getQName().getLocalName().equals(rpcQName.getLocalName())) {
                     def = rpcDefinition;
                     break;
                 }
             }
-            return new InstanceIdentifierContext<>(mountYangInstanceIdentifier, def, mountPoint.get(),
-                    mountPoint.get().getSchemaContext());
+            return new InstanceIdentifierContext<>(pathYangInstanceIdentifier, def, domMountPoint, mountSchemaContext);
         } else {
             final YangInstanceIdentifier deserialize = IdentifierCodec.deserialize(identifier, schemaContext);
             final DataSchemaContextNode<?> child = DataSchemaContextTree.from(schemaContext).getChild(deserialize);
@@ -158,7 +160,7 @@ public final class ParserIdentifier {
         }
 
         final int mountIndex = identifier.indexOf(RestconfConstants.MOUNT);
-        String moduleNameAndRevision = "";
+        final String moduleNameAndRevision;
         if (mountIndex >= 0) {
             moduleNameAndRevision = identifier.substring(mountIndex + RestconfConstants.MOUNT.length())
                     .replaceFirst(String.valueOf(RestconfConstants.SLASH), "");
index cb3d10c3a435362ca0d0fd9ff94db5c8ce6f4b3a..e4e687b37d27231703665e5a691a9ad08873af38 100644 (file)
@@ -36,6 +36,9 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -126,6 +129,29 @@ public class XmlBodyReaderMountPointTest extends AbstractBodyReaderTest {
         checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue);
     }
 
+    @Test
+    public void rpcModuleInputTest() throws Exception {
+        final String uri = "instance-identifier-module:cont/yang-ext:mount/invoke-rpc-module:rpc-test";
+        mockBodyReader(uri, this.xmlBodyReader, true);
+        final InputStream inputStream = XmlBodyReaderMountPointTest.class
+                .getResourceAsStream("/invoke-rpc/xml/rpc-input.xml");
+        final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null,
+                null, null, this.mediaType, null, inputStream);
+        checkNormalizedNodeContext(returnValue);
+        final ContainerNode contNode = (ContainerNode) returnValue.getData();
+        final YangInstanceIdentifier yangCont = YangInstanceIdentifier.of(QName.create(contNode.getNodeType(), "cont"));
+        final Optional<DataContainerChild<? extends PathArgument, ?>> contDataNodePotential = contNode.getChild(
+                yangCont.getLastPathArgument());
+        assertTrue(contDataNodePotential.isPresent());
+        final ContainerNode contDataNode = (ContainerNode) contDataNodePotential.get();
+        final YangInstanceIdentifier yangLeaf =
+                YangInstanceIdentifier.of(QName.create(contDataNode.getNodeType(), "lf"));
+        final Optional<DataContainerChild<? extends PathArgument, ?>> leafDataNode = contDataNode.getChild(
+                yangLeaf.getLastPathArgument());
+        assertTrue(leafDataNode.isPresent());
+        assertTrue("lf-test".equalsIgnoreCase(leafDataNode.get().getValue().toString()));
+    }
+
     private void checkExpectValueNormalizeNodeContext(
             final DataSchemaNode dataSchemaNode,
             final NormalizedNodeContext nnContext) {
index f87ef3588225c08b608ca9de2e6193a5a9662cde..705f7e42dcbd4c7e1eb7c3246f78ffac986b1fb5 100644 (file)
@@ -34,6 +34,7 @@ import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.netconf.sal.restconf.impl.RestconfError;
 import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag;
 import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType;
+import org.opendaylight.restconf.parser.IdentifierCodec;
 import org.opendaylight.restconf.utils.RestconfConstants;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
@@ -86,6 +87,8 @@ public class ParserIdentifierTest {
     private static final String TEST_MODULE_REVISION = "2016-06-02";
     private static final String TEST_MODULE_NAMESPACE = "test:module";
 
+    private static final String INVOKE_RPC = "invoke-rpc-module:rpc-test";
+
     // mount point and mount point service
     private DOMMountPoint mountPoint;
     private DOMMountPointService mountPointService;
@@ -642,4 +645,48 @@ public class ParserIdentifierTest {
                 + TEST_MODULE_REVISION,
                 this.mockMountPointService);
     }
+
+    /**
+     * Test invoke RPC.
+     *
+     * <p>
+     * Verify if RPC schema node was found.
+     */
+    @Test
+    public void invokeRpcTest() {
+        final InstanceIdentifierContext<?> result = ParserIdentifier.toInstanceIdentifier(
+                INVOKE_RPC, this.schemaContext, Optional.absent());
+
+        // RPC schema node
+        final QName rpcQName = result.getSchemaNode().getQName();
+        assertEquals("invoke:rpc:module", rpcQName.getModule().getNamespace().toString());
+        assertEquals("rpc-test", rpcQName.getLocalName());
+
+        // other fields
+        assertEquals(IdentifierCodec.deserialize(INVOKE_RPC, schemaContext), result.getInstanceIdentifier());
+        assertEquals(null, result.getMountPoint());
+        assertEquals(this.schemaContext, result.getSchemaContext());
+    }
+
+    /**
+     * Test invoke RPC on mount point.
+     *
+     * <p>
+     * Verify if RPC schema node was found.
+     */
+    @Test
+    public void invokeRpcOnMountPointTest() {
+        final InstanceIdentifierContext<?> result = ParserIdentifier.toInstanceIdentifier(
+                MOUNT_POINT_IDENT + "/" + INVOKE_RPC, this.schemaContext, Optional.of(this.mountPointService));
+
+        // RPC schema node
+        final QName rpcQName = result.getSchemaNode().getQName();
+        assertEquals("invoke:rpc:module", rpcQName.getModule().getNamespace().toString());
+        assertEquals("rpc-test", rpcQName.getLocalName());
+
+        // other fields
+        assertEquals(IdentifierCodec.deserialize(INVOKE_RPC, schemaContext), result.getInstanceIdentifier());
+        assertEquals(this.mountPoint, result.getMountPoint());
+        assertEquals(this.schemaContextOnMountPoint, result.getSchemaContext());
+    }
 }
diff --git a/restconf/sal-rest-connector/src/test/resources/parser-identifier/invoke-rpc-module.yang b/restconf/sal-rest-connector/src/test/resources/parser-identifier/invoke-rpc-module.yang
new file mode 100644 (file)
index 0000000..7a8bcff
--- /dev/null
@@ -0,0 +1,26 @@
+module invoke-rpc-module {
+  namespace "invoke:rpc:module";
+  prefix "inrpcmod";
+  yang-version 1;
+
+  revision 2017-05-23 {
+      description "Initial revision.";
+  }
+
+  rpc rpc-test {
+      input {
+          container cont {
+              leaf lf {
+                  type string;
+              }
+          }
+      }
+      output {
+          container cont-out {
+              leaf lf-out {
+                  type string;
+              }
+          }
+      }
+  }
+}
\ No newline at end of file