Skip to content

Commit

Permalink
Merge pull request #5045 from bharathv/cluster_config_schema
Browse files Browse the repository at this point in the history
admin/build: introduce cluster config schema util
  • Loading branch information
bharathv committed Jun 15, 2022
2 parents a9d9fcf + 9cf93b9 commit db8b21f
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 64 deletions.
1 change: 1 addition & 0 deletions src/v/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ add_subdirectory(security)
add_subdirectory(serde)
add_subdirectory(cloud_storage)
add_subdirectory(v8_engine)
add_subdirectory(rp_util)

option(ENABLE_GIT_VERSION "Build with Git metadata" OFF)
if(${ENABLE_GIT_VERSION})
Expand Down
12 changes: 12 additions & 0 deletions src/v/redpanda/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,21 @@ foreach(swag ${swags})
list(APPEND swag_files ${${swag}_swagger_files})
endforeach()

# Client facing utilities
v_cc_library(
NAME clientutil
SRCS
cluster_config_schema_util.cc
${cluster_config_swagger_files}
DEPS
v::config
)

v_cc_library(
NAME application
SRCS
${swag_files}
cluster_config_schema_util.cc
admin_server.cc
cli_parser.cc
request_auth.cc
Expand Down Expand Up @@ -56,4 +67,5 @@ if(CMAKE_BUILD_TYPE MATCHES Release)
set_property(TARGET redpanda PROPERTY INTERPROCEDURAL_OPTIMIZATION ON)
endif()
endif()

install(TARGETS redpanda DESTINATION bin)
66 changes: 2 additions & 64 deletions src/v/redpanda/admin_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "cluster/topics_frontend.h"
#include "cluster/tx_gateway_frontend.h"
#include "cluster/types.h"
#include "cluster_config_schema_util.h"
#include "config/configuration.h"
#include "config/endpoint_tls_config.h"
#include "finjector/hbadger.h"
Expand All @@ -46,7 +47,6 @@
#include "raft/types.h"
#include "redpanda/admin/api-doc/broker.json.h"
#include "redpanda/admin/api-doc/cluster.json.h"
#include "redpanda/admin/api-doc/cluster_config.json.h"
#include "redpanda/admin/api-doc/config.json.h"
#include "redpanda/admin/api-doc/debug.json.h"
#include "redpanda/admin/api-doc/features.json.h"
Expand Down Expand Up @@ -856,69 +856,7 @@ void admin_server::register_cluster_config_routes() {
ss::httpd::cluster_config_json::get_cluster_config_schema,
[](std::unique_ptr<ss::httpd::request> req)
-> ss::future<ss::json::json_return_type> {
using property_map = std::map<
ss::sstring,
ss::httpd::cluster_config_json::cluster_config_property_metadata>;

property_map properties;

config::shard_local_cfg().for_each(
[&properties](const config::base_property& p) {
if (p.get_visibility() == config::visibility::deprecated) {
// Do not mention deprecated settings in schema: they
// only exist internally to avoid making existing stored
// configs invalid.
return;
}

auto [pm_i, inserted] = properties.emplace(
ss::sstring(p.name()),
ss::httpd::cluster_config_json::
cluster_config_property_metadata());
vassert(inserted, "Emplace failed, duplicate property name?");

auto& pm = pm_i->second;
pm.description = ss::sstring(p.desc());
pm.needs_restart = p.needs_restart();
pm.visibility = ss::sstring(
config::to_string_view(p.get_visibility()));
pm.nullable = p.is_nullable();
pm.is_secret = p.is_secret();

if (p.is_array()) {
pm.type = "array";

auto items = ss::httpd::cluster_config_json::
cluster_config_property_metadata_items();
items.type = ss::sstring(p.type_name());
pm.items = items;
} else {
pm.type = ss::sstring(p.type_name());
}

auto enum_values = p.enum_values();
if (!enum_values.empty()) {
// In swagger, this field would just be called 'enum', but
// because we use C++ code generation for our structures,
// we cannot use that reserved word
pm.enum_values = enum_values;
}

const auto& example = p.example();
if (example.has_value()) {
pm.example = ss::sstring(example.value());
}

const auto& units = p.units_name();
if (units.has_value()) {
pm.units = ss::sstring(units.value());
}
});

std::map<ss::sstring, property_map> response = {
{ss::sstring("properties"), std::move(properties)}};

co_return ss::json::json_return_type(std::move(response));
co_return util::generate_json_schema(config::shard_local_cfg());
});

register_route<superuser, true>(
Expand Down
77 changes: 77 additions & 0 deletions src/v/redpanda/cluster_config_schema_util.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright 2020 Redpanda Data, Inc.
*
* Use of this software is governed by the Business Source License
* included in the file licenses/BSL.md
*
* As of the Change Date specified in that file, in accordance with
* the Business Source License, use of this software will be governed
* by the Apache License, Version 2.0
*/
#include "cluster_config_schema_util.h"

// This is factored out to make it a separate binary that can generate schema
// without bringing up a redpanda cluster. Down stream tools can make use of
// this for config generation.
ss::json::json_return_type
util::generate_json_schema(const config::configuration& conf) {
using property_map = std::map<
ss::sstring,
ss::httpd::cluster_config_json::cluster_config_property_metadata>;

property_map properties;

conf.for_each([&properties](const config::base_property& p) {
if (p.get_visibility() == config::visibility::deprecated) {
// Do not mention deprecated settings in schema: they
// only exist internally to avoid making existing stored
// configs invalid.
return;
}

auto [pm_i, inserted] = properties.emplace(
ss::sstring(p.name()),
ss::httpd::cluster_config_json::cluster_config_property_metadata());
vassert(inserted, "Emplace failed, duplicate property name?");

auto& pm = pm_i->second;
pm.description = ss::sstring(p.desc());
pm.needs_restart = p.needs_restart();
pm.visibility = ss::sstring(config::to_string_view(p.get_visibility()));
pm.nullable = p.is_nullable();
pm.is_secret = p.is_secret();

if (p.is_array()) {
pm.type = "array";

auto items = ss::httpd::cluster_config_json::
cluster_config_property_metadata_items();
items.type = ss::sstring(p.type_name());
pm.items = items;
} else {
pm.type = ss::sstring(p.type_name());
}

auto enum_values = p.enum_values();
if (!enum_values.empty()) {
// In swagger, this field would just be called 'enum', but
// because we use C++ code generation for our structures,
// we cannot use that reserved word
pm.enum_values = enum_values;
}

const auto& example = p.example();
if (example.has_value()) {
pm.example = ss::sstring(example.value());
}

const auto& units = p.units_name();
if (units.has_value()) {
pm.units = ss::sstring(units.value());
}
});

std::map<ss::sstring, property_map> response = {
{ss::sstring("properties"), std::move(properties)}};
return ss::json::json_return_type(std::move(response));
}
26 changes: 26 additions & 0 deletions src/v/redpanda/cluster_config_schema_util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2020 Redpanda Data, Inc.
*
* Use of this software is governed by the Business Source License
* included in the file licenses/BSL.md
*
* As of the Change Date specified in that file, in accordance with
* the Business Source License, use of this software will be governed
* by the Apache License, Version 2.0
*/

#pragma once

#include "config/configuration.h"
#include "redpanda/admin/api-doc/cluster_config.json.h"

namespace util {

/**
* @brief Generates json schema for a given configuration.
* @return ss::json::json_return_type
*/
ss::json::json_return_type
generate_json_schema(const config::configuration& conf);

} // namespace util
5 changes: 5 additions & 0 deletions src/v/rp_util/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Packages utilities exposed by core that are useful to clients.
add_executable(rp_util main.cc)
set_property(TARGET rp_util PROPERTY POSITION_INDEPENDENT_CODE ON)
target_link_libraries(rp_util PUBLIC v::clientutil)
install(TARGETS rp_util DESTINATION bin)
47 changes: 47 additions & 0 deletions src/v/rp_util/main.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright 2020 Redpanda Data, Inc.
*
* Use of this software is governed by the Business Source License
* included in the file licenses/BSL.md
*
* As of the Change Date specified in that file, in accordance with
* the Business Source License, use of this software will be governed
* by the Apache License, Version 2.0
*/

#include "boost/program_options.hpp"
#include "redpanda/cluster_config_schema_util.h"
#include "version.h"

#include <iostream>

namespace po = boost::program_options;

/**
* This binary is meant to host developer friendly utilities related to core.
* Few things to note when adding new capabilities to this.
*
* - This is _not_ customer facing tooling.
* - This is _not_ a CLI tool to access Redpanda services.
* - This may _not_ be shipped as a part of official release artifacts.
* - This tool provides _no backward compatibility_ of any sorts.
*/
int main(int ac, char* av[]) {
po::options_description desc("Allowed options");
desc.add_options()("help", "Allowed options")(
"config_schema_json", "Generates JSON schema for cluster configuration")(
"version", "Redpanda core version for this utility");
po::variables_map vm;
po::store(po::parse_command_line(ac, av, desc), vm);
po::notify(vm);

if (vm.count("help")) {
std::cout << desc << "\n";
} else if (vm.count("config_schema_json")) {
std::cout << util::generate_json_schema(config::configuration())._res
<< "\n";
} else if (vm.count("version")) {
std::cout << redpanda_version() << "\n";
}
return 0;
}

0 comments on commit db8b21f

Please sign in to comment.