diff --git a/src/v/features/BUILD b/src/v/features/BUILD index fb5e353341f4..34c6cdf90471 100644 --- a/src/v/features/BUILD +++ b/src/v/features/BUILD @@ -34,3 +34,20 @@ redpanda_cc_library( "@seastar", ], ) + +redpanda_cc_library( + name = "enterprise_features", + srcs = [ + "enterprise_features.cc", + ], + hdrs = [ + "enterprise_features.h", + ], + include_prefix = "features", + visibility = ["//visibility:public"], + deps = [ + "//src/v/base", + "@abseil-cpp//absl/container:flat_hash_set", + "@boost//:range", + ], +) diff --git a/src/v/features/CMakeLists.txt b/src/v/features/CMakeLists.txt index 449e78492abf..3c0253f0b89d 100644 --- a/src/v/features/CMakeLists.txt +++ b/src/v/features/CMakeLists.txt @@ -14,4 +14,12 @@ v_cc_library( add_dependencies(v_features kafka_codegen_headers) +v_cc_library( + NAME enterprise_features + SRCS + enterprise_features.cc + DEPS + absl::flat_hash_set +) + add_subdirectory(tests) diff --git a/src/v/features/enterprise_features.cc b/src/v/features/enterprise_features.cc new file mode 100644 index 000000000000..7db399f42859 --- /dev/null +++ b/src/v/features/enterprise_features.cc @@ -0,0 +1,61 @@ +/* + * Copyright 2024 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 "enterprise_features.h" + +#include "base/vassert.h" + +#include + +namespace features { + +std::ostream& operator<<(std::ostream& os, license_required_feature f) { + switch (f) { + case license_required_feature::audit_logging: + return os << "audit_logging"; + case license_required_feature::cloud_storage: + return os << "cloud_storage"; + case license_required_feature::partition_auto_balancing_continuous: + return os << "partition_auto_balancing_continuous"; + case license_required_feature::core_balancing_continuous: + return os << "core_balancing_continuous"; + case license_required_feature::gssapi: + return os << "gssapi"; + case license_required_feature::oidc: + return os << "oidc"; + case license_required_feature::schema_id_validation: + return os << "schema_id_validation"; + case license_required_feature::rbac: + return os << "rbac"; + case license_required_feature::fips: + return os << "fips"; + } + __builtin_unreachable(); +} + +void enterprise_feature_report::set( + license_required_feature feat, bool enabled) { + auto insert = [feat](vtype& dest, const vtype& other) { + vassert( + !other.contains(feat), + "feature {{{}}} cannot be both enabled and disabled", + feat); + dest.insert(feat); + }; + + if (enabled) { + insert(_enabled, _disabled); + } else { + insert(_disabled, _enabled); + } +} + +} // namespace features diff --git a/src/v/features/enterprise_features.h b/src/v/features/enterprise_features.h new file mode 100644 index 000000000000..992b38f14a64 --- /dev/null +++ b/src/v/features/enterprise_features.h @@ -0,0 +1,54 @@ +/* + * Copyright 2024 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 +#include + +#include + +namespace features { + +enum class license_required_feature { + audit_logging, + cloud_storage, + partition_auto_balancing_continuous, + core_balancing_continuous, + gssapi, + oidc, + schema_id_validation, + rbac, + fips, +}; + +std::ostream& operator<<(std::ostream&, license_required_feature); + +/** + * Thin wrapper around two sets to indicate the current state of enterprise + * features in the cluster. + */ +class enterprise_feature_report { + using vtype = absl::flat_hash_set; + using range = boost::iterator_range; + +public: + void set(license_required_feature feat, bool enabled); + range enabled() const { return _enabled; } + range disabled() const { return _disabled; } + bool any() const { return !_enabled.empty(); } + +private: + vtype _enabled; + vtype _disabled; +}; + +} // namespace features