diff --git a/src/main/charts/bitbucket/README.md b/src/main/charts/bitbucket/README.md index a86d49c7c..eac24ef47 100644 --- a/src/main/charts/bitbucket/README.md +++ b/src/main/charts/bitbucket/README.md @@ -49,6 +49,10 @@ Kubernetes: `>=1.21.x-0` | bitbucket.elasticSearch.credentials.passwordSecretKey | string | `"password"` | The key in the Kubernetes Secret that contains the Elasticsearch password. | | bitbucket.elasticSearch.credentials.secretName | string | `nil` | from-literal=password=' https://kubernetes.io/docs/concepts/configuration/secret/#opaque-secrets | | bitbucket.elasticSearch.credentials.usernameSecretKey | string | `"username"` | The key in the Kubernetes Secret that contains the Elasticsearch username. | +| bitbucket.hazelcastService.annotations | object | `{}` | Additional annotations to apply to the Hazelcast Service | +| bitbucket.hazelcastService.enabled | bool | `false` | Enable or disable an additional Hazelcast service that Bitbucket nodes can use to join a cluster. It is recommended to create a separate Hazelcast service if the Bitbucket service uses a LoadBalancer type (e.g., NLB), ensuring that the Hazelcast port is not exposed at all. | +| bitbucket.hazelcastService.port | int | `5701` | The port on which the Bitbucket K8s Hazelcast Service will listen | +| bitbucket.hazelcastService.type | string | `"ClusterIP"` | The type of the Hazelcast K8s service to use for Bitbucket | | bitbucket.license.secretKey | string | `"license-key"` | The key in the K8s Secret that contains the Bitbucket license key | | bitbucket.license.secretName | string | `nil` | The name of the K8s Secret that contains the Bitbucket license key. If specified, then the license will be automatically populated during Bitbucket setup. Otherwise, it will need to be provided via the browser after initial startup. An Example of creating a K8s secret for the license below: 'kubectl create secret generic --from-literal=license-key= https://kubernetes.io/docs/concepts/configuration/secret/#opaque-secrets | | bitbucket.livenessProbe.enabled | bool | `false` | Whether to apply the livenessProbe check to pod. | diff --git a/src/main/charts/bitbucket/templates/service-hazelcast.yaml b/src/main/charts/bitbucket/templates/service-hazelcast.yaml new file mode 100644 index 000000000..b5d325883 --- /dev/null +++ b/src/main/charts/bitbucket/templates/service-hazelcast.yaml @@ -0,0 +1,21 @@ +{{ if .Values.bitbucket.hazelcastService.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "common.names.fullname" . }}-hazelcast + labels: + {{- include "common.labels.commonLabels" . | nindent 4 }} + annotations: + {{- with .Values.bitbucket.hazelcastService.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.bitbucket.service.type }} + ports: + - port: {{ .Values.bitbucket.ports.hazelcast }} + targetPort: hazelcast + protocol: TCP + name: hazelcast + selector: + {{- include "common.labels.selectorLabels" . | nindent 4 }} +{{ end }} diff --git a/src/main/charts/bitbucket/templates/service.yaml b/src/main/charts/bitbucket/templates/service.yaml index c8d4da88d..c238970d9 100644 --- a/src/main/charts/bitbucket/templates/service.yaml +++ b/src/main/charts/bitbucket/templates/service.yaml @@ -29,9 +29,11 @@ spec: targetPort: ssh protocol: TCP name: ssh + {{- if not .Values.bitbucket.hazelcastService.enabled }} - port: {{ .Values.bitbucket.ports.hazelcast }} targetPort: hazelcast protocol: TCP name: hazelcast + {{- end }} selector: {{- include "common.labels.selectorLabels" . | nindent 4 }} diff --git a/src/main/charts/bitbucket/values.yaml b/src/main/charts/bitbucket/values.yaml index bd66fa2f8..2564ea711 100644 --- a/src/main/charts/bitbucket/values.yaml +++ b/src/main/charts/bitbucket/values.yaml @@ -543,6 +543,25 @@ bitbucket: # annotations: {} + hazelcastService: + + # -- Enable or disable an additional Hazelcast service that Bitbucket nodes can use to join a cluster. + # It is recommended to create a separate Hazelcast service if the Bitbucket service + # uses a LoadBalancer type (e.g., NLB), ensuring that the Hazelcast port is not exposed at all. + enabled: false + + # -- The port on which the Bitbucket K8s Hazelcast Service will listen + # + port: 5701 + + # -- The type of the Hazelcast K8s service to use for Bitbucket + # + type: ClusterIP + + # -- Additional annotations to apply to the Hazelcast Service + # + annotations: {} + # Standard K8s field that holds pod-level security attributes and common container settings. # https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ # Do not populate when deploying to OpenShift, unless anyuid policy is attached to a service account. diff --git a/src/main/charts/confluence/README.md b/src/main/charts/confluence/README.md index 89a0f73ce..b6c0a07cd 100644 --- a/src/main/charts/confluence/README.md +++ b/src/main/charts/confluence/README.md @@ -45,6 +45,10 @@ Kubernetes: `>=1.21.x-0` | confluence.clustering.usePodNameAsClusterNodeName | bool | `true` | Set to 'true' if the K8s pod name should be used as the end-user-visible name of the Data Center cluster node. | | confluence.containerSecurityContext | object | `{}` | Standard K8s field that holds security configurations that will be applied to a container. https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ | | confluence.forceConfigUpdate | bool | `false` | The Docker entrypoint.py generates application configuration on first start; not all of these files are regenerated on subsequent starts. By default, confluence.cfg.xml is generated only once. Set `forceConfigUpdate` to true to change this behavior. | +| confluence.hazelcastService.annotations | object | `{}` | Additional annotations to apply to the Hazelcast Service | +| confluence.hazelcastService.enabled | bool | `false` | Enable or disable an additional Hazelcast service that Confluence nodes can use to join a cluster. It is recommended to create a separate Hazelcast service if the Confluence service uses a LoadBalancer type (e.g., NLB), ensuring that the Hazelcast port is not exposed at all. | +| confluence.hazelcastService.port | int | `5701` | The port on which the Confluence K8s Hazelcast Service will listen | +| confluence.hazelcastService.type | string | `"ClusterIP"` | The type of the Hazelcast K8s service to use for Confluence | | confluence.jvmDebug.enabled | bool | `false` | Set to 'true' for remote debugging. Confluence JVM will be started with debugging port 5005 open. | | confluence.license.secretKey | string | `"license-key"` | The key in the K8s Secret that contains the Confluence license key | | confluence.license.secretName | string | `nil` | The name of the K8s Secret that contains the Confluence license key. If specified, then the license will be automatically populated during Confluence setup. Otherwise, it will need to be provided via the browser after initial startup. An Example of creating a K8s secret for the license below: 'kubectl create secret generic --from-literal=license-key= https://kubernetes.io/docs/concepts/configuration/secret/#opaque-secrets | diff --git a/src/main/charts/confluence/templates/service-hazelcast.yaml b/src/main/charts/confluence/templates/service-hazelcast.yaml new file mode 100644 index 000000000..e32760c40 --- /dev/null +++ b/src/main/charts/confluence/templates/service-hazelcast.yaml @@ -0,0 +1,21 @@ +{{ if .Values.confluence.hazelcastService.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "common.names.fullname" . }}-hazelcast + labels: + {{- include "common.labels.commonLabels" . | nindent 4 }} + annotations: + {{- with .Values.confluence.hazelcastService.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.confluence.service.type }} + ports: + - port: {{ .Values.confluence.ports.hazelcast }} + targetPort: hazelcast + protocol: TCP + name: hazelcast + selector: + {{- include "common.labels.selectorLabels" . | nindent 4 }} +{{ end }} diff --git a/src/main/charts/confluence/templates/service.yaml b/src/main/charts/confluence/templates/service.yaml index f3521d28a..eb7bee378 100644 --- a/src/main/charts/confluence/templates/service.yaml +++ b/src/main/charts/confluence/templates/service.yaml @@ -24,9 +24,11 @@ spec: targetPort: http protocol: TCP name: http + {{- if not .Values.confluence.hazelcastService.enabled }} - port: {{ .Values.confluence.ports.hazelcast }} targetPort: hazelcast protocol: TCP name: hazelcast + {{- end }} selector: {{- include "common.labels.selectorLabels" . | nindent 4 }} diff --git a/src/main/charts/confluence/values.yaml b/src/main/charts/confluence/values.yaml index 456c18329..aabbc4d2f 100644 --- a/src/main/charts/confluence/values.yaml +++ b/src/main/charts/confluence/values.yaml @@ -529,6 +529,25 @@ confluence: # annotations: {} + hazelcastService: + + # -- Enable or disable an additional Hazelcast service that Confluence nodes can use to join a cluster. + # It is recommended to create a separate Hazelcast service if the Confluence service + # uses a LoadBalancer type (e.g., NLB), ensuring that the Hazelcast port is not exposed at all. + enabled: false + + # -- The port on which the Confluence K8s Hazelcast Service will listen + # + port: 5701 + + # -- The type of the Hazelcast K8s service to use for Confluence + # + type: ClusterIP + + # -- Additional annotations to apply to the Hazelcast Service + # + annotations: {} + # Standard K8s field that holds pod-level security attributes and common container settings. # https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ # Do not populate when deploying to OpenShift, unless anyuid policy is attached to a service account. diff --git a/src/test/java/test/ServiceTest.java b/src/test/java/test/ServiceTest.java index 57371772d..b0c1dfe38 100644 --- a/src/test/java/test/ServiceTest.java +++ b/src/test/java/test/ServiceTest.java @@ -131,4 +131,31 @@ void synchrony_service_custom_annotations(Product product) throws Exception { "confluence", "qwerty-synchrony" )); } + + @ParameterizedTest + @EnumSource(value = Product.class, names = {"bitbucket", "confluence"}) + void dedicated_hazelcast_service(Product product) throws Exception { + final var resources = helm.captureKubeResourcesFromHelmChart(product, Map.of( + product.name() + ".hazelcastService.enabled", "true" + )); + + final var hazelcastService = resources.get(Kind.Service, Service.class, product.getHelmReleaseName() + "-hazelcast"); + + assertThat(hazelcastService.getType()).hasTextEqualTo("ClusterIP"); + assertThat(hazelcastService.getPort("hazelcast")) + .hasValueSatisfying(node -> assertThat(node.path("port")).hasValueEqualTo(5701)); + + final var service = resources.get(Kind.Service, Service.class, product.getHelmReleaseName()); + assertThat(service.getPort("hazelcast")).isEmpty(); + } + + @ParameterizedTest + @EnumSource(value = Product.class, names = {"bitbucket", "confluence"}) + void hazelcast_one_service(Product product) throws Exception { + final var resources = helm.captureKubeResourcesFromHelmChart(product, Map.of()); + + final var service = resources.get(Kind.Service, Service.class, product.getHelmReleaseName()); + assertThat(service.getPort("hazelcast")) + .hasValueSatisfying(node -> assertThat(node.path("port")).hasValueEqualTo(5701)); + } }