From 7388a1ae99ab3cfece7ecff091e9dea579a2f58e Mon Sep 17 00:00:00 2001 From: Gwenneg Lepage Date: Wed, 15 Nov 2023 18:33:55 +0100 Subject: [PATCH] Introduce notifications-connector-common-http (#2335) Co-authored-by: Mikel Alejo --- .rhcicd/clowdapp-connector-drawer.yaml | 10 ++ .rhcicd/clowdapp-connector-email.yaml | 18 ++-- .rhcicd/clowdapp-connector-google-chat.yaml | 10 ++ .../clowdapp-connector-microsoft-teams.yaml | 10 ++ .rhcicd/clowdapp-connector-servicenow.yaml | 16 +-- .rhcicd/clowdapp-connector-splunk.yaml | 16 +-- .rhcicd/clowdapp-connector-webhook.yaml | 4 +- connector-common-http/pom.xml | 94 ++++++++++++++++ .../connector/http/ExchangeProperty.java | 8 ++ .../http/HttpComponentConfigurator.java | 29 +++++ .../connector/http/HttpConnectorConfig.java | 102 ++++++++++++++++++ .../http/HttpExceptionProcessor.java | 66 ++++++++++++ .../connector/http}/SslTrustAllManager.java | 2 +- .../connector/CamelComponentConfigurator.java | 13 +++ .../connector/ConnectorConfig.java | 26 +++-- .../EngineToConnectorRouteBuilder.java | 34 +++--- .../connector/ExceptionProcessor.java | 3 - .../connector/IncomingCloudEventFilter.java | 4 +- .../connector/SedaComponentConfigurator.java | 26 +++++ .../IncomingCloudEventFilterTest.java | 23 +++- .../src/test/resources/application.properties | 1 + connector-drawer/pom.xml | 8 +- .../connector/drawer/DrawerRouteBuilder.java | 2 +- .../drawer/config/DrawerConnectorConfig.java | 23 ++-- .../src/main/resources/application.properties | 5 + connector-email/pom.xml | 6 +- .../email/EmailExceptionProcessor.java | 30 ------ .../connector/email/EmailRouteBuilder.java | 13 +-- .../email/config/EmailConnectorConfig.java | 43 ++++---- .../processors/bop/ssl/BOPTrustManager.java | 23 ---- .../src/main/resources/application.properties | 4 + .../email/EmailRouteBuilderTest.java | 6 +- connector-google-chat/pom.xml | 8 +- .../chat/GoogleChatExceptionProcessor.java | 45 -------- .../google/chat/GoogleChatRouteBuilder.java | 6 +- .../src/main/resources/application.properties | 1 + connector-microsoft-teams/pom.xml | 8 +- .../teams/TeamsExceptionProcessor.java | 31 ------ .../microsoft/teams/TeamsRouteBuilder.java | 6 +- .../src/main/resources/application.properties | 1 + connector-servicenow/pom.xml | 8 +- .../servicenow/ServiceNowConnectorConfig.java | 37 ------- .../ServiceNowExceptionProcessor.java | 43 -------- .../servicenow/ServiceNowRouteBuilder.java | 17 +-- .../servicenow/ServiceNowTrustAllManager.java | 26 ----- .../src/main/resources/application.properties | 2 + .../connector/slack/SlackRouteBuilder.java | 2 +- .../src/main/resources/application.properties | 1 + connector-splunk/pom.xml | 8 +- .../splunk/SplunkConnectorConfig.java | 37 ------- .../splunk/SplunkExceptionProcessor.java | 43 -------- .../connector/splunk/SplunkRouteBuilder.java | 17 +-- .../splunk/SplunkTrustAllManager.java | 26 ----- .../src/main/resources/application.properties | 2 + connector-webhook/pom.xml | 6 +- .../webhook/CloudEventHistoryBuilder.java | 20 ++-- .../connector/webhook/ExchangeProperty.java | 4 - .../webhook/WebhookConnectorConfig.java | 65 ----------- .../webhook/WebhookExceptionProcessor.java | 55 ---------- .../WebhookIncomingCloudEventFilter.java | 18 ---- .../webhook/WebhookRouteBuilder.java | 27 ++--- .../src/main/resources/application.properties | 3 +- .../webhook/WebhookConnectorRoutesTest.java | 8 +- pom.xml | 1 + 64 files changed, 562 insertions(+), 698 deletions(-) create mode 100644 connector-common-http/pom.xml create mode 100644 connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/ExchangeProperty.java create mode 100644 connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/HttpComponentConfigurator.java create mode 100644 connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/HttpConnectorConfig.java create mode 100644 connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/HttpExceptionProcessor.java rename {connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook => connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http}/SslTrustAllManager.java (94%) create mode 100644 connector-common/src/main/java/com/redhat/cloud/notifications/connector/CamelComponentConfigurator.java create mode 100644 connector-common/src/main/java/com/redhat/cloud/notifications/connector/SedaComponentConfigurator.java delete mode 100644 connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/EmailExceptionProcessor.java delete mode 100644 connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/processors/bop/ssl/BOPTrustManager.java delete mode 100644 connector-google-chat/src/main/java/com/redhat/cloud/notifications/connector/google/chat/GoogleChatExceptionProcessor.java delete mode 100644 connector-microsoft-teams/src/main/java/com/redhat/cloud/notifications/connector/microsoft/teams/TeamsExceptionProcessor.java delete mode 100644 connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowConnectorConfig.java delete mode 100644 connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowExceptionProcessor.java delete mode 100644 connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowTrustAllManager.java delete mode 100644 connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkConnectorConfig.java delete mode 100644 connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkExceptionProcessor.java delete mode 100644 connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkTrustAllManager.java delete mode 100644 connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookConnectorConfig.java delete mode 100644 connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookExceptionProcessor.java delete mode 100644 connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookIncomingCloudEventFilter.java diff --git a/.rhcicd/clowdapp-connector-drawer.yaml b/.rhcicd/clowdapp-connector-drawer.yaml index 1b286b9ea7..2a31e3074b 100644 --- a/.rhcicd/clowdapp-connector-drawer.yaml +++ b/.rhcicd/clowdapp-connector-drawer.yaml @@ -57,6 +57,10 @@ objects: env: - name: ENV_NAME value: ${ENV_NAME} + - name: NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS + value: ${NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS} + - name: NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS + value: ${NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS} - name: NOTIFICATIONS_CONNECTOR_KAFKA_INCOMING_MAX_POLL_INTERVAL_MS value: ${KAFKA_MAX_POLL_INTERVAL_MS} - name: NOTIFICATIONS_CONNECTOR_KAFKA_INCOMING_MAX_POLL_RECORDS @@ -128,6 +132,12 @@ parameters: value: 250Mi - name: MIN_REPLICAS value: "3" +- name: NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS + description: Maximum time in milliseconds allowed to establish an HTTP connection + value: "2500" +- name: NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS + description: Maximum time in milliseconds allowed to wait for HTTP data + value: "180000" - name: NOTIFICATIONS_CONNECTOR_SEDA_CONCURRENT_CONSUMERS description: Number of concurrent threads processing exchanges with SEDA value: "20" diff --git a/.rhcicd/clowdapp-connector-email.yaml b/.rhcicd/clowdapp-connector-email.yaml index d01f3169ed..52c5653f44 100644 --- a/.rhcicd/clowdapp-connector-email.yaml +++ b/.rhcicd/clowdapp-connector-email.yaml @@ -77,10 +77,10 @@ objects: value: ${NOTIFICATIONS_CONNECTOR_ENDPOINT_CACHE_MAX_SIZE} - name: NOTIFICATIONS_CONNECTOR_FETCH_USERS_RBAC_ENABLED value: ${NOTIFICATIONS_CONNECTOR_FETCH_USERS_RBAC_ENABLED} - - name: NOTIFICATIONS_CONNECTOR_HTTPS_CONNECT_TIMEOUT_MS - value: ${NOTIFICATIONS_CONNECTOR_HTTPS_CONNECT_TIMEOUT_MS} - - name: NOTIFICATIONS_CONNECTOR_HTTPS_SOCKET_TIMEOUT_MS - value: ${NOTIFICATIONS_CONNECTOR_HTTPS_SOCKET_TIMEOUT_MS} + - name: NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS + value: ${NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS} + - name: NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS + value: ${NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS} - name: NOTIFICATIONS_CONNECTOR_KAFKA_INCOMING_MAX_POLL_INTERVAL_MS value: ${KAFKA_MAX_POLL_INTERVAL_MS} - name: NOTIFICATIONS_CONNECTOR_KAFKA_INCOMING_MAX_POLL_RECORDS @@ -217,12 +217,12 @@ parameters: - name: NOTIFICATIONS_CONNECTOR_FETCH_USERS_RBAC_ENABLED description: Is RBAC used to fetch the users? value: "true" -- name: NOTIFICATIONS_CONNECTOR_HTTPS_CONNECT_TIMEOUT_MS - description: Maximum time in milliseconds allowed to establish an HTTPS connection - value: "2500" -- name: NOTIFICATIONS_CONNECTOR_HTTPS_SOCKET_TIMEOUT_MS - description: Maximum time in milliseconds allowed to wait for HTTPS data +- name: NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS + description: Maximum time in milliseconds allowed to establish an HTTP connection value: "2500" +- name: NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS + description: Maximum time in milliseconds allowed to wait for HTTP data + value: "180000" - name: NOTIFICATIONS_CONNECTOR_REDELIVERY_DELAY description: Delay in milliseconds between two redelivery attempts value: "1000" diff --git a/.rhcicd/clowdapp-connector-google-chat.yaml b/.rhcicd/clowdapp-connector-google-chat.yaml index 58c878d1e0..8b95ff761a 100644 --- a/.rhcicd/clowdapp-connector-google-chat.yaml +++ b/.rhcicd/clowdapp-connector-google-chat.yaml @@ -57,6 +57,10 @@ objects: value: ${ENV_NAME} - name: NOTIFICATIONS_CONNECTOR_ENDPOINT_CACHE_MAX_SIZE value: ${NOTIFICATIONS_CONNECTOR_ENDPOINT_CACHE_MAX_SIZE} + - name: NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS + value: ${NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS} + - name: NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS + value: ${NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS} - name: NOTIFICATIONS_CONNECTOR_KAFKA_INCOMING_MAX_POLL_INTERVAL_MS value: ${KAFKA_MAX_POLL_INTERVAL_MS} - name: NOTIFICATIONS_CONNECTOR_KAFKA_INCOMING_MAX_POLL_RECORDS @@ -135,6 +139,12 @@ parameters: - name: NOTIFICATIONS_CONNECTOR_ENDPOINT_CACHE_MAX_SIZE description: Maximum size of the Camel endpoints cache value: "100" +- name: NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS + description: Maximum time in milliseconds allowed to establish an HTTP connection + value: "2500" +- name: NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS + description: Maximum time in milliseconds allowed to wait for HTTP data + value: "2500" - name: NOTIFICATIONS_CONNECTOR_REDELIVERY_DELAY description: Delay in milliseconds between two redelivery attempts value: "1000" diff --git a/.rhcicd/clowdapp-connector-microsoft-teams.yaml b/.rhcicd/clowdapp-connector-microsoft-teams.yaml index b20905c4c0..05920e10fc 100644 --- a/.rhcicd/clowdapp-connector-microsoft-teams.yaml +++ b/.rhcicd/clowdapp-connector-microsoft-teams.yaml @@ -57,6 +57,10 @@ objects: value: ${ENV_NAME} - name: NOTIFICATIONS_CONNECTOR_ENDPOINT_CACHE_MAX_SIZE value: ${NOTIFICATIONS_CONNECTOR_ENDPOINT_CACHE_MAX_SIZE} + - name: NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS + value: ${NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS} + - name: NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS + value: ${NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS} - name: NOTIFICATIONS_CONNECTOR_KAFKA_INCOMING_MAX_POLL_INTERVAL_MS value: ${KAFKA_MAX_POLL_INTERVAL_MS} - name: NOTIFICATIONS_CONNECTOR_KAFKA_INCOMING_MAX_POLL_RECORDS @@ -135,6 +139,12 @@ parameters: - name: NOTIFICATIONS_CONNECTOR_ENDPOINT_CACHE_MAX_SIZE description: Maximum size of the Camel endpoints cache value: "100" +- name: NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS + description: Maximum time in milliseconds allowed to establish an HTTP connection + value: "2500" +- name: NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS + description: Maximum time in milliseconds allowed to wait for HTTP data + value: "2500" - name: NOTIFICATIONS_CONNECTOR_REDELIVERY_DELAY description: Delay in milliseconds between two redelivery attempts value: "1000" diff --git a/.rhcicd/clowdapp-connector-servicenow.yaml b/.rhcicd/clowdapp-connector-servicenow.yaml index bdc3598169..cba7625a6b 100644 --- a/.rhcicd/clowdapp-connector-servicenow.yaml +++ b/.rhcicd/clowdapp-connector-servicenow.yaml @@ -63,10 +63,10 @@ objects: value: ${ENV_NAME} - name: NOTIFICATIONS_CONNECTOR_ENDPOINT_CACHE_MAX_SIZE value: ${NOTIFICATIONS_CONNECTOR_ENDPOINT_CACHE_MAX_SIZE} - - name: NOTIFICATIONS_CONNECTOR_HTTPS_CONNECT_TIMEOUT_MS - value: ${NOTIFICATIONS_CONNECTOR_HTTPS_CONNECT_TIMEOUT_MS} - - name: NOTIFICATIONS_CONNECTOR_HTTPS_SOCKET_TIMEOUT_MS - value: ${NOTIFICATIONS_CONNECTOR_HTTPS_SOCKET_TIMEOUT_MS} + - name: NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS + value: ${NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS} + - name: NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS + value: ${NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS} - name: NOTIFICATIONS_CONNECTOR_KAFKA_INCOMING_MAX_POLL_INTERVAL_MS value: ${KAFKA_MAX_POLL_INTERVAL_MS} - name: NOTIFICATIONS_CONNECTOR_KAFKA_INCOMING_MAX_POLL_RECORDS @@ -145,11 +145,11 @@ parameters: - name: NOTIFICATIONS_CONNECTOR_ENDPOINT_CACHE_MAX_SIZE description: Maximum size of the Camel endpoints cache value: "100" -- name: NOTIFICATIONS_CONNECTOR_HTTPS_CONNECT_TIMEOUT_MS - description: Maximum time in milliseconds allowed to establish an HTTPS connection +- name: NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS + description: Maximum time in milliseconds allowed to establish an HTTP connection value: "2500" -- name: NOTIFICATIONS_CONNECTOR_HTTPS_SOCKET_TIMEOUT_MS - description: Maximum time in milliseconds allowed to wait for HTTPS data +- name: NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS + description: Maximum time in milliseconds allowed to wait for HTTP data value: "2500" - name: NOTIFICATIONS_CONNECTOR_REDELIVERY_DELAY description: Delay in milliseconds between two redelivery attempts diff --git a/.rhcicd/clowdapp-connector-splunk.yaml b/.rhcicd/clowdapp-connector-splunk.yaml index 25a35f06a0..64d79a3d4c 100644 --- a/.rhcicd/clowdapp-connector-splunk.yaml +++ b/.rhcicd/clowdapp-connector-splunk.yaml @@ -63,10 +63,10 @@ objects: value: ${ENV_NAME} - name: NOTIFICATIONS_CONNECTOR_ENDPOINT_CACHE_MAX_SIZE value: ${NOTIFICATIONS_CONNECTOR_ENDPOINT_CACHE_MAX_SIZE} - - name: NOTIFICATIONS_CONNECTOR_HTTPS_CONNECT_TIMEOUT_MS - value: ${NOTIFICATIONS_CONNECTOR_HTTPS_CONNECT_TIMEOUT_MS} - - name: NOTIFICATIONS_CONNECTOR_HTTPS_SOCKET_TIMEOUT_MS - value: ${NOTIFICATIONS_CONNECTOR_HTTPS_SOCKET_TIMEOUT_MS} + - name: NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS + value: ${NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS} + - name: NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS + value: ${NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS} - name: NOTIFICATIONS_CONNECTOR_KAFKA_INCOMING_MAX_POLL_INTERVAL_MS value: ${KAFKA_MAX_POLL_INTERVAL_MS} - name: NOTIFICATIONS_CONNECTOR_KAFKA_INCOMING_MAX_POLL_RECORDS @@ -145,11 +145,11 @@ parameters: - name: NOTIFICATIONS_CONNECTOR_ENDPOINT_CACHE_MAX_SIZE description: Maximum size of the Camel endpoints cache value: "100" -- name: NOTIFICATIONS_CONNECTOR_HTTPS_CONNECT_TIMEOUT_MS - description: Maximum time in milliseconds allowed to establish an HTTPS connection +- name: NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS + description: Maximum time in milliseconds allowed to establish an HTTP connection value: "2500" -- name: NOTIFICATIONS_CONNECTOR_HTTPS_SOCKET_TIMEOUT_MS - description: Maximum time in milliseconds allowed to wait for HTTPS data +- name: NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS + description: Maximum time in milliseconds allowed to wait for HTTP data value: "2500" - name: NOTIFICATIONS_CONNECTOR_REDELIVERY_DELAY description: Delay in milliseconds between two redelivery attempts diff --git a/.rhcicd/clowdapp-connector-webhook.yaml b/.rhcicd/clowdapp-connector-webhook.yaml index c2e78a6b99..174e3b6dc3 100644 --- a/.rhcicd/clowdapp-connector-webhook.yaml +++ b/.rhcicd/clowdapp-connector-webhook.yaml @@ -148,7 +148,7 @@ parameters: description: Maximum size of the Camel endpoints cache value: "100" - name: NOTIFICATIONS_CONNECTOR_HTTP_CONNECT_TIMEOUT_MS - description: Maximum time in milliseconds allowed to establish an HTTPS connection + description: Maximum time in milliseconds allowed to establish an HTTP connection value: "30000" - name: NOTIFICATIONS_CONNECTOR_HTTP_CONNECTIONS_PER_ROUTE description: Maximum number of HTTP connections per route @@ -157,7 +157,7 @@ parameters: description: Maximum number of HTTP connections value: "200" - name: NOTIFICATIONS_CONNECTOR_HTTP_SOCKET_TIMEOUT_MS - description: Maximum time in milliseconds allowed to wait for HTTPS data + description: Maximum time in milliseconds allowed to wait for HTTP data value: "30000" - name: NOTIFICATIONS_CONNECTOR_REDELIVERY_DELAY description: Delay in milliseconds between two redelivery attempts diff --git a/connector-common-http/pom.xml b/connector-common-http/pom.xml new file mode 100644 index 0000000000..9c69a30c5a --- /dev/null +++ b/connector-common-http/pom.xml @@ -0,0 +1,94 @@ + + + 4.0.0 + + notifications-connector-common-http + + + com.redhat.cloud.notifications + notifications-parent + 1.0.0-SNAPSHOT + + + + + + + resolve-test-jars-if-tests-are-not-skipped + + + maven.test.skip + !true + + + + + com.redhat.cloud.notifications + notifications-common + ${project.version} + test-jar + test + + + + + + + + + + + + + com.redhat.cloud.notifications + notifications-connector-common + ${project.version} + + + + + org.apache.camel.quarkus + camel-quarkus-http + + + + + + + + + + org.jboss.jandex + jandex-maven-plugin + 1.2.3 + + + make-index + + jandex + + + + + + + maven-compiler-plugin + ${compiler-plugin.version} + + + + maven-surefire-plugin + ${surefire-plugin.version} + + + + + diff --git a/connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/ExchangeProperty.java b/connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/ExchangeProperty.java new file mode 100644 index 0000000000..66840fea6d --- /dev/null +++ b/connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/ExchangeProperty.java @@ -0,0 +1,8 @@ +package com.redhat.cloud.notifications.connector.http; + +public class ExchangeProperty { + + public static final String HTTP_CLIENT_ERROR = "httpClientError"; + public static final String HTTP_SERVER_ERROR = "httpServerError"; + public static final String HTTP_STATUS_CODE = "httpStatusCode"; +} diff --git a/connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/HttpComponentConfigurator.java b/connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/HttpComponentConfigurator.java new file mode 100644 index 0000000000..8015b615fe --- /dev/null +++ b/connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/HttpComponentConfigurator.java @@ -0,0 +1,29 @@ +package com.redhat.cloud.notifications.connector.http; + +import com.redhat.cloud.notifications.connector.CamelComponentConfigurator; +import io.quarkus.logging.Log; +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; +import org.apache.camel.CamelContext; +import org.apache.camel.component.http.HttpComponent; +import org.apache.hc.core5.util.Timeout; + +@Dependent +public class HttpComponentConfigurator implements CamelComponentConfigurator { + + @Inject + HttpConnectorConfig connectorConfig; + + @Override + public void configure(CamelContext context) { + for (String httpComponent : connectorConfig.getHttpComponents()) { + HttpComponent component = context.getComponent(httpComponent, HttpComponent.class); + component.setConnectTimeout(Timeout.ofMilliseconds(connectorConfig.getHttpConnectTimeout())); + component.setConnectionsPerRoute(connectorConfig.getHttpConnectionsPerRoute()); + component.setFollowRedirects(connectorConfig.isFollowRedirects()); + component.setMaxTotalConnections(connectorConfig.getHttpMaxTotalConnections()); + component.setSoTimeout(Timeout.ofMilliseconds(connectorConfig.getHttpSocketTimeout())); + Log.debugf("Configured %s component", httpComponent); + } + } +} diff --git a/connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/HttpConnectorConfig.java b/connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/HttpConnectorConfig.java new file mode 100644 index 0000000000..675f70bb88 --- /dev/null +++ b/connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/HttpConnectorConfig.java @@ -0,0 +1,102 @@ +package com.redhat.cloud.notifications.connector.http; + +import com.redhat.cloud.notifications.connector.ConnectorConfig; +import jakarta.enterprise.context.ApplicationScoped; +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import java.util.List; +import java.util.Map; + +import static org.jboss.logging.Logger.Level; + +@ApplicationScoped +public class HttpConnectorConfig extends ConnectorConfig { + + private static final String CLIENT_ERROR_LOG_LEVEL = "notifications.connector.http.client-error.log-level"; + private static final String COMPONENTS = "notifications.connector.http.components"; + private static final String CONNECT_TIMEOUT_MS = "notifications.connector.http.connect-timeout-ms"; + private static final String CONNECTIONS_PER_ROUTE = "notifications.connector.http.connections-per-route"; + private static final String DISABLE_FAULTY_ENDPOINTS = "notifications.connector.http.disable-faulty-endpoints"; + private static final String FOLLOW_REDIRECTS = "notifications.connector.http.follow-redirects"; + private static final String MAX_TOTAL_CONNECTIONS = "notifications.connector.http.max-total-connections"; + private static final String SERVER_ERROR_LOG_LEVEL = "notifications.connector.http.server-error.log-level"; + private static final String SOCKET_TIMEOUT_MS = "notifications.connector.http.socket-timeout-ms"; + + @ConfigProperty(name = CLIENT_ERROR_LOG_LEVEL, defaultValue = "DEBUG") + Level clientErrorLogLevel; + + @ConfigProperty(name = COMPONENTS, defaultValue = "http,https") + List httpComponents; + + @ConfigProperty(name = CONNECT_TIMEOUT_MS, defaultValue = "2500") + int httpConnectTimeout; + + @ConfigProperty(name = CONNECTIONS_PER_ROUTE, defaultValue = "20") + int httpConnectionsPerRoute; + + @ConfigProperty(name = DISABLE_FAULTY_ENDPOINTS, defaultValue = "true") + boolean disableFaultyEndpoints; + + @ConfigProperty(name = FOLLOW_REDIRECTS, defaultValue = "false") + boolean followRedirects; + + @ConfigProperty(name = MAX_TOTAL_CONNECTIONS, defaultValue = "200") + int httpMaxTotalConnections; + + @ConfigProperty(name = SERVER_ERROR_LOG_LEVEL, defaultValue = "DEBUG") + Level serverErrorLogLevel; + + @ConfigProperty(name = SOCKET_TIMEOUT_MS, defaultValue = "2500") + int httpSocketTimeout; + + @Override + protected Map getLoggedConfiguration() { + Map config = super.getLoggedConfiguration(); + config.put(CLIENT_ERROR_LOG_LEVEL, clientErrorLogLevel); + config.put(COMPONENTS, httpComponents); + config.put(CONNECT_TIMEOUT_MS, httpConnectTimeout); + config.put(CONNECTIONS_PER_ROUTE, httpConnectionsPerRoute); + config.put(DISABLE_FAULTY_ENDPOINTS, disableFaultyEndpoints); + config.put(FOLLOW_REDIRECTS, followRedirects); + config.put(MAX_TOTAL_CONNECTIONS, httpMaxTotalConnections); + config.put(SERVER_ERROR_LOG_LEVEL, serverErrorLogLevel); + config.put(SOCKET_TIMEOUT_MS, httpSocketTimeout); + return config; + } + + public Level getClientErrorLogLevel() { + return clientErrorLogLevel; + } + + public List getHttpComponents() { + return httpComponents; + } + + public int getHttpConnectTimeout() { + return httpConnectTimeout; + } + + public int getHttpConnectionsPerRoute() { + return httpConnectionsPerRoute; + } + + public boolean isDisableFaultyEndpoints() { + return disableFaultyEndpoints; + } + + public boolean isFollowRedirects() { + return followRedirects; + } + + public int getHttpMaxTotalConnections() { + return httpMaxTotalConnections; + } + + public Level getServerErrorLogLevel() { + return serverErrorLogLevel; + } + + public int getHttpSocketTimeout() { + return httpSocketTimeout; + } +} diff --git a/connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/HttpExceptionProcessor.java b/connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/HttpExceptionProcessor.java new file mode 100644 index 0000000000..e174bbe4a8 --- /dev/null +++ b/connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/HttpExceptionProcessor.java @@ -0,0 +1,66 @@ +package com.redhat.cloud.notifications.connector.http; + +import com.redhat.cloud.notifications.connector.ExceptionProcessor; +import io.quarkus.logging.Log; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import org.apache.camel.Exchange; +import org.apache.camel.http.base.HttpOperationFailedException; +import org.jboss.logging.Logger; + +import java.io.IOException; + +import static com.redhat.cloud.notifications.connector.http.ExchangeProperty.HTTP_CLIENT_ERROR; +import static com.redhat.cloud.notifications.connector.http.ExchangeProperty.HTTP_SERVER_ERROR; +import static com.redhat.cloud.notifications.connector.http.ExchangeProperty.HTTP_STATUS_CODE; +import static org.apache.http.HttpStatus.SC_TOO_MANY_REQUESTS; +import static org.jboss.logging.Logger.Level.ERROR; + +@ApplicationScoped +public class HttpExceptionProcessor extends ExceptionProcessor { + + private static final String HTTP_ERROR_LOG_MSG = "Message sending failed [routeId=%s, orgId=%s, historyId=%s, targetUrl=%s, statusCode=%d, responseBody=%s]"; + + @Inject + HttpConnectorConfig connectorConfig; + + @Override + protected void process(Throwable t, Exchange exchange) { + if (t instanceof HttpOperationFailedException e) { + exchange.setProperty(HTTP_STATUS_CODE, e.getStatusCode()); + if (e.getStatusCode() >= 400 && e.getStatusCode() < 500 && e.getStatusCode() != SC_TOO_MANY_REQUESTS) { + if (connectorConfig.isDisableFaultyEndpoints()) { + exchange.setProperty(HTTP_CLIENT_ERROR, true); + } + logHttpError(connectorConfig.getClientErrorLogLevel(), e, exchange); + } else if (e.getStatusCode() == SC_TOO_MANY_REQUESTS || e.getStatusCode() >= 500) { + if (connectorConfig.isDisableFaultyEndpoints()) { + exchange.setProperty(HTTP_SERVER_ERROR, true); + } + logHttpError(connectorConfig.getServerErrorLogLevel(), e, exchange); + } else { + logHttpError(ERROR, e, exchange); + } + } else if (t instanceof IOException e) { + if (connectorConfig.isDisableFaultyEndpoints()) { + exchange.setProperty(HTTP_SERVER_ERROR, true); + } + logDefault(t, exchange); + } else { + logDefault(t, exchange); + } + } + + private void logHttpError(Logger.Level level, HttpOperationFailedException e, Exchange exchange) { + Log.logf( + level, + HTTP_ERROR_LOG_MSG, + getRouteId(exchange), + getOrgId(exchange), + getExchangeId(exchange), + getTargetUrl(exchange), + e.getStatusCode(), + e.getResponseBody() + ); + } +} diff --git a/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/SslTrustAllManager.java b/connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/SslTrustAllManager.java similarity index 94% rename from connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/SslTrustAllManager.java rename to connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/SslTrustAllManager.java index 866cfe22eb..932bc18187 100644 --- a/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/SslTrustAllManager.java +++ b/connector-common-http/src/main/java/com/redhat/cloud/notifications/connector/http/SslTrustAllManager.java @@ -1,4 +1,4 @@ -package com.redhat.cloud.notifications.connector.webhook; +package com.redhat.cloud.notifications.connector.http; import org.apache.camel.support.jsse.SSLContextParameters; import org.apache.camel.support.jsse.TrustManagersParameters; diff --git a/connector-common/src/main/java/com/redhat/cloud/notifications/connector/CamelComponentConfigurator.java b/connector-common/src/main/java/com/redhat/cloud/notifications/connector/CamelComponentConfigurator.java new file mode 100644 index 0000000000..bfe956039d --- /dev/null +++ b/connector-common/src/main/java/com/redhat/cloud/notifications/connector/CamelComponentConfigurator.java @@ -0,0 +1,13 @@ +package com.redhat.cloud.notifications.connector; + +import jakarta.enterprise.context.Dependent; +import org.apache.camel.CamelContext; + +/** + * Implement this interface in a {@link Dependent @Dependent} bean to configure a Camel component before the + * Camel routes are initialized. Multiple implementations of this interface may coexist in the same application. + */ +public interface CamelComponentConfigurator { + + void configure(CamelContext context); +} diff --git a/connector-common/src/main/java/com/redhat/cloud/notifications/connector/ConnectorConfig.java b/connector-common/src/main/java/com/redhat/cloud/notifications/connector/ConnectorConfig.java index 35ea8054d1..ada59e5c18 100644 --- a/connector-common/src/main/java/com/redhat/cloud/notifications/connector/ConnectorConfig.java +++ b/connector-common/src/main/java/com/redhat/cloud/notifications/connector/ConnectorConfig.java @@ -5,7 +5,7 @@ import jakarta.enterprise.context.ApplicationScoped; import org.eclipse.microprofile.config.inject.ConfigProperty; -import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -28,6 +28,7 @@ public class ConnectorConfig { private static final String REDELIVERY_MAX_ATTEMPTS = "notifications.connector.redelivery.max-attempts"; private static final String SEDA_CONCURRENT_CONSUMERS = "notifications.connector.seda.concurrent-consumers"; private static final String SEDA_QUEUE_SIZE = "notifications.connector.seda.queue-size"; + private static final String SUPPORTED_CONNECTOR_HEADERS = "notifications.connector.supported-connector-headers"; @ConfigProperty(name = ENDPOINT_CACHE_MAX_SIZE, defaultValue = "100") int endpointCacheMaxSize; @@ -72,12 +73,17 @@ public class ConnectorConfig { @ConfigProperty(name = SEDA_QUEUE_SIZE, defaultValue = "1000") int sedaQueueSize; + @ConfigProperty(name = SUPPORTED_CONNECTOR_HEADERS) + List supportedConnectorHeaders; + public void log() { - log(Collections.emptyMap()); + Log.info("=== Connector configuration ==="); + for (Entry configEntry : getLoggedConfiguration().entrySet()) { + Log.infof("%s=%s", configEntry.getKey(), configEntry.getValue()); + } } - protected void log(Map additionalConfig) { - + protected Map getLoggedConfiguration() { Map config = new TreeMap<>(); config.put(ENDPOINT_CACHE_MAX_SIZE, endpointCacheMaxSize); config.put(KAFKA_INCOMING_GROUP_ID, incomingKafkaGroupId); @@ -92,12 +98,8 @@ protected void log(Map additionalConfig) { config.put(REDELIVERY_MAX_ATTEMPTS, redeliveryMaxAttempts); config.put(SEDA_CONCURRENT_CONSUMERS, sedaConcurrentConsumers); config.put(SEDA_QUEUE_SIZE, sedaQueueSize); - config.putAll(additionalConfig); - - Log.info("=== Connector configuration ==="); - for (Entry configEntry : config.entrySet()) { - Log.infof("%s=%s", configEntry.getKey(), configEntry.getValue()); - } + config.put(SUPPORTED_CONNECTOR_HEADERS, supportedConnectorHeaders); + return config; } public int getEndpointCacheMaxSize() { @@ -151,4 +153,8 @@ public int getSedaConcurrentConsumers() { public int getSedaQueueSize() { return sedaQueueSize; } + + public List getSupportedConnectorHeaders() { + return supportedConnectorHeaders; + } } diff --git a/connector-common/src/main/java/com/redhat/cloud/notifications/connector/EngineToConnectorRouteBuilder.java b/connector-common/src/main/java/com/redhat/cloud/notifications/connector/EngineToConnectorRouteBuilder.java index 08de0023fd..d138211f04 100644 --- a/connector-common/src/main/java/com/redhat/cloud/notifications/connector/EngineToConnectorRouteBuilder.java +++ b/connector-common/src/main/java/com/redhat/cloud/notifications/connector/EngineToConnectorRouteBuilder.java @@ -1,8 +1,8 @@ package com.redhat.cloud.notifications.connector; +import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; import org.apache.camel.builder.endpoint.EndpointRouteBuilder; -import org.apache.camel.component.seda.SedaComponent; import static org.apache.camel.LoggingLevel.DEBUG; import static org.apache.camel.builder.endpoint.dsl.KafkaEndpointBuilderFactory.KafkaEndpointConsumerBuilder; @@ -29,9 +29,15 @@ public abstract class EngineToConnectorRouteBuilder extends EndpointRouteBuilder @Inject RedeliveryPredicate redeliveryPredicate; + @Inject + Instance camelComponentsConfigurators; + @Override public void configure() throws Exception { + // Camel components must be configured before they are included in Camel routes definitions. + configureComponents(); + onException(Throwable.class) .onWhen(redeliveryPredicate::matches) .handled(true) @@ -46,8 +52,6 @@ public void configure() throws Exception { .handled(true) .process(exceptionProcessor); - configureSedaComponent(); - from(buildKafkaEndpoint()) .routeId(ENGINE_TO_CONNECTOR) .to(log(getClass().getName()).level("DEBUG").showHeaders(true).showBody(true)) @@ -58,10 +62,20 @@ public void configure() throws Exception { .to(log(getClass().getName()).level("DEBUG").showProperties(true)) .to(seda(ENGINE_TO_CONNECTOR)); - configureRoute(); + configureRoutes(); } - public abstract void configureRoute() throws Exception; + private void configureComponents() { + // All CDI beans implementing CamelComponentConfigurator are retrieved from the CDI container. + for (CamelComponentConfigurator configurator : camelComponentsConfigurators) { + // Each one of them is executed. + configurator.configure(getContext()); + // Then destroyed because it's not needed anymore and would use memory for nothing otherwise. + camelComponentsConfigurators.destroy(configurator); + } + } + + protected abstract void configureRoutes() throws Exception; private KafkaEndpointConsumerBuilder buildKafkaEndpoint() { return kafka(connectorConfig.getIncomingKafkaTopic()) @@ -70,14 +84,4 @@ private KafkaEndpointConsumerBuilder buildKafkaEndpoint() { .maxPollIntervalMs(connectorConfig.getIncomingKafkaMaxPollIntervalMs()) .pollOnError(connectorConfig.getIncomingKafkaPollOnError()); } - - private void configureSedaComponent() { - SedaComponent component = getContext().getComponent("seda", SedaComponent.class); - component.setConcurrentConsumers(connectorConfig.getSedaConcurrentConsumers()); - component.setQueueSize(connectorConfig.getSedaQueueSize()); - // The Kafka messages consumption is blocked (paused) when the SEDA queue is full. - component.setDefaultBlockWhenFull(true); - // The onException clauses will work with SEDA only if this is set to true. - component.setBridgeErrorHandler(true); - } } diff --git a/connector-common/src/main/java/com/redhat/cloud/notifications/connector/ExceptionProcessor.java b/connector-common/src/main/java/com/redhat/cloud/notifications/connector/ExceptionProcessor.java index 56bf458cc3..cb2daa08f1 100644 --- a/connector-common/src/main/java/com/redhat/cloud/notifications/connector/ExceptionProcessor.java +++ b/connector-common/src/main/java/com/redhat/cloud/notifications/connector/ExceptionProcessor.java @@ -34,9 +34,6 @@ public class ExceptionProcessor implements Processor { @Inject ProducerTemplate producerTemplate; - @Inject - ConnectorConfig connectorConfig; - @Override public void process(Exchange exchange) { diff --git a/connector-common/src/main/java/com/redhat/cloud/notifications/connector/IncomingCloudEventFilter.java b/connector-common/src/main/java/com/redhat/cloud/notifications/connector/IncomingCloudEventFilter.java index 6ad5463289..608f77c166 100644 --- a/connector-common/src/main/java/com/redhat/cloud/notifications/connector/IncomingCloudEventFilter.java +++ b/connector-common/src/main/java/com/redhat/cloud/notifications/connector/IncomingCloudEventFilter.java @@ -1,12 +1,10 @@ package com.redhat.cloud.notifications.connector; -import io.quarkus.arc.DefaultBean; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import org.apache.camel.Exchange; import org.apache.camel.Predicate; -@DefaultBean @ApplicationScoped public class IncomingCloudEventFilter implements Predicate { @@ -18,6 +16,6 @@ public class IncomingCloudEventFilter implements Predicate { @Override public boolean matches(Exchange exchange) { String connectorHeader = exchange.getIn().getHeader(X_RH_NOTIFICATIONS_CONNECTOR_HEADER, String.class); - return connectorConfig.getConnectorName().equals(connectorHeader); + return connectorConfig.getSupportedConnectorHeaders().contains(connectorHeader); } } diff --git a/connector-common/src/main/java/com/redhat/cloud/notifications/connector/SedaComponentConfigurator.java b/connector-common/src/main/java/com/redhat/cloud/notifications/connector/SedaComponentConfigurator.java new file mode 100644 index 0000000000..821d2cb968 --- /dev/null +++ b/connector-common/src/main/java/com/redhat/cloud/notifications/connector/SedaComponentConfigurator.java @@ -0,0 +1,26 @@ +package com.redhat.cloud.notifications.connector; + +import io.quarkus.logging.Log; +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; +import org.apache.camel.CamelContext; +import org.apache.camel.component.seda.SedaComponent; + +@Dependent +public class SedaComponentConfigurator implements CamelComponentConfigurator { + + @Inject + ConnectorConfig connectorConfig; + + @Override + public void configure(CamelContext context) { + SedaComponent component = context.getComponent("seda", SedaComponent.class); + component.setConcurrentConsumers(connectorConfig.getSedaConcurrentConsumers()); + component.setQueueSize(connectorConfig.getSedaQueueSize()); + // The Kafka messages consumption is blocked (paused) when the SEDA queue is full. + component.setDefaultBlockWhenFull(true); + // The onException clauses will work with SEDA only if this is set to true. + component.setBridgeErrorHandler(true); + Log.debugf("Configured seda component"); + } +} diff --git a/connector-common/src/test/java/com/redhat/cloud/notifications/connector/IncomingCloudEventFilterTest.java b/connector-common/src/test/java/com/redhat/cloud/notifications/connector/IncomingCloudEventFilterTest.java index 5c8df8494a..9d44a89e46 100644 --- a/connector-common/src/test/java/com/redhat/cloud/notifications/connector/IncomingCloudEventFilterTest.java +++ b/connector-common/src/test/java/com/redhat/cloud/notifications/connector/IncomingCloudEventFilterTest.java @@ -5,9 +5,10 @@ import jakarta.inject.Inject; import org.apache.camel.Exchange; import org.apache.camel.quarkus.test.CamelQuarkusTestSupport; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.List; + import static com.redhat.cloud.notifications.connector.IncomingCloudEventFilter.X_RH_NOTIFICATIONS_CONNECTOR_HEADER; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -22,21 +23,33 @@ public class IncomingCloudEventFilterTest extends CamelQuarkusTestSupport { @InjectMock ConnectorConfig connectorConfig; - @BeforeEach - void beforeEach() { - when(connectorConfig.getConnectorName()).thenReturn("foo"); + @Override + public boolean isUseRouteBuilder() { + return false; } @Test - void shouldAcceptValidConnectorHeader() { + void shouldAcceptValidConnectorHeaderSingleValue() { + mockSupportedConnectorHeaders("foo"); + assertTrue(incomingCloudEventFilter.matches(buildExchange("foo"))); + } + + @Test + void shouldAcceptValidConnectorHeaderMultipleValues() { + mockSupportedConnectorHeaders("bar", "foo"); assertTrue(incomingCloudEventFilter.matches(buildExchange("foo"))); } @Test void shouldRejectInvalidConnectorHeader() { + mockSupportedConnectorHeaders("foo"); assertFalse(incomingCloudEventFilter.matches(buildExchange("bar"))); } + private void mockSupportedConnectorHeaders(String... supportedConnectorHeaders) { + when(connectorConfig.getSupportedConnectorHeaders()).thenReturn(List.of(supportedConnectorHeaders)); + } + private Exchange buildExchange(String connectorHeader) { Exchange exchange = createExchangeWithBody(null); exchange.getIn().setHeader(X_RH_NOTIFICATIONS_CONNECTOR_HEADER, connectorHeader); diff --git a/connector-common/src/test/resources/application.properties b/connector-common/src/test/resources/application.properties index 490aed7d09..0b67634e68 100644 --- a/connector-common/src/test/resources/application.properties +++ b/connector-common/src/test/resources/application.properties @@ -3,6 +3,7 @@ notifications.connector.kafka.incoming.topic=${mp.messaging.tocamel.topic} notifications.connector.kafka.outgoing.topic=${mp.messaging.fromcamel.topic} notifications.connector.name=common notifications.connector.redelivery.counter-name=camel.common.retry.counter +notifications.connector.supported-connector-headers=${notifications.connector.name} quarkus.log.cloudwatch.enabled=false quarkus.log.cloudwatch.level=INFO diff --git a/connector-drawer/pom.xml b/connector-drawer/pom.xml index 57a3ae5632..59335174b7 100644 --- a/connector-drawer/pom.xml +++ b/connector-drawer/pom.xml @@ -56,7 +56,7 @@ com.redhat.cloud.notifications - notifications-connector-common + notifications-connector-common-http ${project.version} @@ -65,12 +65,6 @@ jakarta.validation-api - - - org.apache.camel.quarkus - camel-quarkus-http - - diff --git a/connector-drawer/src/main/java/com/redhat/cloud/notifications/connector/drawer/DrawerRouteBuilder.java b/connector-drawer/src/main/java/com/redhat/cloud/notifications/connector/drawer/DrawerRouteBuilder.java index 199545e4a3..9a3abfb47f 100644 --- a/connector-drawer/src/main/java/com/redhat/cloud/notifications/connector/drawer/DrawerRouteBuilder.java +++ b/connector-drawer/src/main/java/com/redhat/cloud/notifications/connector/drawer/DrawerRouteBuilder.java @@ -30,7 +30,7 @@ public class DrawerRouteBuilder extends EngineToConnectorRouteBuilder { public static final String CONNECTOR_TO_DRAWER = "connector-to-drawer"; @Override - public void configureRoute() { + public void configureRoutes() { from(seda(ENGINE_TO_CONNECTOR)) .routeId(drawerConnectorConfig.getConnectorName()) .process(recipientsResolverPreparer) diff --git a/connector-drawer/src/main/java/com/redhat/cloud/notifications/connector/drawer/config/DrawerConnectorConfig.java b/connector-drawer/src/main/java/com/redhat/cloud/notifications/connector/drawer/config/DrawerConnectorConfig.java index 857717ab5c..bd16e39fc9 100644 --- a/connector-drawer/src/main/java/com/redhat/cloud/notifications/connector/drawer/config/DrawerConnectorConfig.java +++ b/connector-drawer/src/main/java/com/redhat/cloud/notifications/connector/drawer/config/DrawerConnectorConfig.java @@ -1,13 +1,20 @@ package com.redhat.cloud.notifications.connector.drawer.config; -import com.redhat.cloud.notifications.connector.ConnectorConfig; +import com.redhat.cloud.notifications.connector.http.HttpConnectorConfig; +import jakarta.annotation.Priority; import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Alternative; import org.eclipse.microprofile.config.inject.ConfigProperty; -import java.util.HashMap; import java.util.Map; @ApplicationScoped -public class DrawerConnectorConfig extends ConnectorConfig { +/* + * @Alternative and Priority will soon go away. + * See https://github.com/quarkusio/quarkus/issues/37042 for more details about the replacement. + */ +@Alternative +@Priority(0) // The value doesn't matter. +public class DrawerConnectorConfig extends HttpConnectorConfig { private static final String DRAWER_TOPIC = "notifications.connector.kafka.outgoing.drawer.topic"; @@ -19,11 +26,11 @@ public class DrawerConnectorConfig extends ConnectorConfig { String outgoingDrawerTopic; @Override - public void log() { - final Map additionalEntries = new HashMap<>(); - additionalEntries.put(DRAWER_TOPIC, outgoingDrawerTopic); - additionalEntries.put(RECIPIENTS_RESOLVER_USER_SERVICE_URL, recipientsResolverServiceURL); - log(additionalEntries); + protected Map getLoggedConfiguration() { + Map config = super.getLoggedConfiguration(); + config.put(DRAWER_TOPIC, outgoingDrawerTopic); + config.put(RECIPIENTS_RESOLVER_USER_SERVICE_URL, recipientsResolverServiceURL); + return config; } public String getOutgoingDrawerTopic() { diff --git a/connector-drawer/src/main/resources/application.properties b/connector-drawer/src/main/resources/application.properties index a1d6e8104f..a616bcffe6 100644 --- a/connector-drawer/src/main/resources/application.properties +++ b/connector-drawer/src/main/resources/application.properties @@ -1,9 +1,14 @@ +notifications.connector.http.client-error.log-level=ERROR +notifications.connector.http.components=http +notifications.connector.http.disable-faulty-endpoints=false +notifications.connector.http.server-error.log-level=ERROR notifications.connector.kafka.incoming.group-id=notifications-connector-drawer notifications.connector.kafka.incoming.topic=${mp.messaging.tocamel.topic} notifications.connector.kafka.outgoing.topic=${mp.messaging.fromcamel.topic} notifications.connector.kafka.outgoing.drawer.topic=${mp.messaging.todrawer.topic} notifications.connector.name=drawer notifications.connector.redelivery.counter-name=camel.drawer.retry.counter +notifications.connector.supported-connector-headers=${notifications.connector.name} # The following value matches the default value of the `connectionsPerRoute` option from the Camel `http` component. notifications.connector.seda.concurrent-consumers=20 diff --git a/connector-email/pom.xml b/connector-email/pom.xml index d1a602281c..5f237c1473 100644 --- a/connector-email/pom.xml +++ b/connector-email/pom.xml @@ -51,7 +51,7 @@ com.redhat.cloud.notifications - notifications-connector-common + notifications-connector-common-http ${project.version} @@ -70,10 +70,6 @@ org.apache.camel.quarkus camel-quarkus-caffeine - - org.apache.camel.quarkus - camel-quarkus-http - jakarta.validation diff --git a/connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/EmailExceptionProcessor.java b/connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/EmailExceptionProcessor.java deleted file mode 100644 index c5c8174449..0000000000 --- a/connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/EmailExceptionProcessor.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.redhat.cloud.notifications.connector.email; - -import com.redhat.cloud.notifications.connector.ExceptionProcessor; -import io.quarkus.logging.Log; -import jakarta.enterprise.context.ApplicationScoped; -import org.apache.camel.Exchange; -import org.apache.camel.http.base.HttpOperationFailedException; - -@ApplicationScoped -public class EmailExceptionProcessor extends ExceptionProcessor { - - private static final String HTTP_LOG_MSG = "Message sending failed on %s: [orgId=%s, historyId=%s] " + - "with status code [%d] and body [%s]"; - - @Override - protected void process(Throwable t, Exchange exchange) { - if (t instanceof HttpOperationFailedException e) { - Log.errorf( - HTTP_LOG_MSG, - getRouteId(exchange), - getOrgId(exchange), - getExchangeId(exchange), - e.getStatusCode(), - e.getResponseBody() - ); - } else { - logDefault(t, exchange); - } - } -} diff --git a/connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/EmailRouteBuilder.java b/connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/EmailRouteBuilder.java index b202cd123a..5e40eae86f 100644 --- a/connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/EmailRouteBuilder.java +++ b/connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/EmailRouteBuilder.java @@ -10,7 +10,6 @@ import com.redhat.cloud.notifications.connector.email.predicates.NotFinishedFetchingAllPages; import com.redhat.cloud.notifications.connector.email.predicates.rbac.StatusCodeNotFound; import com.redhat.cloud.notifications.connector.email.processors.bop.BOPRequestPreparer; -import com.redhat.cloud.notifications.connector.email.processors.bop.ssl.BOPTrustManager; import com.redhat.cloud.notifications.connector.email.processors.it.ITResponseProcessor; import com.redhat.cloud.notifications.connector.email.processors.it.ITUserRequestPreparer; import com.redhat.cloud.notifications.connector.email.processors.rbac.RBACConstants; @@ -38,7 +37,6 @@ import org.apache.camel.support.jsse.KeyManagersParameters; import org.apache.camel.support.jsse.KeyStoreParameters; import org.apache.camel.support.jsse.SSLContextParameters; -import org.apache.camel.support.jsse.TrustManagersParameters; import org.apache.http.conn.ssl.NoopHostnameVerifier; import java.util.HashSet; @@ -49,6 +47,7 @@ import static com.redhat.cloud.notifications.connector.ExchangeProperty.ORG_ID; import static com.redhat.cloud.notifications.connector.email.constants.ExchangeProperty.EMAIL_RECIPIENTS; import static com.redhat.cloud.notifications.connector.email.constants.ExchangeProperty.FILTERED_USERS; +import static com.redhat.cloud.notifications.connector.http.SslTrustAllManager.getSslContextParameters; import static org.apache.camel.LoggingLevel.INFO; @ApplicationScoped @@ -158,7 +157,7 @@ public class EmailRouteBuilder extends EngineToConnectorRouteBuilder { * @throws Exception if the IT SSL route could not be correctly set up. */ @Override - public void configureRoute() throws Exception { + public void configureRoutes() throws Exception { /* * Configure Caffeine cache. */ @@ -506,14 +505,8 @@ protected HttpEndpointBuilderFactory.HttpEndpointBuilder setUpBOPEndpoint() { // the schema twice. final String fullURL = this.emailConnectorConfig.getBopURL(); if (fullURL.startsWith("https")) { - final TrustManagersParameters trustManagersParameters = new TrustManagersParameters(); - trustManagersParameters.setTrustManager(new BOPTrustManager()); - - final SSLContextParameters sslContextParameters = new SSLContextParameters(); - sslContextParameters.setTrustManagers(trustManagersParameters); - return https(fullURL.replace("https://", "")) - .sslContextParameters(sslContextParameters) + .sslContextParameters(getSslContextParameters()) .x509HostnameVerifier(NoopHostnameVerifier.INSTANCE); } else { return http(fullURL.replace("http://", "")); diff --git a/connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/config/EmailConnectorConfig.java b/connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/config/EmailConnectorConfig.java index e4dd489752..1165730e02 100644 --- a/connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/config/EmailConnectorConfig.java +++ b/connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/config/EmailConnectorConfig.java @@ -1,20 +1,27 @@ package com.redhat.cloud.notifications.connector.email.config; -import com.redhat.cloud.notifications.connector.ConnectorConfig; +import com.redhat.cloud.notifications.connector.http.HttpConnectorConfig; import io.quarkus.logging.Log; import io.vertx.core.json.DecodeException; import io.vertx.core.json.JsonObject; +import jakarta.annotation.Priority; import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Alternative; import org.eclipse.microprofile.config.inject.ConfigProperty; import java.nio.charset.StandardCharsets; import java.util.Base64; -import java.util.HashMap; import java.util.Map; import java.util.Optional; @ApplicationScoped -public class EmailConnectorConfig extends ConnectorConfig { +/* + * @Alternative and Priority will soon go away. + * See https://github.com/quarkusio/quarkus/issues/37042 for more details about the replacement. + */ +@Alternative +@Priority(0) // The value doesn't matter. +public class EmailConnectorConfig extends HttpConnectorConfig { private static final String BOP_API_TOKEN = "notifications.connector.user-provider.bop.api_token"; private static final String BOP_CLIENT_ID = "notifications.connector.user-provider.bop.client_id"; private static final String BOP_ENV = "notifications.connector.user-provider.bop.env"; @@ -105,33 +112,33 @@ public class EmailConnectorConfig extends ConnectorConfig { String recipientsResolverServiceURL; @Override - public void log() { - final Map additionalEntries = new HashMap<>(); + protected Map getLoggedConfiguration() { + Map config = super.getLoggedConfiguration(); /* * /!\ WARNING /!\ * DO NOT log config values that come from OpenShift secrets. */ - additionalEntries.put(BOP_ENV, this.bopEnv); - additionalEntries.put(BOP_URL, this.bopURL); - additionalEntries.put(FETCH_USERS_RBAC_ENABLED, this.fetchUsersWithRBAC); - additionalEntries.put(IT_ELEMENTS_PAGE, this.itElementsPerPage); - additionalEntries.put(IT_KEYSTORE_LOCATION, this.itKeyStoreLocation.orElse("")); - additionalEntries.put(RBAC_APPLICATION_KEY, this.rbacApplicationKey); - additionalEntries.put(RBAC_ELEMENTS_PAGE, this.rbacElementsPerPage); - additionalEntries.put(RBAC_URL, this.rbacURL); - additionalEntries.put(USER_PROVIDER_CACHE_EXPIRE_AFTER_WRITE, this.userProviderCacheExpireAfterWrite); - additionalEntries.put(SKIP_BOP_USERS_RESOLUTION, skipBopUsersResolution); - additionalEntries.put(NOTIFICATIONS_RECIPIENTS_RESOLVER_MODULE_ENABLED, recipientsResolverModuleEnabled); - additionalEntries.put(RECIPIENTS_RESOLVER_USER_SERVICE_URL, recipientsResolverServiceURL); + config.put(BOP_ENV, this.bopEnv); + config.put(BOP_URL, this.bopURL); + config.put(FETCH_USERS_RBAC_ENABLED, this.fetchUsersWithRBAC); + config.put(IT_ELEMENTS_PAGE, this.itElementsPerPage); + config.put(IT_KEYSTORE_LOCATION, this.itKeyStoreLocation.orElse("")); + config.put(RBAC_APPLICATION_KEY, this.rbacApplicationKey); + config.put(RBAC_ELEMENTS_PAGE, this.rbacElementsPerPage); + config.put(RBAC_URL, this.rbacURL); + config.put(USER_PROVIDER_CACHE_EXPIRE_AFTER_WRITE, this.userProviderCacheExpireAfterWrite); + config.put(SKIP_BOP_USERS_RESOLUTION, skipBopUsersResolution); + config.put(NOTIFICATIONS_RECIPIENTS_RESOLVER_MODULE_ENABLED, recipientsResolverModuleEnabled); + config.put(RECIPIENTS_RESOLVER_USER_SERVICE_URL, recipientsResolverServiceURL); /* * /!\ WARNING /!\ * DO NOT log config values that come from OpenShift secrets. */ - log(additionalEntries); + return config; } public String getBopApiToken() { diff --git a/connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/processors/bop/ssl/BOPTrustManager.java b/connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/processors/bop/ssl/BOPTrustManager.java deleted file mode 100644 index 71b592d99e..0000000000 --- a/connector-email/src/main/java/com/redhat/cloud/notifications/connector/email/processors/bop/ssl/BOPTrustManager.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.redhat.cloud.notifications.connector.email.processors.bop.ssl; - -import javax.net.ssl.X509TrustManager; -import java.security.cert.X509Certificate; - -/** - * A NOOP Trust Manager which trusts all the certificates. - */ -public class BOPTrustManager implements X509TrustManager { - - @Override - public void checkClientTrusted(final X509Certificate[] chain, final String authType) { - } - - @Override - public void checkServerTrusted(final X509Certificate[] chain, final String authType) { - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } -} diff --git a/connector-email/src/main/resources/application.properties b/connector-email/src/main/resources/application.properties index 4271d39d0f..6a2c668263 100644 --- a/connector-email/src/main/resources/application.properties +++ b/connector-email/src/main/resources/application.properties @@ -1,3 +1,6 @@ +notifications.connector.http.client-error.log-level=ERROR +notifications.connector.http.disable-faulty-endpoints=false +notifications.connector.http.server-error.log-level=ERROR notifications.connector.kafka.incoming.group-id=notifications-connector-email notifications.connector.kafka.incoming.topic=${mp.messaging.tocamel.topic} notifications.connector.kafka.outgoing.topic=${mp.messaging.fromcamel.topic} @@ -7,6 +10,7 @@ notifications.connector.redelivery.counter-name=camel.email.retry.counter notifications.connector.seda.concurrent-consumers=20 # The following value matches the default value of the `connectionsPerRoute` option from the Camel `http` component. notifications.connector.seda.queue-size=20 +notifications.connector.supported-connector-headers=${notifications.connector.name} quarkus.http.port=9003 diff --git a/connector-email/src/test/java/com/redhat/cloud/notifications/connector/email/EmailRouteBuilderTest.java b/connector-email/src/test/java/com/redhat/cloud/notifications/connector/email/EmailRouteBuilderTest.java index 7dcdbd831a..53bd375125 100644 --- a/connector-email/src/test/java/com/redhat/cloud/notifications/connector/email/EmailRouteBuilderTest.java +++ b/connector-email/src/test/java/com/redhat/cloud/notifications/connector/email/EmailRouteBuilderTest.java @@ -1,7 +1,7 @@ package com.redhat.cloud.notifications.connector.email; import com.redhat.cloud.notifications.connector.email.config.EmailConnectorConfig; -import com.redhat.cloud.notifications.connector.email.processors.bop.ssl.BOPTrustManager; +import com.redhat.cloud.notifications.connector.http.SslTrustAllManager; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.TestProfile; import jakarta.inject.Inject; @@ -45,7 +45,7 @@ public boolean isUseRouteBuilder() { /** * Tests that the function under test creates the BOP endpoint with the - * {@link BOPTrustManager} class as the SSL context parameters, and that + * {@link SslTrustAllManager} class as the SSL context parameters, and that * that class is essentially a NOOP class. * @throws Exception if the endpoint could not be created. */ @@ -55,7 +55,7 @@ void testBuildBOPEndpoint() throws Exception { Assertions.assertEquals(this.emailConnectorConfig.getBopURL(), bopEndpoint.getEndpointBaseUri(), "the base URI of the endpoint is not the same as the one set through the properties"); final String bopEndpointURI = bopEndpoint.getEndpointUri(); - Assertions.assertTrue(bopEndpointURI.contains("trustManager%3Dcom.redhat.cloud.notifications.connector.email.processors.bop.ssl.BOPTrustManager"), "the endpoint does not contain a reference to the BOPTrustManager"); + Assertions.assertTrue(bopEndpointURI.contains("trustManager%3Dcom.redhat.cloud.notifications.connector.http.SslTrustAllManager"), "the endpoint does not contain a reference to the SslTrustAllManager"); Assertions.assertTrue(bopEndpointURI.contains("x509HostnameVerifier=NO_OP"), "the base URI does not contain a mention to the NO_OP hostname verifier"); } } diff --git a/connector-google-chat/pom.xml b/connector-google-chat/pom.xml index 4fa743facc..a1120d9a23 100644 --- a/connector-google-chat/pom.xml +++ b/connector-google-chat/pom.xml @@ -56,16 +56,10 @@ com.redhat.cloud.notifications - notifications-connector-common + notifications-connector-common-http ${project.version} - - - org.apache.camel.quarkus - camel-quarkus-http - - diff --git a/connector-google-chat/src/main/java/com/redhat/cloud/notifications/connector/google/chat/GoogleChatExceptionProcessor.java b/connector-google-chat/src/main/java/com/redhat/cloud/notifications/connector/google/chat/GoogleChatExceptionProcessor.java deleted file mode 100644 index 38d168dbad..0000000000 --- a/connector-google-chat/src/main/java/com/redhat/cloud/notifications/connector/google/chat/GoogleChatExceptionProcessor.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.redhat.cloud.notifications.connector.google.chat; - -import com.redhat.cloud.notifications.connector.ExceptionProcessor; -import io.quarkus.logging.Log; -import jakarta.enterprise.context.ApplicationScoped; -import org.apache.camel.Exchange; -import org.apache.camel.http.base.HttpOperationFailedException; - -import static org.jboss.logging.Logger.Level; -import static org.jboss.logging.Logger.Level.DEBUG; -import static org.jboss.logging.Logger.Level.ERROR; - -@ApplicationScoped -public class GoogleChatExceptionProcessor extends ExceptionProcessor { - - private static final String HTTP_LOG_MSG = "Message sending failed on %s: [orgId=%s, historyId=%s, webhookUrl=%s] " + - "with status code [%d] and body [%s]"; - - @Override - protected void process(Throwable t, Exchange exchange) { - if (t instanceof HttpOperationFailedException e) { - if (e.getStatusCode() >= 400 && e.getStatusCode() < 500) { - // TODO Disable the integration using the 'integration-disabled' event type. - log(DEBUG, e, exchange); - } else { - log(ERROR, e, exchange); - } - } else { - logDefault(t, exchange); - } - } - - private void log(Level level, HttpOperationFailedException e, Exchange exchange) { - Log.logf( - level, - HTTP_LOG_MSG, - getRouteId(exchange), - getOrgId(exchange), - getExchangeId(exchange), - getTargetUrl(exchange), - e.getStatusCode(), - e.getResponseBody() - ); - } -} diff --git a/connector-google-chat/src/main/java/com/redhat/cloud/notifications/connector/google/chat/GoogleChatRouteBuilder.java b/connector-google-chat/src/main/java/com/redhat/cloud/notifications/connector/google/chat/GoogleChatRouteBuilder.java index cb9b75d1a2..3cd7481f27 100644 --- a/connector-google-chat/src/main/java/com/redhat/cloud/notifications/connector/google/chat/GoogleChatRouteBuilder.java +++ b/connector-google-chat/src/main/java/com/redhat/cloud/notifications/connector/google/chat/GoogleChatRouteBuilder.java @@ -1,7 +1,7 @@ package com.redhat.cloud.notifications.connector.google.chat; -import com.redhat.cloud.notifications.connector.ConnectorConfig; import com.redhat.cloud.notifications.connector.EngineToConnectorRouteBuilder; +import com.redhat.cloud.notifications.connector.http.HttpConnectorConfig; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -20,10 +20,10 @@ public class GoogleChatRouteBuilder extends EngineToConnectorRouteBuilder { @Inject - ConnectorConfig connectorConfig; + HttpConnectorConfig connectorConfig; @Override - public void configureRoute() { + public void configureRoutes() { from(seda(ENGINE_TO_CONNECTOR)) .routeId(connectorConfig.getConnectorName()) .setHeader(HTTP_METHOD, constant("POST")) diff --git a/connector-google-chat/src/main/resources/application.properties b/connector-google-chat/src/main/resources/application.properties index af16733516..b8726c1614 100644 --- a/connector-google-chat/src/main/resources/application.properties +++ b/connector-google-chat/src/main/resources/application.properties @@ -7,6 +7,7 @@ notifications.connector.redelivery.counter-name=camel.google.chat.retry.counter notifications.connector.seda.concurrent-consumers=20 # The following value matches the default value of the `connectionsPerRoute` option from the Camel `http` component. notifications.connector.seda.queue-size=20 +notifications.connector.supported-connector-headers=${notifications.connector.name} quarkus.http.port=9001 diff --git a/connector-microsoft-teams/pom.xml b/connector-microsoft-teams/pom.xml index c37bdfe61a..3672000589 100644 --- a/connector-microsoft-teams/pom.xml +++ b/connector-microsoft-teams/pom.xml @@ -56,16 +56,10 @@ com.redhat.cloud.notifications - notifications-connector-common + notifications-connector-common-http ${project.version} - - - org.apache.camel.quarkus - camel-quarkus-http - - diff --git a/connector-microsoft-teams/src/main/java/com/redhat/cloud/notifications/connector/microsoft/teams/TeamsExceptionProcessor.java b/connector-microsoft-teams/src/main/java/com/redhat/cloud/notifications/connector/microsoft/teams/TeamsExceptionProcessor.java deleted file mode 100644 index 0aa1155e21..0000000000 --- a/connector-microsoft-teams/src/main/java/com/redhat/cloud/notifications/connector/microsoft/teams/TeamsExceptionProcessor.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.redhat.cloud.notifications.connector.microsoft.teams; - -import com.redhat.cloud.notifications.connector.ExceptionProcessor; -import io.quarkus.logging.Log; -import jakarta.enterprise.context.ApplicationScoped; -import org.apache.camel.Exchange; -import org.apache.camel.http.base.HttpOperationFailedException; - -@ApplicationScoped -public class TeamsExceptionProcessor extends ExceptionProcessor { - - private static final String HTTP_LOG_MSG = "Message sending failed on %s: [orgId=%s, historyId=%s, webhookUrl=%s] " + - "with status code [%d] and body [%s]"; - - @Override - protected void process(Throwable t, Exchange exchange) { - if (t instanceof HttpOperationFailedException e) { - Log.errorf( - HTTP_LOG_MSG, - getRouteId(exchange), - getOrgId(exchange), - getExchangeId(exchange), - getTargetUrl(exchange), - e.getStatusCode(), - e.getResponseBody() - ); - } else { - logDefault(t, exchange); - } - } -} diff --git a/connector-microsoft-teams/src/main/java/com/redhat/cloud/notifications/connector/microsoft/teams/TeamsRouteBuilder.java b/connector-microsoft-teams/src/main/java/com/redhat/cloud/notifications/connector/microsoft/teams/TeamsRouteBuilder.java index 1ba9e8d5d0..cb6c1d3e54 100644 --- a/connector-microsoft-teams/src/main/java/com/redhat/cloud/notifications/connector/microsoft/teams/TeamsRouteBuilder.java +++ b/connector-microsoft-teams/src/main/java/com/redhat/cloud/notifications/connector/microsoft/teams/TeamsRouteBuilder.java @@ -1,7 +1,7 @@ package com.redhat.cloud.notifications.connector.microsoft.teams; -import com.redhat.cloud.notifications.connector.ConnectorConfig; import com.redhat.cloud.notifications.connector.EngineToConnectorRouteBuilder; +import com.redhat.cloud.notifications.connector.http.HttpConnectorConfig; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -17,10 +17,10 @@ public class TeamsRouteBuilder extends EngineToConnectorRouteBuilder { @Inject - ConnectorConfig connectorConfig; + HttpConnectorConfig connectorConfig; @Override - public void configureRoute() { + public void configureRoutes() { from(seda(ENGINE_TO_CONNECTOR)) .routeId(connectorConfig.getConnectorName()) .setHeader(HTTP_METHOD, constant("POST")) diff --git a/connector-microsoft-teams/src/main/resources/application.properties b/connector-microsoft-teams/src/main/resources/application.properties index 58d3ed2a00..ff5bbdc8bf 100644 --- a/connector-microsoft-teams/src/main/resources/application.properties +++ b/connector-microsoft-teams/src/main/resources/application.properties @@ -7,6 +7,7 @@ notifications.connector.redelivery.counter-name=camel.teams.retry.counter notifications.connector.seda.concurrent-consumers=20 # The following value matches the default value of the `connectionsPerRoute` option from the Camel `http` component. notifications.connector.seda.queue-size=20 +notifications.connector.supported-connector-headers=${notifications.connector.name} quarkus.http.port=9002 diff --git a/connector-servicenow/pom.xml b/connector-servicenow/pom.xml index 9713a6314a..834faa4800 100644 --- a/connector-servicenow/pom.xml +++ b/connector-servicenow/pom.xml @@ -56,16 +56,10 @@ com.redhat.cloud.notifications - notifications-connector-common + notifications-connector-common-http ${project.version} - - - org.apache.camel.quarkus - camel-quarkus-http - - commons-validator diff --git a/connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowConnectorConfig.java b/connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowConnectorConfig.java deleted file mode 100644 index 465936b1da..0000000000 --- a/connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowConnectorConfig.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.redhat.cloud.notifications.connector.servicenow; - -import com.redhat.cloud.notifications.connector.ConnectorConfig; -import jakarta.enterprise.context.ApplicationScoped; -import org.eclipse.microprofile.config.inject.ConfigProperty; - -import java.util.Map; - -@ApplicationScoped -public class ServiceNowConnectorConfig extends ConnectorConfig { - - private static final String HTTPS_CONNECT_TIMEOUT_MS = "notifications.connector.https.connect-timeout-ms"; - private static final String HTTPS_SOCKET_TIMEOUT_MS = "notifications.connector.https.socket-timeout-ms"; - - @ConfigProperty(name = HTTPS_CONNECT_TIMEOUT_MS, defaultValue = "2500") - int httpsConnectTimeout; - - @ConfigProperty(name = HTTPS_SOCKET_TIMEOUT_MS, defaultValue = "2500") - int httpsSocketTimeout; - - @Override - public void log() { - Map additionalEntries = Map.of( - HTTPS_CONNECT_TIMEOUT_MS, httpsConnectTimeout, - HTTPS_SOCKET_TIMEOUT_MS, httpsSocketTimeout - ); - log(additionalEntries); - } - - public int getHttpsConnectTimeout() { - return httpsConnectTimeout; - } - - public int getHttpsSocketTimeout() { - return httpsSocketTimeout; - } -} diff --git a/connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowExceptionProcessor.java b/connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowExceptionProcessor.java deleted file mode 100644 index c7d39b497d..0000000000 --- a/connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowExceptionProcessor.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.redhat.cloud.notifications.connector.servicenow; - -import com.redhat.cloud.notifications.connector.ExceptionProcessor; -import io.quarkus.logging.Log; -import jakarta.enterprise.context.ApplicationScoped; -import org.apache.camel.Exchange; -import org.apache.camel.http.base.HttpOperationFailedException; - -import static com.redhat.cloud.notifications.connector.servicenow.ExchangeProperty.ACCOUNT_ID; - -@ApplicationScoped -public class ServiceNowExceptionProcessor extends ExceptionProcessor { - - private static final String DEFAULT_LOG_MSG = "Message sending failed on %s: [orgId=%s, accountId=%s, historyId=%s, targetUrl=%s]"; - private static final String HTTP_LOG_MSG = "Message sending failed on %s: [orgId=%s, accountId=%s, historyId=%s, targetUrl=%s] " + - "with status code [%d] and body [%s]"; - - @Override - protected void process(Throwable t, Exchange exchange) { - if (t instanceof HttpOperationFailedException e) { - Log.errorf( - HTTP_LOG_MSG, - getRouteId(exchange), - getOrgId(exchange), - exchange.getProperty(ACCOUNT_ID, String.class), - getExchangeId(exchange), - getTargetUrl(exchange), - e.getStatusCode(), - e.getResponseBody() - ); - } else { - Log.errorf( - t, - DEFAULT_LOG_MSG, - getRouteId(exchange), - getOrgId(exchange), - exchange.getProperty(ACCOUNT_ID, String.class), - getExchangeId(exchange), - getTargetUrl(exchange) - ); - } - } -} diff --git a/connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowRouteBuilder.java b/connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowRouteBuilder.java index 718a43205c..c268f138a1 100644 --- a/connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowRouteBuilder.java +++ b/connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowRouteBuilder.java @@ -1,20 +1,19 @@ package com.redhat.cloud.notifications.connector.servicenow; import com.redhat.cloud.notifications.connector.EngineToConnectorRouteBuilder; +import com.redhat.cloud.notifications.connector.http.HttpConnectorConfig; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import org.apache.camel.component.http.HttpComponent; -import org.apache.hc.core5.util.Timeout; import org.apache.http.conn.ssl.NoopHostnameVerifier; import static com.redhat.cloud.notifications.connector.ConnectorToEngineRouteBuilder.SUCCESS; import static com.redhat.cloud.notifications.connector.ExchangeProperty.ID; import static com.redhat.cloud.notifications.connector.ExchangeProperty.ORG_ID; import static com.redhat.cloud.notifications.connector.ExchangeProperty.TARGET_URL; +import static com.redhat.cloud.notifications.connector.http.SslTrustAllManager.getSslContextParameters; import static com.redhat.cloud.notifications.connector.servicenow.ExchangeProperty.ACCOUNT_ID; import static com.redhat.cloud.notifications.connector.servicenow.ExchangeProperty.TARGET_URL_NO_SCHEME; import static com.redhat.cloud.notifications.connector.servicenow.ExchangeProperty.TRUST_ALL; -import static com.redhat.cloud.notifications.connector.servicenow.ServiceNowTrustAllManager.getSslContextParameters; import static org.apache.camel.LoggingLevel.INFO; import static org.apache.camel.builder.endpoint.dsl.HttpEndpointBuilderFactory.HttpEndpointBuilder; @@ -22,12 +21,10 @@ public class ServiceNowRouteBuilder extends EngineToConnectorRouteBuilder { @Inject - ServiceNowConnectorConfig connectorConfig; + HttpConnectorConfig connectorConfig; @Override - public void configureRoute() { - - configureHttpsComponent(); + public void configureRoutes() { from(seda(ENGINE_TO_CONNECTOR)) .routeId(connectorConfig.getConnectorName()) @@ -46,12 +43,6 @@ public void configureRoute() { .to(direct(SUCCESS)); } - private void configureHttpsComponent() { - HttpComponent httpComponent = getCamelContext().getComponent("https", HttpComponent.class); - httpComponent.setConnectTimeout(Timeout.ofMilliseconds(connectorConfig.getHttpsConnectTimeout())); - httpComponent.setSoTimeout(Timeout.ofMilliseconds(connectorConfig.getHttpsSocketTimeout())); - } - private HttpEndpointBuilder buildServiceNowEndpoint(boolean trustAll) { HttpEndpointBuilder endpointBuilder = https("${exchangeProperty." + TARGET_URL_NO_SCHEME + "}").httpMethod("POST"); if (trustAll) { diff --git a/connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowTrustAllManager.java b/connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowTrustAllManager.java deleted file mode 100644 index eea9297ce0..0000000000 --- a/connector-servicenow/src/main/java/com/redhat/cloud/notifications/connector/servicenow/ServiceNowTrustAllManager.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.redhat.cloud.notifications.connector.servicenow; - -import org.apache.camel.support.jsse.SSLContextParameters; -import org.apache.camel.support.jsse.TrustManagersParameters; - -import javax.net.ssl.X509TrustManager; -import java.security.cert.X509Certificate; - -public class ServiceNowTrustAllManager implements X509TrustManager { - - public static SSLContextParameters getSslContextParameters() { - TrustManagersParameters trustManagersParameters = new TrustManagersParameters(); - trustManagersParameters.setTrustManager(new ServiceNowTrustAllManager()); - SSLContextParameters sslContextParameters = new SSLContextParameters(); - sslContextParameters.setTrustManagers(trustManagersParameters); - return sslContextParameters; - } - - public void checkClientTrusted(X509Certificate[] chain, String authType) { } - - public void checkServerTrusted(X509Certificate[] chain, String authType) { } - - public X509Certificate[] getAcceptedIssuers() { - return null; - } -} diff --git a/connector-servicenow/src/main/resources/application.properties b/connector-servicenow/src/main/resources/application.properties index 7a9b8481f4..6bac8ba190 100644 --- a/connector-servicenow/src/main/resources/application.properties +++ b/connector-servicenow/src/main/resources/application.properties @@ -1,3 +1,4 @@ +notifications.connector.http.components=https notifications.connector.kafka.incoming.group-id=notifications-connector-servicenow notifications.connector.kafka.incoming.topic=${mp.messaging.tocamel.topic} notifications.connector.kafka.outgoing.topic=${mp.messaging.fromcamel.topic} @@ -7,6 +8,7 @@ notifications.connector.redelivery.counter-name=camel.servicenow.retry.counter notifications.connector.seda.concurrent-consumers=20 # The following value matches the default value of the `connectionsPerRoute` option from the Camel `http` component. notifications.connector.seda.queue-size=20 +notifications.connector.supported-connector-headers=${notifications.connector.name} quarkus.http.port=9003 diff --git a/connector-slack/src/main/java/com/redhat/cloud/notifications/connector/slack/SlackRouteBuilder.java b/connector-slack/src/main/java/com/redhat/cloud/notifications/connector/slack/SlackRouteBuilder.java index 3042c97b78..eab6edf78c 100644 --- a/connector-slack/src/main/java/com/redhat/cloud/notifications/connector/slack/SlackRouteBuilder.java +++ b/connector-slack/src/main/java/com/redhat/cloud/notifications/connector/slack/SlackRouteBuilder.java @@ -19,7 +19,7 @@ public class SlackRouteBuilder extends EngineToConnectorRouteBuilder { ConnectorConfig connectorConfig; @Override - public void configureRoute() { + public void configureRoutes() { from(seda(ENGINE_TO_CONNECTOR)) .routeId(connectorConfig.getConnectorName()) .toD(slack("${exchangeProperty." + CHANNEL + "}").webhookUrl("${exchangeProperty." + TARGET_URL + "}"), connectorConfig.getEndpointCacheMaxSize()) diff --git a/connector-slack/src/main/resources/application.properties b/connector-slack/src/main/resources/application.properties index ab74543053..56ce626d18 100644 --- a/connector-slack/src/main/resources/application.properties +++ b/connector-slack/src/main/resources/application.properties @@ -7,6 +7,7 @@ notifications.connector.redelivery.counter-name=camel.slack.retry.counter notifications.connector.seda.concurrent-consumers=5 # The following value matches the default size of the OkHttp connection pool. notifications.connector.seda.queue-size=5 +notifications.connector.supported-connector-headers=${notifications.connector.name} quarkus.http.port=9004 diff --git a/connector-splunk/pom.xml b/connector-splunk/pom.xml index 40b89b47de..4567af88d8 100644 --- a/connector-splunk/pom.xml +++ b/connector-splunk/pom.xml @@ -56,16 +56,10 @@ com.redhat.cloud.notifications - notifications-connector-common + notifications-connector-common-http ${project.version} - - - org.apache.camel.quarkus - camel-quarkus-http - - commons-validator diff --git a/connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkConnectorConfig.java b/connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkConnectorConfig.java deleted file mode 100644 index a055099035..0000000000 --- a/connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkConnectorConfig.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.redhat.cloud.notifications.connector.splunk; - -import com.redhat.cloud.notifications.connector.ConnectorConfig; -import jakarta.enterprise.context.ApplicationScoped; -import org.eclipse.microprofile.config.inject.ConfigProperty; - -import java.util.Map; - -@ApplicationScoped -public class SplunkConnectorConfig extends ConnectorConfig { - - private static final String HTTPS_CONNECT_TIMEOUT_MS = "notifications.connector.https.connect-timeout-ms"; - private static final String HTTPS_SOCKET_TIMEOUT_MS = "notifications.connector.https.socket-timeout-ms"; - - @ConfigProperty(name = HTTPS_CONNECT_TIMEOUT_MS, defaultValue = "2500") - int httpsConnectTimeout; - - @ConfigProperty(name = HTTPS_SOCKET_TIMEOUT_MS, defaultValue = "2500") - int httpsSocketTimeout; - - @Override - public void log() { - Map additionalEntries = Map.of( - HTTPS_CONNECT_TIMEOUT_MS, httpsConnectTimeout, - HTTPS_SOCKET_TIMEOUT_MS, httpsSocketTimeout - ); - log(additionalEntries); - } - - public int getHttpsConnectTimeout() { - return httpsConnectTimeout; - } - - public int getHttpsSocketTimeout() { - return httpsSocketTimeout; - } -} diff --git a/connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkExceptionProcessor.java b/connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkExceptionProcessor.java deleted file mode 100644 index 0a9d1e68ac..0000000000 --- a/connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkExceptionProcessor.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.redhat.cloud.notifications.connector.splunk; - -import com.redhat.cloud.notifications.connector.ExceptionProcessor; -import io.quarkus.logging.Log; -import jakarta.enterprise.context.ApplicationScoped; -import org.apache.camel.Exchange; -import org.apache.camel.http.base.HttpOperationFailedException; - -import static com.redhat.cloud.notifications.connector.splunk.ExchangeProperty.ACCOUNT_ID; - -@ApplicationScoped -public class SplunkExceptionProcessor extends ExceptionProcessor { - - private static final String DEFAULT_LOG_MSG = "Message sending failed on %s: [orgId=%s, accountId=%s, historyId=%s, targetUrl=%s]"; - private static final String HTTP_LOG_MSG = "Message sending failed on %s: [orgId=%s, accountId=%s, historyId=%s, targetUrl=%s] " + - "with status code [%d] and body [%s]"; - - @Override - protected void process(Throwable t, Exchange exchange) { - if (t instanceof HttpOperationFailedException e) { - Log.errorf( - HTTP_LOG_MSG, - getRouteId(exchange), - getOrgId(exchange), - exchange.getProperty(ACCOUNT_ID, String.class), - getExchangeId(exchange), - getTargetUrl(exchange), - e.getStatusCode(), - e.getResponseBody() - ); - } else { - Log.errorf( - t, - DEFAULT_LOG_MSG, - getRouteId(exchange), - getOrgId(exchange), - exchange.getProperty(ACCOUNT_ID, String.class), - getExchangeId(exchange), - getTargetUrl(exchange) - ); - } - } -} diff --git a/connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkRouteBuilder.java b/connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkRouteBuilder.java index 377018557c..1713e07426 100644 --- a/connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkRouteBuilder.java +++ b/connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkRouteBuilder.java @@ -1,21 +1,20 @@ package com.redhat.cloud.notifications.connector.splunk; import com.redhat.cloud.notifications.connector.EngineToConnectorRouteBuilder; +import com.redhat.cloud.notifications.connector.http.HttpConnectorConfig; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import org.apache.camel.component.http.HttpComponent; -import org.apache.hc.core5.util.Timeout; import org.apache.http.conn.ssl.NoopHostnameVerifier; import static com.redhat.cloud.notifications.connector.ConnectorToEngineRouteBuilder.SUCCESS; import static com.redhat.cloud.notifications.connector.ExchangeProperty.ID; import static com.redhat.cloud.notifications.connector.ExchangeProperty.ORG_ID; import static com.redhat.cloud.notifications.connector.ExchangeProperty.TARGET_URL; +import static com.redhat.cloud.notifications.connector.http.SslTrustAllManager.getSslContextParameters; import static com.redhat.cloud.notifications.connector.splunk.ExchangeProperty.ACCOUNT_ID; import static com.redhat.cloud.notifications.connector.splunk.ExchangeProperty.AUTHENTICATION_TOKEN; import static com.redhat.cloud.notifications.connector.splunk.ExchangeProperty.TARGET_URL_NO_SCHEME; import static com.redhat.cloud.notifications.connector.splunk.ExchangeProperty.TRUST_ALL; -import static com.redhat.cloud.notifications.connector.splunk.SplunkTrustAllManager.getSslContextParameters; import static org.apache.camel.LoggingLevel.INFO; import static org.apache.camel.builder.endpoint.dsl.HttpEndpointBuilderFactory.HttpEndpointBuilder; @@ -23,15 +22,13 @@ public class SplunkRouteBuilder extends EngineToConnectorRouteBuilder { @Inject - SplunkConnectorConfig connectorConfig; + HttpConnectorConfig connectorConfig; @Inject EventsSplitter eventsSplitter; @Override - public void configureRoute() { - - configureHttpsComponent(); + public void configureRoutes() { from(seda(ENGINE_TO_CONNECTOR)) .routeId(connectorConfig.getConnectorName()) @@ -52,12 +49,6 @@ public void configureRoute() { .to(direct(SUCCESS)); } - private void configureHttpsComponent() { - HttpComponent httpComponent = getCamelContext().getComponent("https", HttpComponent.class); - httpComponent.setConnectTimeout(Timeout.ofMilliseconds(connectorConfig.getHttpsConnectTimeout())); - httpComponent.setSoTimeout(Timeout.ofMilliseconds(connectorConfig.getHttpsSocketTimeout())); - } - private HttpEndpointBuilder buildSplunkEndpoint(boolean trustAll) { HttpEndpointBuilder endpointBuilder = https("${exchangeProperty." + TARGET_URL_NO_SCHEME + "}").httpMethod("POST"); if (trustAll) { diff --git a/connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkTrustAllManager.java b/connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkTrustAllManager.java deleted file mode 100644 index 6f20954647..0000000000 --- a/connector-splunk/src/main/java/com/redhat/cloud/notifications/connector/splunk/SplunkTrustAllManager.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.redhat.cloud.notifications.connector.splunk; - -import org.apache.camel.support.jsse.SSLContextParameters; -import org.apache.camel.support.jsse.TrustManagersParameters; - -import javax.net.ssl.X509TrustManager; -import java.security.cert.X509Certificate; - -public class SplunkTrustAllManager implements X509TrustManager { - - public static SSLContextParameters getSslContextParameters() { - TrustManagersParameters trustManagersParameters = new TrustManagersParameters(); - trustManagersParameters.setTrustManager(new SplunkTrustAllManager()); - SSLContextParameters sslContextParameters = new SSLContextParameters(); - sslContextParameters.setTrustManagers(trustManagersParameters); - return sslContextParameters; - } - - public void checkClientTrusted(X509Certificate[] chain, String authType) { } - - public void checkServerTrusted(X509Certificate[] chain, String authType) { } - - public X509Certificate[] getAcceptedIssuers() { - return null; - } -} diff --git a/connector-splunk/src/main/resources/application.properties b/connector-splunk/src/main/resources/application.properties index a2151ce405..9c966dd45a 100644 --- a/connector-splunk/src/main/resources/application.properties +++ b/connector-splunk/src/main/resources/application.properties @@ -1,3 +1,4 @@ +notifications.connector.http.components=https notifications.connector.kafka.incoming.group-id=notifications-connector-splunk notifications.connector.kafka.incoming.topic=${mp.messaging.tocamel.topic} notifications.connector.kafka.outgoing.topic=${mp.messaging.fromcamel.topic} @@ -7,6 +8,7 @@ notifications.connector.redelivery.counter-name=camel.splunk.retry.counter notifications.connector.seda.concurrent-consumers=20 # The following value matches the default value of the `connectionsPerRoute` option from the Camel `http` component. notifications.connector.seda.queue-size=20 +notifications.connector.supported-connector-headers=${notifications.connector.name} quarkus.http.port=9005 diff --git a/connector-webhook/pom.xml b/connector-webhook/pom.xml index fbe989fbe0..e19f206ea6 100644 --- a/connector-webhook/pom.xml +++ b/connector-webhook/pom.xml @@ -56,7 +56,7 @@ com.redhat.cloud.notifications - notifications-connector-common + notifications-connector-common-http ${project.version} @@ -65,10 +65,6 @@ org.apache.camel.quarkus camel-quarkus-bean - - org.apache.camel.quarkus - camel-quarkus-http - diff --git a/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/CloudEventHistoryBuilder.java b/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/CloudEventHistoryBuilder.java index 9f4aae89a4..ffe4c86825 100644 --- a/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/CloudEventHistoryBuilder.java +++ b/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/CloudEventHistoryBuilder.java @@ -6,28 +6,32 @@ import org.apache.camel.Exchange; import org.apache.camel.Message; -import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.DISABLE_ENDPOINT_CLIENT_ERRORS; -import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.HTTP_STATUS_CODE; -import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.INCREMENT_ENDPOINT_SERVER_ERRORS; +import static com.redhat.cloud.notifications.connector.http.ExchangeProperty.HTTP_CLIENT_ERROR; +import static com.redhat.cloud.notifications.connector.http.ExchangeProperty.HTTP_SERVER_ERROR; +import static com.redhat.cloud.notifications.connector.http.ExchangeProperty.HTTP_STATUS_CODE; @ApplicationScoped public class CloudEventHistoryBuilder extends OutgoingCloudEventBuilder { + public static final String STATUS_CODE = "HttpStatusCode"; + public static final String DISABLE_ENDPOINT_CLIENT_ERRORS = "disableEndpointClientErrors"; + public static final String INCREMENT_ENDPOINT_SERVER_ERRORS = "incrementEndpointServerErrors"; + @Override public void process(Exchange exchange) throws Exception { super.process(exchange); - boolean clientError = exchange.getProperty(DISABLE_ENDPOINT_CLIENT_ERRORS, false, boolean.class); - boolean serverError = exchange.getProperty(INCREMENT_ENDPOINT_SERVER_ERRORS, false, boolean.class); + boolean clientError = exchange.getProperty(HTTP_CLIENT_ERROR, false, boolean.class); + boolean serverError = exchange.getProperty(HTTP_SERVER_ERROR, false, boolean.class); if (clientError || serverError) { Message in = exchange.getIn(); JsonObject cloudEvent = new JsonObject(in.getBody(String.class)); JsonObject data = new JsonObject(cloudEvent.getString("data")); - data.getJsonObject("details").put(HTTP_STATUS_CODE, exchange.getProperty(HTTP_STATUS_CODE)); + data.getJsonObject("details").put(STATUS_CODE, exchange.getProperty(HTTP_STATUS_CODE)); if (clientError) { - data.put(DISABLE_ENDPOINT_CLIENT_ERRORS, exchange.getProperty(DISABLE_ENDPOINT_CLIENT_ERRORS)); + data.put(DISABLE_ENDPOINT_CLIENT_ERRORS, exchange.getProperty(HTTP_CLIENT_ERROR)); } else { - data.put(INCREMENT_ENDPOINT_SERVER_ERRORS, exchange.getProperty(INCREMENT_ENDPOINT_SERVER_ERRORS)); + data.put(INCREMENT_ENDPOINT_SERVER_ERRORS, exchange.getProperty(HTTP_SERVER_ERROR)); } cloudEvent.put("data", data.encode()); in.setBody(cloudEvent.encode()); diff --git a/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/ExchangeProperty.java b/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/ExchangeProperty.java index 3f4f5061aa..ebef93630b 100644 --- a/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/ExchangeProperty.java +++ b/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/ExchangeProperty.java @@ -8,8 +8,4 @@ public final class ExchangeProperty { public static final String BASIC_AUTH_PASSWORD = "basic-auth-password"; public static final String BEARER_TOKEN = "Bearer"; public static final String INSIGHT_TOKEN_HEADER = "X-Insight-Token"; - public static final String INCREMENT_ENDPOINT_SERVER_ERRORS = "incrementEndpointServerErrors"; - public static final String DISABLE_ENDPOINT_CLIENT_ERRORS = "disableEndpointClientErrors"; - public static final String HTTP_STATUS_CODE = "HttpStatusCode"; - } diff --git a/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookConnectorConfig.java b/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookConnectorConfig.java deleted file mode 100644 index 916900da14..0000000000 --- a/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookConnectorConfig.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.redhat.cloud.notifications.connector.webhook; - -import com.redhat.cloud.notifications.connector.ConnectorConfig; -import jakarta.enterprise.context.ApplicationScoped; -import org.eclipse.microprofile.config.inject.ConfigProperty; - -import java.util.List; -import java.util.Map; - -@ApplicationScoped -public class WebhookConnectorConfig extends ConnectorConfig { - - private static final String HTTP_CONNECT_TIMEOUT_MS = "notifications.connector.http.connect-timeout-ms"; - private static final String HTTP_CONNECTIONS_PER_ROUTE = "notifications.connector.http.connections-per-route"; - private static final String HTTP_MAX_TOTAL_CONNECTIONS = "notifications.connector.http.max-total-connections"; - private static final String HTTP_SOCKET_TIMEOUT_MS = "notifications.connector.http.socket-timeout-ms"; - private static final String ALTERNATIVE_NAMES = "notifications.connector.alternative.names"; - - @ConfigProperty(name = HTTP_CONNECT_TIMEOUT_MS, defaultValue = "2500") - int httpConnectTimeout; - - @ConfigProperty(name = HTTP_CONNECTIONS_PER_ROUTE, defaultValue = "20") - int httpConnectionsPerRoute; - - @ConfigProperty(name = HTTP_MAX_TOTAL_CONNECTIONS, defaultValue = "200") - int httpMaxTotalConnections; - - @ConfigProperty(name = HTTP_SOCKET_TIMEOUT_MS, defaultValue = "2500") - int httpSocketTimeout; - - @ConfigProperty(name = ALTERNATIVE_NAMES, defaultValue = "ansible") - List alternativeNames; - - @Override - public void log() { - Map additionalEntries = Map.of( - HTTP_CONNECT_TIMEOUT_MS, httpConnectTimeout, - HTTP_CONNECTIONS_PER_ROUTE, httpConnectionsPerRoute, - HTTP_MAX_TOTAL_CONNECTIONS, httpMaxTotalConnections, - HTTP_SOCKET_TIMEOUT_MS, httpSocketTimeout, - ALTERNATIVE_NAMES, alternativeNames - ); - log(additionalEntries); - } - - public int getHttpConnectTimeout() { - return httpConnectTimeout; - } - - public int getHttpConnectionsPerRoute() { - return httpConnectionsPerRoute; - } - - public int getHttpMaxTotalConnections() { - return httpMaxTotalConnections; - } - - public int getHttpSocketTimeout() { - return httpSocketTimeout; - } - - public List getAlternativeNames() { - return alternativeNames; - } -} diff --git a/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookExceptionProcessor.java b/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookExceptionProcessor.java deleted file mode 100644 index c4950052ee..0000000000 --- a/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookExceptionProcessor.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.redhat.cloud.notifications.connector.webhook; - -import com.redhat.cloud.notifications.connector.ExceptionProcessor; -import io.quarkus.logging.Log; -import jakarta.enterprise.context.ApplicationScoped; -import org.apache.camel.Exchange; -import org.apache.camel.http.base.HttpOperationFailedException; -import org.jboss.logging.Logger; -import java.io.IOException; -import java.time.temporal.ValueRange; - -import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.DISABLE_ENDPOINT_CLIENT_ERRORS; -import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.HTTP_STATUS_CODE; -import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.INCREMENT_ENDPOINT_SERVER_ERRORS; -import static org.jboss.logging.Logger.Level.DEBUG; - -@ApplicationScoped -public class WebhookExceptionProcessor extends ExceptionProcessor { - - private static final String HTTP_LOG_MSG = "Message sending failed on %s: [orgId=%s, historyId=%s, webhookUrl=%s] " + - "with status code [%d] and body [%s]"; - - final ValueRange http400ErrorRange = ValueRange.of(400, 499); - - @Override - protected void process(Throwable t, Exchange exchange) { - if (t instanceof HttpOperationFailedException e) { - log(DEBUG, e, exchange); - exchange.setProperty(HTTP_STATUS_CODE, e.getStatusCode()); - if (http400ErrorRange.isValidValue(e.getStatusCode())) { - exchange.setProperty(DISABLE_ENDPOINT_CLIENT_ERRORS, true); - } else { - exchange.setProperty(INCREMENT_ENDPOINT_SERVER_ERRORS, true); - } - } else if (t instanceof IOException) { - logDefault(t, exchange); - exchange.setProperty(INCREMENT_ENDPOINT_SERVER_ERRORS, true); - } else { - logDefault(t, exchange); - } - } - - private void log(Logger.Level level, HttpOperationFailedException e, Exchange exchange) { - Log.logf( - level, - HTTP_LOG_MSG, - getRouteId(exchange), - getOrgId(exchange), - getExchangeId(exchange), - getTargetUrl(exchange), - e.getStatusCode(), - e.getResponseBody() - ); - } -} diff --git a/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookIncomingCloudEventFilter.java b/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookIncomingCloudEventFilter.java deleted file mode 100644 index 0f291e4f31..0000000000 --- a/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookIncomingCloudEventFilter.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.redhat.cloud.notifications.connector.webhook; - -import com.redhat.cloud.notifications.connector.IncomingCloudEventFilter; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import org.apache.camel.Exchange; - -@ApplicationScoped -public class WebhookIncomingCloudEventFilter extends IncomingCloudEventFilter { - @Inject - WebhookConnectorConfig connectorConfig; - - @Override - public boolean matches(Exchange exchange) { - String connectorHeader = exchange.getIn().getHeader(X_RH_NOTIFICATIONS_CONNECTOR_HEADER, String.class); - return connectorConfig.getConnectorName().equals(connectorHeader) || connectorConfig.getAlternativeNames().contains(connectorHeader); - } -} diff --git a/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookRouteBuilder.java b/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookRouteBuilder.java index 01457bb12a..54c150a196 100644 --- a/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookRouteBuilder.java +++ b/connector-webhook/src/main/java/com/redhat/cloud/notifications/connector/webhook/WebhookRouteBuilder.java @@ -1,15 +1,14 @@ package com.redhat.cloud.notifications.connector.webhook; import com.redhat.cloud.notifications.connector.EngineToConnectorRouteBuilder; +import com.redhat.cloud.notifications.connector.http.HttpConnectorConfig; import com.redhat.cloud.notifications.connector.webhook.authentication.BasicAuthenticationProcessor; import com.redhat.cloud.notifications.connector.webhook.authentication.BearerTokenAuthenticationProcessor; import com.redhat.cloud.notifications.connector.webhook.authentication.InsightsTokenAuthenticationProcessor; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import org.apache.camel.builder.endpoint.dsl.HttpEndpointBuilderFactory; -import org.apache.camel.component.http.HttpComponent; import org.apache.camel.component.micrometer.routepolicy.MicrometerRoutePolicyFactory; -import org.apache.hc.core5.util.Timeout; import org.apache.http.conn.ssl.NoopHostnameVerifier; import static com.redhat.cloud.notifications.connector.ConnectorToEngineRouteBuilder.SUCCESS; @@ -17,12 +16,12 @@ import static com.redhat.cloud.notifications.connector.ExchangeProperty.ORG_ID; import static com.redhat.cloud.notifications.connector.ExchangeProperty.TARGET_URL; import static com.redhat.cloud.notifications.connector.ExchangeProperty.TYPE; +import static com.redhat.cloud.notifications.connector.http.SslTrustAllManager.getSslContextParameters; import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.BASIC_AUTH_USERNAME; import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.BEARER_TOKEN; import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.INSIGHT_TOKEN_HEADER; import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.TARGET_URL_NO_SCHEME; import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.TRUST_ALL; -import static com.redhat.cloud.notifications.connector.webhook.SslTrustAllManager.getSslContextParameters; import static org.apache.camel.Exchange.CONTENT_TYPE; import static org.apache.camel.LoggingLevel.INFO; @@ -37,18 +36,15 @@ public class WebhookRouteBuilder extends EngineToConnectorRouteBuilder { static final String TIMER_ACTION_STOP = "?action=stop"; @Inject - WebhookConnectorConfig webhookConnectorConfig; + HttpConnectorConfig connectorConfig; @Override - public void configureRoute() { + public void configureRoutes() { getContext().addRoutePolicyFactory(new MicrometerRoutePolicyFactory()); - configureHttpComponent("http"); - configureHttpComponent("https"); - from(seda(ENGINE_TO_CONNECTOR)) .setHeader(CONTENT_TYPE, constant(APPLICATION_JSON)) - .routeId(webhookConnectorConfig.getConnectorName()) + .routeId(connectorConfig.getConnectorName()) .choice() .when(exchangeProperty(INSIGHT_TOKEN_HEADER)) .process(new InsightsTokenAuthenticationProcessor()) @@ -63,11 +59,11 @@ public void configureRoute() { // SSL certificates may or may not be verified depending on the integration settings. .choice() .when(exchangeProperty(TRUST_ALL)) - .toD(buildUnsecureSslEndpoint(), webhookConnectorConfig.getEndpointCacheMaxSize()) + .toD(buildUnsecureSslEndpoint(), connectorConfig.getEndpointCacheMaxSize()) .endChoice() .otherwise() .to(ENDPOINT_RESPONSE_TIME_METRIC + TIMER_ACTION_START) - .toD("${exchangeProperty." + TARGET_URL + "}", webhookConnectorConfig.getEndpointCacheMaxSize()) + .toD("${exchangeProperty." + TARGET_URL + "}", connectorConfig.getEndpointCacheMaxSize()) .to(ENDPOINT_RESPONSE_TIME_METRIC + TIMER_ACTION_STOP) .end() .log(INFO, getClass().getName(), "Sent ${exchangeProperty." + TYPE + ".replace('" + CLOUD_EVENT_TYPE_PREFIX + "', '')} notification " + @@ -75,15 +71,6 @@ public void configureRoute() { .to(direct(SUCCESS)); } - private void configureHttpComponent(String componentName) { - HttpComponent component = getContext().getComponent(componentName, HttpComponent.class); - component.setConnectTimeout(Timeout.ofMilliseconds(webhookConnectorConfig.getHttpConnectTimeout())); - component.setSoTimeout(Timeout.ofMilliseconds(webhookConnectorConfig.getHttpSocketTimeout())); - component.setConnectionsPerRoute(webhookConnectorConfig.getHttpConnectionsPerRoute()); - component.setMaxTotalConnections(webhookConnectorConfig.getHttpMaxTotalConnections()); - component.setFollowRedirects(true); - } - private HttpEndpointBuilderFactory.HttpEndpointBuilder buildUnsecureSslEndpoint() { return https("${exchangeProperty." + TARGET_URL_NO_SCHEME + "}") .sslContextParameters(getSslContextParameters()) diff --git a/connector-webhook/src/main/resources/application.properties b/connector-webhook/src/main/resources/application.properties index ae097db1ab..477875f1ec 100644 --- a/connector-webhook/src/main/resources/application.properties +++ b/connector-webhook/src/main/resources/application.properties @@ -1,13 +1,14 @@ +notifications.connector.http.follow-redirects=true notifications.connector.kafka.incoming.group-id=notifications-connector-webhook notifications.connector.kafka.incoming.topic=${mp.messaging.tocamel.topic} notifications.connector.kafka.outgoing.topic=${mp.messaging.fromcamel.topic} notifications.connector.name=webhook notifications.connector.redelivery.counter-name=camel.webhook.retry.counter -notifications.connector.alternative.names=ansible # The following value matches the default value of the `connectionsPerRoute` option from the Camel `http` component. notifications.connector.seda.concurrent-consumers=20 # The following value matches the default value of the `connectionsPerRoute` option from the Camel `http` component. notifications.connector.seda.queue-size=20 +notifications.connector.supported-connector-headers=ansible,webhook quarkus.http.port=9006 diff --git a/connector-webhook/src/test/java/com/redhat/cloud/notifications/connector/webhook/WebhookConnectorRoutesTest.java b/connector-webhook/src/test/java/com/redhat/cloud/notifications/connector/webhook/WebhookConnectorRoutesTest.java index 5faa20ad10..fd535b7116 100644 --- a/connector-webhook/src/test/java/com/redhat/cloud/notifications/connector/webhook/WebhookConnectorRoutesTest.java +++ b/connector-webhook/src/test/java/com/redhat/cloud/notifications/connector/webhook/WebhookConnectorRoutesTest.java @@ -17,9 +17,9 @@ import static com.redhat.cloud.notifications.connector.ConnectorToEngineRouteBuilder.CONNECTOR_TO_ENGINE; import static com.redhat.cloud.notifications.connector.ConnectorToEngineRouteBuilder.SUCCESS; import static com.redhat.cloud.notifications.connector.EngineToConnectorRouteBuilder.ENGINE_TO_CONNECTOR; -import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.DISABLE_ENDPOINT_CLIENT_ERRORS; -import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.HTTP_STATUS_CODE; -import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.INCREMENT_ENDPOINT_SERVER_ERRORS; +import static com.redhat.cloud.notifications.connector.webhook.CloudEventHistoryBuilder.DISABLE_ENDPOINT_CLIENT_ERRORS; +import static com.redhat.cloud.notifications.connector.webhook.CloudEventHistoryBuilder.INCREMENT_ENDPOINT_SERVER_ERRORS; +import static com.redhat.cloud.notifications.connector.webhook.CloudEventHistoryBuilder.STATUS_CODE; import static com.redhat.cloud.notifications.connector.webhook.ExchangeProperty.INSIGHT_TOKEN_HEADER; import static com.redhat.cloud.notifications.connector.webhook.WebhookCloudEventDataExtractor.BASIC_AUTHENTICATION; import static com.redhat.cloud.notifications.connector.webhook.WebhookCloudEventDataExtractor.ENDPOINT_PROPERTIES; @@ -130,7 +130,7 @@ private void testFailedNotificationAndReturnedFlagsToEngine(int httpReturnCode, JsonObject data = new JsonObject(returnToEngine.getString("data")); assertTrue(data.getBoolean(flagNameThatShouldBeTrue)); JsonObject details = data.getJsonObject("details"); - assertEquals(httpReturnCode, details.getInteger(HTTP_STATUS_CODE)); + assertEquals(httpReturnCode, details.getInteger(STATUS_CODE)); } @Test diff --git a/pom.xml b/pom.xml index a6ab666335..83311ea3e3 100644 --- a/pom.xml +++ b/pom.xml @@ -16,6 +16,7 @@ common common-aggregator connector-common + connector-common-http connector-drawer connector-email connector-google-chat