Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5d58580
fix(openapi): Use OpenAPI 3.1.1 with JSON Schema Draft 07 dialect
pjungkamp May 18, 2026
c34719d
fix(redocly): Fix linter configuration
pjungkamp May 18, 2026
d40016d
feat(editorconfig): Add yaml configuration
pjungkamp May 18, 2026
382687e
feat(openapi): Make redocly configuration more strict
pjungkamp May 18, 2026
4978bd2
fix(hook-pmu_dft): Fix configuration typos
pjungkamp Aug 10, 2026
8a375a9
refactor(openapi): Rewrite all schema files
pjungkamp Jun 2, 2026
5d6327a
feat(node): Introduce json-schema-validator for bundled schemas
pjungkamp Jul 15, 2026
fb80d42
feat(clangd): Add compilation database path to build dir
pjungkamp Aug 7, 2026
4197cb5
feat(config): Validate configuration against JSON schema
pjungkamp Aug 7, 2026
de260b3
feat(gdb): Add gdbinit for nlohmann::json pretty printing
pjungkamp Aug 9, 2026
d509d90
fix(tool): Catch std::exception instead of std::runtime_error
pjungkamp Aug 9, 2026
775d062
fix(node): Remove enabled and initial_sequenceno from configuration
pjungkamp Aug 9, 2026
4f86d16
fix(tests): Fix invalid test and example configurations
pjungkamp Aug 9, 2026
e62c417
fix(tests): Reap left-over children from integration tests
pjungkamp Aug 9, 2026
08b0ff5
feat(config): Allow JSON files with comments
pjungkamp Aug 9, 2026
075eec2
chore(docker): Bump fedore-minimal container to Fedora 43
pjungkamp Aug 9, 2026
9c33e33
fix(docker): Add workaround for local/lib libraries
pjungkamp Aug 9, 2026
a541b5e
feat(nix): Use gcc14Stdenv for devShell.default
pjungkamp Aug 10, 2026
7d7eaa2
chore(hooks): Remove enabled setting for hooks
pjungkamp Aug 10, 2026
ad154d9
fix(super_node): Remove unused broken code
pjungkamp Aug 10, 2026
6bdac46
fix(format-raw): Remove unnecessary exception
pjungkamp Aug 10, 2026
5f3422c
fix(hook-limit_value): Fix memory corruption
pjungkamp Aug 10, 2026
be3adbe
fix(hook-pmu): Allow explicit none window configuration
pjungkamp Aug 10, 2026
e485929
fix(config): Always allow integers where floats are allowed
pjungkamp Aug 10, 2026
437930e
fix(node-loopback): Fix use of undefined macro
pjungkamp Aug 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions .clangd
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
---
Diagnostics:
UnusedIncludes: Strict

CompileFlags:
CompilationDatabase: build
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ indent_size = 4
indent_style = space
indent_size = 4

[*.{nix,json}]
[*.{nix,json,yaml}]
indent_style = space
indent_size = 2

Expand Down
12 changes: 12 additions & 0 deletions .gdbinit
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, RWTH Aachen University
# SPDX-License-Identifier: Apache-2.0
# Author: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

python

import os
import gdb

if nlohmann_json_src := os.environ.get('NLOHMANN_JSON_SRC'):
gdb.execute(f"source {nlohmann_json_src}/tools/gdb_pretty_printer/nlohmann-json.py")
end
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ repos:
exclude: .devcontainer/devcontainer\.json
- id: check-toml
- id: check-added-large-files
exclude: ^paper\.md$
exclude: ^(?:paper\.md|lib/json_schema\.cpp)$
- id: pretty-format-json
# black has its own mind of formatting Jupyter notebooks
exclude: \.ipynb$|^.devcontainer/devcontainer\.json$|package-lock\.json$
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ find_package(PkgConfig REQUIRED)
find_package(spdlog REQUIRED)
find_package(Threads REQUIRED)
find_package(nlohmann_json REQUIRED)
find_package(nlohmann_json_schema_validator REQUIRED)
find_package(OpenMP)
find_package(IBVerbs)
find_package(RDMACM)
Expand Down
16 changes: 0 additions & 16 deletions common/include/villas/exceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,6 @@ class MemoryAllocationError : public RuntimeError {
MemoryAllocationError() : RuntimeError("Failed to allocate memory") {}
};

class JsonError : public std::runtime_error {

protected:
json_error_t error;

public:
template <typename... Args>
JsonError(const json_t *s, const json_error_t &e,
const std::string &what = std::string(), Args &&...args)
: std::runtime_error(
fmt::format("{}: {} in {}:{}:{}",
fmt::format(what, std::forward<Args>(args)...),
error.text, error.source, error.line, error.column)),
error(e) {}
};

class ConfigError : public std::runtime_error {

protected:
Expand Down
15 changes: 7 additions & 8 deletions common/include/villas/jansson.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,20 @@ class JanssonPtr {

::json_t *release() { return std::exchange(inner, nullptr); }

void reset() {
json_decref(inner);
inner = nullptr;
}

void reset(::json_t *json) {
void reset(::json_t *json = nullptr) {
json_decref(inner);
inner = json_incref(json);
}

void swap(JanssonPtr &other) { std::swap(inner, other.inner); }

operator bool() { return inner != nullptr; }
::json_t *get() const { return inner; }
::json_t *operator->() const { return inner; }

::json_t const *get() const { return inner; }
::json_t *get() { return inner; }

::json_t const *operator->() const { return inner; }
::json_t *operator->() { return inner; }

friend void swap(JanssonPtr &lhs, JanssonPtr &rhs) { lhs.swap(rhs); }
friend auto operator<=>(JanssonPtr const &, JanssonPtr const &) = default;
Expand Down
1 change: 1 addition & 0 deletions common/include/villas/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct LoadConfigFileOptions {
bool allow_libconfig = false;
bool allow_environment = false;
bool allow_include = false;
bool allow_comments = false;
};

// load a configuration file
Expand Down
26 changes: 16 additions & 10 deletions common/lib/json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ void to_json(Json &json, JanssonPtr const &jansson) {
namespace {

// Implement the deprecated variable substitution syntax.
void expand_substitutions(Json &value, bool resolve_env,
void expand_substitutions(Json &value, bool resolve_env, bool allow_comments,
fs::path const *include_dir) {
if (not value.is_string())
return;
Expand Down Expand Up @@ -204,6 +204,7 @@ void expand_substitutions(Json &value, bool resolve_env,
.allow_libconfig = false,
.allow_environment = resolve_env,
.allow_include = include_dir != nullptr,
.allow_comments = allow_comments,
});
if (result.is_null())
result = partial_result;
Expand All @@ -225,14 +226,16 @@ void expand_substitutions(Json &value, bool resolve_env,
#ifdef WITH_CONFIG

Json parse_libconfig_setting(::config_setting_t const *setting,
bool resolve_env, fs::path const *include_dir) {
bool resolve_env, bool allow_comments,
fs::path const *include_dir) {
switch (config_setting_type(setting)) {
case CONFIG_TYPE_ARRAY:
case CONFIG_TYPE_LIST: {
auto array = Json::array();
for (auto const idx : std::views::iota(0, config_setting_length(setting))) {
auto const elem = config_setting_get_elem(setting, idx);
array.push_back(parse_libconfig_setting(elem, resolve_env, include_dir));
array.push_back(parse_libconfig_setting(elem, resolve_env, allow_comments,
include_dir));
}

return array;
Expand All @@ -244,15 +247,16 @@ Json parse_libconfig_setting(::config_setting_t const *setting,
auto const elem = config_setting_get_elem(setting, idx);
auto name = std::string(config_setting_name(elem));
object.emplace(std::move(name),
parse_libconfig_setting(elem, resolve_env, include_dir));
parse_libconfig_setting(elem, resolve_env, allow_comments,
include_dir));
}

return object;
}

case CONFIG_TYPE_STRING: {
auto json = Json(std::string(config_setting_get_string(setting)));
expand_substitutions(json, resolve_env, include_dir);
expand_substitutions(json, resolve_env, allow_comments, include_dir);
return json;
}

Expand Down Expand Up @@ -299,7 +303,8 @@ extern "C" char const **libconfig_include_func(::config_t *config, char const *,
}

auto pattern_json = Json(pattern);
expand_substitutions(pattern_json, hook->resolve_env, nullptr);
// The null include_dir only expands environment variables in the pattern.
expand_substitutions(pattern_json, hook->resolve_env, false, nullptr);
auto const &pattern_expanded = pattern_json.get_ref<std::string const &>();

try {
Expand Down Expand Up @@ -327,7 +332,7 @@ extern "C" char const **libconfig_include_func(::config_t *config, char const *,

#endif

Json load_libconfig_file(std::FILE *file, bool resolve_env,
Json load_libconfig_file(std::FILE *file, bool resolve_env, bool allow_comments,
fs::path const *include_dir) {
using ConfigDestroy = decltype([](::config_t *c) { ::config_destroy(c); });
using ConfigGuard = std::unique_ptr<::config_t, ConfigDestroy>;
Expand Down Expand Up @@ -359,7 +364,7 @@ Json load_libconfig_file(std::FILE *file, bool resolve_env,
}

return parse_libconfig_setting(config_root_setting(&config), resolve_env,
include_dir);
allow_comments, include_dir);
}

#endif // WITH_CONFIG
Expand All @@ -381,16 +386,17 @@ Json load_config_file(fs::path const &path, LoadConfigFileOptions const &opts) {
auto parser_callback = [&](int depth, Json::parse_event_t event,
Json &value) {
if (event == Json::parse_event_t::value)
expand_substitutions(value, opts.allow_environment,
expand_substitutions(value, opts.allow_environment, opts.allow_comments,
opts.allow_include ? &include_dir : nullptr);

return true;
};

return Json::parse(file.get(), parser_callback);
return Json::parse(file.get(), parser_callback, true, opts.allow_comments);
} else if (opts.allow_libconfig) {
#ifdef WITH_CONFIG
return load_libconfig_file(file.get(), opts.allow_environment,
opts.allow_comments,
opts.allow_include ? &include_dir : nullptr);
#else
throw std::runtime_error(
Expand Down
2 changes: 1 addition & 1 deletion common/lib/tool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ int Tool::run() {
logger->info(CLR_GRN("Goodbye!"));

return ret;
} catch (const std::runtime_error &e) {
} catch (const std::exception &e) {
logger->error("{}", e.what());

return -1;
Expand Down
18 changes: 0 additions & 18 deletions doc/.redocly.yaml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
---
type: object
properties:
enabled:
type: boolean
default: true
title: Enable HTTP server
description: |
When set to `false`, the built-in HTTP & WebSocket server is disabled and will not listen on any port.

port:
type: integer
default: 80
Expand All @@ -26,3 +33,5 @@ properties:
The private x509 key used for server-side SSL encryption.

example: /etc/ssl/private/mykey.pem

additionalProperties: false
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
type: object
title: Logging configuration
properties:

level:
title: The log level
description: |
Expand Down Expand Up @@ -69,3 +68,6 @@ properties:
- error
- critical
- 'off'
additionalProperties: false

additionalProperties: false
Loading
Loading