diff --git a/Extensions.md b/Extensions.md index 0bfbd5bd98..f719918249 100644 --- a/Extensions.md +++ b/Extensions.md @@ -80,7 +80,9 @@ extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { .deinit = nullptr, .user_data = nullptr, .processors_count = 0, - .processors_ptr = nullptr + .processors_ptr = nullptr, + .controller_services_count = 0, + .controller_services_ptr = nullptr, }; return MinifiCreateCppExtension(&ext_create_info); } diff --git a/core-framework/include/agent/agent_docs.h b/core-framework/include/agent/agent_docs.h index 14544f2d6b..4c7e250356 100644 --- a/core-framework/include/agent/agent_docs.h +++ b/core-framework/include/agent/agent_docs.h @@ -16,18 +16,17 @@ */ #pragma once -#include "minifi-cpp/agent/agent_docs.h" - #include #include #include #include -#include "utils/StringUtils.h" #include "core/ClassName.h" -#include "minifi-cpp/core/OutputAttribute.h" -#include "minifi-cpp/core/ControllerServiceApi.h" +#include "minifi-cpp/agent/agent_docs.h" +#include "minifi-cpp/core/ControllerServiceType.h" #include "minifi-cpp/core/DynamicProperty.h" +#include "minifi-cpp/core/OutputAttribute.h" +#include "utils/StringUtils.h" namespace org::apache::nifi::minifi { @@ -44,8 +43,8 @@ inline auto toVector(std::span attributes) return std::vector(attributes.begin(), attributes.end()); } -inline auto toVector(std::span apis) { - return std::vector(apis.begin(), apis.end()); +inline auto toVector(std::span apis) { + return std::vector(apis.begin(), apis.end()); } inline auto toVector(std::span properties) { diff --git a/core-framework/include/core/controller/ControllerServiceBase.h b/core-framework/include/core/controller/ControllerServiceBase.h index 2fd22b2990..621f482959 100644 --- a/core-framework/include/core/controller/ControllerServiceBase.h +++ b/core-framework/include/core/controller/ControllerServiceBase.h @@ -28,8 +28,8 @@ #include "core/Connectable.h" #include "minifi-cpp/core/controller/ControllerServiceApi.h" #include "minifi-cpp/core/controller/ControllerServiceInterface.h" -#include "minifi-cpp/core/ControllerServiceApiDefinition.h" -#include "minifi-cpp/core/controller/ControllerServiceMetadata.h" +#include "minifi-cpp/core/ControllerServiceTypeDefinition.h" +#include "minifi-cpp/core/ControllerServiceMetadata.h" namespace org::apache::nifi::minifi::core::controller { @@ -95,7 +95,7 @@ class ControllerServiceBase : public ControllerServiceApi { } - static constexpr auto ImplementsApis = std::array{}; + static constexpr auto ImplementsApis = std::array{}; protected: std::string name_; diff --git a/core-framework/include/core/controller/ControllerServiceFactoryImpl.h b/core-framework/include/core/controller/ControllerServiceFactoryImpl.h index 4060e9d18e..a30bd48c65 100644 --- a/core-framework/include/core/controller/ControllerServiceFactoryImpl.h +++ b/core-framework/include/core/controller/ControllerServiceFactoryImpl.h @@ -17,10 +17,12 @@ #pragma once -#include #include +#include #include + #include "core/ClassName.h" +#include "minifi-cpp/core/ControllerServiceMetadata.h" #include "minifi-cpp/core/controller/ControllerServiceFactory.h" namespace org::apache::nifi::minifi::core::controller { diff --git a/core-framework/include/http/HTTPClient.h b/core-framework/include/http/HTTPClient.h index 9339a5b216..b27c54df52 100644 --- a/core-framework/include/http/HTTPClient.h +++ b/core-framework/include/http/HTTPClient.h @@ -45,6 +45,7 @@ #include "minifi-cpp/core/logging/Logger.h" #include "core/logging/LoggerFactory.h" #include "minifi-cpp/controllers/SSLContextServiceInterface.h" +#include "minifi-cpp/core/PropertyDefinition.h" #include "utils/ByteArrayCallback.h" namespace org::apache::nifi::minifi::http { diff --git a/extensions/ExtensionInitializer.cpp b/extensions/ExtensionInitializer.cpp index e735a78e77..3f44395f99 100644 --- a/extensions/ExtensionInitializer.cpp +++ b/extensions/ExtensionInitializer.cpp @@ -29,7 +29,9 @@ extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { .deinit = nullptr, .user_data = nullptr, .processors_count = 0, - .processors_ptr = nullptr + .processors_ptr = nullptr, + .controller_services_count = 0, + .controller_services_ptr = nullptr, }; return minifi::utils::MinifiCreateCppExtension(&ext_create_info); } diff --git a/extensions/aws/tests/MultipartUploadStateStorageTest.cpp b/extensions/aws/tests/MultipartUploadStateStorageTest.cpp index c791e85c9c..fc6f757be3 100644 --- a/extensions/aws/tests/MultipartUploadStateStorageTest.cpp +++ b/extensions/aws/tests/MultipartUploadStateStorageTest.cpp @@ -32,7 +32,7 @@ class MultipartUploadStateStorageTestFixture { MultipartUploadStateStorageTestFixture() { LogTestController::getInstance().setDebug(); const auto storage_uuid = minifi::utils::IdGenerator::getIdGenerator()->generate(); - state_storage_ = std::make_unique(core::controller::ControllerServiceMetadata{ + state_storage_ = std::make_unique(core::ControllerServiceMetadata{ .uuid = storage_uuid, .name = "KeyValueStateStorage", .logger = logging::LoggerFactory::getLogger(storage_uuid) diff --git a/extensions/llamacpp/processors/ExtensionInitializer.cpp b/extensions/llamacpp/processors/ExtensionInitializer.cpp index 29316f8b34..4da94d071c 100644 --- a/extensions/llamacpp/processors/ExtensionInitializer.cpp +++ b/extensions/llamacpp/processors/ExtensionInitializer.cpp @@ -36,6 +36,8 @@ extern "C" MinifiExtension* MinifiInitExtension(MinifiConfig* /*config*/) { .user_data = nullptr, .processors_count = 1, .processors_ptr = &description, + .controller_services_count = 0, + .controller_services_ptr = nullptr, }; extension = MinifiCreateExtension(&ext_create_info); }); diff --git a/extensions/opencv/OpenCVLoader.cpp b/extensions/opencv/OpenCVLoader.cpp index 53f61dbcaf..1dc69c73ec 100644 --- a/extensions/opencv/OpenCVLoader.cpp +++ b/extensions/opencv/OpenCVLoader.cpp @@ -40,7 +40,9 @@ extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { .deinit = nullptr, .user_data = nullptr, .processors_count = 0, - .processors_ptr = nullptr + .processors_ptr = nullptr, + .controller_services_count = 0, + .controller_services_ptr = nullptr, }; return minifi::utils::MinifiCreateCppExtension(&ext_create_info); } diff --git a/extensions/python/pythonlibloader/PythonLibLoader.cpp b/extensions/python/pythonlibloader/PythonLibLoader.cpp index 9c9a35d284..45aea023e9 100644 --- a/extensions/python/pythonlibloader/PythonLibLoader.cpp +++ b/extensions/python/pythonlibloader/PythonLibLoader.cpp @@ -112,7 +112,9 @@ extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* config) { .deinit = nullptr, .user_data = nullptr, .processors_count = 0, - .processors_ptr = nullptr + .processors_ptr = nullptr, + .controller_services_count = 0, + .controller_services_ptr = nullptr, }; return minifi::utils::MinifiCreateCppExtension(&ext_create_info); } diff --git a/extensions/python/pythonloader/PyProcLoader.cpp b/extensions/python/pythonloader/PyProcLoader.cpp index cd9cbb9986..23f54eca7d 100644 --- a/extensions/python/pythonloader/PyProcLoader.cpp +++ b/extensions/python/pythonloader/PyProcLoader.cpp @@ -47,7 +47,9 @@ extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* config) { .deinit = nullptr, .user_data = nullptr, .processors_count = 0, - .processors_ptr = nullptr + .processors_ptr = nullptr, + .controller_services_count = 0, + .controller_services_ptr = nullptr, }; return minifi::utils::MinifiCreateCppExtension( &ext_create_info); } diff --git a/extensions/sftp/SFTPLoader.cpp b/extensions/sftp/SFTPLoader.cpp index 333ab173e5..4f3fe71b8e 100644 --- a/extensions/sftp/SFTPLoader.cpp +++ b/extensions/sftp/SFTPLoader.cpp @@ -42,7 +42,9 @@ extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { }, .user_data = nullptr, .processors_count = 0, - .processors_ptr = nullptr + .processors_ptr = nullptr, + .controller_services_count = 0, + .controller_services_ptr = nullptr, }; return minifi::utils::MinifiCreateCppExtension(&ext_create_info); } diff --git a/libminifi/include/controllers/NetworkPrioritizerService.h b/libminifi/include/controllers/NetworkPrioritizerService.h index 6e8e8593bb..a3fc85cb6e 100644 --- a/libminifi/include/controllers/NetworkPrioritizerService.h +++ b/libminifi/include/controllers/NetworkPrioritizerService.h @@ -51,7 +51,7 @@ class NetworkPrioritizerService : public core::controller::ControllerServiceBase public: using ControllerServiceBase::ControllerServiceBase; - explicit NetworkPrioritizerService(core::controller::ControllerServiceMetadata metadata, + explicit NetworkPrioritizerService(core::ControllerServiceMetadata metadata, std::shared_ptr clock) : ControllerServiceBase(std::move(metadata)), clock_(std::move(clock)) { diff --git a/libminifi/include/core/controller/ControllerService.h b/libminifi/include/core/controller/ControllerService.h index c80830db71..0dff3a884c 100644 --- a/libminifi/include/core/controller/ControllerService.h +++ b/libminifi/include/core/controller/ControllerService.h @@ -27,7 +27,7 @@ #include "core/ConfigurableComponentImpl.h" #include "core/Connectable.h" #include "minifi-cpp/core/controller/ControllerServiceApi.h" -#include "minifi-cpp/core/ControllerServiceApiDefinition.h" +#include "minifi-cpp/core/ControllerServiceTypeDefinition.h" namespace org::apache::nifi::minifi::core::controller { @@ -44,6 +44,7 @@ class ControllerService : public ConfigurableComponentImpl, public CoreComponent public: explicit ControllerServiceDescriptorImpl(ControllerService& impl): impl_(impl) {} void setSupportedProperties(std::span properties) override; + void setSupportedProperties(std::span properties) override; private: ControllerService& impl_; @@ -130,7 +131,7 @@ class ControllerService : public ConfigurableComponentImpl, public CoreComponent return false; } - static constexpr auto ImplementsApis = std::array{}; + static constexpr auto ImplementsApis = std::array{}; protected: std::unique_ptr impl_; @@ -146,6 +147,10 @@ inline void ControllerService::ControllerServiceDescriptorImpl::setSupportedProp impl_.setSupportedProperties(properties); } +inline void ControllerService::ControllerServiceDescriptorImpl::setSupportedProperties(std::span properties) { + impl_.setSupportedProperties(properties); +} + inline nonstd::expected ControllerService::ControllerServiceContextImpl::getProperty(std::string_view name) const { return impl_.getProperty(name); } diff --git a/libminifi/include/utils/CControllerService.h b/libminifi/include/utils/CControllerService.h new file mode 100644 index 0000000000..0d0ea4929d --- /dev/null +++ b/libminifi/include/utils/CControllerService.h @@ -0,0 +1,110 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include "minifi-c/minifi-c.h" +#include "minifi-cpp/Exception.h" +#include "minifi-cpp/core/ControllerServiceMetadata.h" +#include "minifi-cpp/core/Property.h" +#include "minifi-cpp/core/controller/ControllerServiceApi.h" + +namespace org::apache::nifi::minifi::utils { +class CControllerService; + + +struct CControllerServiceClassDescription { + std::string group_name; + std::string name; + std::string version; + + std::vector class_properties; + + MinifiControllerServiceCallbacks callbacks; +}; + +class CControllerService final : public core::controller::ControllerServiceApi, public core::controller::ControllerServiceInterface { + public: + CControllerService(CControllerServiceClassDescription class_description, core::ControllerServiceMetadata metadata) + : class_description_(std::move(class_description)), + metadata_(std::move(metadata)) { + MinifiControllerServiceMetadata c_metadata; + auto uuid_str = metadata_.uuid.to_string(); + c_metadata.uuid = MinifiStringView{.data = uuid_str.data(), .length = uuid_str.length()}; + c_metadata.name = MinifiStringView{.data = metadata_.name.data(), .length = metadata_.name.length()}; + c_metadata.logger = reinterpret_cast(&metadata_.logger); + impl_ = class_description_.callbacks.create(c_metadata); + } + CControllerService(CControllerServiceClassDescription class_description, core::ControllerServiceMetadata metadata, gsl::owner impl) + : class_description_(std::move(class_description)), + impl_(impl), + metadata_(std::move(metadata)) {} + ~CControllerService() override { + class_description_.callbacks.destroy(impl_); + } + + void initialize(core::controller::ControllerServiceDescriptor& descriptor) override { + descriptor.setSupportedProperties(std::span(class_description_.class_properties)); + } + + void onEnable(core::controller::ControllerServiceContext& controller_service_context, + const std::shared_ptr&, + const std::vector>&) override { + const auto enable_status = class_description_.callbacks.enable(impl_, reinterpret_cast(&controller_service_context)); + if (enable_status != MINIFI_STATUS_SUCCESS) { + throw Exception(PROCESS_SCHEDULE_EXCEPTION, "Could not enable controller service"); + } + } + + void notifyStop() override { + class_description_.callbacks.notifyStop(impl_); + } + + ControllerServiceInterface* getControllerServiceInterface() override { + return this; + } + + [[nodiscard]] std::string getName() const { + return metadata_.name; + } + + [[nodiscard]] Identifier getUUID() const { + return metadata_.uuid; + } + + [[nodiscard]] void* getImpl() const { + return this->impl_; + } + + [[nodiscard]] const CControllerServiceClassDescription& getClassDescription() const { + return class_description_; + } + + private: + CControllerServiceClassDescription class_description_; + gsl::owner impl_; + minifi::core::ControllerServiceMetadata metadata_; +}; + +void useCControllerServiceClassDescription(const MinifiControllerServiceClassDefinition& class_description, + const BundleIdentifier& bundle_id, + const std::function& fn); + +} // namespace org::apache::nifi::minifi::utils diff --git a/libminifi/include/utils/CProcessor.h b/libminifi/include/utils/CProcessor.h index bef73d9e9b..6b8e6660ec 100644 --- a/libminifi/include/utils/CProcessor.h +++ b/libminifi/include/utils/CProcessor.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include "minifi-cpp/core/Annotation.h" #include "core/ProcessorMetrics.h" @@ -63,18 +64,18 @@ class CProcessor : public minifi::core::ProcessorApi { CProcessor(CProcessorClassDescription class_description, minifi::core::ProcessorMetadata metadata) : class_description_(std::move(class_description)), metrics_extension_(std::make_shared(*this)) { - metadata_ = metadata; + metadata_ = std::move(metadata); MinifiProcessorMetadata c_metadata; - auto uuid_str = metadata.uuid.to_string(); + const auto uuid_str = metadata.uuid.to_string(); c_metadata.uuid = MinifiStringView{.data = uuid_str.data(), .length = uuid_str.length()}; - c_metadata.name = MinifiStringView{.data = metadata.name.data(), .length = metadata.name.length()}; + c_metadata.name = MinifiStringView{.data = metadata_.name.data(), .length = metadata_.name.length()}; c_metadata.logger = reinterpret_cast(&metadata_.logger); impl_ = class_description_.callbacks.create(c_metadata); } CProcessor(CProcessorClassDescription class_description, minifi::core::ProcessorMetadata metadata, gsl::owner impl) : class_description_(std::move(class_description)), impl_(impl), - metadata_(metadata), + metadata_(std::move(metadata)), metrics_extension_(std::make_shared(*this)) {} ~CProcessor() override { class_description_.callbacks.destroy(impl_); diff --git a/libminifi/src/controllers/SSLContextService.cpp b/libminifi/src/controllers/SSLContextService.cpp index 584b5109d9..5d7cfc72ef 100644 --- a/libminifi/src/controllers/SSLContextService.cpp +++ b/libminifi/src/controllers/SSLContextService.cpp @@ -598,7 +598,7 @@ void SSLContextService::verifyCertificateExpiration() { std::shared_ptr SSLContextService::createAndEnable(std::string_view name, const std::shared_ptr& configuration) { auto uuid = utils::IdGenerator::getIdGenerator()->generate(); auto logger = core::logging::LoggerFactory::getLogger(uuid); - auto service = std::make_shared(name, uuid, std::make_unique(core::controller::ControllerServiceMetadata{ + auto service = std::make_shared(name, uuid, std::make_unique(core::ControllerServiceMetadata{ .uuid = uuid, .name = std::string{name}, .logger = logger, diff --git a/libminifi/src/minifi-c.cpp b/libminifi/src/minifi-c.cpp index e2ba672b9d..3fc5c1ec46 100644 --- a/libminifi/src/minifi-c.cpp +++ b/libminifi/src/minifi-c.cpp @@ -36,12 +36,17 @@ #include "minifi-cpp/core/logging/Logger.h" #include "minifi-cpp/core/state/PublishedMetricProvider.h" #include "utils/CProcessor.h" +#include "utils/CControllerService.h" #include "utils/PropertyErrors.h" namespace minifi = org::apache::nifi::minifi; namespace { +MinifiStringView minifiStringView(const std::string_view s) { + return MinifiStringView{.data = s.data(), .length = s.size()}; +} + std::string toString(MinifiStringView sv) { return {sv.data, sv.length}; } @@ -146,6 +151,37 @@ class CProcessorFactory : public minifi::core::ProcessorFactory { minifi::utils::CProcessorClassDescription class_description_; }; +class CControllerServiceFactory : public minifi::core::controller::ControllerServiceFactory { + public: + CControllerServiceFactory(std::string group_name, std::string class_name, minifi::utils::CControllerServiceClassDescription class_description) + : group_name_(std::move(group_name)), + class_name_(std::move(class_name)), + class_description_(std::move(class_description)) {} + std::unique_ptr create(minifi::core::ControllerServiceMetadata metadata) override { + return std::make_unique(class_description_, std::move(metadata)); + } + + [[nodiscard]] std::string getGroupName() const override { + return group_name_; + } + + [[nodiscard]] std::string getClassName() const override { + return class_name_; + } + + CControllerServiceFactory() = delete; + CControllerServiceFactory(const CControllerServiceFactory&) = delete; + CControllerServiceFactory& operator=(const CControllerServiceFactory&) = delete; + CControllerServiceFactory(CControllerServiceFactory&&) = delete; + CControllerServiceFactory& operator=(CControllerServiceFactory&&) = delete; + ~CControllerServiceFactory() override = default; + + private: + std::string group_name_; + std::string class_name_; + minifi::utils::CControllerServiceClassDescription class_description_; +}; + } // namespace namespace org::apache::nifi::minifi::utils { @@ -221,6 +257,35 @@ void useCProcessorClassDescription(const MinifiProcessorClassDefinition& class_d fn(description, c_class_description); } +void useCControllerServiceClassDescription(const MinifiControllerServiceClassDefinition& class_description, + const BundleIdentifier& bundle_id, + const std::function& fn) { + std::vector properties; + properties.reserve(class_description.class_properties_count); + for (size_t i = 0; i < class_description.class_properties_count; ++i) { + properties.push_back(createProperty(&class_description.class_properties_ptr[i])); + } + + auto name_segments = minifi::utils::string::split(toStringView(class_description.full_name), "::"); + gsl_Assert(!name_segments.empty()); + + minifi::ClassDescription description{ + .type_ = minifi::ResourceType::ControllerService, + .short_name_ = name_segments.back(), + .full_name_ = minifi::utils::string::join(".", name_segments), + .description_ = toString(class_description.description), + .class_properties_ = properties, + }; + + minifi::utils::CControllerServiceClassDescription c_class_description{ + .group_name = bundle_id.name, + .name = name_segments.back(), + .version = bundle_id.version, + .class_properties = properties, + .callbacks = class_description.callbacks + }; + fn(description, c_class_description); +} } // namespace org::apache::nifi::minifi::utils extern "C" { @@ -243,6 +308,14 @@ MinifiExtension* MinifiCreateExtension(const MinifiExtensionCreateInfo* extensio bundle_components.processors.emplace_back(description); }); } + for (size_t controller_service_idx = 0; controller_service_idx < extension_create_info->controller_services_count; ++controller_service_idx) { + minifi::utils::useCControllerServiceClassDescription(extension_create_info->controller_services_ptr[controller_service_idx], bundle, [&](const auto& description, const auto& c_class_description) { + minifi::core::ClassLoader::getDefaultClassLoader().getClassLoader(extension_name).registerClass( + c_class_description.name, + std::make_unique(extension_name, toString(extension_create_info->controller_services_ptr[controller_service_idx].full_name), c_class_description)); + bundle_components.controller_services.emplace_back(description); + }); + } return reinterpret_cast(new org::apache::nifi::minifi::core::extension::Extension::Info{ .name = toString(extension_create_info->name), .version = toString(extension_create_info->version), @@ -261,7 +334,7 @@ MinifiStatus MinifiProcessContextGetProperty(MinifiProcessContext* context, Mini auto result = reinterpret_cast(context)->getProperty(toStringView(property_name), flowfile != MINIFI_NULL ? reinterpret_cast*>(flowfile)->get() : nullptr); if (result) { - result_cb(user_ctx, MinifiStringView{.data = result.value().data(), .length = result.value().length()}); + result_cb(user_ctx, minifiStringView(result.value())); return MINIFI_STATUS_SUCCESS; } switch (static_cast(result.error().value())) { @@ -276,7 +349,7 @@ MinifiStatus MinifiProcessContextGetProperty(MinifiProcessContext* context, Mini void MinifiProcessContextGetProcessorName(MinifiProcessContext* context, void(*cb)(void* user_ctx, MinifiStringView result), void* user_ctx) { gsl_Assert(context != MINIFI_NULL); auto name = reinterpret_cast(context)->getProcessorInfo().getName(); - cb(user_ctx, MinifiStringView{.data = name.data(), .length = name.length()}); + cb(user_ctx, minifiStringView(name)); } MinifiBool MinifiProcessContextHasNonEmptyProperty(MinifiProcessContext* context, MinifiStringView property_name) { @@ -288,10 +361,7 @@ void MinifiConfigGet(MinifiConfig* configure, MinifiStringView key, void(*cb)(vo gsl_Assert(configure != MINIFI_NULL); auto value = reinterpret_cast(configure)->get(toString(key)); if (value) { - cb(user_ctx, MinifiStringView{ - .data = value->data(), - .length = value->length() - }); + cb(user_ctx, minifiStringView(*value)); } } @@ -415,7 +485,7 @@ void MinifiStatusToString(MinifiStatus status, void(*cb)(void* user_ctx, MinifiS default: return "Unknown error"; } }(); - cb(user_ctx, MinifiStringView{.data = message.data(), .length = message.size()}); + cb(user_ctx, minifiStringView(message)); } void MinifiFlowFileSetAttribute(MinifiProcessSession* session, MinifiFlowFile* flowfile, MinifiStringView attribute_name, const MinifiStringView* attribute_value) { @@ -437,7 +507,7 @@ MinifiBool MinifiFlowFileGetAttribute(MinifiProcessSession* session, MinifiFlowF if (!value.has_value()) { return false; } - cb(user_ctx, MinifiStringView{.data = value->data(), .length = value->size()}); + cb(user_ctx, minifiStringView(*value)); return true; } @@ -446,8 +516,56 @@ void MinifiFlowFileGetAttributes(MinifiProcessSession* session, MinifiFlowFile* gsl_Assert(session != MINIFI_NULL); gsl_Assert(flowfile != MINIFI_NULL); for (auto& [key, value] : (*reinterpret_cast*>(flowfile))->getAttributes()) { - cb(user_ctx, MinifiStringView{.data = key.data(), .length = key.size()}, MinifiStringView{.data = value.data(), .length = value.size()}); + cb(user_ctx, minifiStringView(key), minifiStringView(value)); + } +} + +MinifiStatus MinifiControllerServiceContextGetProperty(MinifiControllerServiceContext* context, MinifiStringView property_name, + void (*result_cb)(void* user_ctx, MinifiStringView result), void* user_ctx) { + gsl_Assert(context != MINIFI_NULL); + auto result = reinterpret_cast(context)->getProperty(toStringView(property_name)); + if (result) { + result_cb(user_ctx, minifiStringView(result.value())); + return MINIFI_STATUS_SUCCESS; } + switch (static_cast(result.error().value())) { + case minifi::core::PropertyErrorCode::NotSupportedProperty: return MINIFI_STATUS_NOT_SUPPORTED_PROPERTY; + case minifi::core::PropertyErrorCode::DynamicPropertiesNotSupported: return MINIFI_STATUS_DYNAMIC_PROPERTIES_NOT_SUPPORTED; + case minifi::core::PropertyErrorCode::PropertyNotSet: return MINIFI_STATUS_PROPERTY_NOT_SET; + case minifi::core::PropertyErrorCode::ValidationFailed: return MINIFI_STATUS_VALIDATION_FAILED; + default: return MINIFI_STATUS_UNKNOWN_ERROR; + } +} + + +MinifiStatus MinifiProcessContextGetControllerService( + MinifiProcessContext* process_context, + const MinifiStringView controller_service_name, + MinifiStatus(*cb)( + void* user_ctx, + void* service, + MinifiStringView type, + MinifiStringView group, + MinifiStringView version), + void* user_ctx) { + + gsl_Assert(process_context != MINIFI_NULL); + const auto context = reinterpret_cast(process_context); + const auto name_str = std::string{toStringView(controller_service_name)}; + const auto service_shared_ptr = context->getControllerService(name_str, context->getProcessorInfo().getUUID()); + if (!service_shared_ptr) { + return MINIFI_STATUS_VALIDATION_FAILED; + } + if (const minifi::utils::CControllerService* c_controller_service = dynamic_cast(&*service_shared_ptr)) { + const auto class_description = c_controller_service->getClassDescription(); + return cb(user_ctx, + c_controller_service->getImpl(), + minifiStringView(class_description.name), + minifiStringView(class_description.group_name), + minifiStringView(class_description.version)); + } + return MINIFI_STATUS_VALIDATION_FAILED; } + } // extern "C" diff --git a/libminifi/src/properties/Properties.cpp b/libminifi/src/properties/Properties.cpp index 1624a8557e..2f5723a641 100644 --- a/libminifi/src/properties/Properties.cpp +++ b/libminifi/src/properties/Properties.cpp @@ -22,6 +22,7 @@ #include #include "core/logging/LoggerConfiguration.h" +#include "minifi-cpp/core/PropertyValidator.h" #include "properties/Configuration.h" #include "properties/PropertiesFile.h" #include "utils/StringUtils.h" diff --git a/libminifi/test/libtest/integration/HTTPHandlers.h b/libminifi/test/libtest/integration/HTTPHandlers.h index 25a0dba5d4..40304948af 100644 --- a/libminifi/test/libtest/integration/HTTPHandlers.h +++ b/libminifi/test/libtest/integration/HTTPHandlers.h @@ -21,21 +21,22 @@ #include #include #include +#include #include +#include #include #include -#include -#include -#include "civetweb.h" #include "CivetServer.h" -#include "concurrentqueue.h" -#include "rapidjson/document.h" -#include "utils/HTTPUtils.h" #include "ServerAwareHandler.h" #include "c2/C2Payload.h" +#include "civetweb.h" +#include "concurrentqueue.h" +#include "minifi-cpp/properties/Configure.h" #include "properties/Configure.h" +#include "rapidjson/document.h" #include "unit/Catch.h" +#include "utils/HTTPUtils.h" namespace org::apache::nifi::minifi::test { diff --git a/libminifi/test/libtest/unit/ControllerServiceUtils.h b/libminifi/test/libtest/unit/ControllerServiceUtils.h index ff19982d31..ee8d79c379 100644 --- a/libminifi/test/libtest/unit/ControllerServiceUtils.h +++ b/libminifi/test/libtest/unit/ControllerServiceUtils.h @@ -29,7 +29,7 @@ std::unique_ptr make_controller_service(std if (!uuid) { uuid = minifi::utils::IdGenerator::getIdGenerator()->generate(); } - auto processor_impl = std::make_unique(core::controller::ControllerServiceMetadata{ + auto processor_impl = std::make_unique(core::ControllerServiceMetadata{ .uuid = uuid.value(), .name = std::string{name}, .logger = minifi::core::logging::LoggerFactory::getLogger(uuid.value()) diff --git a/libminifi/test/unit/NetworkPrioritizerServiceTests.cpp b/libminifi/test/unit/NetworkPrioritizerServiceTests.cpp index a54ba109ac..a05d21ad2b 100644 --- a/libminifi/test/unit/NetworkPrioritizerServiceTests.cpp +++ b/libminifi/test/unit/NetworkPrioritizerServiceTests.cpp @@ -31,7 +31,7 @@ std::shared_ptr createNetworkPrioritizerSer const std::shared_ptr& clock = std::make_shared()) { return std::make_shared( name, utils::Identifier{}, - std::make_unique(core::controller::ControllerServiceMetadata{ + std::make_unique(core::ControllerServiceMetadata{ .uuid = utils::Identifier{}, .name = name, .logger = logging::LoggerFactory::getLogger() diff --git a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceMetadata.h b/minifi-api/common/include/minifi-cpp/core/ControllerServiceMetadata.h similarity index 84% rename from minifi-api/include/minifi-cpp/core/controller/ControllerServiceMetadata.h rename to minifi-api/common/include/minifi-cpp/core/ControllerServiceMetadata.h index 3c6fb63b74..22200a84d8 100644 --- a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceMetadata.h +++ b/minifi-api/common/include/minifi-cpp/core/ControllerServiceMetadata.h @@ -1,5 +1,5 @@ /** - * Licensed to the Apache Software Foundation (ASF) under one or more +* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 @@ -21,7 +21,7 @@ #include "minifi-cpp/utils/Id.h" #include "minifi-cpp/core/logging/Logger.h" -namespace org::apache::nifi::minifi::core::controller { +namespace org::apache::nifi::minifi::core { struct ControllerServiceMetadata { utils::Identifier uuid; @@ -29,4 +29,4 @@ struct ControllerServiceMetadata { std::shared_ptr logger; }; -} // namespace org::apache::nifi::minifi::core::controller +} // namespace org::apache::nifi::minifi::core diff --git a/minifi-api/include/minifi-c/minifi-c.h b/minifi-api/include/minifi-c/minifi-c.h index b1f4af4616..ce4eb39d27 100644 --- a/minifi-api/include/minifi-c/minifi-c.h +++ b/minifi-api/include/minifi-c/minifi-c.h @@ -96,6 +96,8 @@ typedef struct MinifiExtension MinifiExtension; typedef struct MinifiPublishedMetrics MinifiPublishedMetrics; typedef struct MinifiAgent MinifiAgent; +typedef struct MinifiControllerServiceContext MinifiControllerServiceContext; + typedef enum MinifiStatus { MINIFI_STATUS_SUCCESS = 0, MINIFI_STATUS_UNKNOWN_ERROR = 1, @@ -149,6 +151,12 @@ typedef struct MinifiProcessorMetadata { MinifiLogger* logger; // borrowed reference, live until the processor is live } MinifiProcessorMetadata; +typedef struct MinifiControllerServiceMetadata { + MinifiStringView uuid; + MinifiStringView name; + MinifiLogger* logger; // borrowed reference, live until the controller service is live +} MinifiControllerServiceMetadata; + typedef struct MinifiProcessorCallbacks { MINIFI_OWNED void*(*create)(MinifiProcessorMetadata); void(*destroy)(MINIFI_OWNED void*); @@ -161,6 +169,13 @@ typedef struct MinifiProcessorCallbacks { MINIFI_OWNED MinifiPublishedMetrics*(*calculateMetrics)(void*); } MinifiProcessorCallbacks; +typedef struct MinifiControllerServiceCallbacks { + MINIFI_OWNED void*(*create)(MinifiControllerServiceMetadata); + void(*destroy)(MINIFI_OWNED void*); + MinifiStatus(*enable)(void*, MinifiControllerServiceContext*); + void(*notifyStop)(void*); +} MinifiControllerServiceCallbacks; + typedef struct MinifiProcessorClassDefinition { MinifiStringView full_name; // '::'-delimited fully qualified name e.g. 'org::apache::nifi::minifi::GenerateFlowFile' MinifiStringView description; @@ -180,6 +195,16 @@ typedef struct MinifiProcessorClassDefinition { MinifiProcessorCallbacks callbacks; } MinifiProcessorClassDefinition; +typedef struct MinifiControllerServiceClassDefinition { + MinifiStringView full_name; // '::'-delimited fully qualified name e.g. 'org::apache::nifi::minifi::extensions::gcp::GCPCredentialsControllerService + MinifiStringView description; + size_t class_properties_count; + const MinifiPropertyDefinition* class_properties_ptr; + + MinifiControllerServiceCallbacks callbacks; +} MinifiControllerServiceClassDefinition; + + typedef struct MinifiExtensionCreateInfo { MinifiStringView name; MinifiStringView version; @@ -187,6 +212,8 @@ typedef struct MinifiExtensionCreateInfo { void* user_data; size_t processors_count; const MinifiProcessorClassDefinition* processors_ptr; + size_t controller_services_count; + const MinifiControllerServiceClassDefinition* controller_services_ptr; } MinifiExtensionCreateInfo; MinifiExtension* MINIFI_CREATE_EXTENSION_FN(const MinifiExtensionCreateInfo* create_info); @@ -198,6 +225,9 @@ MinifiStatus MinifiProcessContextGetProperty(MinifiProcessContext* context, Mini void MinifiProcessContextGetProcessorName(MinifiProcessContext* context, void(*cb)(void* user_ctx, MinifiStringView processor_name), void* user_ctx); MinifiBool MinifiProcessContextHasNonEmptyProperty(MinifiProcessContext* context, MinifiStringView property_name); +MinifiStatus MinifiProcessContextGetControllerService(MinifiProcessContext*, MinifiStringView controller_service_name, + MinifiStatus(*cb)(void* user_ctx, void* service, MinifiStringView type, MinifiStringView group, MinifiStringView version), void* user_ctx); + void MinifiLoggerSetMaxLogSize(MinifiLogger*, int32_t); void MinifiLoggerLogString(MinifiLogger*, MinifiLogLevel, MinifiStringView); MinifiBool MinifiLoggerShouldLog(MinifiLogger*, MinifiLogLevel); @@ -226,6 +256,11 @@ MinifiBool MinifiFlowFileGetAttribute(MinifiProcessSession* session, MinifiFlowF void(*cb)(void* user_ctx, MinifiStringView attribute_value), void* user_ctx); void MinifiFlowFileGetAttributes(MinifiProcessSession* session, MinifiFlowFile* flowfile, void(*cb)(void* user_ctx, MinifiStringView attribute_name, MinifiStringView attribute_value), void* user_ctx); +MinifiStatus MinifiControllerServiceContextGetProperty(MinifiControllerServiceContext* context, + MinifiStringView property_name, + void(*cb)(void* user_ctx, MinifiStringView property_value), + void* user_ctx); + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/minifi-api/include/minifi-cpp/agent/agent_docs.h b/minifi-api/include/minifi-cpp/agent/agent_docs.h index 912377d39c..b6a6b9017c 100644 --- a/minifi-api/include/minifi-cpp/agent/agent_docs.h +++ b/minifi-api/include/minifi-cpp/agent/agent_docs.h @@ -22,7 +22,7 @@ #include #include "minifi-cpp/core/Annotation.h" -#include "minifi-cpp/core/ControllerServiceApi.h" +#include "minifi-cpp/core/ControllerServiceType.h" #include "minifi-cpp/core/DynamicProperty.h" #include "minifi-cpp/core/OutputAttribute.h" #include "minifi-cpp/core/Property.h" @@ -44,7 +44,7 @@ struct ClassDescription { std::vector dynamic_properties_{}; std::vector class_relationships_{}; std::vector output_attributes_{}; - std::vector api_implementations{}; + std::vector api_implementations{}; bool supports_dynamic_properties_ = false; bool supports_dynamic_relationships_ = false; std::string inputRequirement_{}; diff --git a/minifi-api/include/minifi-cpp/controllers/RecordSetReader.h b/minifi-api/include/minifi-cpp/controllers/RecordSetReader.h index f91dee3617..2b8b8731dd 100644 --- a/minifi-api/include/minifi-cpp/controllers/RecordSetReader.h +++ b/minifi-api/include/minifi-cpp/controllers/RecordSetReader.h @@ -17,7 +17,7 @@ #pragma once #include "minifi-cpp/core/controller/ControllerServiceInterface.h" -#include "minifi-cpp/core/ControllerServiceApiDefinition.h" +#include "minifi-cpp/core/ControllerServiceTypeDefinition.h" #include "minifi-cpp/core/Record.h" #include "utils/Enum.h" #include "utils/ProcessorConfigUtils.h" @@ -28,7 +28,7 @@ namespace org::apache::nifi::minifi::core { class RecordSetReader : public controller::ControllerServiceInterface { public: - static constexpr auto ProvidesApi = core::ControllerServiceApiDefinition{ + static constexpr auto ProvidesApi = core::ControllerServiceTypeDefinition{ .artifact = "minifi-system", .group = "org.apache.nifi.minifi", .type = "org.apache.nifi.minifi.core.RecordSetReader", diff --git a/minifi-api/include/minifi-cpp/controllers/RecordSetWriter.h b/minifi-api/include/minifi-cpp/controllers/RecordSetWriter.h index bbe1ebdde5..8453f2215d 100644 --- a/minifi-api/include/minifi-cpp/controllers/RecordSetWriter.h +++ b/minifi-api/include/minifi-cpp/controllers/RecordSetWriter.h @@ -18,7 +18,7 @@ #include "minifi-cpp/core/controller/ControllerServiceInterface.h" -#include "minifi-cpp/core/ControllerServiceApiDefinition.h" +#include "minifi-cpp/core/ControllerServiceTypeDefinition.h" #include "minifi-cpp/core/FlowFile.h" #include "minifi-cpp/core/ProcessSession.h" #include "minifi-cpp/core/Record.h" @@ -28,7 +28,7 @@ namespace org::apache::nifi::minifi::core { class RecordSetWriter : public controller::ControllerServiceInterface { public: - static constexpr auto ProvidesApi = core::ControllerServiceApiDefinition{ + static constexpr auto ProvidesApi = core::ControllerServiceTypeDefinition{ .artifact = "minifi-system", .group = "org.apache.nifi.minifi", .type = "org.apache.nifi.minifi.core.RecordSetWriter", diff --git a/minifi-api/include/minifi-cpp/controllers/SSLContextServiceInterface.h b/minifi-api/include/minifi-cpp/controllers/SSLContextServiceInterface.h index 68d79380b9..3058ade0ba 100644 --- a/minifi-api/include/minifi-cpp/controllers/SSLContextServiceInterface.h +++ b/minifi-api/include/minifi-cpp/controllers/SSLContextServiceInterface.h @@ -16,12 +16,12 @@ */ #pragma once -#include +#include #include #include #include -#include "minifi-cpp/core/ControllerServiceApiDefinition.h" +#include "minifi-cpp/core/ControllerServiceTypeDefinition.h" #include "minifi-cpp/agent/agent_version.h" #include "minifi-cpp/core/controller/ControllerServiceInterface.h" @@ -37,7 +37,7 @@ namespace org::apache::nifi::minifi::controllers { */ class SSLContextServiceInterface : public core::controller::ControllerServiceInterface { public: - static constexpr auto ProvidesApi = core::ControllerServiceApiDefinition{ + static constexpr auto ProvidesApi = core::ControllerServiceTypeDefinition{ .artifact = "minifi-system", .group = "org.apache.nifi.minifi", .type = "org.apache.nifi.minifi.controllers.SSLContextServiceInterface", diff --git a/minifi-api/include/minifi-cpp/core/ControllerServiceApi.h b/minifi-api/include/minifi-cpp/core/ControllerServiceType.h similarity index 84% rename from minifi-api/include/minifi-cpp/core/ControllerServiceApi.h rename to minifi-api/include/minifi-cpp/core/ControllerServiceType.h index fe0d450f7d..6d5b39de3d 100644 --- a/minifi-api/include/minifi-cpp/core/ControllerServiceApi.h +++ b/minifi-api/include/minifi-cpp/core/ControllerServiceType.h @@ -17,16 +17,16 @@ #pragma once #include -#include "minifi-cpp/core/ControllerServiceApiDefinition.h" +#include "minifi-cpp/core/ControllerServiceTypeDefinition.h" namespace org::apache::nifi::minifi::core { -struct ControllerServiceApi { +struct ControllerServiceType { std::string artifact; std::string group; std::string type; - ControllerServiceApi(const ControllerServiceApiDefinition& definition) // NOLINT(runtime/explicit) + ControllerServiceType(const ControllerServiceTypeDefinition& definition) // NOLINT(runtime/explicit) : artifact(definition.artifact), group(definition.group), type(definition.type) {} diff --git a/minifi-api/include/minifi-cpp/core/ControllerServiceApiDefinition.h b/minifi-api/include/minifi-cpp/core/ControllerServiceTypeDefinition.h similarity index 96% rename from minifi-api/include/minifi-cpp/core/ControllerServiceApiDefinition.h rename to minifi-api/include/minifi-cpp/core/ControllerServiceTypeDefinition.h index 37084baeaa..f40d871a6f 100644 --- a/minifi-api/include/minifi-cpp/core/ControllerServiceApiDefinition.h +++ b/minifi-api/include/minifi-cpp/core/ControllerServiceTypeDefinition.h @@ -20,7 +20,7 @@ namespace org::apache::nifi::minifi::core { -struct ControllerServiceApiDefinition { +struct ControllerServiceTypeDefinition { std::string_view artifact; std::string_view group; std::string_view type; diff --git a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceDescriptor.h b/minifi-api/include/minifi-cpp/core/controller/ControllerServiceDescriptor.h index 525a6d6cea..39fb6da89d 100644 --- a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceDescriptor.h +++ b/minifi-api/include/minifi-cpp/core/controller/ControllerServiceDescriptor.h @@ -26,6 +26,7 @@ class ControllerServiceDescriptor { virtual ~ControllerServiceDescriptor() = default; virtual void setSupportedProperties(std::span properties) = 0; + virtual void setSupportedProperties(std::span properties) = 0; }; } // namespace org::apache::nifi::minifi::core::controller diff --git a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceFactory.h b/minifi-api/include/minifi-cpp/core/controller/ControllerServiceFactory.h index 725944bfa3..aafc571dcd 100644 --- a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceFactory.h +++ b/minifi-api/include/minifi-cpp/core/controller/ControllerServiceFactory.h @@ -17,10 +17,11 @@ #pragma once -#include #include +#include #include -#include "minifi-cpp/core/controller/ControllerServiceMetadata.h" + +#include "minifi-cpp/core/ControllerServiceMetadata.h" namespace org::apache::nifi::minifi::core::controller { diff --git a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceInterface.h b/minifi-api/include/minifi-cpp/core/controller/ControllerServiceInterface.h index e1d7da19ea..799446f691 100644 --- a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceInterface.h +++ b/minifi-api/include/minifi-cpp/core/controller/ControllerServiceInterface.h @@ -17,23 +17,8 @@ */ #pragma once -#include -#include -#include -#include - -#include "minifi-cpp/properties/Configure.h" -#include "minifi-cpp/core/ConfigurableComponent.h" -#include "minifi-cpp/core/Connectable.h" - namespace org::apache::nifi::minifi::core::controller { -/** - * Controller Service base class that contains some pure virtual methods. - * - * Design: OnEnable is executed when the controller service is being enabled. - * Note that keeping state here must be protected in this function. - */ class ControllerServiceInterface { public: virtual ~ControllerServiceInterface() = default; diff --git a/minifi-api/minifi-c-api.def b/minifi-api/minifi-c-api.def index e26ed81e11..11c07093cf 100644 --- a/minifi-api/minifi-c-api.def +++ b/minifi-api/minifi-c-api.def @@ -2,9 +2,11 @@ LIBRARY core-minifi.dll EXPORTS MinifiCreateExtension MinifiPublishedMetricsCreate + MinifiProcessContextGetControllerService MinifiProcessContextGetProperty MinifiProcessContextGetProcessorName MinifiProcessContextHasNonEmptyProperty + MinifiControllerServiceContextGetProperty MinifiLoggerSetMaxLogSize MinifiLoggerLogString MinifiLoggerShouldLog