Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Generate config descriptions #1842

Open
wants to merge 15 commits into
base: develop
Choose a base branch
from
22 changes: 18 additions & 4 deletions src/app/CliArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include "migration/MigrationApplication.hpp"
#include "util/build/Build.hpp"
#include "util/newconfig/ConfigDescription.hpp"

#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
Expand All @@ -29,6 +30,7 @@
#include <boost/program_options/variables_map.hpp>

#include <cstdlib>
#include <filesystem>
#include <iostream>
#include <string>
#include <utility>
Expand All @@ -42,12 +44,13 @@ CliArgs::parse(int argc, char const* argv[])
// clang-format off
po::options_description description("Options");
description.add_options()
("help,h", "print help message and exit")
("version,v", "print version and exit")
("conf,c", po::value<std::string>()->default_value(kDEFAULT_CONFIG_PATH), "configuration file")
("help,h", "Print help message and exit")
("version,v", "Print version and exit")
("conf,c", po::value<std::string>()->default_value(kDEFAULT_CONFIG_PATH), "Configuration file")
("ng-web-server,w", "Use ng-web-server")
("migrate", po::value<std::string>(), "start migration helper")
("migrate", po::value<std::string>(), "Start migration helper")
("verify", "Checks the validity of config values")
("config-description,d", po::value<std::string>(), "Generate config description markdown file")
;
// clang-format on
po::positional_options_description positional;
Expand All @@ -67,6 +70,17 @@ CliArgs::parse(int argc, char const* argv[])
return Action{Action::Exit{EXIT_SUCCESS}};
}

if (parsed.count("config-description") != 0u) {
std::filesystem::path filePath = parsed["config-description"].as<std::string>();

auto const res = util::config::ClioConfigDescription::generateConfigDescriptionToFile(filePath);
if (res.has_value())
return Action{Action::Exit{EXIT_SUCCESS}};

std::cerr << res.error().error << std::endl;
return Action{Action::Exit{EXIT_FAILURE}};
}

auto configPath = parsed["conf"].as<std::string>();

if (parsed.count("migrate") != 0u) {
Expand Down
1 change: 1 addition & 0 deletions src/util/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ target_sources(
newconfig/ConfigDefinition.cpp
newconfig/ConfigFileJson.cpp
newconfig/ObjectView.cpp
newconfig/Types.cpp
newconfig/ValueView.cpp
)

Expand Down
15 changes: 15 additions & 0 deletions src/util/newconfig/Array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include <cstddef>
#include <optional>
#include <ostream>
#include <string_view>
#include <vector>

Expand Down Expand Up @@ -103,4 +104,18 @@ class Array {
std::vector<ConfigValue> elements_;
};

/**
* @brief Custom output stream for Array
*
* @param stream The output stream
* @param arr The Array
* @return The same ostream we were given
*/
inline std::ostream&
operator<<(std::ostream& stream, Array arr)
{
stream << arr.getArrayPattern();
return stream;
}

} // namespace util::config
78 changes: 78 additions & 0 deletions src/util/newconfig/ConfigConstraints.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <cstdint>
#include <limits>
#include <optional>
#include <ostream>
#include <string>
#include <string_view>
#include <variant>
Expand Down Expand Up @@ -149,6 +150,28 @@ class Constraint {
*/
virtual std::optional<Error>
checkValueImpl(Value const& val) const = 0;

/**
* @brief Prints to the output stream for this specific constraint.
*
* @param stream The output stream
*/
virtual void
print(std::ostream& stream) const = 0;

/**
* @brief Custom output stream for constraint
*
* @param stream The output stream
* @param cons The constraint
* @return The same ostream we were given
*/
friend std::ostream&
operator<<(std::ostream& stream, Constraint const& cons)
{
cons.print(stream);
return stream;
}
};

/**
Expand Down Expand Up @@ -177,6 +200,17 @@ class PortConstraint final : public Constraint {
[[nodiscard]] std::optional<Error>
checkValueImpl(Value const& port) const override;

/**
* @brief Prints to the output stream for this specific constraint.
*
* @param stream The output stream
*/
void
print(std::ostream& stream) const override
{
stream << fmt::format("The minimum value is `{}`. The maximum value is `{}", kPORT_MIN, kPORT_MAX);
}

static constexpr uint32_t kPORT_MIN = 1;
static constexpr uint32_t kPORT_MAX = 65535;
};
Expand Down Expand Up @@ -206,6 +240,17 @@ class ValidIPConstraint final : public Constraint {
*/
[[nodiscard]] std::optional<Error>
checkValueImpl(Value const& ip) const override;

/**
* @brief Prints to the output stream for this specific constraint.
*
* @param stream The output stream
*/
void
print(std::ostream& stream) const override
{
stream << "The value must be a valid IP address";
}
};

/**
Expand Down Expand Up @@ -260,6 +305,17 @@ class OneOf final : public Constraint {
return Error{makeErrorMsg(key_, val, arr_)};
}

/**
* @brief Prints to the output stream for this specific constraint.
*
* @param stream The output stream
*/
void
print(std::ostream& stream) const override
{
stream << fmt::format("The value must be one of the following: `{}`", fmt::join(arr_, ", "));
}

std::string_view key_;
std::array<char const*, ArrSize> arr_;
};
Expand Down Expand Up @@ -312,6 +368,17 @@ class NumberValueConstraint final : public Constraint {
return Error{fmt::format("Number must be between {} and {}", min_, max_)};
}

/**
* @brief Prints to the output stream for this specific constraint.
*
* @param stream The output stream
*/
void
print(std::ostream& stream) const override
{
stream << fmt::format("The minimum value is `{}`. The maximum value is `{}`", min_, max_);
}

NumType min_;
NumType max_;
};
Expand Down Expand Up @@ -341,6 +408,17 @@ class PositiveDouble final : public Constraint {
*/
[[nodiscard]] std::optional<Error>
checkValueImpl(Value const& num) const override;

/**
* @brief Prints to the output stream for this specific constraint.
*
* @param stream The output stream
*/
void
print(std::ostream& stream) const override
{
stream << fmt::format("The value must be a positive double number");
}
};

static constinit PortConstraint gValidatePort{};
Expand Down
1 change: 1 addition & 0 deletions src/util/newconfig/ConfigDefinition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ ClioConfigDefinition::getObject(std::string_view prefix, std::optional<std::size
auto const hasPrefix = mapKey.starts_with(prefixWithDot);
if (idx.has_value() && hasPrefix && std::holds_alternative<Array>(mapVal)) {
ASSERT(std::get<Array>(mapVal).size() > idx.value(), "Index provided is out of scope");

// we want to support getObject("array") and getObject("array.[]"), so we check if "[]" exists
if (!prefix.contains("[]"))
return ObjectView{prefixWithDot + "[]", idx.value(), *this};
Expand Down
27 changes: 0 additions & 27 deletions src/util/newconfig/ConfigDefinition.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,17 @@
#include "util/Assert.hpp"
#include "util/newconfig/Array.hpp"
#include "util/newconfig/ConfigConstraints.hpp"
#include "util/newconfig/ConfigDescription.hpp"
#include "util/newconfig/ConfigFileInterface.hpp"
#include "util/newconfig/ConfigValue.hpp"
#include "util/newconfig/Error.hpp"
#include "util/newconfig/ObjectView.hpp"
#include "util/newconfig/Types.hpp"
#include "util/newconfig/ValueView.hpp"

#include <boost/json/value.hpp>
#include <boost/json/value_to.hpp>
#include <fmt/core.h>

#include <algorithm>
#include <cassert>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <expected>
#include <initializer_list>
#include <optional>
#include <string>
Expand Down Expand Up @@ -84,26 +77,6 @@ class ClioConfigDefinition {
[[nodiscard]] std::optional<std::vector<Error>>
parse(ConfigFileInterface const& config);

/**
* @brief Validates the configuration file
*
* Should only check for valid values, without populating
*
* @param config The configuration file interface
* @return An optional vector of Error objects stating all the failures if validation fails
*/
[[nodiscard]] std::optional<std::vector<Error>>
validate(ConfigFileInterface const& config) const;

/**
* @brief Generate markdown file of all the clio config descriptions
*
* @param configDescription The configuration description object
* @return An optional Error if generating markdown fails
*/
[[nodiscard]] std::expected<std::string, Error>
getMarkdown(ClioConfigDescription const& configDescription) const;

/**
* @brief Returns the ObjectView specified with the prefix
*
Expand Down
Loading
Loading