Add new package: Rousette - a RESTConf server

This commit is contained in:
Mattias Walström
2024-06-04 13:38:03 +02:00
parent 3339fc5738
commit 4f3ae3b9a4
21 changed files with 887 additions and 3 deletions
+20
View File
@@ -0,0 +1,20 @@
#%PAM-1.0
auth requisite pam_nologin.so
auth [success=1 default=ignore] pam_unix.so nullok
auth requisite pam_deny.so
auth required pam_permit.so
account requisite pam_nologin.so
account [success=1 default=ignore] pam_unix.so
account requisite pam_deny.so
account required pam_permit.so
password [success=1 default=ignore] pam_unix.so
password requisite pam_deny.so
password required pam_permit.so
session required pam_loginuid.so
session include common-session
session optional pam_keyinit.so force revoke
session optional pam_lastlog.so showfailed
session optional pam_motd.so
+5
View File
@@ -24,3 +24,8 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/podman/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/python-statd/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/skeleton-init-finit/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/tetris/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/libyang-cpp/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/sysrepo-cpp/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/rousette/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/nghttp2-asio/Config.in"
+6 -1
View File
@@ -34,7 +34,12 @@ define CONFD_INSTALL_EXTRA
cp $(CONFD_PKGDIR)/avahi.service $(TARGET_DIR)/etc/avahi/services/netconf.service
endef
define CONFD_INSTALL_YANG_MODULES
USE_CONTAINERS=$(BR2_PACKAGE_PODMAN) SYSREPO_SHM_PREFIX=$(CONFD_SYSREPO_SHM_PREFIX) SYSREPOCTL_EXECUTABLE="$(HOST_DIR)/bin/sysrepoctl" SYSREPOCFG_EXECUTABLE="$(HOST_DIR)/bin/sysrepocfg" SEARCH_PATH="$(TARGET_DIR)/usr/share/yang/modules/confd/" $(@D)/scripts/setup.sh
USE_CONTAINERS=$(BR2_PACKAGE_PODMAN) \
SYSREPO_SHM_PREFIX=$(CONFD_SYSREPO_SHM_PREFIX) \
SYSREPOCTL_EXECUTABLE="$(HOST_DIR)/bin/sysrepoctl" \
SYSREPOCFG_EXECUTABLE="$(HOST_DIR)/bin/sysrepocfg" \
SEARCH_PATH="$(TARGET_DIR)/usr/share/yang/modules/confd/" \
$(@D)/scripts/setup.sh
endef
define CONFD_PERMISSIONS
/etc/sysrepo/data/ r 660 root wheel - - - - -
+6
View File
@@ -0,0 +1,6 @@
config BR2_PACKAGE_LIBYANG_CPP
bool "libyang-cpp"
depends on BR2_USE_MMU
select BR2_PACKAGE_LIBYANG
help
Libyang CPP bindings
+3
View File
@@ -0,0 +1,3 @@
# Locally calculated
sha256 82e3758011ec44c78e98d0777799d6e12aec5b8a64b32ebb20d0fe50e32488bb LICENSE
sha256 fc5ae5218d441afef697d4fc7912ddbe322060103c053d50fc2db829bd359458 libyang-cpp-b852ea3b9a2729da364f2c4122db05d882df37f2-br1.tar.gz
+14
View File
@@ -0,0 +1,14 @@
################################################################################
#
# CPP bindings for libyang
#
################################################################################
LIBYANG_CPP_VERSION = b852ea3b9a2729da364f2c4122db05d882df37f2
LIBYANG_CPP_SITE = https://github.com/kernelkit/libyang-cpp.git
LIBYANG_CPP_SITE_METHOD = git
LIBYANG_CPP_LICENSE = BSD-3-Clause
LIBYANG_CPP_LICENSE_FILES = LICENCE
LIBYANG_CPP_DEPENDENCIES = libyang
LIBYANG_CPP_INSTALL_STAGING = YES
$(eval $(cmake-package))
+7
View File
@@ -0,0 +1,7 @@
config BR2_PACKAGE_LIBNGHTTP2_ASIO
bool "libnghttp2-asio"
depends on BR2_USE_MMU
select BR2_PACKAGE_NGHTTP2
select BR2_PACKAGE_BOOST
help
C++ bindings for nghttp2
+23
View File
@@ -0,0 +1,23 @@
The MIT License
Copyright (c) 2012, 2014, 2015, 2016 Tatsuhiro Tsujikawa
Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+4
View File
@@ -0,0 +1,4 @@
# Locally calculated
sha256 6b94f3abc1aabd0c72a7c7d92a77f79dda7c8a0cb3df839a97890b4116a2de2a LICENSE
sha256 6bd96a33f41f73d6ca524efa946b5e592227a5dd6dd21f193fadf4be3583552d nghttp2-asio-e877868abe06a83ed0a6ac6e245c07f6f20866b5-br1.tar.gz
+17
View File
@@ -0,0 +1,17 @@
################################################################################
#
# nghttp2-asio
#
################################################################################
NGHTTP2_ASIO_VERSION = e877868abe06a83ed0a6ac6e245c07f6f20866b5
NGHTTP2_ASIO_SITE = https://github.com/kernelkit/nghttp2-asio.git
NGHTTP2_ASIO_SITE_METHOD = git
NGHTTP2_ASIO_LICENSE = MIT
NGHTTP2_ASIO_LICENSE_FILES = LICENCE
NGHTTP2_ASIO_DEPENDENCIES = boost nghttp2
NGHTTP2_ASIO_INSTALL_STAGING = YES
NGHTTP2_ASIO_AUTOGEN = YES
NGHTTP2_ASIO_AUTORECONF = YES
$(eval $(cmake-package))
+16
View File
@@ -0,0 +1,16 @@
config BR2_PACKAGE_ROUSETTE
bool "rousette"
depends on BR2_USE_MMU
select BR2_PACKAGE_BOOST
select BR2_PACKAGE_BOOST_ATOMIC
select BR2_PACKAGE_BOOST_THREAD
select BR2_PACKAGE_BOOST_SYSTEM
select BR2_PACKAGE_DOCOPT_CPP
select BR2_PACKAGE_LIBYANG_CPP
select BR2_PACKAGE_NGHTTP2
select BR2_PACKAGE_LIBNGHTTP2_ASIO
select BR2_PACKAGE_NGHTTP2_ASIO
select BR2_PACKAGE_SPDLOG
select BR2_PACKAGE_SYSREPO_CPP
help
RESTconf server
+3
View File
@@ -0,0 +1,3 @@
# Locally calculated
sha256 cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30 LICENSE
sha256 74b0d3115e73335399c5f8847fb7baa4d23497be75d12fccf56a754015af4c76 rousette-226a2410376e5befd0bf6dc180618a108b11b256-br1.tar.gz
+22
View File
@@ -0,0 +1,22 @@
################################################################################
#
# Rousette RESTconf server
#
################################################################################
ROUSETTE_VERSION = 226a2410376e5befd0bf6dc180618a108b11b256
ROUSETTE_SITE = https://github.com/kernelkit/rousette.git
ROUSETTE_SITE_METHOD = git
ROUSETTE_LICENSE = Apache-2.0
ROUSETTE_LICENSE_FILES = LICENCE
ROUSETTE_DEPENDENCIES = boost docopt-cpp nghttp2-asio spdlog sysrepo-cpp linux-pam
ROUSETTE_CONF_OPTS = \
-DTESTAR=on \
-DTHREADS_PTHREAD_ARG:STRING=-pthread
define ROUSETTE_USERS
yangnobody 333666 yangnobody 333666 * - - - Unauthenticated operations via RESTCONF
endef
$(eval $(cmake-package))
+7
View File
@@ -0,0 +1,7 @@
config BR2_PACKAGE_SYSREPO_CPP
bool "sysrepo-cpp"
depends on BR2_USE_MMU
select BR2_PACKAGE_LIBYANG_CPP
select BR2_PACKAGE_SYSREPO
help
Sysrepo CPP bindings
+3
View File
@@ -0,0 +1,3 @@
# Locally calculated
sha256 82e3758011ec44c78e98d0777799d6e12aec5b8a64b32ebb20d0fe50e32488bb LICENSE
sha256 74d7d89307c9fc188c7f23ae5128fe320a569f455a325286122eaa927a0d95ed sysrepo-cpp-99747f74e57a09c664251ea1f4e059e3f4f8e66a-br1.tar.gz
+15
View File
@@ -0,0 +1,15 @@
################################################################################
#
# CPP bindings for sysrepo
#
################################################################################
SYSREPO_CPP_VERSION = 99747f74e57a09c664251ea1f4e059e3f4f8e66a
SYSREPO_CPP_SITE = git@github.com:sysrepo/sysrepo-cpp.git
SYSREPO_CPP_SITE_METHOD = git
SYSREPO_CPP_LICENSE = BSD-3-Clause
SYSREPO_CPP_LICENSE_FILES = LICENCE
SYSREPO_CPP_DEPENDENCIES = sysrepo libyang-cpp
SYSREPO_CPP_INSTALL_STAGING = YES
$(eval $(cmake-package))
@@ -0,0 +1,300 @@
From 0a09b00dab204bb5890978a17bb23c4c25280580 Mon Sep 17 00:00:00 2001
From: Jan Kundrát <jan.kundrat@cesnet.cz>
Date: Sun, 24 Mar 2024 20:41:25 +0100
Subject: [PATCH] Port to libyang v3
Four parts, really:
- some enum reshuffling when creating new nodes
- a more capable XPath finding, but we have not been exporting any
"non-JSON XPaths", whatever that might be
- system-ordered lists are now ordered alphabetically
- a more capable error handling API
Change-Id: Ic6de06f004c16e56cef93fae0136c07d903394c0
---
diff --git a/.zuul.yaml b/.zuul.yaml
index d9d95e1..b41c490 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -4,13 +4,13 @@
- f38-gcc-cover:
required-projects:
- name: github/CESNET/libyang
- override-checkout: cesnet/2024-03--v2-latest
+ override-checkout: devel
- name: github/onqtam/doctest
override-checkout: v2.3.6
- f38-clang-asan-ubsan:
required-projects: &projects
- name: github/CESNET/libyang
- override-checkout: cesnet/2024-03--v2-latest
+ override-checkout: devel
- name: github/onqtam/doctest
override-checkout: v2.4.11
- f38-clang-tsan:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 288b62a..6e54707 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,7 +28,7 @@
option(BUILD_SHARED_LIBS "By default, shared libs are enabled. Turn off for a static build." ON)
find_package(PkgConfig REQUIRED)
-pkg_check_modules(LIBYANG REQUIRED libyang>=2.1.140 IMPORTED_TARGET)
+pkg_check_modules(LIBYANG REQUIRED libyang>=2.2.3 IMPORTED_TARGET)
set(LIBYANG_CPP_PKG_VERSION "1.1.0")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
diff --git a/README.md b/README.md
index 5e79a23..9009a54 100644
--- a/README.md
+++ b/README.md
@@ -8,8 +8,7 @@
Object lifetimes are managed automatically via RAII.
## Dependencies
-- [libyang](https://github.com/CESNET/libyang) - ~~the `devel` branch (even for the `master` branch of *libyang-cpp*)~~
- - temporarily (March 2024) this requires the [pre-v3 API of libyang (commit `b3d079fc3`)](https://github.com/CESNET/libyang/tree/b3d079fc37ac119f5a2a4a120b86d1c7102c3a08)
+- [libyang v3](https://github.com/CESNET/libyang) - the `devel` branch (even for the `master` branch of *libyang-cpp*)
- C++20 compiler (e.g., GCC 10.x+, clang 10+)
- CMake 3.19+
diff --git a/include/libyang-cpp/Context.hpp b/include/libyang-cpp/Context.hpp
index 1dab9f3..6f6e233 100644
--- a/include/libyang-cpp/Context.hpp
+++ b/include/libyang-cpp/Context.hpp
@@ -69,7 +69,9 @@
LogLevel level;
std::string message;
ErrorCode code;
- std::optional<std::string> path;
+ std::optional<std::string> dataPath;
+ std::optional<std::string> schemaPath;
+ uint64_t line;
ValidationErrorCode validationCode;
};
diff --git a/include/libyang-cpp/Enum.hpp b/include/libyang-cpp/Enum.hpp
index 3ded4d2..85dcc83 100644
--- a/include/libyang-cpp/Enum.hpp
+++ b/include/libyang-cpp/Enum.hpp
@@ -115,11 +115,15 @@
};
enum class CreationOptions : uint32_t {
- Update = 0x01,
- Output = 0x02,
- Opaque = 0x04,
- // BinaryLyb = 0x08, TODO
- CanonicalValue = 0x10
+ Output = 0x01,
+ StoreOnly = 0x02,
+ // BinaryLyb = 0x04, TODO
+ CanonicalValue = 0x08,
+ ClearDefaultFromParents = 0x10,
+ Update = 0x20,
+ Opaque = 0x40,
+ PathWithOpaque = 0x80,
+ // LYD_NEW_ANY_USE_VALUE is not relevant
};
/**
diff --git a/src/Context.cpp b/src/Context.cpp
index 337070f..713c50f 100644
--- a/src/Context.cpp
+++ b/src/Context.cpp
@@ -579,8 +579,10 @@
.appTag = errIt->apptag ? std::optional{errIt->apptag} : std::nullopt,
.level = utils::toLogLevel(errIt->level),
.message = errIt->msg,
- .code = static_cast<ErrorCode>(errIt->no),
- .path = errIt->path ? std::optional{errIt->path} : std::nullopt,
+ .code = static_cast<ErrorCode>(errIt->err),
+ .dataPath = errIt->data_path ? std::optional{errIt->data_path} : std::nullopt,
+ .schemaPath = errIt->schema_path ? std::optional{errIt->schema_path} : std::nullopt,
+ .line = errIt->line,
.validationCode = utils::toValidationErrorCode(errIt->vecode)
});
diff --git a/src/DataNode.cpp b/src/DataNode.cpp
index ab8cb4a..0e609c4 100644
--- a/src/DataNode.cpp
+++ b/src/DataNode.cpp
@@ -1187,7 +1187,8 @@
const std::string& xpath)
{
ly_set* set;
- auto ret = lyd_find_xpath3(contextNode ? contextNode->m_node : nullptr, forest.m_node, xpath.c_str(), nullptr, &set);
+ auto ret = lyd_find_xpath3(contextNode ? contextNode->m_node : nullptr, forest.m_node, xpath.c_str(),
+ LY_VALUE_JSON, nullptr, nullptr, &set);
throwIfError(ret, "libyang::findXPathAt:");
diff --git a/src/utils/enum.hpp b/src/utils/enum.hpp
index 7674fc6..5e02d24 100644
--- a/src/utils/enum.hpp
+++ b/src/utils/enum.hpp
@@ -72,11 +72,14 @@
{
return static_cast<uint32_t>(flags);
}
-static_assert(LYD_NEW_PATH_UPDATE == toCreationOptions(CreationOptions::Update));
-static_assert(LYD_NEW_PATH_OUTPUT == toCreationOptions(CreationOptions::Output));
-static_assert(LYD_NEW_PATH_OPAQ == toCreationOptions(CreationOptions::Opaque));
+static_assert(LYD_NEW_VAL_OUTPUT == toCreationOptions(CreationOptions::Output));
+static_assert(LYD_NEW_VAL_STORE_ONLY == toCreationOptions(CreationOptions::StoreOnly));
// static_assert(LYD_NEW_PATH_BIN_VALUE == toCreationOptions(CreationOptions::BinaryLyb));
-static_assert(LYD_NEW_PATH_CANON_VALUE == toCreationOptions(CreationOptions::CanonicalValue));
+static_assert(LYD_NEW_VAL_CANON == toCreationOptions(CreationOptions::CanonicalValue));
+static_assert(LYD_NEW_META_CLEAR_DFLT == toCreationOptions(CreationOptions::ClearDefaultFromParents));
+static_assert(LYD_NEW_PATH_UPDATE == toCreationOptions(CreationOptions::Update));
+static_assert(LYD_NEW_PATH_OPAQ == toCreationOptions(CreationOptions::Opaque));
+static_assert(LYD_NEW_PATH_WITH_OPAQ == toCreationOptions(CreationOptions::PathWithOpaque));
constexpr uint32_t toDuplicationOptions(const DuplicationOptions options)
{
diff --git a/tests/context.cpp b/tests/context.cpp
index d19f78b..cb629ef 100644
--- a/tests/context.cpp
+++ b/tests/context.cpp
@@ -457,7 +457,9 @@
.level = libyang::LogLevel::Error,
.message = "Invalid character sequence \"invalid\", expected a keyword.",
.code = libyang::ErrorCode::ValidationFailure,
- .path = "Line number 1.",
+ .dataPath = std::nullopt,
+ .schemaPath = std::nullopt,
+ .line = 1,
.validationCode = libyang::ValidationErrorCode::Syntax,
}
};
@@ -476,7 +478,9 @@
.level = libyang::LogLevel::Error,
.message = "Value \"9001\" is out of type int8 min/max bounds.",
.code = libyang::ErrorCode::ValidationFailure,
- .path = "Schema location \"/example-schema:leafInt8\".",
+ .dataPath = std::nullopt,
+ .schemaPath = "/example-schema:leafInt8",
+ .line = 0,
.validationCode = libyang::ValidationErrorCode::Data,
}
};
@@ -491,7 +495,9 @@
.level = libyang::LogLevel::Error,
.message = "Invalid type int8 empty value.",
.code = libyang::ErrorCode::ValidationFailure,
- .path = "Schema location \"/example-schema:leafInt8\".",
+ .dataPath = std::nullopt,
+ .schemaPath = "/example-schema:leafInt8",
+ .line = 0,
.validationCode = libyang::ValidationErrorCode::Data,
},
libyang::ErrorInfo {
@@ -499,7 +505,9 @@
.level = libyang::LogLevel::Error,
.message = "Value \"9001\" is out of type int8 min/max bounds.",
.code = libyang::ErrorCode::ValidationFailure,
- .path = "Schema location \"/example-schema:leafInt8\".",
+ .dataPath = std::nullopt,
+ .schemaPath = "/example-schema:leafInt8",
+ .line = 0,
.validationCode = libyang::ValidationErrorCode::Data,
}
};
diff --git a/tests/data_node.cpp b/tests/data_node.cpp
index 15fb727..2d27979 100644
--- a/tests/data_node.cpp
+++ b/tests/data_node.cpp
@@ -1026,12 +1026,12 @@
"/example-schema:bigTree/one",
"/example-schema:bigTree/one/myLeaf",
"/example-schema:bigTree/two",
- "/example-schema:bigTree/two/myList[thekey='43221']",
- "/example-schema:bigTree/two/myList[thekey='43221']/thekey",
+ "/example-schema:bigTree/two/myList[thekey='213']",
+ "/example-schema:bigTree/two/myList[thekey='213']/thekey",
"/example-schema:bigTree/two/myList[thekey='432']",
"/example-schema:bigTree/two/myList[thekey='432']/thekey",
- "/example-schema:bigTree/two/myList[thekey='213']",
- "/example-schema:bigTree/two/myList[thekey='213']/thekey"
+ "/example-schema:bigTree/two/myList[thekey='43221']",
+ "/example-schema:bigTree/two/myList[thekey='43221']/thekey",
};
REQUIRE(res == expected);
@@ -1255,6 +1255,7 @@
DOCTEST_SUBCASE("DataNode::findXPath")
{
+ // libyang v3 sorts these alphabetically
const auto data3 = R"({
"example-schema:person": [
{
@@ -1308,13 +1309,13 @@
auto set = node->findXPath("/example-schema:person");
REQUIRE(set.size() == 3);
- REQUIRE(set.front().path() == "/example-schema:person[name='John']");
- REQUIRE(set.back().path() == "/example-schema:person[name='David']");
+ REQUIRE(set.front().path() == "/example-schema:person[name='Dan']");
+ REQUIRE(set.back().path() == "/example-schema:person[name='John']");
auto iter = set.begin();
- REQUIRE((iter++)->path() == "/example-schema:person[name='John']");
REQUIRE((iter++)->path() == "/example-schema:person[name='Dan']");
REQUIRE((iter++)->path() == "/example-schema:person[name='David']");
+ REQUIRE((iter++)->path() == "/example-schema:person[name='John']");
REQUIRE(iter == set.end());
REQUIRE_THROWS_WITH_AS(*iter, "Dereferenced an .end() iterator", std::out_of_range);
}
@@ -1324,23 +1325,23 @@
auto set = node->findXPath("/example-schema:person");
REQUIRE((set.begin() + 0) == set.begin());
- REQUIRE((set.begin() + 0)->path() == "/example-schema:person[name='John']");
- REQUIRE((set.begin() + 1)->path() == "/example-schema:person[name='Dan']");
- REQUIRE((set.begin() + 2)->path() == "/example-schema:person[name='David']");
+ REQUIRE((set.begin() + 0)->path() == "/example-schema:person[name='Dan']");
+ REQUIRE((set.begin() + 1)->path() == "/example-schema:person[name='David']");
+ REQUIRE((set.begin() + 2)->path() == "/example-schema:person[name='John']");
REQUIRE((set.begin() + 3) == set.end());
REQUIRE_THROWS(set.begin() + 4);
REQUIRE((set.end() - 0) == set.end());
- REQUIRE((set.end() - 1)->path() == "/example-schema:person[name='David']");
- REQUIRE((set.end() - 2)->path() == "/example-schema:person[name='Dan']");
- REQUIRE((set.end() - 3)->path() == "/example-schema:person[name='John']");
+ REQUIRE((set.end() - 1)->path() == "/example-schema:person[name='John']");
+ REQUIRE((set.end() - 2)->path() == "/example-schema:person[name='David']");
+ REQUIRE((set.end() - 3)->path() == "/example-schema:person[name='Dan']");
REQUIRE((set.end() - 3) == set.begin());
REQUIRE_THROWS(set.end() - 4);
auto iter = set.end();
+ REQUIRE((--iter)->path() == "/example-schema:person[name='John']");
REQUIRE((--iter)->path() == "/example-schema:person[name='David']");
REQUIRE((--iter)->path() == "/example-schema:person[name='Dan']");
- REQUIRE((--iter)->path() == "/example-schema:person[name='John']");
REQUIRE_THROWS(--iter);
}
diff --git a/tests/pretty_printers.hpp b/tests/pretty_printers.hpp
index 6ae8934..6bbc16f 100644
--- a/tests/pretty_printers.hpp
+++ b/tests/pretty_printers.hpp
@@ -59,7 +59,9 @@
oss << "appTag: " << (err.appTag ? *err.appTag : "std::nullopt") << "\n ";
oss << "code: " << err.code << "\n ";
oss << "message: " << err.message << "\n ";
- oss << "path: " << (err.path ? *err.path : "std::nullopt") << "\n ";
+ oss << "dataPath: " << (err.dataPath ? *err.dataPath : "std::nullopt") << "\n ";
+ oss << "schemaPath: " << (err.schemaPath ? *err.schemaPath : "std::nullopt") << "\n ";
+ oss << "line: " << err.line << "\n ";
oss << "level: " << err.level << "\n ";
oss << "validationCode: " << err.validationCode << "\n }";
return oss.str();
@@ -0,0 +1,135 @@
From 6277d5f51f3a66df027bdd1752ea0ad58beb26fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= <lazzer@gmail.com>
Date: Mon, 27 May 2024 18:29:15 +0200
Subject: [PATCH] Make systemd optional
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Organization: Addiva Elektronik
If compile with systemd, set USE_SYSTEMD variable
Signed-off-by: Mattias Walström <lazzer@gmail.com>
---
CMakeLists.txt | 13 ++++++++++---
src/restconf/main.cpp | 36 +++++++++++++++++++++++++++---------
2 files changed, 37 insertions(+), 12 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7f82660..0f5bed9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -72,10 +72,12 @@ find_package(spdlog REQUIRED)
find_package(PkgConfig)
pkg_check_modules(nghttp2 REQUIRED IMPORTED_TARGET libnghttp2_asio>=0.0.90 libnghttp2)
find_package(Boost REQUIRED COMPONENTS system thread)
-
pkg_check_modules(SYSREPO-CPP REQUIRED IMPORTED_TARGET sysrepo-cpp>=1.1.0)
pkg_check_modules(LIBYANG-CPP REQUIRED IMPORTED_TARGET libyang-cpp>=1.1.0)
-pkg_check_modules(SYSTEMD REQUIRED IMPORTED_TARGET libsystemd)
+if(USE_SYSTEMD)
+ add_definitions(-DUSE_SYSTEMD=1)
+ pkg_check_modules(SYSTEMD REQUIRED IMPORTED_TARGET libsystemd)
+endif()
pkg_check_modules(PAM REQUIRED IMPORTED_TARGET pam)
add_library(rousette-http STATIC
@@ -116,7 +118,12 @@ add_executable(watch-operational-ds
target_link_libraries(watch-operational-ds PUBLIC rousette-sysrepo)
add_executable(rousette src/restconf/main.cpp)
-target_link_libraries(rousette PUBLIC rousette-restconf PkgConfig::SYSTEMD)
+
+if(USE_SYSTEMD)
+ target_link_libraries(rousette PUBLIC rousette-restconf PkgConfig::SYSTEMD)
+else()
+ target_link_libraries(rousette PUBLIC rousette-restconf)
+endif()
install(TARGETS
# clock-demo
diff --git a/src/restconf/main.cpp b/src/restconf/main.cpp
index bba3cbf..3162dcd 100644
--- a/src/restconf/main.cpp
+++ b/src/restconf/main.cpp
@@ -3,13 +3,17 @@
*
* Written by Jan Kundrát <jan.kundrat@cesnet.cz>
*
-*/
+ */
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <inttypes.h>
+#ifdef USE_SYSTEMD
#include <spdlog/sinks/systemd_sink.h>
+#else
+#include <spdlog/sinks/syslog_sink.h>
+#endif
#include <spdlog/sinks/ansicolor_sink.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -19,6 +23,7 @@
#include "restconf/Server.h"
namespace {
+#ifdef USE_SYSTEMD
/** @short Is stderr connected to journald? Not thread safe. */
bool is_journald_active()
{
@@ -39,29 +44,42 @@ bool is_journald_active()
}
/** @short Provide better levels, see https://github.com/gabime/spdlog/pull/1292#discussion_r340777258 */
-template<typename Mutex>
+template <typename Mutex>
class journald_sink : public spdlog::sinks::systemd_sink<Mutex> {
public:
journald_sink()
{
this->syslog_levels_ = {/* spdlog::level::trace */ LOG_DEBUG,
- /* spdlog::level::debug */ LOG_INFO,
- /* spdlog::level::info */ LOG_NOTICE,
- /* spdlog::level::warn */ LOG_WARNING,
- /* spdlog::level::err */ LOG_ERR,
- /* spdlog::level::critical */ LOG_CRIT,
- /* spdlog::level::off */ LOG_ALERT};
+ /* spdlog::level::debug */ LOG_INFO,
+ /* spdlog::level::info */ LOG_NOTICE,
+ /* spdlog::level::warn */ LOG_WARNING,
+ /* spdlog::level::err */ LOG_ERR,
+ /* spdlog::level::critical */ LOG_CRIT,
+ /* spdlog::level::off */ LOG_ALERT};
}
};
+#else
+void configure_syslog_logger()
+{
+ auto syslog_sink = std::make_shared<spdlog::sinks::syslog_sink_mt>("rousette", LOG_PID, LOG_USER, true);
+ auto logger = std::make_shared<spdlog::logger>("rousette", syslog_sink);
+ spdlog::set_default_logger(logger);
+ spdlog::set_level(spdlog::level::trace);
+}
+#endif
}
-int main(int argc [[maybe_unused]], char* argv [[maybe_unused]] [])
+int main(int argc [[maybe_unused]], char* argv [[maybe_unused]][])
{
+#ifdef USE_SYSTEMD
if (is_journald_active()) {
auto sink = std::make_shared<journald_sink<std::mutex>>();
auto logger = std::make_shared<spdlog::logger>("rousette", sink);
spdlog::set_default_logger(logger);
}
+#else
+ configure_syslog_logger();
+#endif
spdlog::set_level(spdlog::level::trace);
/* We will parse URIs using boost::spirit's alnum/alpha/... matchers which are locale-dependent.
--
2.34.1
+2 -1
View File
@@ -68,12 +68,13 @@ MODULES=(
"ietf-keystore@2023-12-28.yang -e central-keystore-supported -e inline-definitions-supported -e asymmetric-keys -e symmetric-keys"
"ietf-ssh-server@2023-12-28.yang -e local-user-auth-password -e local-user-auth-publickey"
"ietf-tls-server@2023-12-28.yang -e server-ident-raw-public-key -e server-ident-x509-cert"
"ietf-restconf@2017-01-26.yang"
)
if [ -n "$USE_CONTAINERS" ]; then
CONTAINERS=" -e containers";
MODULES+=("infix-containers@2024-03-27.yang")
fi
MODULES+=("infix-interfaces@2024-01-15.yang $CONTAINERS -e vlan-filtering")
CMD_INSTALL=
@@ -0,0 +1,278 @@
module ietf-restconf {
yang-version 1.1;
namespace "urn:ietf:params:xml:ns:yang:ietf-restconf";
prefix "rc";
organization
"IETF NETCONF (Network Configuration) Working Group";
contact
"WG Web: <https://datatracker.ietf.org/wg/netconf/>
WG List: <mailto:netconf@ietf.org>
Author: Andy Bierman
<mailto:andy@yumaworks.com>
Author: Martin Bjorklund
<mailto:mbj@tail-f.com>
Author: Kent Watsen
<mailto:kwatsen@juniper.net>";
description
"This module contains conceptual YANG specifications
for basic RESTCONF media type definitions used in
RESTCONF protocol messages.
Note that the YANG definitions within this module do not
represent configuration data of any kind.
The 'restconf-media-type' YANG extension statement
provides a normative syntax for XML and JSON
message-encoding purposes.
Copyright (c) 2017 IETF Trust and the persons identified as
authors of the code. All rights reserved.
Redistribution and use in source and binary forms, with or
without modification, is permitted pursuant to, and subject
to the license terms contained in, the Simplified BSD License
set forth in Section 4.c of the IETF Trust's Legal Provisions
Relating to IETF Documents
(http://trustee.ietf.org/license-info).
This version of this YANG module is part of RFC 8040; see
the RFC itself for full legal notices.";
revision 2017-01-26 {
description
"Initial revision.";
reference
"RFC 8040: RESTCONF Protocol.";
}
extension yang-data {
argument name {
yin-element true;
}
description
"This extension is used to specify a YANG data template that
represents conceptual data defined in YANG. It is
intended to describe hierarchical data independent of
protocol context or specific message-encoding format.
Data definition statements within a yang-data extension
specify the generic syntax for the specific YANG data
template, whose name is the argument of the 'yang-data'
extension statement.
Note that this extension does not define a media type.
A specification using this extension MUST specify the
message-encoding rules, including the content media type.
The mandatory 'name' parameter value identifies the YANG
data template that is being defined. It contains the
template name.
This extension is ignored unless it appears as a top-level
statement. It MUST contain data definition statements
that result in exactly one container data node definition.
An instance of a YANG data template can thus be translated
into an XML instance document, whose top-level element
corresponds to the top-level container.
The module name and namespace values for the YANG module using
the extension statement are assigned to instance document data
conforming to the data definition statements within
this extension.
The substatements of this extension MUST follow the
'data-def-stmt' rule in the YANG ABNF.
The XPath document root is the extension statement itself,
such that the child nodes of the document root are
represented by the data-def-stmt substatements within
this extension. This conceptual document is the context
for the following YANG statements:
- must-stmt
- when-stmt
- path-stmt
- min-elements-stmt
- max-elements-stmt
- mandatory-stmt
- unique-stmt
- ordered-by
- instance-identifier data type
The following data-def-stmt substatements are constrained
when used within a 'yang-data' extension statement.
- The list-stmt is not required to have a key-stmt defined.
- The if-feature-stmt is ignored if present.
- The config-stmt is ignored if present.
- The available identity values for any 'identityref'
leaf or leaf-list nodes are limited to the module
containing this extension statement and the modules
imported into that module.
";
}
rc:yang-data yang-errors {
uses errors;
}
rc:yang-data yang-api {
uses restconf;
}
grouping errors {
description
"A grouping that contains a YANG container
representing the syntax and semantics of a
YANG Patch error report within a response message.";
container errors {
description
"Represents an error report returned by the server if
a request results in an error.";
list error {
description
"An entry containing information about one
specific error that occurred while processing
a RESTCONF request.";
reference
"RFC 6241, Section 4.3.";
leaf error-type {
type enumeration {
enum transport {
description
"The transport layer.";
}
enum rpc {
description
"The rpc or notification layer.";
}
enum protocol {
description
"The protocol operation layer.";
}
enum application {
description
"The server application layer.";
}
}
mandatory true;
description
"The protocol layer where the error occurred.";
}
leaf error-tag {
type string;
mandatory true;
description
"The enumerated error-tag.";
}
leaf error-app-tag {
type string;
description
"The application-specific error-tag.";
}
leaf error-path {
type instance-identifier;
description
"The YANG instance identifier associated
with the error node.";
}
leaf error-message {
type string;
description
"A message describing the error.";
}
anydata error-info {
description
"This anydata value MUST represent a container with
zero or more data nodes representing additional
error information.";
}
}
}
}
grouping restconf {
description
"Conceptual grouping representing the RESTCONF
root resource.";
container restconf {
description
"Conceptual container representing the RESTCONF
root resource.";
container data {
description
"Container representing the datastore resource.
Represents the conceptual root of all state data
and configuration data supported by the server.
The child nodes of this container can be any data
resources that are defined as top-level data nodes
from the YANG modules advertised by the server in
the 'ietf-yang-library' module.";
}
container operations {
description
"Container for all operation resources.
Each resource is represented as an empty leaf with the
name of the RPC operation from the YANG 'rpc' statement.
For example, the 'system-restart' RPC operation defined
in the 'ietf-system' module would be represented as
an empty leaf in the 'ietf-system' namespace. This is
a conceptual leaf and will not actually be found in
the module:
module ietf-system {
leaf system-reset {
type empty;
}
}
To invoke the 'system-restart' RPC operation:
POST /restconf/operations/ietf-system:system-restart
To discover the RPC operations supported by the server:
GET /restconf/operations
In XML, the YANG module namespace identifies the module:
<system-restart
xmlns='urn:ietf:params:xml:ns:yang:ietf-system'/>
In JSON, the YANG module name identifies the module:
{ 'ietf-system:system-restart' : [null] }
";
}
leaf yang-library-version {
type string {
pattern '\d{4}-\d{2}-\d{2}';
}
config false;
mandatory true;
description
"Identifies the revision date of the 'ietf-yang-library'
module that is implemented by this RESTCONF server.
Indicates the year, month, and day in YYYY-MM-DD
numeric format.";
}
}
}
}