From aeea9742bcb013cdd666b9ea9edaf34c0981cdc8 Mon Sep 17 00:00:00 2001 From: Ferenc Gerlits Date: Wed, 9 Aug 2023 14:50:53 +0200 Subject: [PATCH 1/7] MINIFICPP-2164 Use a list of types for allowed types in PropertyDefinition --- extensions/elasticsearch/PostElasticsearch.h | 9 +- extensions/gcp/processors/GCSProcessor.h | 4 +- extensions/http-curl/processors/InvokeHTTP.h | 4 +- extensions/librdkafka/KafkaProcessorBase.h | 48 ++++----- extensions/splunk/SplunkHECProcessor.h | 40 ++++---- .../standard-processors/processors/GetTCP.h | 4 +- .../processors/ListenSyslog.h | 4 +- .../processors/ListenTCP.h | 4 +- .../standard-processors/processors/PutFile.h | 2 +- .../standard-processors/processors/PutTCP.h | 98 +++++++++---------- .../standard-processors/processors/TailFile.h | 4 +- .../tests/unit/YamlConfigurationTests.cpp | 8 +- libminifi/include/core/PropertyDefinition.h | 10 +- .../include/core/PropertyDefinitionBuilder.h | 36 +++---- libminifi/include/utils/meta/type_list.h | 9 ++ .../test/unit/ComponentManifestTests.cpp | 3 +- libminifi/test/unit/TypeListTests.cpp | 62 ++++++++++++ 17 files changed, 206 insertions(+), 143 deletions(-) create mode 100644 libminifi/test/unit/TypeListTests.cpp diff --git a/extensions/elasticsearch/PostElasticsearch.h b/extensions/elasticsearch/PostElasticsearch.h index 367e35d21e..2accf8be2f 100644 --- a/extensions/elasticsearch/PostElasticsearch.h +++ b/extensions/elasticsearch/PostElasticsearch.h @@ -53,16 +53,16 @@ class PostElasticsearch : public core::Processor { .withPropertyType(core::StandardPropertyTypes::UNSIGNED_LONG_TYPE) .withDefaultValue("100") .build(); - EXTENSIONAPI static constexpr auto ElasticCredentials = core::PropertyDefinitionBuilder<0, 1>::createProperty("Elasticsearch Credentials Provider Service") + EXTENSIONAPI static constexpr auto ElasticCredentials = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: + createProperty("Elasticsearch Credentials Provider Service") .withDescription("The Controller Service used to obtain Elasticsearch credentials.") .isRequired(true) - .withAllowedTypes({core::className()}) .build(); - EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0, 1>::createProperty("SSL Context Service") + EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: + createProperty("SSL Context Service") .withDescription("The SSL Context Service used to provide client certificate " "information for TLS/SSL (https) connections.") .isRequired(false) - .withAllowedTypes({core::className()}) .build(); EXTENSIONAPI static constexpr auto Hosts = core::PropertyDefinitionBuilder<>::createProperty("Hosts") .withDescription("A comma-separated list of HTTP hosts that host Elasticsearch query nodes. Currently only supports a single host.") @@ -90,7 +90,6 @@ class PostElasticsearch : public core::Processor { Identifier }; - EXTENSIONAPI static constexpr auto Success = core::RelationshipDefinition{"success", "All flowfiles that succeed in being transferred into Elasticsearch go here."}; EXTENSIONAPI static constexpr auto Failure = core::RelationshipDefinition{"failure", "All flowfiles that fail for reasons unrelated to server availability go to this relationship."}; EXTENSIONAPI static constexpr auto Error = core::RelationshipDefinition{"error", "All flowfiles that Elasticsearch responded to with an error go to this relationship."}; diff --git a/extensions/gcp/processors/GCSProcessor.h b/extensions/gcp/processors/GCSProcessor.h index b54fbe6919..3bec6405c3 100644 --- a/extensions/gcp/processors/GCSProcessor.h +++ b/extensions/gcp/processors/GCSProcessor.h @@ -39,10 +39,10 @@ class GCSProcessor : public core::Processor { logger_(std::move(logger)) { } - EXTENSIONAPI static constexpr auto GCPCredentials = core::PropertyDefinitionBuilder<0, 1>::createProperty("GCP Credentials Provider Service") + EXTENSIONAPI static constexpr auto GCPCredentials = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: + createProperty("GCP Credentials Provider Service") .withDescription("The Controller Service used to obtain Google Cloud Platform credentials. Should be the name of a GCPCredentialsControllerService.") .isRequired(true) - .withAllowedTypes({core::className()}) .build(); EXTENSIONAPI static constexpr auto NumberOfRetries = core::PropertyDefinitionBuilder<>::createProperty("Number of retries") .withDescription("How many retry attempts should be made before routing to the failure relationship.") diff --git a/extensions/http-curl/processors/InvokeHTTP.h b/extensions/http-curl/processors/InvokeHTTP.h index c9d291a349..f73f716449 100644 --- a/extensions/http-curl/processors/InvokeHTTP.h +++ b/extensions/http-curl/processors/InvokeHTTP.h @@ -103,10 +103,10 @@ class InvokeHTTP : public core::Processor { EXTENSIONAPI static constexpr auto AttributesToSend = core::PropertyDefinitionBuilder<>::createProperty("Attributes to Send") .withDescription("Regular expression that defines which attributes to send as HTTP headers in the request. If not defined, no attributes are sent as headers.") .build(); - EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0, 1, 0, 1>::createProperty("SSL Context Service") + EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0, 0, 1, utils::meta::type_list>:: + createProperty("SSL Context Service") .withDescription("The SSL Context Service used to provide client certificate information for TLS/SSL (https) connections.") .isRequired(false) - .withAllowedTypes({core::className()}) .withExclusiveOfProperties({{{"Remote URL", "^http:.*$"}}}) .build(); EXTENSIONAPI static constexpr auto ProxyHost = core::PropertyDefinitionBuilder<>::createProperty("Proxy Host") diff --git a/extensions/librdkafka/KafkaProcessorBase.h b/extensions/librdkafka/KafkaProcessorBase.h index eecc3f2fcb..352d653cea 100644 --- a/extensions/librdkafka/KafkaProcessorBase.h +++ b/extensions/librdkafka/KafkaProcessorBase.h @@ -47,37 +47,37 @@ enum class SASLMechanismOption { class KafkaProcessorBase : public core::Processor { public: - EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 1>::createProperty("SSL Context Service") - .withDescription("SSL Context Service Name") - .withAllowedTypes({core::className()}) - .build(); + EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: + createProperty("SSL Context Service") + .withDescription("SSL Context Service Name") + .build(); EXTENSIONAPI static constexpr auto SecurityProtocol = core::PropertyDefinitionBuilder()>::createProperty("Security Protocol") - .withDescription("Protocol used to communicate with brokers. Corresponds to Kafka's 'security.protocol' property.") - .withDefaultValue(magic_enum::enum_name(kafka::SecurityProtocolOption::plaintext)) - .withAllowedValues(magic_enum::enum_names()) - .isRequired(true) - .build(); + .withDescription("Protocol used to communicate with brokers. Corresponds to Kafka's 'security.protocol' property.") + .withDefaultValue(magic_enum::enum_name(kafka::SecurityProtocolOption::plaintext)) + .withAllowedValues(magic_enum::enum_names()) + .isRequired(true) + .build(); EXTENSIONAPI static constexpr auto KerberosServiceName = core::PropertyDefinitionBuilder<>::createProperty("Kerberos Service Name") - .withDescription("Kerberos Service Name") - .build(); + .withDescription("Kerberos Service Name") + .build(); EXTENSIONAPI static constexpr auto KerberosPrincipal = core::PropertyDefinitionBuilder<>::createProperty("Kerberos Principal") - .withDescription("Kerberos Principal") - .build(); + .withDescription("Kerberos Principal") + .build(); EXTENSIONAPI static constexpr auto KerberosKeytabPath = core::PropertyDefinitionBuilder<>::createProperty("Kerberos Keytab Path") - .withDescription("The path to the location on the local filesystem where the kerberos keytab is located. Read permission on the file is required.") - .build(); + .withDescription("The path to the location on the local filesystem where the kerberos keytab is located. Read permission on the file is required.") + .build(); EXTENSIONAPI static constexpr auto SASLMechanism = core::PropertyDefinitionBuilder()>::createProperty("SASL Mechanism") - .withDescription("The SASL mechanism to use for authentication. Corresponds to Kafka's 'sasl.mechanism' property.") - .withDefaultValue(magic_enum::enum_name(kafka::SASLMechanismOption::GSSAPI)) - .withAllowedValues(magic_enum::enum_names()) - .isRequired(true) - .build(); + .withDescription("The SASL mechanism to use for authentication. Corresponds to Kafka's 'sasl.mechanism' property.") + .withDefaultValue(magic_enum::enum_name(kafka::SASLMechanismOption::GSSAPI)) + .withAllowedValues(magic_enum::enum_names()) + .isRequired(true) + .build(); EXTENSIONAPI static constexpr auto Username = core::PropertyDefinitionBuilder<>::createProperty("Username") - .withDescription("The username when the SASL Mechanism is sasl_plaintext") - .build(); + .withDescription("The username when the SASL Mechanism is sasl_plaintext") + .build(); EXTENSIONAPI static constexpr auto Password = core::PropertyDefinitionBuilder<>::createProperty("Password") - .withDescription("The password for the given username when the SASL Mechanism is sasl_plaintext") - .build(); + .withDescription("The password for the given username when the SASL Mechanism is sasl_plaintext") + .build(); EXTENSIONAPI static constexpr auto Properties = std::array{ SSLContextService, SecurityProtocol, diff --git a/extensions/splunk/SplunkHECProcessor.h b/extensions/splunk/SplunkHECProcessor.h index e33a2bf920..6256571ccb 100644 --- a/extensions/splunk/SplunkHECProcessor.h +++ b/extensions/splunk/SplunkHECProcessor.h @@ -36,29 +36,29 @@ namespace org::apache::nifi::minifi::extensions::splunk { class SplunkHECProcessor : public core::Processor { public: EXTENSIONAPI static constexpr auto Hostname = core::PropertyDefinitionBuilder<>::createProperty("Hostname") - .withDescription("The ip address or hostname of the Splunk server.") - .isRequired(true) - .build(); + .withDescription("The ip address or hostname of the Splunk server.") + .isRequired(true) + .build(); EXTENSIONAPI static constexpr auto Port = core::PropertyDefinitionBuilder<>::createProperty("Port") - .withDescription("The HTTP Event Collector HTTP Port Number.") - .withPropertyType(core::StandardPropertyTypes::PORT_TYPE) - .withDefaultValue("8088") - .isRequired(true) - .build(); + .withDescription("The HTTP Event Collector HTTP Port Number.") + .withPropertyType(core::StandardPropertyTypes::PORT_TYPE) + .withDefaultValue("8088") + .isRequired(true) + .build(); EXTENSIONAPI static constexpr auto Token = core::PropertyDefinitionBuilder<>::createProperty("Token") - .withDescription("HTTP Event Collector token starting with the string Splunk. For example \'Splunk 1234578-abcd-1234-abcd-1234abcd\'") - .isRequired(true) - .build(); + .withDescription("HTTP Event Collector token starting with the string Splunk. For example \'Splunk 1234578-abcd-1234-abcd-1234abcd\'") + .isRequired(true) + .build(); EXTENSIONAPI static constexpr auto SplunkRequestChannel = core::PropertyDefinitionBuilder<>::createProperty("Splunk Request Channel") - .withDescription("Identifier of the used request channel.") - .isRequired(true) - .build(); - EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0, 1, 0, 1>::createProperty("SSL Context Service") - .withDescription("The SSL Context Service used to provide client certificate information for TLS/SSL (https) connections.") - .isRequired(false) - .withExclusiveOfProperties({{{"Hostname", "^http:.*$"}}}) - .withAllowedTypes({core::className()}) - .build(); + .withDescription("Identifier of the used request channel.") + .isRequired(true) + .build(); + EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0, 0, 1, utils::meta::type_list>:: + createProperty("SSL Context Service") + .withDescription("The SSL Context Service used to provide client certificate information for TLS/SSL (https) connections.") + .isRequired(false) + .withExclusiveOfProperties({{{"Hostname", "^http:.*$"}}}) + .build(); EXTENSIONAPI static constexpr auto Properties = std::array{ Hostname, Port, diff --git a/extensions/standard-processors/processors/GetTCP.h b/extensions/standard-processors/processors/GetTCP.h index 5846956be5..a7496df3e9 100644 --- a/extensions/standard-processors/processors/GetTCP.h +++ b/extensions/standard-processors/processors/GetTCP.h @@ -69,9 +69,9 @@ class GetTCP : public core::Processor { .withDescription("A comma delimited list of the endpoints to connect to. The format should be :.") .isRequired(true) .build(); - EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 1>::createProperty("SSL Context Service") + EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: + createProperty("SSL Context Service") .withDescription("SSL Context Service Name") - .withAllowedTypes({core::className()}) .build(); EXTENSIONAPI static constexpr auto MessageDelimiter = core::PropertyDefinitionBuilder<>::createProperty("Message Delimiter") .withDescription("Character that denotes the end of the message.") diff --git a/extensions/standard-processors/processors/ListenSyslog.h b/extensions/standard-processors/processors/ListenSyslog.h index 3f975cb2c9..0fee2eb5fc 100644 --- a/extensions/standard-processors/processors/ListenSyslog.h +++ b/extensions/standard-processors/processors/ListenSyslog.h @@ -75,10 +75,10 @@ class ListenSyslog : public NetworkListenerProcessor { .withPropertyType(core::StandardPropertyTypes::UNSIGNED_LONG_TYPE) .withDefaultValue("10000") .build(); - EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 1>::createProperty("SSL Context Service") + EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: + createProperty("SSL Context Service") .withDescription("The Controller Service to use in order to obtain an SSL Context. If this property is set, messages will be received over a secure connection. " "This Property is only considered if the Property has a value of \"TCP\".") - .withAllowedTypes({core::className()}) .build(); EXTENSIONAPI static constexpr auto ClientAuth = core::PropertyDefinitionBuilder()>::createProperty("Client Auth") .withDescription("The client authentication policy to use for the SSL Context. Only used if an SSL Context Service is provided.") diff --git a/extensions/standard-processors/processors/ListenTCP.h b/extensions/standard-processors/processors/ListenTCP.h index 9f096838ad..6fcf68576a 100644 --- a/extensions/standard-processors/processors/ListenTCP.h +++ b/extensions/standard-processors/processors/ListenTCP.h @@ -60,9 +60,9 @@ class ListenTCP : public NetworkListenerProcessor { .withDefaultValue("10000") .isRequired(true) .build(); - EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 1>::createProperty("SSL Context Service") + EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: + createProperty("SSL Context Service") .withDescription("The Controller Service to use in order to obtain an SSL Context. If this property is set, messages will be received over a secure connection.") - .withAllowedTypes({core::className()}) .build(); EXTENSIONAPI static constexpr auto ClientAuth = core::PropertyDefinitionBuilder()>::createProperty("Client Auth") .withDescription("The client authentication policy to use for the SSL Context. Only used if an SSL Context Service is provided.") diff --git a/extensions/standard-processors/processors/PutFile.h b/extensions/standard-processors/processors/PutFile.h index 26d49571b7..9067a1f6c7 100644 --- a/extensions/standard-processors/processors/PutFile.h +++ b/extensions/standard-processors/processors/PutFile.h @@ -71,7 +71,7 @@ class PutFile : public core::Processor { .withAllowedValues({CONFLICT_RESOLUTION_STRATEGY_FAIL, CONFLICT_RESOLUTION_STRATEGY_IGNORE, CONFLICT_RESOLUTION_STRATEGY_REPLACE}) .withDefaultValue(CONFLICT_RESOLUTION_STRATEGY_FAIL) .build(); - EXTENSIONAPI static constexpr auto CreateDirs = core::PropertyDefinitionBuilder<0, 0, 1>::createProperty("Create Missing Directories") + EXTENSIONAPI static constexpr auto CreateDirs = core::PropertyDefinitionBuilder<0, 1>::createProperty("Create Missing Directories") .withDescription("If true, then missing destination directories will be created. If false, flowfiles are penalized and sent to failure.") .withDefaultValue("true") .isRequired(true) diff --git a/extensions/standard-processors/processors/PutTCP.h b/extensions/standard-processors/processors/PutTCP.h index 923f90a24d..86439ac485 100644 --- a/extensions/standard-processors/processors/PutTCP.h +++ b/extensions/standard-processors/processors/PutTCP.h @@ -63,55 +63,55 @@ class PutTCP final : public core::Processor { "An optional \"Connection Per FlowFile\" parameter can be specified to change the behaviour so that each FlowFiles content is transmitted over a single TCP connection " "which is closed after the FlowFile has been sent."; -EXTENSIONAPI static constexpr auto Hostname = core::PropertyDefinitionBuilder<>::createProperty("Hostname") - .withDescription("The ip address or hostname of the destination.") - .withDefaultValue("localhost") - .isRequired(true) - .supportsExpressionLanguage(true) - .build(); -EXTENSIONAPI static constexpr auto Port = core::PropertyDefinitionBuilder<>::createProperty("Port") - .withDescription("The port or service on the destination.") - .isRequired(true) - .supportsExpressionLanguage(true) - .build(); -EXTENSIONAPI static constexpr auto IdleConnectionExpiration = core::PropertyDefinitionBuilder<>::createProperty("Idle Connection Expiration") - .withDescription("The amount of time a connection should be held open without being used before closing the connection. A value of 0 seconds will disable this feature.") - .withPropertyType(core::StandardPropertyTypes::TIME_PERIOD_TYPE) - .withDefaultValue("15 seconds") - .isRequired(true) - .supportsExpressionLanguage(true) - .build(); -EXTENSIONAPI static constexpr auto Timeout = core::PropertyDefinitionBuilder<>::createProperty("Timeout") - .withDescription("The timeout for connecting to and communicating with the destination.") - .withPropertyType(core::StandardPropertyTypes::TIME_PERIOD_TYPE) - .withDefaultValue("15 seconds") - .isRequired(true) - .supportsExpressionLanguage(true) - .build(); -EXTENSIONAPI static constexpr auto ConnectionPerFlowFile = core::PropertyDefinitionBuilder<>::createProperty("Connection Per FlowFile") - .withDescription("Specifies whether to send each FlowFile's content on an individual connection.") - .withPropertyType(core::StandardPropertyTypes::BOOLEAN_TYPE) - .withDefaultValue("false") - .isRequired(true) - .supportsExpressionLanguage(false) - .build(); -EXTENSIONAPI static constexpr auto OutgoingMessageDelimiter = core::PropertyDefinitionBuilder<>::createProperty("Outgoing Message Delimiter") - .withDescription("Specifies the delimiter to use when sending messages out over the same TCP stream. " - "The delimiter is appended to each FlowFile message that is transmitted over the stream so that the receiver can determine when one message ends and the next message begins. " - "Users should ensure that the FlowFile content does not contain the delimiter character to avoid errors.") - .isRequired(false) - .supportsExpressionLanguage(true) - .build(); -EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 1>::createProperty("SSL Context Service") - .withDescription("The Controller Service to use in order to obtain an SSL Context. If this property is set, messages will be sent over a secure connection.") - .isRequired(false) - .withAllowedTypes({core::className()}) - .build(); -EXTENSIONAPI static constexpr auto MaxSizeOfSocketSendBuffer = core::PropertyDefinitionBuilder<>::createProperty("Max Size of Socket Send Buffer") - .withDescription("The maximum size of the socket send buffer that should be used. This is a suggestion to the Operating System to indicate how big the socket buffer should be.") - .isRequired(false) - .withPropertyType(core::StandardPropertyTypes::DATA_SIZE_TYPE) - .build(); + EXTENSIONAPI static constexpr auto Hostname = core::PropertyDefinitionBuilder<>::createProperty("Hostname") + .withDescription("The ip address or hostname of the destination.") + .withDefaultValue("localhost") + .isRequired(true) + .supportsExpressionLanguage(true) + .build(); + EXTENSIONAPI static constexpr auto Port = core::PropertyDefinitionBuilder<>::createProperty("Port") + .withDescription("The port or service on the destination.") + .isRequired(true) + .supportsExpressionLanguage(true) + .build(); + EXTENSIONAPI static constexpr auto IdleConnectionExpiration = core::PropertyDefinitionBuilder<>::createProperty("Idle Connection Expiration") + .withDescription("The amount of time a connection should be held open without being used before closing the connection. A value of 0 seconds will disable this feature.") + .withPropertyType(core::StandardPropertyTypes::TIME_PERIOD_TYPE) + .withDefaultValue("15 seconds") + .isRequired(true) + .supportsExpressionLanguage(true) + .build(); + EXTENSIONAPI static constexpr auto Timeout = core::PropertyDefinitionBuilder<>::createProperty("Timeout") + .withDescription("The timeout for connecting to and communicating with the destination.") + .withPropertyType(core::StandardPropertyTypes::TIME_PERIOD_TYPE) + .withDefaultValue("15 seconds") + .isRequired(true) + .supportsExpressionLanguage(true) + .build(); + EXTENSIONAPI static constexpr auto ConnectionPerFlowFile = core::PropertyDefinitionBuilder<>::createProperty("Connection Per FlowFile") + .withDescription("Specifies whether to send each FlowFile's content on an individual connection.") + .withPropertyType(core::StandardPropertyTypes::BOOLEAN_TYPE) + .withDefaultValue("false") + .isRequired(true) + .supportsExpressionLanguage(false) + .build(); + EXTENSIONAPI static constexpr auto OutgoingMessageDelimiter = core::PropertyDefinitionBuilder<>::createProperty("Outgoing Message Delimiter") + .withDescription("Specifies the delimiter to use when sending messages out over the same TCP stream. " + "The delimiter is appended to each FlowFile message that is transmitted over the stream so that the receiver can determine when one message ends and the next message begins. " + "Users should ensure that the FlowFile content does not contain the delimiter character to avoid errors.") + .isRequired(false) + .supportsExpressionLanguage(true) + .build(); + EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: + createProperty("SSL Context Service") + .withDescription("The Controller Service to use in order to obtain an SSL Context. If this property is set, messages will be sent over a secure connection.") + .isRequired(false) + .build(); + EXTENSIONAPI static constexpr auto MaxSizeOfSocketSendBuffer = core::PropertyDefinitionBuilder<>::createProperty("Max Size of Socket Send Buffer") + .withDescription("The maximum size of the socket send buffer that should be used. This is a suggestion to the Operating System to indicate how big the socket buffer should be.") + .isRequired(false) + .withPropertyType(core::StandardPropertyTypes::DATA_SIZE_TYPE) + .build(); EXTENSIONAPI static constexpr auto Properties = std::array{ Hostname, Port, diff --git a/extensions/standard-processors/processors/TailFile.h b/extensions/standard-processors/processors/TailFile.h index 809d80fdc2..b1bc455646 100644 --- a/extensions/standard-processors/processors/TailFile.h +++ b/extensions/standard-processors/processors/TailFile.h @@ -179,9 +179,9 @@ class TailFile : public core::Processor { .withDefaultValue(magic_enum::enum_name(InitialStartPositions::BEGINNING_OF_FILE)) .withAllowedValues(magic_enum::enum_names()) .build(); - EXTENSIONAPI static constexpr auto AttributeProviderService = core::PropertyDefinitionBuilder<0, 1>::createProperty("Attribute Provider Service") + EXTENSIONAPI static constexpr auto AttributeProviderService = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: + createProperty("Attribute Provider Service") .withDescription("Provides a list of key-value pair records which can be used in the Base Directory property using Expression Language. Requires Multiple file mode.") - .withAllowedTypes({core::className()}) .build(); EXTENSIONAPI static constexpr auto BatchSize = core::PropertyDefinitionBuilder<>::createProperty("Batch Size") .withDescription("Maximum number of flowfiles emitted in a single trigger. If set to 0 all new content will be processed.") diff --git a/extensions/standard-processors/tests/unit/YamlConfigurationTests.cpp b/extensions/standard-processors/tests/unit/YamlConfigurationTests.cpp index be7a60c975..deac64ba4f 100644 --- a/extensions/standard-processors/tests/unit/YamlConfigurationTests.cpp +++ b/extensions/standard-processors/tests/unit/YamlConfigurationTests.cpp @@ -585,7 +585,7 @@ TEST_CASE("Test Dependent Property", "[YamlConfigurationDependentProperty]") { const auto component = std::make_shared(); component->setSupportedProperties(std::array{ core::PropertyDefinitionBuilder<>::createProperty("Prop A").withDescription("Prop A desc").withDefaultValue("val A").isRequired(true).build(), - core::PropertyDefinitionBuilder<0, 0, 1>::createProperty("Prop B").withDescription("Prop B desc").withDefaultValue("val B").isRequired(true).withDependentProperties({ "Prop A" }).build() + core::PropertyDefinitionBuilder<0, 1>::createProperty("Prop B").withDescription("Prop B desc").withDefaultValue("val B").isRequired(true).withDependentProperties({ "Prop A" }).build() }); yamlConfig.validateComponentProperties(*component, "component A", "section A"); REQUIRE(true); // Expected to get here w/o any exceptions @@ -598,7 +598,7 @@ TEST_CASE("Test Dependent Property 2", "[YamlConfigurationDependentProperty2]") const auto component = std::make_shared(); component->setSupportedProperties(std::array{ core::PropertyDefinitionBuilder<>::createProperty("Prop A").withDescription("Prop A desc").isRequired(false).build(), - core::PropertyDefinitionBuilder<0, 0, 1>::createProperty("Prop B").withDescription("Prop B desc").withDefaultValue("val B").isRequired(true).withDependentProperties({ "Prop A" }).build() + core::PropertyDefinitionBuilder<0, 1>::createProperty("Prop B").withDescription("Prop B desc").withDefaultValue("val B").isRequired(true).withDependentProperties({ "Prop A" }).build() }); bool config_failed = false; try { @@ -619,7 +619,7 @@ TEST_CASE("Test Exclusive Property", "[YamlConfigurationExclusiveOfProperty]") { const auto component = std::make_shared(); component->setSupportedProperties(std::array{ core::PropertyDefinitionBuilder<>::createProperty("Prop A").withDescription("Prop A desc").withDefaultValue("val A").isRequired(true).build(), - core::PropertyDefinitionBuilder<0, 0, 0, 1>::createProperty("Prop B").withDescription("Prop B desc").withDefaultValue("val B").isRequired(true) + core::PropertyDefinitionBuilder<0, 0, 1>::createProperty("Prop B").withDescription("Prop B desc").withDefaultValue("val B").isRequired(true) .withExclusiveOfProperties({{ { "Prop A", "^abcd.*$" } }}).build() }); yamlConfig.validateComponentProperties(*component, "component A", "section A"); @@ -633,7 +633,7 @@ TEST_CASE("Test Exclusive Property 2", "[YamlConfigurationExclusiveOfProperty2]" const auto component = std::make_shared(); component->setSupportedProperties(std::array{ core::PropertyDefinitionBuilder<>::createProperty("Prop A").withDescription("Prop A desc").withDefaultValue("val A").isRequired(true).build(), - core::PropertyDefinitionBuilder<0, 0, 0, 1>::createProperty("Prop B").withDescription("Prop B desc").withDefaultValue("val B").isRequired(true) + core::PropertyDefinitionBuilder<0, 0, 1>::createProperty("Prop B").withDescription("Prop B desc").withDefaultValue("val B").isRequired(true) .withExclusiveOfProperties({{ { "Prop A", "^val.*$" } }}).build() }); bool config_failed = false; diff --git a/libminifi/include/core/PropertyDefinition.h b/libminifi/include/core/PropertyDefinition.h index 99022855d1..f768c8f4f1 100644 --- a/libminifi/include/core/PropertyDefinition.h +++ b/libminifi/include/core/PropertyDefinition.h @@ -23,17 +23,17 @@ #include "core/PropertyType.h" #include "utils/gsl.h" +#include "utils/meta/type_list.h" namespace org::apache::nifi::minifi::core { -template +template> struct PropertyDefinition { std::string_view name; std::string_view display_name; std::string_view description; bool is_required = false; std::array allowed_values; - std::array allowed_types; std::array dependent_properties; std::array, NumExclusiveOfProperties> exclusive_of_properties; std::optional default_value; @@ -56,14 +56,14 @@ struct PropertyReference { constexpr PropertyReference() = default; - template - constexpr PropertyReference(const PropertyDefinition& property_definition) // NOLINT: non-explicit on purpose + template> + constexpr PropertyReference(const PropertyDefinition& property_definition) // NOLINT: non-explicit on purpose : name{property_definition.name}, display_name{property_definition.display_name}, description{property_definition.description}, is_required{property_definition.is_required}, allowed_values{property_definition.allowed_values}, - allowed_types{property_definition.allowed_types}, + allowed_types{AllowedTypes::AsStringViews}, dependent_properties{property_definition.dependent_properties}, exclusive_of_properties{property_definition.exclusive_of_properties}, default_value{property_definition.default_value}, diff --git a/libminifi/include/core/PropertyDefinitionBuilder.h b/libminifi/include/core/PropertyDefinitionBuilder.h index 801faf59e2..8c56e03d10 100644 --- a/libminifi/include/core/PropertyDefinitionBuilder.h +++ b/libminifi/include/core/PropertyDefinitionBuilder.h @@ -23,75 +23,69 @@ namespace org::apache::nifi::minifi::core { -template +template> struct PropertyDefinitionBuilder { - static constexpr PropertyDefinitionBuilder createProperty(std::string_view name) { - PropertyDefinitionBuilder builder; + static constexpr PropertyDefinitionBuilder createProperty(std::string_view name) { + PropertyDefinitionBuilder builder; builder.property.name = name; return builder; } - static constexpr PropertyDefinitionBuilder createProperty(std::string_view name, std::string_view display_name) { - PropertyDefinitionBuilder builder; + static constexpr PropertyDefinitionBuilder createProperty(std::string_view name, std::string_view display_name) { + PropertyDefinitionBuilder builder; builder.property.name = name; builder.property.display_name = display_name; return builder; } - constexpr PropertyDefinitionBuilder withDescription(std::string_view description) { + constexpr PropertyDefinitionBuilder withDescription(std::string_view description) { property.description = description; return *this; } - constexpr PropertyDefinitionBuilder isRequired(bool required) { + constexpr PropertyDefinitionBuilder isRequired(bool required) { property.is_required = required; return *this; } - constexpr PropertyDefinitionBuilder supportsExpressionLanguage(bool supports_expression_language) { + constexpr PropertyDefinitionBuilder supportsExpressionLanguage(bool supports_expression_language) { property.supports_expression_language = supports_expression_language; return *this; } - constexpr PropertyDefinitionBuilder withDefaultValue(std::string_view default_value) { + constexpr PropertyDefinitionBuilder withDefaultValue(std::string_view default_value) { property.default_value = std::optional{default_value}; // workaround for gcc 11.1; on gcc 11.3 and later, `property.default_value = default_value` works, too return *this; } - constexpr PropertyDefinitionBuilder withAllowedValues( + constexpr PropertyDefinitionBuilder withAllowedValues( std::array allowed_values) { property.allowed_values = allowed_values; return *this; } - constexpr PropertyDefinitionBuilder withAllowedTypes( - std::array types) { - property.allowed_types = types; - return *this; - } - - constexpr PropertyDefinitionBuilder withDependentProperties( + constexpr PropertyDefinitionBuilder withDependentProperties( std::array dependent_properties) { property.dependent_properties = dependent_properties; return *this; } - constexpr PropertyDefinitionBuilder withExclusiveOfProperties( + constexpr PropertyDefinitionBuilder withExclusiveOfProperties( std::array, NumExclusiveOfProperties> exclusive_of_properties) { property.exclusive_of_properties = exclusive_of_properties; return *this; } - constexpr PropertyDefinitionBuilder withPropertyType(const PropertyType& property_type) { + constexpr PropertyDefinitionBuilder withPropertyType(const PropertyType& property_type) { property.type = gsl::make_not_null(&property_type); return *this; } - constexpr PropertyDefinition build() { + constexpr PropertyDefinition build() { return property; } - PropertyDefinition property{}; + PropertyDefinition property{}; }; } // namespace org::apache::nifi::minifi::core diff --git a/libminifi/include/utils/meta/type_list.h b/libminifi/include/utils/meta/type_list.h index a94899abdd..da7691c107 100644 --- a/libminifi/include/utils/meta/type_list.h +++ b/libminifi/include/utils/meta/type_list.h @@ -15,14 +15,23 @@ * limitations under the License. */ #pragma once + +#include +#include #include +#include "core/Core.h" + namespace org::apache::nifi::minifi::utils::meta { + template struct type_list { template [[nodiscard]] constexpr static bool contains() noexcept { return (std::is_same_v || ...); } + + static constexpr auto AsStringViews = std::array{core::className()...}; }; + } // namespace org::apache::nifi::minifi::utils::meta diff --git a/libminifi/test/unit/ComponentManifestTests.cpp b/libminifi/test/unit/ComponentManifestTests.cpp index 4f5c247377..997d34df91 100644 --- a/libminifi/test/unit/ComponentManifestTests.cpp +++ b/libminifi/test/unit/ComponentManifestTests.cpp @@ -61,10 +61,9 @@ class ExampleProcessor : public core::Processor { using Processor::Processor; static constexpr const char* Description = "An example processor"; - static constexpr auto ExampleProperty = core::PropertyDefinitionBuilder<0, 1>::createProperty("Example Property") + static constexpr auto ExampleProperty = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>::createProperty("Example Property") .withDescription("An example property") .isRequired(false) - .withAllowedTypes({core::className()}) .build(); static constexpr auto Properties = std::array{ExampleProperty}; static constexpr auto Relationships = std::array{}; diff --git a/libminifi/test/unit/TypeListTests.cpp b/libminifi/test/unit/TypeListTests.cpp new file mode 100644 index 0000000000..7876045fbd --- /dev/null +++ b/libminifi/test/unit/TypeListTests.cpp @@ -0,0 +1,62 @@ +/** + * 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. + */ + +#include "../Catch.h" +#include "utils/meta/type_list.h" + +class A {}; + +namespace outer { +class B {}; +class C {}; + +namespace inner { +class D {}; +} +} + +template +using type_list = org::apache::nifi::minifi::utils::meta::type_list; + +TEST_CASE("an empty type_list doesn't contain anything") { + STATIC_CHECK_FALSE(type_list<>::contains()); + STATIC_CHECK_FALSE(type_list<>::contains()); + STATIC_CHECK_FALSE(type_list<>::contains()); + STATIC_CHECK_FALSE(type_list<>::contains()); +} + +TEST_CASE("a non-empty type_list contains what it should") { + STATIC_CHECK(type_list::contains()); + STATIC_CHECK(type_list::contains()); + STATIC_CHECK_FALSE(type_list::contains()); + STATIC_CHECK_FALSE(type_list::contains()); + + STATIC_CHECK(type_list::contains()); + STATIC_CHECK(type_list::contains()); + STATIC_CHECK(type_list::contains()); + STATIC_CHECK_FALSE(type_list::contains()); + STATIC_CHECK_FALSE(type_list::contains()); +} + +TEST_CASE("toStrings() on a type_list produces the correct list of types") { + STATIC_CHECK(type_list<>::AsStringViews.empty()); + STATIC_CHECK(type_list::AsStringViews == std::array{"A"}); + STATIC_CHECK(type_list::AsStringViews == std::array{"A", "outer::B"}); + STATIC_CHECK(type_list::AsStringViews == std::array{"A", "outer::C", "outer::inner::D"}); + STATIC_CHECK(type_list::AsStringViews == std::array{"outer::C", "A", "outer::inner::D", "outer::B"}); + STATIC_CHECK(type_list>::AsStringViews == std::array{"double", "A", "std::vector"}); +} From 2dda7e0b88869f7d2373e6134fe79993d89a892f Mon Sep 17 00:00:00 2001 From: Ferenc Gerlits Date: Thu, 10 Aug 2023 15:43:00 +0200 Subject: [PATCH 2/7] fix unit test failure on Windows --- libminifi/test/unit/TypeListTests.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libminifi/test/unit/TypeListTests.cpp b/libminifi/test/unit/TypeListTests.cpp index 7876045fbd..076be299a2 100644 --- a/libminifi/test/unit/TypeListTests.cpp +++ b/libminifi/test/unit/TypeListTests.cpp @@ -16,6 +16,7 @@ */ #include "../Catch.h" +#include "core/Core.h" #include "utils/meta/type_list.h" class A {}; @@ -58,5 +59,5 @@ TEST_CASE("toStrings() on a type_list produces the correct list of types") { STATIC_CHECK(type_list::AsStringViews == std::array{"A", "outer::B"}); STATIC_CHECK(type_list::AsStringViews == std::array{"A", "outer::C", "outer::inner::D"}); STATIC_CHECK(type_list::AsStringViews == std::array{"outer::C", "A", "outer::inner::D", "outer::B"}); - STATIC_CHECK(type_list>::AsStringViews == std::array{"double", "A", "std::vector"}); + STATIC_CHECK(type_list>::AsStringViews == std::array{"double", "A", org::apache::nifi::minifi::core::className>()}); } From 6fa5d9ae8cf3bac574f91c2dba5b69750c3a50de Mon Sep 17 00:00:00 2001 From: Ferenc Gerlits Date: Mon, 14 Aug 2023 12:07:31 +0200 Subject: [PATCH 3/7] remove AllowedTypes template parameter from PropertyDefinition[Builder] --- extensions/elasticsearch/PostElasticsearch.h | 8 ++--- extensions/gcp/processors/GCSProcessor.h | 4 +-- extensions/http-curl/processors/InvokeHTTP.h | 4 +-- extensions/librdkafka/KafkaProcessorBase.h | 4 +-- extensions/splunk/SplunkHECProcessor.h | 4 +-- .../standard-processors/processors/GetTCP.h | 4 +-- .../processors/ListenSyslog.h | 4 +-- .../processors/ListenTCP.h | 4 +-- .../standard-processors/processors/PutTCP.h | 4 +-- .../standard-processors/processors/TailFile.h | 4 +-- libminifi/include/core/PropertyDefinition.h | 16 ++++++--- .../include/core/PropertyDefinitionBuilder.h | 36 +++++++++++-------- libminifi/include/utils/meta/type_list.h | 9 ----- .../test/unit/ComponentManifestTests.cpp | 3 +- libminifi/test/unit/TypeListTests.cpp | 9 ----- 15 files changed, 56 insertions(+), 61 deletions(-) diff --git a/extensions/elasticsearch/PostElasticsearch.h b/extensions/elasticsearch/PostElasticsearch.h index 2accf8be2f..ec213b9825 100644 --- a/extensions/elasticsearch/PostElasticsearch.h +++ b/extensions/elasticsearch/PostElasticsearch.h @@ -53,16 +53,16 @@ class PostElasticsearch : public core::Processor { .withPropertyType(core::StandardPropertyTypes::UNSIGNED_LONG_TYPE) .withDefaultValue("100") .build(); - EXTENSIONAPI static constexpr auto ElasticCredentials = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: - createProperty("Elasticsearch Credentials Provider Service") + EXTENSIONAPI static constexpr auto ElasticCredentials = core::PropertyDefinitionBuilder<>::createProperty("Elasticsearch Credentials Provider Service") .withDescription("The Controller Service used to obtain Elasticsearch credentials.") .isRequired(true) + .withAllowedTypes() .build(); - EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: - createProperty("SSL Context Service") + EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<>::createProperty("SSL Context Service") .withDescription("The SSL Context Service used to provide client certificate " "information for TLS/SSL (https) connections.") .isRequired(false) + .withAllowedTypes() .build(); EXTENSIONAPI static constexpr auto Hosts = core::PropertyDefinitionBuilder<>::createProperty("Hosts") .withDescription("A comma-separated list of HTTP hosts that host Elasticsearch query nodes. Currently only supports a single host.") diff --git a/extensions/gcp/processors/GCSProcessor.h b/extensions/gcp/processors/GCSProcessor.h index 3bec6405c3..8cfbe9c1d8 100644 --- a/extensions/gcp/processors/GCSProcessor.h +++ b/extensions/gcp/processors/GCSProcessor.h @@ -39,10 +39,10 @@ class GCSProcessor : public core::Processor { logger_(std::move(logger)) { } - EXTENSIONAPI static constexpr auto GCPCredentials = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: - createProperty("GCP Credentials Provider Service") + EXTENSIONAPI static constexpr auto GCPCredentials = core::PropertyDefinitionBuilder<>::createProperty("GCP Credentials Provider Service") .withDescription("The Controller Service used to obtain Google Cloud Platform credentials. Should be the name of a GCPCredentialsControllerService.") .isRequired(true) + .withAllowedTypes() .build(); EXTENSIONAPI static constexpr auto NumberOfRetries = core::PropertyDefinitionBuilder<>::createProperty("Number of retries") .withDescription("How many retry attempts should be made before routing to the failure relationship.") diff --git a/extensions/http-curl/processors/InvokeHTTP.h b/extensions/http-curl/processors/InvokeHTTP.h index f73f716449..99a6a89687 100644 --- a/extensions/http-curl/processors/InvokeHTTP.h +++ b/extensions/http-curl/processors/InvokeHTTP.h @@ -103,10 +103,10 @@ class InvokeHTTP : public core::Processor { EXTENSIONAPI static constexpr auto AttributesToSend = core::PropertyDefinitionBuilder<>::createProperty("Attributes to Send") .withDescription("Regular expression that defines which attributes to send as HTTP headers in the request. If not defined, no attributes are sent as headers.") .build(); - EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0, 0, 1, utils::meta::type_list>:: - createProperty("SSL Context Service") + EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0, 0, 1>::createProperty("SSL Context Service") .withDescription("The SSL Context Service used to provide client certificate information for TLS/SSL (https) connections.") .isRequired(false) + .withAllowedTypes() .withExclusiveOfProperties({{{"Remote URL", "^http:.*$"}}}) .build(); EXTENSIONAPI static constexpr auto ProxyHost = core::PropertyDefinitionBuilder<>::createProperty("Proxy Host") diff --git a/extensions/librdkafka/KafkaProcessorBase.h b/extensions/librdkafka/KafkaProcessorBase.h index 352d653cea..5bc44eb500 100644 --- a/extensions/librdkafka/KafkaProcessorBase.h +++ b/extensions/librdkafka/KafkaProcessorBase.h @@ -47,9 +47,9 @@ enum class SASLMechanismOption { class KafkaProcessorBase : public core::Processor { public: - EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: - createProperty("SSL Context Service") + EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<>::createProperty("SSL Context Service") .withDescription("SSL Context Service Name") + .withAllowedTypes() .build(); EXTENSIONAPI static constexpr auto SecurityProtocol = core::PropertyDefinitionBuilder()>::createProperty("Security Protocol") .withDescription("Protocol used to communicate with brokers. Corresponds to Kafka's 'security.protocol' property.") diff --git a/extensions/splunk/SplunkHECProcessor.h b/extensions/splunk/SplunkHECProcessor.h index 6256571ccb..bc885ac136 100644 --- a/extensions/splunk/SplunkHECProcessor.h +++ b/extensions/splunk/SplunkHECProcessor.h @@ -53,11 +53,11 @@ class SplunkHECProcessor : public core::Processor { .withDescription("Identifier of the used request channel.") .isRequired(true) .build(); - EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0, 0, 1, utils::meta::type_list>:: - createProperty("SSL Context Service") + EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0, 0, 1>::createProperty("SSL Context Service") .withDescription("The SSL Context Service used to provide client certificate information for TLS/SSL (https) connections.") .isRequired(false) .withExclusiveOfProperties({{{"Hostname", "^http:.*$"}}}) + .withAllowedTypes() .build(); EXTENSIONAPI static constexpr auto Properties = std::array{ Hostname, diff --git a/extensions/standard-processors/processors/GetTCP.h b/extensions/standard-processors/processors/GetTCP.h index a7496df3e9..184da62dfc 100644 --- a/extensions/standard-processors/processors/GetTCP.h +++ b/extensions/standard-processors/processors/GetTCP.h @@ -69,9 +69,9 @@ class GetTCP : public core::Processor { .withDescription("A comma delimited list of the endpoints to connect to. The format should be :.") .isRequired(true) .build(); - EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: - createProperty("SSL Context Service") + EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<>::createProperty("SSL Context Service") .withDescription("SSL Context Service Name") + .withAllowedTypes() .build(); EXTENSIONAPI static constexpr auto MessageDelimiter = core::PropertyDefinitionBuilder<>::createProperty("Message Delimiter") .withDescription("Character that denotes the end of the message.") diff --git a/extensions/standard-processors/processors/ListenSyslog.h b/extensions/standard-processors/processors/ListenSyslog.h index 0fee2eb5fc..0f172e35ea 100644 --- a/extensions/standard-processors/processors/ListenSyslog.h +++ b/extensions/standard-processors/processors/ListenSyslog.h @@ -75,10 +75,10 @@ class ListenSyslog : public NetworkListenerProcessor { .withPropertyType(core::StandardPropertyTypes::UNSIGNED_LONG_TYPE) .withDefaultValue("10000") .build(); - EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: - createProperty("SSL Context Service") + EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<>::createProperty("SSL Context Service") .withDescription("The Controller Service to use in order to obtain an SSL Context. If this property is set, messages will be received over a secure connection. " "This Property is only considered if the Property has a value of \"TCP\".") + .withAllowedTypes() .build(); EXTENSIONAPI static constexpr auto ClientAuth = core::PropertyDefinitionBuilder()>::createProperty("Client Auth") .withDescription("The client authentication policy to use for the SSL Context. Only used if an SSL Context Service is provided.") diff --git a/extensions/standard-processors/processors/ListenTCP.h b/extensions/standard-processors/processors/ListenTCP.h index 6fcf68576a..79d13fa1ba 100644 --- a/extensions/standard-processors/processors/ListenTCP.h +++ b/extensions/standard-processors/processors/ListenTCP.h @@ -60,9 +60,9 @@ class ListenTCP : public NetworkListenerProcessor { .withDefaultValue("10000") .isRequired(true) .build(); - EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: - createProperty("SSL Context Service") + EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<>::createProperty("SSL Context Service") .withDescription("The Controller Service to use in order to obtain an SSL Context. If this property is set, messages will be received over a secure connection.") + .withAllowedTypes() .build(); EXTENSIONAPI static constexpr auto ClientAuth = core::PropertyDefinitionBuilder()>::createProperty("Client Auth") .withDescription("The client authentication policy to use for the SSL Context. Only used if an SSL Context Service is provided.") diff --git a/extensions/standard-processors/processors/PutTCP.h b/extensions/standard-processors/processors/PutTCP.h index 86439ac485..5063bae679 100644 --- a/extensions/standard-processors/processors/PutTCP.h +++ b/extensions/standard-processors/processors/PutTCP.h @@ -102,10 +102,10 @@ class PutTCP final : public core::Processor { .isRequired(false) .supportsExpressionLanguage(true) .build(); - EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: - createProperty("SSL Context Service") + EXTENSIONAPI static constexpr auto SSLContextService = core::PropertyDefinitionBuilder<>::createProperty("SSL Context Service") .withDescription("The Controller Service to use in order to obtain an SSL Context. If this property is set, messages will be sent over a secure connection.") .isRequired(false) + .withAllowedTypes() .build(); EXTENSIONAPI static constexpr auto MaxSizeOfSocketSendBuffer = core::PropertyDefinitionBuilder<>::createProperty("Max Size of Socket Send Buffer") .withDescription("The maximum size of the socket send buffer that should be used. This is a suggestion to the Operating System to indicate how big the socket buffer should be.") diff --git a/extensions/standard-processors/processors/TailFile.h b/extensions/standard-processors/processors/TailFile.h index b1bc455646..015eab7d99 100644 --- a/extensions/standard-processors/processors/TailFile.h +++ b/extensions/standard-processors/processors/TailFile.h @@ -179,9 +179,9 @@ class TailFile : public core::Processor { .withDefaultValue(magic_enum::enum_name(InitialStartPositions::BEGINNING_OF_FILE)) .withAllowedValues(magic_enum::enum_names()) .build(); - EXTENSIONAPI static constexpr auto AttributeProviderService = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>:: - createProperty("Attribute Provider Service") + EXTENSIONAPI static constexpr auto AttributeProviderService = core::PropertyDefinitionBuilder<>::createProperty("Attribute Provider Service") .withDescription("Provides a list of key-value pair records which can be used in the Base Directory property using Expression Language. Requires Multiple file mode.") + .withAllowedTypes() .build(); EXTENSIONAPI static constexpr auto BatchSize = core::PropertyDefinitionBuilder<>::createProperty("Batch Size") .withDescription("Maximum number of flowfiles emitted in a single trigger. If set to 0 all new content will be processed.") diff --git a/libminifi/include/core/PropertyDefinition.h b/libminifi/include/core/PropertyDefinition.h index f768c8f4f1..878459aaf0 100644 --- a/libminifi/include/core/PropertyDefinition.h +++ b/libminifi/include/core/PropertyDefinition.h @@ -21,19 +21,25 @@ #include #include +#include "core/Core.h" #include "core/PropertyType.h" #include "utils/gsl.h" -#include "utils/meta/type_list.h" namespace org::apache::nifi::minifi::core { -template> +namespace detail { +template +inline constexpr auto TypeNames = std::array{core::className()...}; +} + +template struct PropertyDefinition { std::string_view name; std::string_view display_name; std::string_view description; bool is_required = false; std::array allowed_values; + gsl::span allowed_types; std::array dependent_properties; std::array, NumExclusiveOfProperties> exclusive_of_properties; std::optional default_value; @@ -56,14 +62,14 @@ struct PropertyReference { constexpr PropertyReference() = default; - template> - constexpr PropertyReference(const PropertyDefinition& property_definition) // NOLINT: non-explicit on purpose + template + constexpr PropertyReference(const PropertyDefinition& property_definition) // NOLINT: non-explicit on purpose : name{property_definition.name}, display_name{property_definition.display_name}, description{property_definition.description}, is_required{property_definition.is_required}, allowed_values{property_definition.allowed_values}, - allowed_types{AllowedTypes::AsStringViews}, + allowed_types{property_definition.allowed_types}, dependent_properties{property_definition.dependent_properties}, exclusive_of_properties{property_definition.exclusive_of_properties}, default_value{property_definition.default_value}, diff --git a/libminifi/include/core/PropertyDefinitionBuilder.h b/libminifi/include/core/PropertyDefinitionBuilder.h index 8c56e03d10..b241d5c410 100644 --- a/libminifi/include/core/PropertyDefinitionBuilder.h +++ b/libminifi/include/core/PropertyDefinitionBuilder.h @@ -23,69 +23,75 @@ namespace org::apache::nifi::minifi::core { -template> +template struct PropertyDefinitionBuilder { - static constexpr PropertyDefinitionBuilder createProperty(std::string_view name) { - PropertyDefinitionBuilder builder; + static constexpr PropertyDefinitionBuilder createProperty(std::string_view name) { + PropertyDefinitionBuilder builder; builder.property.name = name; return builder; } - static constexpr PropertyDefinitionBuilder createProperty(std::string_view name, std::string_view display_name) { - PropertyDefinitionBuilder builder; + static constexpr PropertyDefinitionBuilder createProperty(std::string_view name, std::string_view display_name) { + PropertyDefinitionBuilder builder; builder.property.name = name; builder.property.display_name = display_name; return builder; } - constexpr PropertyDefinitionBuilder withDescription(std::string_view description) { + constexpr PropertyDefinitionBuilder withDescription(std::string_view description) { property.description = description; return *this; } - constexpr PropertyDefinitionBuilder isRequired(bool required) { + constexpr PropertyDefinitionBuilder isRequired(bool required) { property.is_required = required; return *this; } - constexpr PropertyDefinitionBuilder supportsExpressionLanguage(bool supports_expression_language) { + constexpr PropertyDefinitionBuilder supportsExpressionLanguage(bool supports_expression_language) { property.supports_expression_language = supports_expression_language; return *this; } - constexpr PropertyDefinitionBuilder withDefaultValue(std::string_view default_value) { + constexpr PropertyDefinitionBuilder withDefaultValue(std::string_view default_value) { property.default_value = std::optional{default_value}; // workaround for gcc 11.1; on gcc 11.3 and later, `property.default_value = default_value` works, too return *this; } - constexpr PropertyDefinitionBuilder withAllowedValues( + constexpr PropertyDefinitionBuilder withAllowedValues( std::array allowed_values) { property.allowed_values = allowed_values; return *this; } - constexpr PropertyDefinitionBuilder withDependentProperties( + template + constexpr PropertyDefinitionBuilder withAllowedTypes() { + property.allowed_types = {detail::TypeNames}; + return *this; + } + + constexpr PropertyDefinitionBuilder withDependentProperties( std::array dependent_properties) { property.dependent_properties = dependent_properties; return *this; } - constexpr PropertyDefinitionBuilder withExclusiveOfProperties( + constexpr PropertyDefinitionBuilder withExclusiveOfProperties( std::array, NumExclusiveOfProperties> exclusive_of_properties) { property.exclusive_of_properties = exclusive_of_properties; return *this; } - constexpr PropertyDefinitionBuilder withPropertyType(const PropertyType& property_type) { + constexpr PropertyDefinitionBuilder withPropertyType(const PropertyType& property_type) { property.type = gsl::make_not_null(&property_type); return *this; } - constexpr PropertyDefinition build() { + constexpr PropertyDefinition build() { return property; } - PropertyDefinition property{}; + PropertyDefinition property{}; }; } // namespace org::apache::nifi::minifi::core diff --git a/libminifi/include/utils/meta/type_list.h b/libminifi/include/utils/meta/type_list.h index da7691c107..a94899abdd 100644 --- a/libminifi/include/utils/meta/type_list.h +++ b/libminifi/include/utils/meta/type_list.h @@ -15,23 +15,14 @@ * limitations under the License. */ #pragma once - -#include -#include #include -#include "core/Core.h" - namespace org::apache::nifi::minifi::utils::meta { - template struct type_list { template [[nodiscard]] constexpr static bool contains() noexcept { return (std::is_same_v || ...); } - - static constexpr auto AsStringViews = std::array{core::className()...}; }; - } // namespace org::apache::nifi::minifi::utils::meta diff --git a/libminifi/test/unit/ComponentManifestTests.cpp b/libminifi/test/unit/ComponentManifestTests.cpp index 997d34df91..907300750e 100644 --- a/libminifi/test/unit/ComponentManifestTests.cpp +++ b/libminifi/test/unit/ComponentManifestTests.cpp @@ -61,9 +61,10 @@ class ExampleProcessor : public core::Processor { using Processor::Processor; static constexpr const char* Description = "An example processor"; - static constexpr auto ExampleProperty = core::PropertyDefinitionBuilder<0, 0, 0, utils::meta::type_list>::createProperty("Example Property") + static constexpr auto ExampleProperty = core::PropertyDefinitionBuilder<>::createProperty("Example Property") .withDescription("An example property") .isRequired(false) + .withAllowedTypes() .build(); static constexpr auto Properties = std::array{ExampleProperty}; static constexpr auto Relationships = std::array{}; diff --git a/libminifi/test/unit/TypeListTests.cpp b/libminifi/test/unit/TypeListTests.cpp index 076be299a2..4925addadd 100644 --- a/libminifi/test/unit/TypeListTests.cpp +++ b/libminifi/test/unit/TypeListTests.cpp @@ -52,12 +52,3 @@ TEST_CASE("a non-empty type_list contains what it should") { STATIC_CHECK_FALSE(type_list::contains()); STATIC_CHECK_FALSE(type_list::contains()); } - -TEST_CASE("toStrings() on a type_list produces the correct list of types") { - STATIC_CHECK(type_list<>::AsStringViews.empty()); - STATIC_CHECK(type_list::AsStringViews == std::array{"A"}); - STATIC_CHECK(type_list::AsStringViews == std::array{"A", "outer::B"}); - STATIC_CHECK(type_list::AsStringViews == std::array{"A", "outer::C", "outer::inner::D"}); - STATIC_CHECK(type_list::AsStringViews == std::array{"outer::C", "A", "outer::inner::D", "outer::B"}); - STATIC_CHECK(type_list>::AsStringViews == std::array{"double", "A", org::apache::nifi::minifi::core::className>()}); -} From c206ff957f99c96c197235ca36ef0caec7937add Mon Sep 17 00:00:00 2001 From: Ferenc Gerlits Date: Mon, 14 Aug 2023 12:24:17 +0200 Subject: [PATCH 4/7] use std::span instead of gsl::span --- libminifi/include/core/OutputAttributeDefinition.h | 4 ++-- libminifi/include/core/PropertyDefinition.h | 11 ++++++----- libminifi/src/core/Property.cpp | 6 +++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/libminifi/include/core/OutputAttributeDefinition.h b/libminifi/include/core/OutputAttributeDefinition.h index 1057c72dbc..9e4ea9c671 100644 --- a/libminifi/include/core/OutputAttributeDefinition.h +++ b/libminifi/include/core/OutputAttributeDefinition.h @@ -17,9 +17,9 @@ #pragma once #include +#include #include -#include "utils/gsl.h" #include "RelationshipDefinition.h" namespace org::apache::nifi::minifi::core { @@ -48,7 +48,7 @@ struct OutputAttributeReference { } std::string_view name; - gsl::span relationships; + std::span relationships; std::string_view description; }; diff --git a/libminifi/include/core/PropertyDefinition.h b/libminifi/include/core/PropertyDefinition.h index 878459aaf0..ffd3666b07 100644 --- a/libminifi/include/core/PropertyDefinition.h +++ b/libminifi/include/core/PropertyDefinition.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -39,7 +40,7 @@ struct PropertyDefinition { std::string_view description; bool is_required = false; std::array allowed_values; - gsl::span allowed_types; + std::span allowed_types; std::array dependent_properties; std::array, NumExclusiveOfProperties> exclusive_of_properties; std::optional default_value; @@ -52,10 +53,10 @@ struct PropertyReference { std::string_view display_name; std::string_view description; bool is_required = false; - gsl::span allowed_values; - gsl::span allowed_types; - gsl::span dependent_properties; - gsl::span> exclusive_of_properties; + std::span allowed_values; + std::span allowed_types; + std::span dependent_properties; + std::span> exclusive_of_properties; std::optional default_value; gsl::not_null type = gsl::make_not_null(&StandardPropertyTypes::VALID_TYPE); bool supports_expression_language = false; diff --git a/libminifi/src/core/Property.cpp b/libminifi/src/core/Property.cpp index 017deaffbf..79f5fc4883 100644 --- a/libminifi/src/core/Property.cpp +++ b/libminifi/src/core/Property.cpp @@ -91,18 +91,18 @@ std::vector> Property::getExclusiveOfPropert } namespace { -std::vector createPropertyValues(gsl::span values, const core::PropertyParser& property_parser) { +std::vector createPropertyValues(std::span values, const core::PropertyParser& property_parser) { return ranges::views::transform(values, [&property_parser](const auto& value) { return property_parser.parse(value); }) | ranges::to; } -inline std::vector createStrings(gsl::span string_views) { +inline std::vector createStrings(std::span string_views) { return ranges::views::transform(string_views, [](const auto& string_view) { return std::string{string_view}; }) | ranges::to; } -inline std::vector> createStrings(gsl::span> pairs_of_string_views) { +inline std::vector> createStrings(std::span> pairs_of_string_views) { return ranges::views::transform(pairs_of_string_views, [](const auto& pair_of_string_views) { return std::pair(pair_of_string_views); }) | ranges::to; } From 8a0ada2d031751b3973276ac135baf086558ef75 Mon Sep 17 00:00:00 2001 From: Ferenc Gerlits Date: Mon, 14 Aug 2023 18:04:07 +0200 Subject: [PATCH 5/7] add some more test cases in TypeListTests --- libminifi/test/unit/TypeListTests.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libminifi/test/unit/TypeListTests.cpp b/libminifi/test/unit/TypeListTests.cpp index 4925addadd..463a7a26cf 100644 --- a/libminifi/test/unit/TypeListTests.cpp +++ b/libminifi/test/unit/TypeListTests.cpp @@ -26,6 +26,7 @@ class B {}; class C {}; namespace inner { +class C {}; class D {}; } } @@ -51,4 +52,10 @@ TEST_CASE("a non-empty type_list contains what it should") { STATIC_CHECK(type_list::contains()); STATIC_CHECK_FALSE(type_list::contains()); STATIC_CHECK_FALSE(type_list::contains()); + + namespace inner = outer::inner; + STATIC_CHECK(type_list::contains()); + STATIC_CHECK(type_list::contains()); + STATIC_CHECK_FALSE(type_list::contains()); + STATIC_CHECK_FALSE(type_list::contains()); } From b7742b5c8165fe33a11f02e35a7e3d880c673af9 Mon Sep 17 00:00:00 2001 From: Ferenc Gerlits Date: Tue, 15 Aug 2023 09:48:58 +0200 Subject: [PATCH 6/7] move TypeNames from PropertyDefinition to PropertyDefinitionBuilder --- libminifi/include/core/PropertyDefinition.h | 5 ----- libminifi/include/core/PropertyDefinitionBuilder.h | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libminifi/include/core/PropertyDefinition.h b/libminifi/include/core/PropertyDefinition.h index ffd3666b07..1af98de75d 100644 --- a/libminifi/include/core/PropertyDefinition.h +++ b/libminifi/include/core/PropertyDefinition.h @@ -28,11 +28,6 @@ namespace org::apache::nifi::minifi::core { -namespace detail { -template -inline constexpr auto TypeNames = std::array{core::className()...}; -} - template struct PropertyDefinition { std::string_view name; diff --git a/libminifi/include/core/PropertyDefinitionBuilder.h b/libminifi/include/core/PropertyDefinitionBuilder.h index b241d5c410..4ec16838a0 100644 --- a/libminifi/include/core/PropertyDefinitionBuilder.h +++ b/libminifi/include/core/PropertyDefinitionBuilder.h @@ -23,6 +23,11 @@ namespace org::apache::nifi::minifi::core { +namespace detail { +template +inline constexpr auto TypeNames = std::array{core::className()...}; +} + template struct PropertyDefinitionBuilder { static constexpr PropertyDefinitionBuilder createProperty(std::string_view name) { From be77e190e33ccf7866c0b54eadeb429da62086c5 Mon Sep 17 00:00:00 2001 From: Ferenc Gerlits Date: Tue, 15 Aug 2023 10:00:56 +0200 Subject: [PATCH 7/7] clang-tidy fixes --- extensions/librdkafka/KafkaProcessorBase.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/librdkafka/KafkaProcessorBase.h b/extensions/librdkafka/KafkaProcessorBase.h index 5bc44eb500..6e88c66893 100644 --- a/extensions/librdkafka/KafkaProcessorBase.h +++ b/extensions/librdkafka/KafkaProcessorBase.h @@ -92,14 +92,14 @@ class KafkaProcessorBase : public core::Processor { KafkaProcessorBase(std::string name, const utils::Identifier& uuid, std::shared_ptr logger) : core::Processor(std::move(name), uuid), - logger_(logger) { + logger_(std::move(logger)) { } protected: virtual std::optional getSslData(core::ProcessContext& context) const; void setKafkaAuthenticationParameters(core::ProcessContext& context, gsl::not_null config); - kafka::SecurityProtocolOption security_protocol_; + kafka::SecurityProtocolOption security_protocol_{}; std::shared_ptr logger_; };