Refactor RPC input generation
Change-Id: I4fac9ffc939a7df41a6e3f3332199da0070edb9e
diff --git a/src/libyang_utils.cpp b/src/libyang_utils.cpp
index 1f0c372..a6b22cd 100644
--- a/src/libyang_utils.cpp
+++ b/src/libyang_utils.cpp
@@ -90,9 +90,6 @@
}
}
-// This is very similar to the fillMap lambda in SysrepoAccess, however,
-// Sysrepo returns a weird array-like structure, while libnetconf
-// returns libyang::Data_Node
void lyNodesToTree(DatastoreAccess::Tree& res, const std::vector<std::shared_ptr<libyang::Data_Node>> items, std::optional<std::string> ignoredXPathPrefix)
{
for (auto it = items.begin(); it < items.end(); it++) {
@@ -108,3 +105,27 @@
}
}
}
+
+DatastoreAccess::Tree rpcOutputToTree(const std::string& rpcPath, libyang::S_Data_Node output)
+{
+ DatastoreAccess::Tree res;
+ if (output) {
+ // The output is "some top-level node". If we actually want the output of our RPC/action we need to use
+ // find_path. Also, our `path` is fully prefixed, but the output paths aren't. So we use outputNode->path() to
+ // get the unprefixed path.
+
+ auto outputNode = output->find_path(rpcPath.c_str())->data().front();
+ lyNodesToTree(res, {outputNode}, joinPaths(outputNode->path(), "/"));
+ }
+ return res;
+}
+
+libyang::S_Data_Node treeToRpcInput(libyang::S_Context ctx, const std::string& path, DatastoreAccess::Tree in)
+{
+ auto root = std::make_shared<libyang::Data_Node>(ctx, path.c_str(), nullptr, LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_UPDATE);
+ for (const auto& [k, v] : in) {
+ root->new_path(ctx, k.c_str(), leafDataToString(v).c_str(), LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_UPDATE);
+ }
+
+ return root;
+}
diff --git a/src/libyang_utils.hpp b/src/libyang_utils.hpp
index a33e70b..b5f5e96 100644
--- a/src/libyang_utils.hpp
+++ b/src/libyang_utils.hpp
@@ -11,3 +11,5 @@
leaf_data_ leafValueFromNode(libyang::S_Data_Node_Leaf_List node);
void lyNodesToTree(DatastoreAccess::Tree& res, const std::vector<std::shared_ptr<libyang::Data_Node>> items, std::optional<std::string> ignoredXPathPrefix = std::nullopt);
+libyang::S_Data_Node treeToRpcInput(libyang::S_Context ctx, const std::string& path, DatastoreAccess::Tree in);
+DatastoreAccess::Tree rpcOutputToTree(const std::string& rpcPath, libyang::S_Data_Node output);
diff --git a/src/netconf_access.cpp b/src/netconf_access.cpp
index b599c2c..7a4097b 100644
--- a/src/netconf_access.cpp
+++ b/src/netconf_access.cpp
@@ -134,23 +134,11 @@
DatastoreAccess::Tree NetconfAccess::execute(const std::string& path, const Tree& input)
{
- auto root = m_schema->dataNodeFromPath(path);
- for (const auto& [k, v] : input) {
- root->new_path(m_session->libyangContext(), k.c_str(), leafDataToString(v).c_str(), LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_UPDATE);
- }
- auto data = root->print_mem(LYD_XML, 0);
+ auto inputNode = treeToRpcInput(m_session->libyangContext(), path, input);
+ auto data = inputNode->print_mem(LYD_XML, 0);
- Tree res;
auto output = m_session->rpc_or_action(data);
- if (output) {
- // If there's output, it will be a top-level node. In case of action, the output can be nested so we need to use
- // find_path to get to the actual output. Also, our `path` is fully prefixed, but the output paths aren't. So
- // we use outputNode->path() to get the unprefixed path.
-
- auto outputNode = output->find_path(path.c_str())->data().front();
- lyNodesToTree(res, {outputNode}, joinPaths(outputNode->path(), "/"));
- }
- return res;
+ return rpcOutputToTree(path, output);
}
NC_DATASTORE toNcDatastore(Datastore datastore)
diff --git a/src/sysrepo_access.cpp b/src/sysrepo_access.cpp
index dfdb7f0..e9da2ca 100644
--- a/src/sysrepo_access.cpp
+++ b/src/sysrepo_access.cpp
@@ -306,22 +306,9 @@
DatastoreAccess::Tree SysrepoAccess::execute(const std::string& path, const Tree& input)
{
- auto inputNode = m_schema->dataNodeFromPath(path);
- for (const auto& [k, v] : input) {
- inputNode->new_path(m_session->get_context(), k.c_str(), leafDataToString(v).c_str(), LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_UPDATE);
- }
-
- Tree res;
+ auto inputNode = treeToRpcInput(m_session->get_context(), path, input);
auto output = m_session->rpc_send(inputNode);
- if (output) {
- // The output is "some top-level node". If we actually want the output of our RPC/action we need to use
- // find_path. Also, our `path` is fully prefixed, but the output paths aren't. So we use outputNode->path() to
- // get the unprefixed path.
-
- auto outputNode = output->find_path(path.c_str())->data().front();
- lyNodesToTree(res, {outputNode}, joinPaths(outputNode->path(), "/"));
- }
- return res;
+ return rpcOutputToTree(path, output);
}
void SysrepoAccess::copyConfig(const Datastore source, const Datastore destination)