diff --git a/examples/kafka-hub/_resources/consolidator.config.toml b/examples/kafka-hub/_resources/consolidator.config.toml new file mode 100644 index 00000000..dcbccb86 --- /dev/null +++ b/examples/kafka-hub/_resources/consolidator.config.toml @@ -0,0 +1,25 @@ +[consolidatorService.config] +# IP and Port of the Kafka bootstrap node +KAFKA_BOOTSTRAP_NODE = "localhost:9094" + +# Kafka topic which stores websub-events for this server +WEBSUB_EVENTS_TOPIC = "websub-events" + +# Kafka topic which stores the current snapshot for the websub-events +WEBSUB_EVENTS_SNAPSHOT_TOPIC = "websub-events-snapshot" + +# The interval in which Kafka consumers wait for new messages +POLLING_INTERVAL = 10.0 + +# The period in which Kafka close method waits to complete +GRACEFUL_CLOSE_PERIOD = 5.0 + +# The port that is used to start the HTTP endpoint for consolidator +CONSOLIDATOR_HTTP_ENDPOINT_PORT = 10001 + +# The MTLS configurations related to Kafka connection +[consolidatorService.config.KAFKA_MTLS_CONFIG] +cert.path = "./resources/brokercerts/client-truststore.jks" +cert.password = "password" +key.keyStore.path = "./resources/brokercerts/client-keystore.jks" +key.keyStore.password = "password" diff --git a/examples/kafka-hub/_resources/hub.config.toml b/examples/kafka-hub/_resources/hub.config.toml new file mode 100644 index 00000000..e0642102 --- /dev/null +++ b/examples/kafka-hub/_resources/hub.config.toml @@ -0,0 +1,64 @@ +[kafkaHub.config] +# Flag to check whether to enable/disable security +SECURITY_ON = true + +# Server ID is is used to uniquely identify each server +# Each server must have a unique ID +SERVER_ID = "hub-1" + +# IP and Port of the Kafka bootstrap node +KAFKA_BOOTSTRAP_NODE = "localhost:9094" + +# Maximum number of records returned in a single call to consumer-poll +KAFKA_CONSUMER_MAX_POLL_RECORDS = 50 + +# Kafka topic which is stores websub-events for this server +WEBSUB_EVENTS_TOPIC = "websub-events" + +# Consolidator HTTP endpoint to be used to retrieve current state-snapshot +STATE_SNAPSHOT_ENDPOINT = "http://localhost:10001" + +# The interval in which Kafka consumers wait for new messages +POLLING_INTERVAL = 10.0 + +# The period in which Kafka close method waits to complete +GRACEFUL_CLOSE_PERIOD = 5.0 + +# The port that is used to start the hub +HUB_PORT = 9000 + +# SSL keystore file path +SSL_KEYSTORE_PATH = "./resources/hub.keystore.jks" + +# SSL keystore password +KEYSTORE_PASSWORD = "password" + +# The period between retry requests +MESSAGE_DELIVERY_RETRY_INTERVAL = 3.0 + +# The maximum retry count +MESSAGE_DELIVERY_COUNT = 3 + +# The message delivery timeout +MESSAGE_DELIVERY_TIMEOUT = 10.0 + +# The HTTP status codes for which the client should retry +MESSAGE_DELIVERY_RETRYABLE_STATUS_CODES = [500, 502, 503] + +# The Oauth2 authorization related configurations +[kafkaHub.config.OAUTH2_CONFIG] +issuer = "https://localhost:9443/oauth2/token" +audience = "ballerina" +jwksUrl = "https://localhost:9443/oauth2/jwks" +trustStore = "./resources/client-truststore.jks" +trustStorePassword = "wso2carbon" + +# The MTLS configurations related to Kafka connection +[kafkaHub.config.KAFKA_MTLS_CONFIG] +cert.path = "./resources/brokercerts/client-truststore.jks" +cert.password = "password" +key.keyStore.path = "./resources/brokercerts/client-keystore.jks" +key.keyStore.password = "password" + +[ballerina.log] +level = "DEBUG" diff --git a/examples/kafka-hub/consolidator/Cloud.toml b/examples/kafka-hub/consolidator/Cloud.toml index 6f0e1abf..aa31bcd4 100644 --- a/examples/kafka-hub/consolidator/Cloud.toml +++ b/examples/kafka-hub/consolidator/Cloud.toml @@ -1,7 +1,7 @@ [container.image] repository="ballerina" name="consolidator" -tag="7.0.0" +tag="8.0.0" [[container.copy.files]] sourceFile="./resources" diff --git a/examples/kafka-hub/consolidator/Dockerfile b/examples/kafka-hub/consolidator/Dockerfile index 940db40c..1c78bab2 100644 --- a/examples/kafka-hub/consolidator/Dockerfile +++ b/examples/kafka-hub/consolidator/Dockerfile @@ -24,7 +24,7 @@ LABEL maintainer="WSO2 Docker Maintainers " # set Docker image build arguments # build arguments for user/group configurations -ARG USER=consolidator +ARG USER=ballerina ARG USER_ID=10001 ARG USER_GROUP=wso2 ARG USER_GROUP_ID=10001 diff --git a/examples/kafka-hub/docker-compose.yaml b/examples/kafka-hub/docker-compose.yaml index 238df995..19b23318 100644 --- a/examples/kafka-hub/docker-compose.yaml +++ b/examples/kafka-hub/docker-compose.yaml @@ -3,7 +3,7 @@ name: 'kafkahub' services: hub-1: - image: 'ayeshalmeida/kafkahub:12.0.0' + image: 'ayeshalmeida/kafkahub:13.0.0' hostname: hub1 container_name: hub-1 ports: @@ -41,6 +41,8 @@ services: # The HTTP status codes for which the client should retry RETRYABLE_STATUS_CODES: "500,502,503" volumes: + # `Config.toml` file for the websubhub-service + - ./_resources/hub.config.toml:/home/ballerina/Config.toml # Kafka client truststore file - ./_resources/secrets/kafka-client/kafka-client.trustStore.jks:/home/ballerina/resources/brokercerts/client-truststore.jks # Kafka client keystore file @@ -50,7 +52,7 @@ services: # SSL configurations - ./_resources/secrets/hub/hub-1.keystore.jks:/home/ballerina/resources/hub.keystore.jks healthcheck: - test: ["CMD-SHELL", "wget --no-verbose --no-check-certificate --tries=1 --spider 'https://hub1:9000/health' || exit 1"] + test: ["CMD-SHELL", "curl -k --fail https://hub1:9000/health || exit 1"] interval: 30s timeout: 10s start_period: 30s @@ -59,7 +61,7 @@ services: - hub_network consolidator: - image: 'ayeshalmeida/consolidator:7.0.0' + image: 'ayeshalmeida/consolidator:8.0.0' hostname: consolidator container_name: consolidator ports: @@ -83,12 +85,14 @@ services: broker: condition: service_healthy volumes: + # `Config.toml` file for the consolidator-service + - ./_resources/consolidator.config.toml:/home/ballerina/Config.toml # Kafka client truststore file - ./_resources/secrets/kafka-client/kafka-client.trustStore.jks:/home/ballerina/resources/brokercerts/client-truststore.jks # Kafka client keystore file - ./_resources/secrets/kafka-client/kafka-client.keystore.jks:/home/ballerina/resources/brokercerts/client-keystore.jks healthcheck: - test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider 'http://consolidator:10001/health/readiness' || exit 1"] + test: ["CMD-SHELL", "curl --fail http://consolidator:10001/health/readiness || exit 1"] interval: 30s timeout: 10s start_period: 30s diff --git a/examples/kafka-hub/helm/README.md b/examples/kafka-hub/helm/README.md new file mode 100644 index 00000000..129a3167 --- /dev/null +++ b/examples/kafka-hub/helm/README.md @@ -0,0 +1,150 @@ +# Kafka Websubhub Helm charts + +Ballerina Kafka Websubhub is a WebSub compliant `hub` implementation backed by Apache Kafka message broker. + +[Overview of Kafka Websubhub](https://github.com/ballerina-platform/module-ballerina-websubhub/blob/kafkahub-mtls/examples/kafka-hub/A%20Guide%20on%20implementing%20Websub%20Hub%20backed%20by%20Kafka%20Message%20Broker.md) + +## Introduction + +These charts bootstrap a [Kafka Websubhub](https://github.com/ballerina-platform/module-ballerina-websubhub/blob/kafkahub-mtls/examples/kafka-hub) deployment +on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +The **Kafka Websubhub** setup contains two separate components: +- **`hub`** : A WebSub compliant `hub` implementation +- **`consolidator`** : A backend service which manages the overall deployment state + +## Prerequisites + +- Kubernetes 1.32+ +- Helm 3.17.0+ + +## Deployment + +### 1. Deploying the `hub` + +Helm charts related to the `hub` component can be found in the `hub` directory. + +To install the charts with the release name `ballerina-websubhub`, go into the `hub` directory and run the following command: + +```sh + $ cd hub + $ helm install ballerina-websubhub . +``` + +To uninstall/delete the `ballerina-websubhub` statefulset, run the following command: + +```sh + $ helm delete ballerina-websubhub +``` + +#### Configurations + +The Kafka Websubhub container image related configurations can be found under `deployment.image` in the `hub/values.yaml`. + +| Configuration | Description | +|-------------- |-------------------------------------| +| `repository` | Image repository. | +| `pullPolicy` | Image pull policy for the deployment| +| `tag` | Image tag | + + +All the package related configurations can be found under `deployment.config` in the `hub/values.yaml`. + +Following are a list of configurations and their usage. + +| Configuration | Description | +|-----------------------------|---------------------------------------------------------------------------------| +| `port` | The port that is used to start the hub | +| `server_id` | Server ID is used to uniquely identify each server | +| `state_snapshot_endpoint` | Consolidator HTTP endpoint to retrieve the current state snapshot | +| `retryable_status_codes` | The HTTP status codes for which the client should retry during message delivery | +| `logLevel` | The package log level | +| `ssl.keystore_name` | The name of the Java keystore file used to enable HTTPS on `hub` | +| `ssl.keystore_password` | The password for the Java keystore file | +| `idp.jwt_issuer` | The `issuer` claim for OAuth2 (JWT) token | +| `idp.jwt_audience` | The `audience` claim for OAuth2 (JWT) token | +| `idp.jwt_jwks_endpoint` | The JWKS endpoint URL to verify the JWT signature | +| `idp.truststore_name` | The client truststore file name used for JWKS connection | +| `idp.truststore_password` | The client truststore password | +| `kafka.bootstrap_node` | IP and port of the Kafka bootstrap node | +| `kafka.max_poll_records` | Maximum number of records returned in a single call to consumer-poll | +| `kafka.truststore_name` | The client truststore file name used for mTLS connection from `hub` to `broker` | +| `kafka.truststore_password` | The client truststore password | +| `kafka.keystore_name` | The client keystore file name used for mTLS connection from `hub` to `broker` | +| `kafka.keystore_password` | The client keystore password | + +#### Volume mounts + +Apart from the above configurations, several volume mounts are required for the deployment. All volume mounts are Kubernetes secrets, and they are listed under `deployment.secrets` in `hub/values.yaml`. + +Each secret follows the structure below: + +- **`name`**: Name of the secret +- **`mountPath`**: The path on the pod where the secrets should be mounted +- **`content`**: A list of secrets to be mounted to the pod. Each item in the list contains: + - **`filePath`**: The path to the original file + - **`fileKey`**: The key for the secret value in `hub/secret.yaml` + +The deployment requires three sets of volume mounts, each serving a specific purpose: + +- **`ballerina-websubhub-ssl`**: Enables HTTPS for the WebSubHub HTTP endpoint +- **`ballerina-websubhub-idp`**: Supports secure HTTPS communication between WebSubHub and the IdP JWKS endpoint +- **`ballerina-websubhub-broker`**: Establishes an mTLS connection between WebSubHub and the Kafka broker + +### 2. Deploying the `consolidator` + +Helm charts related to the `consolidator` component can be found in the `consolidator` directory. + +To install the charts with the release name `ballerina-consolidator`, go into the `consolidator` directory and run the following command: + +```sh + $ cd consolidator + $ helm install ballerina-consolidator . +``` + +To uninstall/delete the `ballerina-consolidator` deployment, run the following command: + +```sh + $ helm delete ballerina-consolidator +``` + +#### Configurations + +The consolidator container image related configurations can be found under `deployment.image` in the `consolidator/values.yaml`. + +| Configuration | Description | +|-------------- |-------------------------------------| +| `repository` | Image repository. | +| `pullPolicy` | Image pull policy for the deployment| +| `tag` | Image tag | + +All the package related configurations can be found under `deployment.config` in the `consolidator/values.yaml`. + +Following are a list of configurations and their usage. + +| Configuration | Description | +|-----------------------------|-----------------------------------------------------------------------------------------| +| `port` | The port that is used to start the consolidator state snapshot endpoint | +| `kafka.bootstrap_node` | IP and port of the Kafka bootstrap node | +| `kafka.max_poll_records` | Maximum number of records returned in a single call to consumer-poll | +| `kafka.truststore_name` | The client truststore file name used for mTLS connection from `consolidator` to `broker`| +| `kafka.truststore_password` | The client truststore password | +| `kafka.keystore_name` | The client keystore file name used for mTLS connection from `consolidator` to `broker` | +| `kafka.keystore_password` | The client keystore password | + + +#### Volume mounts + +Apart from the above configurations, several volume mounts are required for the deployment. All volume mounts are Kubernetes secrets, and they are listed under `deployment.secrets` in `consolidator/values.yaml`. + +Each secret follows the structure below: + +- **`name`**: Name of the secret +- **`mountPath`**: The path on the pod where the secrets should be mounted +- **`content`**: A list of secrets to be mounted to the pod. Each item in the list contains: + - **`filePath`**: The path to the original file + - **`fileKey`**: The key for the secret value in `hub/secret.yaml` + +The deployment requires three sets of volume mounts, each serving a specific purpose: + +- **`ballerina-consolidator-broker`**: Establishes an mTLS connection between consolidator and the Kafka broker diff --git a/examples/kafka-hub/helm/consolidator/Chart.yaml b/examples/kafka-hub/helm/consolidator/Chart.yaml new file mode 100644 index 00000000..1f3fc69c --- /dev/null +++ b/examples/kafka-hub/helm/consolidator/Chart.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2025 WSO2 LLC. (http://www.wso2.com). +# +# WSO2 LLC. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +apiVersion: v2 +appVersion: 7.0.0 +description: A Helm chart for the deployment of WSO2 Websubhub Consolidator Deployment +name: consolidator +version: 0.1.0 diff --git a/examples/kafka-hub/helm/consolidator/_resources/kafka-client/kafka-client.keystore.jks b/examples/kafka-hub/helm/consolidator/_resources/kafka-client/kafka-client.keystore.jks new file mode 100644 index 00000000..6c02a44d Binary files /dev/null and b/examples/kafka-hub/helm/consolidator/_resources/kafka-client/kafka-client.keystore.jks differ diff --git a/examples/kafka-hub/helm/consolidator/_resources/kafka-client/kafka-client.trustStore.jks b/examples/kafka-hub/helm/consolidator/_resources/kafka-client/kafka-client.trustStore.jks new file mode 100644 index 00000000..9c71e77f Binary files /dev/null and b/examples/kafka-hub/helm/consolidator/_resources/kafka-client/kafka-client.trustStore.jks differ diff --git a/examples/kafka-hub/helm/consolidator/confs/Config.toml b/examples/kafka-hub/helm/consolidator/confs/Config.toml new file mode 100644 index 00000000..1118b3c8 --- /dev/null +++ b/examples/kafka-hub/helm/consolidator/confs/Config.toml @@ -0,0 +1,41 @@ +# Copyright (c) 2025 WSO2 LLC. (http://www.wso2.com). +# +# WSO2 LLC. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +[consolidatorService.config] +# IP and Port of the Kafka bootstrap node +KAFKA_BOOTSTRAP_NODE = {{ .Values.deployment.config.kafka.bootstrap_node | quote }} + +# Kafka topic which stores websub-events for this server +WEBSUB_EVENTS_TOPIC = {{ .Values.deployment.config.kafka.websub_events_topic | quote }} + +# Kafka topic which stores the current snapshot for the websub-events +WEBSUB_EVENTS_SNAPSHOT_TOPIC = {{ .Values.deployment.config.kafka.websub_events_snapshot_topic | quote }} + +# The interval in which Kafka consumers wait for new messages +POLLING_INTERVAL = 10.0 + +# The period in which Kafka close method waits to complete +GRACEFUL_CLOSE_PERIOD = 5.0 + +# The port that is used to start the HTTP endpoint for consolidator +CONSOLIDATOR_HTTP_ENDPOINT_PORT = {{ .Values.deployment.config.port }} + +# The MTLS configurations related to Kafka connection +[consolidatorService.config.KAFKA_MTLS_CONFIG] +cert.path = "/home/ballerina/resources/brokercerts/{{ .Values.deployment.config.kafka.truststore_name }}" +cert.password = {{ .Values.deployment.config.kafka.truststore_password | quote }} +key.keyStore.path = "/home/ballerina/resources/brokercerts/{{ .Values.deployment.config.kafka.keystore_name }}" +key.keyStore.password = {{ .Values.deployment.config.kafka.keystore_password | quote }} diff --git a/examples/kafka-hub/helm/consolidator/templates/conf.yaml b/examples/kafka-hub/helm/consolidator/templates/conf.yaml new file mode 100644 index 00000000..e6de4afc --- /dev/null +++ b/examples/kafka-hub/helm/consolidator/templates/conf.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2025 WSO2 LLC. (http://www.wso2.com). +# +# WSO2 LLC. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +apiVersion: v1 +kind: ConfigMap +metadata: + name: consolidator-svc-cm + namespace : {{ .Release.Namespace }} +data: + Config.toml: {{ tpl (.Files.Get "confs/Config.toml") . | quote }} diff --git a/examples/kafka-hub/helm/consolidator/templates/deployment.yaml b/examples/kafka-hub/helm/consolidator/templates/deployment.yaml new file mode 100644 index 00000000..83287225 --- /dev/null +++ b/examples/kafka-hub/helm/consolidator/templates/deployment.yaml @@ -0,0 +1,60 @@ +# Copyright (c) 2025 WSO2 LLC. (http://www.wso2.com). +# +# WSO2 LLC. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-deployment + labels: + app: {{ .Release.Name }} +spec: + replicas: {{ .Values.deployment.replicas }} + selector: + matchLabels: + app: {{ .Release.Name }} + template: + metadata: + labels: + app: {{ .Release.Name }} + spec: + containers: + - name: {{ .Release.Name }} + image: {{ .Values.deployment.image.repository }}:{{ .Values.deployment.image.tag }} + imagePullPolicy: {{ .Values.deployment.image.pullPolicy }} + ports: + - containerPort: {{ .Values.deployment.config.port }} + env: + - name: "BAL_CONFIG_FILES" + value: "/home/ballerina/conf/Config.toml" + volumeMounts: + - name: "config-config-map-volume" + mountPath: "/home/ballerina/conf" + readOnly: true + {{- range .Values.deployment.secrets }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: true + {{- end }} + + volumes: + - name: "config-config-map-volume" + configMap: + name: "consolidator-svc-cm" + {{- range .Values.deployment.secrets }} + - name: {{ .name }} + secret: + secretName: {{ .name }} + {{- end }} diff --git a/examples/kafka-hub/helm/consolidator/templates/secret.yaml b/examples/kafka-hub/helm/consolidator/templates/secret.yaml new file mode 100644 index 00000000..6c0f1266 --- /dev/null +++ b/examples/kafka-hub/helm/consolidator/templates/secret.yaml @@ -0,0 +1,28 @@ +# Copyright (c) 2025 WSO2 LLC. (http://www.wso2.com). +# +# WSO2 LLC. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +{{- range .Values.deployment.secrets }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name }} +type: Opaque +data: + {{- range .content }} + {{ .fileKey }}: {{ $.Files.Get .filePath | b64enc }} + {{- end }} +--- +{{- end }} diff --git a/examples/kafka-hub/helm/consolidator/templates/service.yaml b/examples/kafka-hub/helm/consolidator/templates/service.yaml new file mode 100644 index 00000000..1cd7e88f --- /dev/null +++ b/examples/kafka-hub/helm/consolidator/templates/service.yaml @@ -0,0 +1,28 @@ +# Copyright (c) 2025 WSO2 LLC. (http://www.wso2.com). +# +# WSO2 LLC. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-service +spec: + type: ClusterIP + selector: + app: {{ .Release.Name }} + ports: + - protocol: TCP + port: {{ .Values.deployment.config.port }} + targetPort: {{ .Values.deployment.config.port }} diff --git a/examples/kafka-hub/helm/consolidator/values.yaml b/examples/kafka-hub/helm/consolidator/values.yaml new file mode 100644 index 00000000..11b360b7 --- /dev/null +++ b/examples/kafka-hub/helm/consolidator/values.yaml @@ -0,0 +1,47 @@ +# Copyright (c) 2025 WSO2 LLC. (http://www.wso2.com). +# +# WSO2 LLC. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +deployment: + replicas: 1 + image: + repository: "ayeshalmeida/consolidator" + pullPolicy: IfNotPresent + tag: 8.0.0 + secrets: + - name: ballerina-consolidator-broker + mountPath: "/home/ballerina/resources/brokercerts" + content: + - filePath: "_resources/kafka-client/kafka-client.trustStore.jks" + fileKey: "client-truststore.jks" + - filePath: "_resources/kafka-client/kafka-client.keystore.jks" + fileKey: "client-keystore.jks" + config: + port: 10001 + kafka: + bootstrap_node: "broker:9094" + truststore_name: "client-truststore.jks" + truststore_password: "password" + keystore_name: "client-keystore.jks" + keystore_password: "password" + websub_events_topic: "websub-events" + websub_events_snapshot_topic: "websub-events-snapshot" + +ingress: + hosts: + - host: ballerina-consolidator.local + paths: + - path: /ballerina + pathType: Prefix diff --git a/examples/kafka-hub/helm/hub/Chart.yaml b/examples/kafka-hub/helm/hub/Chart.yaml new file mode 100644 index 00000000..8d1eb310 --- /dev/null +++ b/examples/kafka-hub/helm/hub/Chart.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2025 WSO2 LLC. (http://www.wso2.com). +# +# WSO2 LLC. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +apiVersion: v2 +appVersion: 12.0.0 +description: A Helm chart for the deployment of WSO2 Websubhub Hub Deployment +name: hub +version: 0.1.0 diff --git a/examples/kafka-hub/helm/hub/_resources/hub-1.keystore.jks b/examples/kafka-hub/helm/hub/_resources/hub-1.keystore.jks new file mode 100644 index 00000000..81c74401 Binary files /dev/null and b/examples/kafka-hub/helm/hub/_resources/hub-1.keystore.jks differ diff --git a/examples/kafka-hub/helm/hub/_resources/idp/client-truststore.jks b/examples/kafka-hub/helm/hub/_resources/idp/client-truststore.jks new file mode 100644 index 00000000..4c5076d2 Binary files /dev/null and b/examples/kafka-hub/helm/hub/_resources/idp/client-truststore.jks differ diff --git a/examples/kafka-hub/helm/hub/_resources/kafka-client/kafka-client.keystore.jks b/examples/kafka-hub/helm/hub/_resources/kafka-client/kafka-client.keystore.jks new file mode 100644 index 00000000..6c02a44d Binary files /dev/null and b/examples/kafka-hub/helm/hub/_resources/kafka-client/kafka-client.keystore.jks differ diff --git a/examples/kafka-hub/helm/hub/_resources/kafka-client/kafka-client.trustStore.jks b/examples/kafka-hub/helm/hub/_resources/kafka-client/kafka-client.trustStore.jks new file mode 100644 index 00000000..9c71e77f Binary files /dev/null and b/examples/kafka-hub/helm/hub/_resources/kafka-client/kafka-client.trustStore.jks differ diff --git a/examples/kafka-hub/helm/hub/confs/Config.toml b/examples/kafka-hub/helm/hub/confs/Config.toml new file mode 100644 index 00000000..60a4ce22 --- /dev/null +++ b/examples/kafka-hub/helm/hub/confs/Config.toml @@ -0,0 +1,81 @@ +# Copyright (c) 2025 WSO2 LLC. (http://www.wso2.com). +# +# WSO2 LLC. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +[kafkaHub.config] +# Flag to check whether to enable/disable security +SECURITY_ON = true + +# Server ID is is used to uniquely identify each server +# Each server must have a unique ID +SERVER_ID = {{ .Values.deployment.config.server_id | quote }} + +# IP and Port of the Kafka bootstrap node +KAFKA_BOOTSTRAP_NODE = {{ .Values.deployment.config.kafka.bootstrap_node | quote }} + +# Maximum number of records returned in a single call to consumer-poll +KAFKA_CONSUMER_MAX_POLL_RECORDS = {{ .Values.deployment.config.kafka.max_poll_records }} + +# Kafka topic which is stores websub-events for this server +WEBSUB_EVENTS_TOPIC = "websub-events" + +# Consolidator HTTP endpoint to be used to retrieve current state-snapshot +STATE_SNAPSHOT_ENDPOINT = {{ .Values.deployment.config.state_snapshot_endpoint | quote }} + +# The interval in which Kafka consumers wait for new messages +POLLING_INTERVAL = 10.0 + +# The period in which Kafka close method waits to complete +GRACEFUL_CLOSE_PERIOD = 5.0 + +# The port that is used to start the hub +HUB_PORT = {{ .Values.deployment.config.port }} + +# SSL keystore file path +# SSL_KEYSTORE_PATH = "./resources/hub.keystore.jks" +SSL_KEYSTORE_PATH = "/home/ballerina/resources/ssl/{{ .Values.deployment.config.ssl.keystore_name }}" + +# SSL keystore password +KEYSTORE_PASSWORD = {{ .Values.deployment.config.ssl.keystore_password | quote }} + +# The period between retry requests +MESSAGE_DELIVERY_RETRY_INTERVAL = 3.0 + +# The maximum retry count +MESSAGE_DELIVERY_COUNT = 3 + +# The message delivery timeout +MESSAGE_DELIVERY_TIMEOUT = 10.0 + +# The HTTP status codes for which the client should retry +MESSAGE_DELIVERY_RETRYABLE_STATUS_CODES = [{{ join ", " .Values.deployment.config.retryable_status_codes }}] + +# The Oauth2 authorization related configurations +[kafkaHub.config.OAUTH2_CONFIG] +issuer = {{ .Values.deployment.config.idp.jwt_issuer | quote }} +audience = {{ .Values.deployment.config.idp.jwt_audience | quote }} +jwksUrl = {{ .Values.deployment.config.idp.jwt_jwks_endpoint | quote }} +trustStore = "/home/ballerina/resources/idp/{{ .Values.deployment.config.idp.truststore_name }}" +trustStorePassword = {{ .Values.deployment.config.idp.truststore_password | quote }} + +# The MTLS configurations related to Kafka connection +[kafkaHub.config.KAFKA_MTLS_CONFIG] +cert.path = "/home/ballerina/resources/brokercerts/{{ .Values.deployment.config.kafka.truststore_name }}" +cert.password = {{ .Values.deployment.config.kafka.truststore_password | quote }} +key.keyStore.path = "/home/ballerina/resources/brokercerts/{{ .Values.deployment.config.kafka.keystore_name }}" +key.keyStore.password = {{ .Values.deployment.config.kafka.keystore_password | quote }} + +[ballerina.log] +level = {{ .Values.deployment.config.logLevel | quote }} diff --git a/examples/kafka-hub/helm/hub/templates/conf.yaml b/examples/kafka-hub/helm/hub/templates/conf.yaml new file mode 100644 index 00000000..d562a76e --- /dev/null +++ b/examples/kafka-hub/helm/hub/templates/conf.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2025 WSO2 LLC. (http://www.wso2.com). +# +# WSO2 LLC. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +apiVersion: v1 +kind: ConfigMap +metadata: + name: websubhub-svc-cm + namespace : {{ .Release.Namespace }} +data: + Config.toml: {{ tpl (.Files.Get "confs/Config.toml") . | quote }} diff --git a/examples/kafka-hub/helm/hub/templates/secret.yaml b/examples/kafka-hub/helm/hub/templates/secret.yaml new file mode 100644 index 00000000..6c0f1266 --- /dev/null +++ b/examples/kafka-hub/helm/hub/templates/secret.yaml @@ -0,0 +1,28 @@ +# Copyright (c) 2025 WSO2 LLC. (http://www.wso2.com). +# +# WSO2 LLC. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +{{- range .Values.deployment.secrets }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name }} +type: Opaque +data: + {{- range .content }} + {{ .fileKey }}: {{ $.Files.Get .filePath | b64enc }} + {{- end }} +--- +{{- end }} diff --git a/examples/kafka-hub/helm/hub/templates/service.yaml b/examples/kafka-hub/helm/hub/templates/service.yaml new file mode 100644 index 00000000..1cd7e88f --- /dev/null +++ b/examples/kafka-hub/helm/hub/templates/service.yaml @@ -0,0 +1,28 @@ +# Copyright (c) 2025 WSO2 LLC. (http://www.wso2.com). +# +# WSO2 LLC. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-service +spec: + type: ClusterIP + selector: + app: {{ .Release.Name }} + ports: + - protocol: TCP + port: {{ .Values.deployment.config.port }} + targetPort: {{ .Values.deployment.config.port }} diff --git a/examples/kafka-hub/helm/hub/templates/statefulset.yaml b/examples/kafka-hub/helm/hub/templates/statefulset.yaml new file mode 100644 index 00000000..4bef7141 --- /dev/null +++ b/examples/kafka-hub/helm/hub/templates/statefulset.yaml @@ -0,0 +1,62 @@ +# Copyright (c) 2025 WSO2 LLC. (http://www.wso2.com). +# +# WSO2 LLC. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ .Release.Name }}-deployment + labels: + app: {{ .Release.Name }} +spec: + replicas: {{ .Values.deployment.replicas }} + selector: + matchLabels: + app: {{ .Release.Name }} + template: + metadata: + labels: + app: {{ .Release.Name }} + spec: + containers: + - name: {{ .Release.Name }} + image: {{ .Values.deployment.image.repository }}:{{ .Values.deployment.image.tag }} + imagePullPolicy: {{ .Values.deployment.image.pullPolicy }} + ports: + - containerPort: {{ .Values.deployment.config.port }} + env: + - name: "BAL_CONFIG_FILES" + value: "/home/ballerina/conf/Config.toml" + - name: "BALLERINA_MAX_POOL_SIZE" + value: "100" + volumeMounts: + - name: "config-config-map-volume" + mountPath: "/home/ballerina/conf" + readOnly: true + {{- range .Values.deployment.secrets }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: true + {{- end }} + + volumes: + - name: "config-config-map-volume" + configMap: + name: "websubhub-svc-cm" + {{- range .Values.deployment.secrets }} + - name: {{ .name }} + secret: + secretName: {{ .name }} + {{- end }} diff --git a/examples/kafka-hub/helm/hub/values.yaml b/examples/kafka-hub/helm/hub/values.yaml new file mode 100644 index 00000000..5f9466fa --- /dev/null +++ b/examples/kafka-hub/helm/hub/values.yaml @@ -0,0 +1,70 @@ +# Copyright (c) 2025 WSO2 LLC. (http://www.wso2.com). +# +# WSO2 LLC. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +deployment: + replicas: 1 + image: + repository: "ayeshalmeida/kafkahub" + pullPolicy: IfNotPresent + tag: 13.0.0 + secrets: + - name: ballerina-websubhub-ssl + mountPath: "/home/ballerina/resources/ssl" + content: + - filePath: "_resources/hub-1.keystore.jks" + fileKey: "hub.keystore.jks" + - name: ballerina-websubhub-idp + mountPath: "/home/ballerina/resources/idp" + content: + - filePath: "_resources/idp/client-truststore.jks" + fileKey: "client-truststore.jks" + - name: ballerina-websubhub-broker + mountPath: "/home/ballerina/resources/brokercerts" + content: + - filePath: "_resources/kafka-client/kafka-client.trustStore.jks" + fileKey: "client-truststore.jks" + - filePath: "_resources/kafka-client/kafka-client.keystore.jks" + fileKey: "client-keystore.jks" + config: + port: 9000 + server_id: "hub-1" + state_snapshot_endpoint: "http://ballerina-consolidator-deployment:10001" + retryable_status_codes: [500, 502, 503] + logLevel: "ERROR" + ssl: + keystore_name: "hub.keystore.jks" + keystore_password: "password" + idp: + jwt_issuer: "https://localhost:9443/oauth2/token" + jwt_audience: "ballerina" + jwt_jwks_endpoint: "https://idp:9443/oauth2/jwks" + truststore_name: "client-truststore.jks" + truststore_password: "wso2carbon" + kafka: + bootstrap_node: "broker:9094" + max_poll_records: 50 + truststore_name: "client-truststore.jks" + truststore_password: "password" + keystore_name: "client-keystore.jks" + keystore_password: "password" + +ingress: + hosts: + - host: ballerina-websubhub.local + paths: + - path: /hub + pathType: Prefix + tls: [] diff --git a/examples/kafka-hub/hub/Cloud.toml b/examples/kafka-hub/hub/Cloud.toml index fe518af5..6418beaf 100644 --- a/examples/kafka-hub/hub/Cloud.toml +++ b/examples/kafka-hub/hub/Cloud.toml @@ -1,7 +1,7 @@ [container.image] repository="ballerina" name="kafkahub" -tag="12.0.0" +tag="13.0.0" [[container.copy.files]] sourceFile="./resources" diff --git a/examples/kafka-hub/hub/Dockerfile b/examples/kafka-hub/hub/Dockerfile index f94d6854..d4f2a48b 100644 --- a/examples/kafka-hub/hub/Dockerfile +++ b/examples/kafka-hub/hub/Dockerfile @@ -24,7 +24,7 @@ LABEL maintainer="WSO2 Docker Maintainers " # set Docker image build arguments # build arguments for user/group configurations -ARG USER=websubhub +ARG USER=ballerina ARG USER_ID=10001 ARG USER_GROUP=wso2 ARG USER_GROUP_ID=10001 diff --git a/examples/kafka-hub/hub/docker/alpine/Dockerfile b/examples/kafka-hub/hub/docker/alpine/Dockerfile deleted file mode 100644 index 47ae927f..00000000 --- a/examples/kafka-hub/hub/docker/alpine/Dockerfile +++ /dev/null @@ -1,61 +0,0 @@ -# ------------------------------------------------------------------------ -# -# Copyright (c) 2022, WSO2 LLC. (http://www.wso2.com). All Rights Reserved. -# -# This software is the property of WSO2 LLC. and its suppliers, if any. -# Dissemination of any information or reproduction of any material contained -# herein in any form is strictly forbidden, unless permitted by WSO2 -# expressly. You may not alter or remove any copyright or other notice from -# copies of this content. -# -# ------------------------------------------------------------------------ - -ARG BASE_IMAGE_DIGEST -FROM adoptopenjdk/openjdk11@${BASE_IMAGE_DIGEST} -LABEL maintainer="WSO2 Docker Maintainers " - -# set Docker image build arguments -# build arguments for user/group configurations -ARG USER=websubhub -ARG USER_ID=10001 -ARG USER_GROUP=wso2 -ARG USER_GROUP_ID=10001 -ARG USER_HOME=/home/${USER} -# build arguments for WSO2 product installation -ARG JAR_FILE_PATH=kafkaHub.jar - - -# build argument for MOTD -ARG MOTD="\n\ -Welcome to WSO2 Docker resources.\n\ ------------------------------------- \n\ -This Docker container comprises of a WSO2 product, running with its latest GA release \n\ -which is under the Apache License, Version 2.0. \n\ -Read more about Apache License, Version 2.0 here @ http://www.apache.org/licenses/LICENSE-2.0.\n" - -# create the non-root user and group and set MOTD login message -RUN \ - addgroup -g ${USER_GROUP_ID} -S ${USER_GROUP} && adduser -u ${USER_ID} -S ${USER} \ - -G ${USER_GROUP} -h ${USER_HOME} \ - && echo '[ ! -z "${TERM}" -a -r /etc/motd ] && cat /etc/motd' >> /etc/bash.bashrc; echo "${MOTD}" > /etc/motd - -# create Java prefs dir -# this is to avoid warning logs printed by FileSystemPreferences class -RUN \ - mkdir -p ${USER_HOME}/.java/.systemPrefs \ - && mkdir -p ${USER_HOME}/.java/.userPrefs \ - && chmod -R 755 ${USER_HOME}/.java \ - && chown -R ${USER}:${USER_GROUP} ${USER_HOME}/.java - -# copy init script to user home -COPY --chown=${USER}:${USER_GROUP} ${JAR_FILE_PATH} ${USER_HOME}/ - -# set the user and work directory -USER ${USER_ID} -WORKDIR ${USER_HOME} - -# set environment variables -ENV JAVA_OPTS="-Djava.util.prefs.systemRoot=${USER_HOME}/.java -Djava.util.prefs.userRoot=${USER_HOME}/.java/.userPrefs" \ - WORKING_DIRECTORY=${USER_HOME} - -CMD java -jar ${JAR_FILE_PATH}