From ad0d4805b4ae2a0ce44e7ace80c3ae71abd041d9 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Tue, 7 Jan 2025 13:54:06 +0100 Subject: [PATCH 1/8] Helm chart redesign for Quarkus-based runtimes --- .github/workflows/helm.yml | 6 +- helm/polaris/README.md | 213 +++++- helm/polaris/README.md.gotmpl | 76 +- helm/polaris/ci/extra-service-values.yaml | 47 ++ helm/polaris/ci/fixtures/persistence.yaml | 7 +- helm/polaris/ci/fixtures/postgres.yaml | 72 ++ helm/polaris/ci/fixtures/storage.yaml | 27 + helm/polaris/ci/fixtures/token-broker.yaml | 59 ++ helm/polaris/ci/persistence-values.yaml | 31 +- helm/polaris/ci/simple-values.yaml | 10 + helm/polaris/templates/_helpers.tpl | 242 +++++++ helm/polaris/templates/configmap.yaml | 175 ++++- helm/polaris/templates/deployment.yaml | 77 +-- helm/polaris/templates/ingress.yaml | 2 +- helm/polaris/templates/job.yaml | 74 +- helm/polaris/templates/service-extra.yaml | 69 ++ helm/polaris/templates/service-mgmt.yaml | 61 ++ helm/polaris/templates/service.yaml | 33 +- helm/polaris/templates/servicemonitor.yaml | 49 ++ helm/polaris/templates/storage.yaml | 41 ++ .../templates/tests/test-connection.yaml | 11 +- helm/polaris/tests/configmap_test.yaml | 463 +++++++------ helm/polaris/tests/deployment_test.yaml | 648 +++++++++++++++--- helm/polaris/tests/ingress_test.yaml | 2 +- helm/polaris/tests/job_test.yaml | 281 +++----- helm/polaris/tests/logging_storage_test.yaml | 106 +++ helm/polaris/tests/quantity_test.yaml | 101 +++ helm/polaris/tests/service_extra_test.yaml | 349 ++++++++++ helm/polaris/tests/service_mgmt_test.yaml | 253 +++++++ helm/polaris/tests/service_monitor_test.yaml | 76 ++ helm/polaris/tests/service_test.yaml | 131 +++- helm/polaris/values.yaml | 607 +++++++++++----- 32 files changed, 3557 insertions(+), 842 deletions(-) create mode 100644 helm/polaris/ci/extra-service-values.yaml create mode 100644 helm/polaris/ci/fixtures/postgres.yaml create mode 100644 helm/polaris/ci/fixtures/storage.yaml create mode 100644 helm/polaris/ci/fixtures/token-broker.yaml create mode 100644 helm/polaris/templates/service-extra.yaml create mode 100644 helm/polaris/templates/service-mgmt.yaml create mode 100644 helm/polaris/templates/servicemonitor.yaml create mode 100644 helm/polaris/templates/storage.yaml create mode 100644 helm/polaris/tests/logging_storage_test.yaml create mode 100644 helm/polaris/tests/quantity_test.yaml create mode 100644 helm/polaris/tests/service_extra_test.yaml create mode 100644 helm/polaris/tests/service_mgmt_test.yaml create mode 100644 helm/polaris/tests/service_monitor_test.yaml diff --git a/.github/workflows/helm.yml b/.github/workflows/helm.yml index e6a7bf88ac..e03ad3d829 100644 --- a/.github/workflows/helm.yml +++ b/.github/workflows/helm.yml @@ -79,7 +79,7 @@ jobs: if: steps.list-changed.outputs.changed == 'true' run: | helm plugin install https://github.com/helm-unittest/helm-unittest.git || true - helm unittest helm/polaris + helm unittest helm/polaris 2> >(grep -v 'found symbolic link' >&2) - name: Run chart-testing (lint) if: steps.list-changed.outputs.changed == 'true' @@ -99,9 +99,9 @@ jobs: if: steps.list-changed.outputs.changed == 'true' run: | eval $(minikube -p minikube docker-env) - ./gradlew :polaris-quarkus-server:assemble \ + ./gradlew :polaris-quarkus-server:assemble :polaris-quarkus-admin:assemble \ -Dquarkus.container-image.build=true \ - -PeclipseLinkDeps=com.h2database:h2:2.3.232 + -PeclipseLinkDeps=org.postgresql:postgresql:42.7.4 minikube image ls - name: Install fixtures diff --git a/helm/polaris/README.md b/helm/polaris/README.md index 3230cc1720..d3756e06a1 100644 --- a/helm/polaris/README.md +++ b/helm/polaris/README.md @@ -27,15 +27,18 @@ # Polaris Helm chart -![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.0.0-incubating-SNAPSHOT](https://img.shields.io/badge/AppVersion-1.0.0--incubating--SNAPSHOT-informational?style=flat-square) -A Helm chart for Polaris. +A Helm chart for Apache Polaris (incubating). **Homepage:** ## Maintainers * [MonkeyCanCode](https://github.com/MonkeyCanCode) * [adutra](https://github.com/adutra) +* [collado-mike](https://github.com/collado-mike) +* [gerrit-k](https://github.com/gerrit-k) +* [snazy](https://github.com/snazy) ## Source Code @@ -45,41 +48,139 @@ A Helm chart for Polaris. ### Optional -When using a custom `persistence.xml`, a Kubernetes Secret must be created for `.persistenceConfigSecret`. Below is a sample command: +When using a custom `persistence.xml`, a Kubernetes Secret must be created for it. Below is a sample command: ```bash kubectl create secret generic polaris-secret -n polaris --from-file=persistence.xml ``` -### From local directory (for development purposes) +### Running the unit tests -From Polaris repo root: +Helm unit tests do not require a Kubernetes cluster. To run the unit tests from the Polaris repo +root: ```bash -$ helm install polaris helm/polaris --namespace polaris --create-namespace +helm unittest helm/polaris 2> >(grep -v 'found symbolic link' >&2) +``` + +Note: the `grep` command is used to filter out the annoying warning messages about symbolic links; +see https://github.com/helm/helm/issues/7019. + +### Running locally with a Kind cluster + +The below instructions assume Kind and Helm are installed. + +Simply run the `run.sh` script from the Polaris repo root, making sure to specify the +`--eclipse-link-deps` option: + +```bash +./run.sh --eclipse-link-deps=org.postgresql:postgresql:42.7.4 +``` + +This script will create a Kind cluster, deploy a local Docker registry, build the Polaris Docker +images with support for Postgres and load them into the Kind cluster. (It will also create an +example Deployment and Service with in-memory storage.) + +### Running locally with a Minikube cluster + +The below instructions assume a Minikube cluster is already running and Helm is installed. + +If necessary, build and load the Docker images with support for Postgres into Minikube: + +```bash +eval $(minikube -p minikube docker-env) + +./gradlew :polaris-quarkus-server:assemble :polaris-quarkus-admin:assemble \ + -Dquarkus.container-image.build=true \ + -PeclipseLinkDeps=org.postgresql:postgresql:42.7.4 +``` + +### Installing the chart locally + +The below instructions assume a local Kubernetes cluster is running and Helm is installed. + +Create and populate the target namespace: + +```bash +kubectl create namespace polaris +kubectl apply --namespace polaris -f helm/polaris/ci/fixtures/ +``` + +Finally, install the chart. From Polaris repo root: + +```bash +helm upgrade --install --namespace polaris \ + --debug --values helm/polaris/ci/simple-values.yaml \ + polaris helm/polaris +``` + +The `helm/polaris/ci` contains a number of values files that can be used to install the chart with +different configurations. + +You can also run `ct` (chart-testing): + +```bash +ct lint --charts helm/polaris +ct install --namespace polaris --debug --charts ./helm/polaris ``` ### Uninstalling the chart ```bash -$ helm uninstall --namespace polaris polaris +helm uninstall --namespace polaris polaris ``` ## Values | Key | Type | Default | Description | |-----|------|---------|-------------| +| advancedConfig | object | `{}` | Advanced configuration. You can pass here any valid Polaris or Quarkus configuration property. Any property that is defined here takes precedence over all the other configuration values generated by this chart. Properties can be passed "flattened" or as nested YAML objects (see examples below). Note: values should be strings; avoid using numbers, booleans, or other types. | | affinity | object | `{}` | Affinity and anti-affinity for polaris pods. See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity. | +| authentication | object | `{"authenticator":{"type":"default"},"tokenBroker":{"maxTokenGeneration":"PT1H","secret":{"name":null,"privateKey":"private.pem","publicKey":"public.pem","secretKey":"secret"},"type":"rsa-key-pair"},"tokenService":{"type":"default"}}` | Polaris authentication configuration. | +| authentication.authenticator | object | `{"type":"default"}` | The type of authentication to use. Two built-in types are supported: default and test; test is not recommended for production. | +| authentication.tokenBroker | object | `{"maxTokenGeneration":"PT1H","secret":{"name":null,"privateKey":"private.pem","publicKey":"public.pem","secretKey":"secret"},"type":"rsa-key-pair"}` | The type of token broker to use. Two built-in types are supported: rsa-key-pair and symmetric-key. | +| authentication.tokenBroker.secret | object | `{"name":null,"privateKey":"private.pem","publicKey":"public.pem","secretKey":"secret"}` | The secret name to pull the public and private keys, or the symmetric key secret from. | +| authentication.tokenBroker.secret.name | string | `nil` | The name of the secret to pull the keys from. If not provided, a key pair will be generated. This is not recommended for production. | +| authentication.tokenBroker.secret.privateKey | string | `"private.pem"` | The private key file to use for RSA key pair token broker. Only required when using rsa-key-pair. | +| authentication.tokenBroker.secret.publicKey | string | `"public.pem"` | The public key file to use for RSA key pair token broker. Only required when using rsa-key-pair. | +| authentication.tokenBroker.secret.secretKey | string | `"secret"` | The symmetric key file to use for symmetric key token broker. Only required when using symmetric-key. | +| authentication.tokenService | object | `{"type":"default"}` | The type of token service to use. Two built-in types are supported: default and test; test is not recommended for production. | | autoscaling.enabled | bool | `false` | Specifies whether automatic horizontal scaling should be enabled. Do not enable this when using in-memory version store type. | | autoscaling.maxReplicas | int | `3` | The maximum number of replicas to maintain. | | autoscaling.minReplicas | int | `1` | The minimum number of replicas to maintain. | | autoscaling.targetCPUUtilizationPercentage | int | `80` | Optional; set to zero or empty to disable. | | autoscaling.targetMemoryUtilizationPercentage | string | `nil` | Optional; set to zero or empty to disable. | -| bootstrapExtraEnv | list | `[]` | Extra environment variables to add to the bootstrap metastore manager job (see `extraEnv` for an example) | -| bootstrapMetastoreManager | bool | `false` | Configures whether to enable the bootstrap metastore manager job | +| bootstrap | object | `{"credentials":[],"enabled":false,"extraEnv":[],"image":{"configDir":"/deployments/config","pullPolicy":"IfNotPresent","repository":"apache/polaris-admin-tool","tag":"latest"},"realms":[]}` | Configures whether to enable the bootstrap metastore manager job. It is recommended to bootstrap realms using the Polaris Admin Tool; use this only if you need to bootstrap realms while deploying Polaris at the same time. | +| bootstrap.credentials | list | `[]` | The root credentials to create during the bootstrap. If you don't provide credentials for the root principal of each realm to bootstrap, random credentials will be generated. Each entry in the array must be of the form: realm,clientId,clientSecret | +| bootstrap.enabled | bool | `false` | Specifies whether the bootstrap metastore manager job should be enabled. | +| bootstrap.extraEnv | list | `[]` | Extra environment variables to add to the bootstrap metastore manager job (see `extraEnv` for an example) | +| bootstrap.image | object | `{"configDir":"/deployments/config","pullPolicy":"IfNotPresent","repository":"apache/polaris-admin-tool","tag":"latest"}` | The image to use for the bootstrap metastore manager job. | +| bootstrap.image.configDir | string | `"/deployments/config"` | The path to the directory where the application.properties file, and other configuration files, if any, should be mounted. | +| bootstrap.image.pullPolicy | string | `"IfNotPresent"` | The image pull policy. | +| bootstrap.image.repository | string | `"apache/polaris-admin-tool"` | The image repository to pull from. | +| bootstrap.image.tag | string | `"latest"` | The image tag. | +| bootstrap.realms | list | `[]` | The names of the realms to bootstrap. | | configMapLabels | object | `{}` | Additional Labels to apply to polaris configmap. | +| containerSecurityContext | object | `{}` | Security context for the polaris container. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/. | +| cors | object | `{"accessControlAllowCredentials":null,"accessControlMaxAge":null,"allowedHeaders":[],"allowedMethods":[],"allowedOrigins":[],"exposedHeaders":[]}` | Polaris CORS configuration. | +| cors.accessControlAllowCredentials | string | `nil` | The `Access-Control-Allow-Credentials` response header. The value of this header will default to `true` if `allowedOrigins` property is set and there is a match with the precise `Origin` header. | +| cors.accessControlMaxAge | string | `nil` | The `Access-Control-Max-Age` response header value indicating how long the results of a pre-flight request can be cached. Must be a valid duration. | +| cors.allowedHeaders | list | `[]` | HTTP headers allowed for CORS, ex: X-Custom, Content-Disposition. If this is not set or empty, all requested headers are considered allowed. | +| cors.allowedMethods | list | `[]` | HTTP methods allowed for CORS, ex: GET, PUT, POST. If this is not set or empty, all requested methods are considered allowed. | +| cors.allowedOrigins | list | `[]` | Origins allowed for CORS, e.g. http://polaris.io, http://localhost:8181. In case an entry of the list is surrounded by forward slashes, it is interpreted as a regular expression. | +| cors.exposedHeaders | list | `[]` | HTTP headers exposed to the client, ex: X-Custom, Content-Disposition. The default is an empty list. | | extraEnv | list | `[]` | Advanced configuration via Environment Variables. Extra environment variables to add to the Polaris server container. You can pass here any valid EnvVar object: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#envvar-v1-core This can be useful to get configuration values from Kubernetes secrets or config maps. | +| extraInitContainers | list | `[]` | Add additional init containers to the polaris pod(s) See https://kubernetes.io/docs/concepts/workloads/pods/init-containers/. | +| extraServices | list | `[]` | Additional service definitions. All service definitions always select all Polaris pods. Use this if you need to expose specific ports with different configurations, e.g. expose polaris-http with an alternate LoadBalancer service instead of ClusterIP. | +| extraVolumeMounts | list | `[]` | Extra volume mounts to add to the polaris container. See https://kubernetes.io/docs/concepts/storage/volumes/. | +| extraVolumes | list | `[]` | Extra volumes to add to the polaris pod. See https://kubernetes.io/docs/concepts/storage/volumes/. | +| features | object | `{"defaults":{},"realmOverrides":{}}` | Polaris features configuration. | +| features.defaults | object | `{}` | Features to enable or disable globally. If a feature is not present in the map, the default built-in value is used. | +| features.realmOverrides | object | `{}` | Features to enable or disable per realm. This field is a map of maps. The realm name is the key, and the value is a map of feature names to values. If a feature is not present in the map, the default value from the 'defaults' field is used. | +| fileIo | object | `{"type":"default"}` | Polaris FileIO configuration. | +| fileIo.type | string | `"default"` | The type of file IO to use. Two built-in types are supported: default and wasb. The wasb one translates WASB paths to ABFS ones. | +| image.configDir | string | `"/deployments/config"` | The path to the directory where the application.properties file, and other configuration files, if any, should be mounted. | | image.pullPolicy | string | `"IfNotPresent"` | The image pull policy. | -| image.repository | string | `"localhost:5001/polaris"` | The image repository to pull from. | +| image.repository | string | `"apache/polaris"` | The image repository to pull from. | | image.tag | string | `"latest"` | The image tag. | | imagePullSecrets | list | `[]` | References to secrets in the same namespace to use for pulling any of the images used by this chart. Each entry is a LocalObjectReference to an existing secret in the namespace. The secret must contain a .dockerconfigjson key with a base64-encoded Docker configuration file. See https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ for more information. | | ingress.annotations | object | `{}` | Annotations to add to the ingress. | @@ -94,30 +195,104 @@ $ helm uninstall --namespace polaris polaris | livenessProbe.successThreshold | int | `1` | Minimum consecutive successes for the probe to be considered successful after having failed. Minimum value is 1. | | livenessProbe.terminationGracePeriodSeconds | int | `30` | Optional duration in seconds the pod needs to terminate gracefully upon probe failure. Minimum value is 1. | | livenessProbe.timeoutSeconds | int | `10` | Number of seconds after which the probe times out. Minimum value is 1. | +| logging | object | `{"categories":{"org.apache.iceberg.rest":"INFO","org.apache.polaris":"INFO"},"console":{"enabled":true,"format":"%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] [%X{requestId},%X{realmId}] [%X{traceId},%X{parentId},%X{spanId},%X{sampled}] (%t) %s%e%n","json":false,"threshold":"ALL"},"file":{"enabled":false,"fileName":"polaris.log","format":"%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] [%X{requestId},%X{realmId}] [%X{traceId},%X{parentId},%X{spanId},%X{sampled}] (%t) %s%e%n","json":false,"logsDir":"/deployments/logs","rotation":{"fileSuffix":null,"maxBackupIndex":5,"maxFileSize":"100Mi"},"storage":{"className":"standard","selectorLabels":{},"size":"512Gi"},"threshold":"ALL"},"level":"INFO","mdc":{},"requestIdHeaderName":"Polaris-Request-Id"}` | Logging configuration. | +| logging.categories | object | `{"org.apache.iceberg.rest":"INFO","org.apache.polaris":"INFO"}` | Configuration for specific log categories. | +| logging.console | object | `{"enabled":true,"format":"%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] [%X{requestId},%X{realmId}] [%X{traceId},%X{parentId},%X{spanId},%X{sampled}] (%t) %s%e%n","json":false,"threshold":"ALL"}` | Configuration for the console appender. | +| logging.console.enabled | bool | `true` | Whether to enable the console appender. | +| logging.console.format | string | `"%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] [%X{requestId},%X{realmId}] [%X{traceId},%X{parentId},%X{spanId},%X{sampled}] (%t) %s%e%n"` | The log format to use. Ignored if JSON format is enabled. See https://quarkus.io/guides/logging#logging-format for details. | +| logging.console.json | bool | `false` | Whether to log in JSON format. | +| logging.console.threshold | string | `"ALL"` | The log level of the console appender. | +| logging.file | object | `{"enabled":false,"fileName":"polaris.log","format":"%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] [%X{requestId},%X{realmId}] [%X{traceId},%X{parentId},%X{spanId},%X{sampled}] (%t) %s%e%n","json":false,"logsDir":"/deployments/logs","rotation":{"fileSuffix":null,"maxBackupIndex":5,"maxFileSize":"100Mi"},"storage":{"className":"standard","selectorLabels":{},"size":"512Gi"},"threshold":"ALL"}` | Configuration for the file appender. | +| logging.file.enabled | bool | `false` | Whether to enable the file appender. | +| logging.file.fileName | string | `"polaris.log"` | The log file name. | +| logging.file.format | string | `"%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] [%X{requestId},%X{realmId}] [%X{traceId},%X{parentId},%X{spanId},%X{sampled}] (%t) %s%e%n"` | The log format to use. Ignored if JSON format is enabled. See https://quarkus.io/guides/logging#logging-format for details. | +| logging.file.json | bool | `false` | Whether to log in JSON format. | +| logging.file.logsDir | string | `"/deployments/logs"` | The local directory where log files are stored. The persistent volume claim will be mounted here. | +| logging.file.rotation | object | `{"fileSuffix":null,"maxBackupIndex":5,"maxFileSize":"100Mi"}` | Log rotation configuration. | +| logging.file.rotation.fileSuffix | string | `nil` | An optional suffix to append to the rotated log files. If present, the rotated log files will be grouped in time buckets, and each bucket will contain at most maxBackupIndex files. The suffix must be in a date-time format that is understood by DateTimeFormatter. If the suffix ends with .gz or .zip, the rotated files will also be compressed using the corresponding algorithm. | +| logging.file.rotation.maxBackupIndex | int | `5` | The maximum number of backup files to keep. | +| logging.file.rotation.maxFileSize | string | `"100Mi"` | The maximum size of the log file before it is rotated. Should be expressed as a Kubernetes quantity. | +| logging.file.storage | object | `{"className":"standard","selectorLabels":{},"size":"512Gi"}` | The log storage configuration. A persistent volume claim will be created using these settings. | +| logging.file.storage.className | string | `"standard"` | The storage class name of the persistent volume claim to create. | +| logging.file.storage.selectorLabels | object | `{}` | Labels to add to the persistent volume claim spec selector; a persistent volume with matching labels must exist. Leave empty if using dynamic provisioning. | +| logging.file.storage.size | string | `"512Gi"` | The size of the persistent volume claim to create. | +| logging.file.threshold | string | `"ALL"` | The log level of the file appender. | +| logging.level | string | `"INFO"` | The log level of the root category, which is used as the default log level for all categories. | +| logging.mdc | object | `{}` | Configuration for MDC (Mapped Diagnostic Context). Values specified here will be added to the log context of all incoming requests and can be used in log patterns. | +| logging.requestIdHeaderName | string | `"Polaris-Request-Id"` | The header name to use for the request ID. | +| managementService | object | `{"annotations":{},"clusterIP":null,"externalTrafficPolicy":null,"internalTrafficPolicy":null,"ports":[{"name":"polaris-mgmt","nodePort":null,"port":8182,"protocol":null,"targetPort":null}],"sessionAffinity":null,"trafficDistribution":null,"type":"ClusterIP"}` | Management service settings. These settings are used to configure liveness and readiness probes, and to configure the dedicated headless service that will expose health checks and metrics, e.g. for metrics scraping and service monitoring. | +| managementService.annotations | object | `{}` | Annotations to add to the service. | +| managementService.ports | list | `[{"name":"polaris-mgmt","nodePort":null,"port":8182,"protocol":null,"targetPort":null}]` | The ports the management service will listen on. At least one port is required; the first port implicitly becomes the HTTP port that the application will use for serving management requests. By default, it's 8182. Note: port names must be unique and no more than 15 characters long. | +| managementService.ports[0] | object | `{"name":"polaris-mgmt","nodePort":null,"port":8182,"protocol":null,"targetPort":null}` | The name of the management port. Required. | +| managementService.ports[0].nodePort | string | `nil` | The port on each node on which this service is exposed when type is NodePort or LoadBalancer. Usually assigned by the system. If not specified, a port will be allocated if this Service requires one. If this field is specified when creating a Service which does not need it, creation will fail. | +| managementService.ports[0].port | int | `8182` | The port the management service listens on. By default, the management interface is exposed on HTTP port 8182. | +| managementService.ports[0].protocol | string | `nil` | The IP protocol for this port. Supports "TCP", "UDP", and "SCTP". Default is TCP. | +| managementService.ports[0].targetPort | string | `nil` | Number or name of the port to access on the pods targeted by the service. If this is a string, it will be looked up as a named port in the target Pod's container ports. If this is not specified, the value of the 'port' field is used. | +| managementService.type | string | `"ClusterIP"` | The type of service to create. Valid values are: ExternalName, ClusterIP, NodePort, and LoadBalancer. The default value is ClusterIP. | +| metrics.enabled | bool | `true` | Specifies whether metrics for the polaris server should be enabled. | +| metrics.tags | object | `{}` | Additional tags (dimensional labels) to add to the metrics. | | nodeSelector | object | `{}` | Node labels which must match for the polaris pod to be scheduled on that node. See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector. | -| persistenceConfigSecret | string | `nil` | The secret name to pull persistence.xml from (ensure the key name is 'persistence.xml') | +| persistence | object | `{"eclipseLink":{"persistenceUnit":"polaris","secret":{"key":"persistence.xml","name":null}},"type":"eclipse-link"}` | Polaris persistence configuration. | +| persistence.eclipseLink | object | `{"persistenceUnit":"polaris","secret":{"key":"persistence.xml","name":null}}` | The configuration for the eclipse-link persistence manager. | +| persistence.eclipseLink.persistenceUnit | string | `"polaris"` | The persistence unit name to use. | +| persistence.eclipseLink.secret | object | `{"key":"persistence.xml","name":null}` | The secret name to pull persistence.xml from. | +| persistence.eclipseLink.secret.key | string | `"persistence.xml"` | The key in the secret to pull persistence.xml from. | +| persistence.eclipseLink.secret.name | string | `nil` | The name of the secret to pull persistence.xml from. If not provided, the default built-in persistence.xml will be used. This is probably not what you want. | +| persistence.type | string | `"eclipse-link"` | The type of persistence to use. Two built-in types are supported: in-memory and eclipse-link. | | podAnnotations | object | `{}` | Annotations to apply to polaris pods. | | podLabels | object | `{}` | Additional Labels to apply to polaris pods. | | podSecurityContext | object | `{}` | Security context for the polaris pod. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/. | -| polarisServerConfig | object | `{"authenticator":{"class":"org.apache.polaris.service.auth.TestInlineBearerTokenPolarisAuthenticator"},"callContextResolver":{"type":"default"},"cors":{"allowed-credentials":true,"allowed-headers":["*"],"allowed-methods":["PATCH","POST","DELETE","GET","PUT"],"allowed-origins":["http://localhost:8080"],"allowed-timing-origins":["http://localhost:8080"],"exposed-headers":["*"],"preflight-max-age":600},"defaultRealms":["default-realm"],"featureConfiguration":{"ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING":false,"SUPPORTED_CATALOG_STORAGE_TYPES":["S3","GCS","AZURE","FILE"]},"io":{"factoryType":"default"},"logging":{"appenders":[{"logFormat":"%-5p [%d{ISO8601} - %-6r] [%t] [%X{aid}%X{sid}%X{tid}%X{wid}%X{oid}%X{srv}%X{job}%X{rid}] %c{30}: %m %kvp%n%ex","threshold":"ALL","type":"console"}],"level":"INFO","loggers":{"org.apache.iceberg.rest":"DEBUG","org.apache.polaris":"DEBUG"}},"maxRequestBodyBytes":-1,"metaStoreManager":{"type":"in-memory"},"oauth2":{"type":"test"},"rateLimiter":{"type":"no-op"},"realmContextResolver":{"type":"default"},"server":{"adminConnectors":[{"port":8182,"type":"http"}],"applicationConnectors":[{"port":8181,"type":"http"}],"maxThreads":200,"minThreads":10,"requestLog":{"appenders":[{"type":"console"}]}}}` | Configures for polaris-server.yml | +| rateLimiter | object | `{"tokenBucket":{"requestsPerSecond":9999,"type":"default","window":"PT10S"},"type":"no-op"}` | Polaris rate limiter configuration. | +| rateLimiter.tokenBucket | object | `{"requestsPerSecond":9999,"type":"default","window":"PT10S"}` | The configuration for the default rate limiter, which uses the token bucket algorithm with one bucket per realm. | +| rateLimiter.tokenBucket.requestsPerSecond | int | `9999` | The maximum number of requests per second allowed for each realm. | +| rateLimiter.tokenBucket.type | string | `"default"` | The type of the token bucket rate limiter. Only the default type is supported out of the box. | +| rateLimiter.tokenBucket.window | string | `"PT10S"` | The time window. | +| rateLimiter.type | string | `"no-op"` | The type of rate limiter filter to use. Two built-in types are supported: default and no-op. | | readinessProbe | object | `{"failureThreshold":3,"initialDelaySeconds":5,"periodSeconds":10,"successThreshold":1,"timeoutSeconds":10}` | Configures the readiness probe for polaris pods. | | readinessProbe.failureThreshold | int | `3` | Minimum consecutive failures for the probe to be considered failed after having succeeded. Minimum value is 1. | | readinessProbe.initialDelaySeconds | int | `5` | Number of seconds after the container has started before readiness probes are initiated. Minimum value is 0. | | readinessProbe.periodSeconds | int | `10` | How often (in seconds) to perform the probe. Minimum value is 1. | | readinessProbe.successThreshold | int | `1` | Minimum consecutive successes for the probe to be considered successful after having failed. Minimum value is 1. | | readinessProbe.timeoutSeconds | int | `10` | Number of seconds after which the probe times out. Minimum value is 1. | +| realmContext | object | `{"realms":["POLARIS"],"type":"default"}` | Realm context resolver configuration. | +| realmContext.realms | list | `["POLARIS"]` | List of valid realms, for use with the default realm context resolver. The first realm in the list is the default realm. Realms not in this list will be rejected. | +| realmContext.type | string | `"default"` | The type of realm context resolver to use. Two built-in types are supported: default and test; test is not recommended for production as it does not perform any realm validation. | | replicaCount | int | `1` | The number of replicas to deploy (horizontal scaling). Beware that replicas are stateless; don't set this number > 1 when using in-memory meta store manager. | | resources | object | `{}` | Configures the resources requests and limits for polaris pods. We usually recommend not to specify default resources and to leave this as a conscious choice for the user. This also increases chances charts run on environments with little resources, such as Minikube. If you do want to specify resources, uncomment the following lines, adjust them as necessary, and remove the curly braces after 'resources:'. | | revisionHistoryLimit | string | `nil` | The number of old ReplicaSets to retain to allow rollback (if not set, the default Kubernetes value is set to 10). | -| securityContext | object | `{}` | Security context for the polaris container. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/. | +| service | object | `{"annotations":{},"clusterIP":null,"externalTrafficPolicy":null,"internalTrafficPolicy":null,"ports":[{"name":"polaris-http","nodePort":null,"port":8181,"protocol":null,"targetPort":null}],"sessionAffinity":null,"trafficDistribution":null,"type":"ClusterIP"}` | Polaris main service settings. | | service.annotations | object | `{}` | Annotations to add to the service. | -| service.ports | object | `{"polaris-metrics":8182,"polaris-service":8181}` | The ports the service will listen on. Two ports are required: one for the Polaris service and one for the metrics API. Note: port names must be unique and no more than 15 characters long. | -| service.sessionAffinity | string | `"None"` | The session affinity for the service. Valid values are: None, ClientIP. ClientIP enables sticky sessions based on the client's IP address. This is generally beneficial to Polaris deployments, but some testing may be required in order to make sure that the load is distributed evenly among the pods. Also, this setting affects only internal clients, not external ones. If Ingress is enabled, it is recommended to set sessionAffinity to None. | -| service.type | string | `"ClusterIP"` | The type of service to create. | +| service.clusterIP | string | `nil` | You can specify your own cluster IP address If you define a Service that has the .spec.clusterIP set to "None" then Kubernetes does not assign an IP address. Instead, DNS records for the service will return the IP addresses of each pod targeted by the server. This is called a headless service. See https://kubernetes.io/docs/concepts/services-networking/service/#headless-services | +| service.externalTrafficPolicy | string | `nil` | Controls how traffic from external sources is routed. Valid values are Cluster and Local. The default value is Cluster. Set the field to Cluster to route traffic to all ready endpoints. Set the field to Local to only route to ready node-local endpoints. If the traffic policy is Local and there are no node-local endpoints, traffic is dropped by kube-proxy. | +| service.internalTrafficPolicy | string | `nil` | Controls how traffic from internal sources is routed. Valid values are Cluster and Local. The default value is Cluster. Set the field to Cluster to route traffic to all ready endpoints. Set the field to Local to only route to ready node-local endpoints. If the traffic policy is Local and there are no node-local endpoints, traffic is dropped by kube-proxy. | +| service.ports | list | `[{"name":"polaris-http","nodePort":null,"port":8181,"protocol":null,"targetPort":null}]` | The ports the service will listen on. At least one port is required; the first port implicitly becomes the HTTP port that the application will use for serving API requests. By default, it's 8181. Note: port names must be unique and no more than 15 characters long. | +| service.ports[0] | object | `{"name":"polaris-http","nodePort":null,"port":8181,"protocol":null,"targetPort":null}` | The name of the port. Required. | +| service.ports[0].nodePort | string | `nil` | The port on each node on which this service is exposed when type is NodePort or LoadBalancer. Usually assigned by the system. If not specified, a port will be allocated if this Service requires one. If this field is specified when creating a Service which does not need it, creation will fail. | +| service.ports[0].port | int | `8181` | The port the service listens on. By default, the HTTP port is 8181. | +| service.ports[0].protocol | string | `nil` | The IP protocol for this port. Supports "TCP", "UDP", and "SCTP". Default is TCP. | +| service.ports[0].targetPort | string | `nil` | Number or name of the port to access on the pods targeted by the service. If this is a string, it will be looked up as a named port in the target Pod's container ports. If this is not specified, the value of the 'port' field is used. | +| service.sessionAffinity | string | `nil` | The session affinity for the service. Valid values are: None, ClientIP. The default value is None. ClientIP enables sticky sessions based on the client's IP address. This is generally beneficial to Polaris deployments, but some testing may be required in order to make sure that the load is distributed evenly among the pods. Also, this setting affects only internal clients, not external ones. If Ingress is enabled, it is recommended to set sessionAffinity to None. | +| service.trafficDistribution | string | `nil` | The traffic distribution field provides another way to influence traffic routing within a Kubernetes Service. While traffic policies focus on strict semantic guarantees, traffic distribution allows you to express preferences such as routing to topologically closer endpoints. The only valid value is: PreferClose. The default value is implementation-specific. | +| service.type | string | `"ClusterIP"` | The type of service to create. Valid values are: ExternalName, ClusterIP, NodePort, and LoadBalancer. The default value is ClusterIP. | | serviceAccount.annotations | object | `{}` | Annotations to add to the service account. | | serviceAccount.create | bool | `true` | Specifies whether a service account should be created. | | serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. | +| serviceMonitor.enabled | bool | `true` | Specifies whether a ServiceMonitor for Prometheus operator should be created. | +| serviceMonitor.interval | string | `""` | The scrape interval; leave empty to let Prometheus decide. Must be a valid duration, e.g. 1d, 1h30m, 5m, 10s. | +| serviceMonitor.labels | object | `{}` | Labels for the created ServiceMonitor so that Prometheus operator can properly pick it up. | +| serviceMonitor.metricRelabelings | list | `[]` | Relabeling rules to apply to metrics. Ref https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config. | +| storage | object | `{"secret":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"gcpToken":null,"gcpTokenLifespan":null,"name":null}}` | Storage credentials for the server. If the following properties are unset, default credentials will be used, in which case the pod must have the necessary permissions to access the storage. | +| storage.secret | object | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"gcpToken":null,"gcpTokenLifespan":null,"name":null}` | The secret to pull storage credentials from. | +| storage.secret.awsAccessKeyId | string | `nil` | The key in the secret to pull the AWS access key ID from. Only required when using AWS. | +| storage.secret.awsSecretAccessKey | string | `nil` | The key in the secret to pull the AWS secret access key from. Only required when using AWS. | +| storage.secret.gcpToken | string | `nil` | The key in the secret to pull the GCP token from. Only required when using GCP. | +| storage.secret.gcpTokenLifespan | string | `nil` | The key in the secret to pull the GCP token expiration time from. Only required when using GCP. Must be a valid ISO 8601 duration. The default is PT1H (1 hour). | +| storage.secret.name | string | `nil` | The name of the secret to pull storage credentials from. | +| tasks | object | `{"maxConcurrentTasks":null,"maxQueuedTasks":null}` | Polaris asynchronous task executor configuration. | +| tasks.maxConcurrentTasks | string | `nil` | The maximum number of concurrent tasks that can be executed at the same time. The default is the number of available cores. | +| tasks.maxQueuedTasks | string | `nil` | The maximum number of tasks that can be queued up for execution. The default is Integer.MAX_VALUE. | | tolerations | list | `[]` | A list of tolerations to apply to polaris pods. See https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/. | -| toolsImage.pullPolicy | string | `"IfNotPresent"` | The image pull policy. | -| toolsImage.repository | string | `"registry.access.redhat.com/ubi9/openjdk-21"` | The image repository to pull from (must have jar binary included). | -| toolsImage.tag | string | `"latest"` | The image tag. | \ No newline at end of file +| tracing.attributes | object | `{}` | Resource attributes to identify the polaris service among other tracing sources. See https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/#service. If left empty, traces will be attached to a service named "Apache Polaris"; to change this, provide a service.name attribute here. | +| tracing.enabled | bool | `false` | Specifies whether tracing for the polaris server should be enabled. | +| tracing.endpoint | string | `"http://otlp-collector:4317"` | The collector endpoint URL to connect to (required). The endpoint URL must have either the http:// or the https:// scheme. The collector must talk the OpenTelemetry protocol (OTLP) and the port must be its gRPC port (by default 4317). See https://quarkus.io/guides/opentelemetry for more information. | +| tracing.sample | string | `"1.0d"` | Which requests should be sampled. Valid values are: "all", "none", or a ratio between 0.0 and "1.0d" (inclusive). E.g. "0.5d" means that 50% of the requests will be sampled. Note: avoid entering numbers here, always prefer a string representation of the ratio. | \ No newline at end of file diff --git a/helm/polaris/README.md.gotmpl b/helm/polaris/README.md.gotmpl index 43a5f2be0f..97a1dbdb2c 100644 --- a/helm/polaris/README.md.gotmpl +++ b/helm/polaris/README.md.gotmpl @@ -6,9 +6,9 @@ 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 @@ -49,23 +49,85 @@ ### Optional -When using a custom `persistence.xml`, a Kubernetes Secret must be created for `.persistenceConfigSecret`. Below is a sample command: +When using a custom `persistence.xml`, a Kubernetes Secret must be created for it. Below is a sample command: ```bash kubectl create secret generic polaris-secret -n polaris --from-file=persistence.xml ``` -### From local directory (for development purposes) +### Running the unit tests + +Helm unit tests do not require a Kubernetes cluster. To run the unit tests from the Polaris repo +root: + +```bash +helm unittest helm/polaris 2> >(grep -v 'found symbolic link' >&2) +``` + +Note: the `grep` command is used to filter out the annoying warning messages about symbolic links; +see https://github.com/helm/helm/issues/7019. + +### Running locally with a Kind cluster + +The below instructions assume Kind and Helm are installed. + +Simply run the `run.sh` script from the Polaris repo root, making sure to specify the +`--eclipse-link-deps` option: + +```bash +./run.sh --eclipse-link-deps=org.postgresql:postgresql:42.7.4 +``` + +This script will create a Kind cluster, deploy a local Docker registry, build the Polaris Docker +images with support for Postgres and load them into the Kind cluster. (It will also create an +example Deployment and Service with in-memory storage.) + +### Running locally with a Minikube cluster + +The below instructions assume a Minikube cluster is already running and Helm is installed. + +If necessary, build and load the Docker images with support for Postgres into Minikube: + +```bash +eval $(minikube -p minikube docker-env) + +./gradlew :polaris-quarkus-server:assemble :polaris-quarkus-admin:assemble \ + -Dquarkus.container-image.build=true \ + -PeclipseLinkDeps=org.postgresql:postgresql:42.7.4 +``` + +### Installing the chart locally + +The below instructions assume a local Kubernetes cluster is running and Helm is installed. + +Create and populate the target namespace: + +```bash +kubectl create namespace polaris +kubectl apply --namespace polaris -f helm/polaris/ci/fixtures/ +``` + +Finally, install the chart. From Polaris repo root: + +```bash +helm upgrade --install --namespace polaris \ + --debug --values helm/polaris/ci/simple-values.yaml \ + polaris helm/polaris +``` + +The `helm/polaris/ci` contains a number of values files that can be used to install the chart with +different configurations. -From Polaris repo root: +You can also run `ct` (chart-testing): ```bash -$ helm install polaris helm/polaris --namespace polaris --create-namespace +ct lint --charts helm/polaris +ct install --namespace polaris --debug --charts ./helm/polaris ``` ### Uninstalling the chart ```bash -$ helm uninstall --namespace polaris polaris +helm uninstall --namespace polaris polaris ``` {{ template "chart.valuesSection" . }} \ No newline at end of file diff --git a/helm/polaris/ci/extra-service-values.yaml b/helm/polaris/ci/extra-service-values.yaml new file mode 100644 index 0000000000..e19835a831 --- /dev/null +++ b/helm/polaris/ci/extra-service-values.yaml @@ -0,0 +1,47 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +image: + pullPolicy: Never + +service: + type: ClusterIP + sessionAffinity: ClientIP + internalTrafficPolicy: Cluster + externalTrafficPolicy: Cluster + ports: + - name: polaris-http + port: 18181 + targetPort: 8181 + protocol: TCP + - name: polaris-http2 + port: 28181 + targetPort: 8181 + protocol: TCP + +extraServices: + - nameSuffix: "ext" + type: ClusterIP + sessionAffinity: None + internalTrafficPolicy: Local + externalTrafficPolicy: Local + ports: + - name: polaris-http2 + port: 38181 + targetPort: 8181 diff --git a/helm/polaris/ci/fixtures/persistence.yaml b/helm/polaris/ci/fixtures/persistence.yaml index 78e078112b..18731d7046 100644 --- a/helm/polaris/ci/fixtures/persistence.yaml +++ b/helm/polaris/ci/fixtures/persistence.yaml @@ -38,9 +38,10 @@ stringData: org.apache.polaris.jpa.models.ModelSequenceId NONE - - - + + + diff --git a/helm/polaris/ci/fixtures/postgres.yaml b/helm/polaris/ci/fixtures/postgres.yaml new file mode 100644 index 0000000000..155321d960 --- /dev/null +++ b/helm/polaris/ci/fixtures/postgres.yaml @@ -0,0 +1,72 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres +spec: + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: postgres:17.2 + ports: + - containerPort: 5432 + resources: + limits: + memory: "128Mi" + env: + - name: POSTGRES_USER + value: "postgres" + - name: POSTGRES_PASSWORD + value: "postgres" + - name: POSTGRES_DB + value: "POLARIS" + - name: POSTGRES_INITDB_ARGS + value: "--encoding UTF8 --data-checksums" + readinessProbe: + exec: + command: + - pg_isready + - -U + - postgres + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 2 + failureThreshold: 15 +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres +spec: + selector: + app: postgres + ports: + - protocol: TCP + port: 5432 + targetPort: 5432 diff --git a/helm/polaris/ci/fixtures/storage.yaml b/helm/polaris/ci/fixtures/storage.yaml new file mode 100644 index 0000000000..85aca71076 --- /dev/null +++ b/helm/polaris/ci/fixtures/storage.yaml @@ -0,0 +1,27 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +apiVersion: v1 +kind: Secret +metadata: + name: polaris-storage +type: Opaque +stringData: + access-key: "my-key" + secret-key: "my-secret" \ No newline at end of file diff --git a/helm/polaris/ci/fixtures/token-broker.yaml b/helm/polaris/ci/fixtures/token-broker.yaml new file mode 100644 index 0000000000..5a10fbc083 --- /dev/null +++ b/helm/polaris/ci/fixtures/token-broker.yaml @@ -0,0 +1,59 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +apiVersion: v1 +kind: Secret +metadata: + name: polaris-token-broker +type: Opaque +stringData: + private.pem: |- + -----BEGIN PRIVATE KEY----- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDiae5jQnQ+Dt8Optpa4fLNuUfI + 37Sy29JPfn22CkGNo54SJi8NtR38Q958Bx9B+30IZPm3KtZGPC38Tm78/C508h7/Bd0jO7S3/UuQ + rYlg9H8gC59j14fE5cKEiKCvHrNK35Act9LrfhwEoGBs7G+90KD3SBIWzoc4vS8AB/ey09kRN3+M + dQ/DuRrafRgEx8ecq0x4KPggrmvworVVm1ya+H2JNKUQ+uQugmwxeRDE1GuJrgNnn4+ajueEnGdc + ohgz067AgZExzoyRlujJXBuL6JRtOSbEYVpNV1laVdA8UJ2b5I1PiNnVvx1m4gFi/Cela479EO6t + +AC+a1ez+MxTAgMBAAECggEAA1QiXJQ4CEeIsPrz/90NiEe+je34Bp8jtuZ5q6j38MCkjMjB7VYp + 1DEdPr6OD5bGbk6puy8mik7NMEXo7NA6UJ7UpNQtvZxdmkzfhQeAGwxNKCfzlnCvPs5P70ng7uIp + KaMix8FOGQc4GztOX5uUQvqjuy70kSBFLajeXYZAdoEOu+E3QDaCUqiJlK3cRAJhg39Br+XfOHDp + cBdhlbxqQKZHWqDR010XUNoQpMHXWTu/e779Xze9uAvmYw98YGtCW8JB5AqjnqAmCZFaktKYw5Z3 + IHZCA9hTVngk0WTanuIeTlB2bbl0df+87xHfim2yDuXEkTfAOCug/Qpf+pEhfQKBgQD9M14a1MQ2 + Omf9f7X401Ig32e2YfX6sW73THB8Lupz9MCBZxNFCZlzVl55bL2o2vOROEeaneGdboqASW+1ph6e + QbdipiYAfHsG/mvkysqH/plo8QT69GUlzs2yt5zdmFjvkwaZmRmbB6Gjg2sSHKBt3YjTPbdmpuKV + oLvpmaslvQKBgQDk6r+4CGTZwfKYcrTNqJYPdOwfaVjSCulm0wHRw3PvJEi5Eb5qNaJbNICLl5FD + wkOAg33CZ+9h9FJnPd2IbBUBUGcNL5sGNZZNMH16LuFlRYKGgYxjlOjktOC5OXXa7iqkwMqf1dFf + GYU/wHGXYamUKOlinA9rFmbQCUNJL6mzTwKBgQC5Ky/O/3rfDaevRA6YgjK1x6vZPZreU5SLVmOM + 7eKYGo4OFIuLGZIXPzqoIlYxfq5RrY7wDDZLI+Q2HX6MoYgSxIyQoGF6SY7PdpEBKS0kd5VJobm6 + rbCrDapw4MbfZ+LiketpuQV40wPqyNkszbKlpjXCBohxkepy8rF6DN+VIQKBgFYHFnedx/DB316F + NQdYxNQYN6hyWavN5/r5b2SaVFZZx26tiWa2s0YdS/WpxzC0r9N7FubZUm/4doNQD5H2NEqjIacl + 7dd+ifaGM5GYTqJVZgEQbGb8Di3s/8r8Ghtlh+cUgNFidGWN3LKhqs6eKDGC0np5dZ3j9E1YPc4i + OF8nAoGAYeFjfXBXKQhQXItTlL5NMd+yNvMGJDOvNYOn90acZrDld8GvqHI9A1kQf2IuYfA8Yfxg + O2lpCWjiPAsAC3W5BMhfkzjxpikW6YLpXXx7wpDzNAUBAuhEHlmFSMOoa4CIBnN2+6Zw8PSsKnrI + 49N28pje/ZyABaY7SYP3fcJY17o= + -----END PRIVATE KEY----- + public.pem: |- + -----BEGIN PUBLIC KEY----- + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4mnuY0J0Pg7fDqbaWuHyzblHyN+0stvS + T359tgpBjaOeEiYvDbUd/EPefAcfQft9CGT5tyrWRjwt/E5u/PwudPIe/wXdIzu0t/1LkK2JYPR/ + IAufY9eHxOXChIigrx6zSt+QHLfS634cBKBgbOxvvdCg90gSFs6HOL0vAAf3stPZETd/jHUPw7ka + 2n0YBMfHnKtMeCj4IK5r8KK1VZtcmvh9iTSlEPrkLoJsMXkQxNRria4DZ5+Pmo7nhJxnXKIYM9Ou + wIGRMc6MkZboyVwbi+iUbTkmxGFaTVdZWlXQPFCdm+SNT4jZ1b8dZuIBYvwnpWuO/RDurfgAvmtX + s/jMUwIDAQAB + -----END PUBLIC KEY----- diff --git a/helm/polaris/ci/persistence-values.yaml b/helm/polaris/ci/persistence-values.yaml index 5317f6f4a8..ff97a5ecc8 100644 --- a/helm/polaris/ci/persistence-values.yaml +++ b/helm/polaris/ci/persistence-values.yaml @@ -20,10 +20,29 @@ image: pullPolicy: Never -persistenceConfigSecret: polaris-persistence +authentication: + tokenBroker: + secret: + name: polaris-token-broker -polarisServerConfig: - metaStoreManager: - type: eclipse-link - persistence-unit: polaris - conf-file: /eclipselink-config/conf.jar!/persistence.xml +logging: + file: + enabled: true + json: true + storage: + size: 50Mi + +persistence: + type: eclipse-link + eclipseLink: + secret: + name: polaris-persistence + +bootstrap: + enabled: true + realms: + - POLARIS + credentials: + - POLARIS,root,secret + image: + pullPolicy: Never diff --git a/helm/polaris/ci/simple-values.yaml b/helm/polaris/ci/simple-values.yaml index 0e6d291dac..e3e7c41da2 100644 --- a/helm/polaris/ci/simple-values.yaml +++ b/helm/polaris/ci/simple-values.yaml @@ -19,3 +19,13 @@ image: pullPolicy: Never + +storage: + secret: + name: polaris-storage + awsAccessKeyId: access-key + awsSecretAccessKey: secret-key + +extraEnv: + - name: POLARIS_BOOTSTRAP_CREDENTIALS + value: root,root,secret diff --git a/helm/polaris/templates/_helpers.tpl b/helm/polaris/templates/_helpers.tpl index 3514deb61c..7a7dfb9ad7 100644 --- a/helm/polaris/templates/_helpers.tpl +++ b/helm/polaris/templates/_helpers.tpl @@ -42,6 +42,29 @@ {{- end }} {{- end }} +{{/* + Create a default fully qualified app name, with a custom suffix. Useful when the name will + have a suffix appended to it, such as for the management service name. +*/}} +{{- define "polaris.fullnameWithSuffix" -}} +{{- $global := index . 0 }} +{{- $suffix := index . 1 }} +{{- if not (hasPrefix "-" $suffix) }} +{{- $suffix = printf "-%s" $suffix }} +{{- end }} +{{- $length := int (sub 63 (len $suffix)) }} +{{- if $global.Values.fullnameOverride }} +{{- $global.Values.fullnameOverride | trunc $length }}{{ $suffix }} +{{- else }} +{{- $name := default $global.Chart.Name $global.Values.nameOverride }} +{{- if contains $name $global.Release.Name }} +{{- $global.Release.Name | trunc $length }}{{ $suffix }} +{{- else }} +{{- printf "%s-%s" $global.Release.Name $name | trunc $length }}{{ $suffix }} +{{- end }} +{{- end }} +{{- end }} + {{/* Create chart name and version as used by the chart label. */}} @@ -79,3 +102,222 @@ app.kubernetes.io/instance: {{ .Release.Name }} {{- default "default" .Values.serviceAccount.name }} {{- end }} {{- end }} + +{{/* +Merges a configuration tree into the destination configuration map. See configmap.yaml template. +Two styles of configuration trees are supported: +- Flattened configuration tree: The configuration option names are specified as a dot-separated + string, and the configuration option values are the values of the configuration options. E.g.: + "key1.subkey1": "value1" + "key1.subkey2.subsubkey1": "value2" +- Nested configuration tree: The configuration option names are specified as a nested structure. + The resulting option names are formed by concatenating the nested keys with a dot separator. + E.g.: + key1: + subkey1: "value1" + subkey2: + subsubkey1: "value2" +The configuration option values are evaluated as templates against the global context before being +printed. +*/}} +{{- define "polaris.mergeConfigTree" -}} +{{- $advConfig := index . 0 -}} +{{- $prefix := index . 1 -}} +{{- $dest := index . 2 -}} +{{- range $key, $val := $advConfig -}} +{{- $name := ternary $key (print $prefix "." $key) (eq $prefix "") -}} +{{- if kindOf $val | eq "map" -}} +{{- list $val $name $dest | include "polaris.mergeConfigTree" -}} +{{- else -}} +{{- $_ := set $dest $name $val -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Prints the configuration option to the destination configmap entry. See configmap.yaml template. +Any nil values will be printed as empty config options; otherwise, the value will be evaluated +as a template against the global context, then printed. Furthermore, if the value contains +line breaks, they will be escaped and a multi-line option will be printed. +*/}} +{{- define "polaris.appendConfigOption" -}} +{{- $key := index . 0 -}} +{{- $value := index . 1 -}} +{{- $global := index . 2 -}} +{{- $valAsString := "" -}} +{{- if ne $value nil -}} +{{- $valAsString = tpl (toString $value) $global -}} +{{- if contains "\r\n" $valAsString -}} +{{- $valAsString = $valAsString | nindent 4 | replace "\r\n" "\\\r\n" -}} +{{- else if contains "\n" $valAsString -}} +{{- $valAsString = $valAsString | nindent 4 | replace "\n" "\\\n" -}} +{{- end -}} +{{- end -}} +{{ print $key "=" $valAsString }} +{{- end -}} + +{{/* +Convert a dict into a string formed by a comma-separated list of key-value pairs: key1=value1,key2=value2, ... +*/}} +{{- define "polaris.dictToString" -}} +{{- $list := list -}} +{{- range $k, $v := . -}} +{{- $list = append $list (printf "%s=%s" $k $v) -}} +{{- end -}} +{{ join "," $list }} +{{- end -}} + +{{/* +Prints the config volume definition for deployments and jobs. +*/}} +{{- define "polaris.configVolume" -}} +- name: config-volume + projected: + sources: + - configMap: + name: {{ include "polaris.fullname" . }} + items: + - key: application.properties + path: application.properties + {{- if .Values.authentication.tokenBroker.secret.name }} + - secret: + name: {{ tpl .Values.authentication.tokenBroker.secret.name . }} + items: + {{- if eq .Values.authentication.tokenBroker.type "rsa-key-pair" }} + - key: {{ tpl .Values.authentication.tokenBroker.secret.publicKey . }} + path: public.pem + - key: {{ tpl .Values.authentication.tokenBroker.secret.privateKey . }} + path: private.pem + {{- end }} + {{- if eq .Values.authentication.tokenBroker.type "symmetric-key" }} + - key: {{ tpl .Values.authentication.tokenBroker.secret.secretKey . }} + path: symmetric.key + {{- end }} + {{- end }} + {{- if and ( eq .Values.persistence.type "eclipse-link" ) .Values.persistence.eclipseLink.secret.name }} + - secret: + name: {{ tpl .Values.persistence.eclipseLink.secret.name . }} + items: + - key: {{ tpl .Values.persistence.eclipseLink.secret.key . }} + path: persistence.xml + {{- end }} +{{- end -}} + +{{/* +Prints an environment variable for a secret key reference. +*/}} +{{- define "polaris.secretToEnv" -}} +{{- $secret := index . 0 -}} +{{- $keyRef := index . 1 -}} +{{- $varName := index . 2 -}} +{{- $key := get $secret $keyRef -}} +{{- if and $secret.name $key }} +- name: {{ $varName }} + valueFrom: + secretKeyRef: + name: {{ $secret.name }} + key: {{ $key }} +{{- end -}} +{{- end -}} + +{{/* +Converts a Kubernetes quantity to a number (int64 if possible or float64 otherwise). +It handles raw numbers as well as quantities with suffixes +like m, k, M, G, T, P, E, ki, Mi, Gi, Ti, Pi, Ei. +It also handles scientific notation. +Quantities should be positive, so negative values, zero, or any unparseable number +will result in a failure. +https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/quantity/ +*/}} +{{- define "polaris.quantity" -}} +{{- $quantity := . -}} +{{- $n := $quantity | float64 -}} +{{- if kindIs "string" $quantity -}} +{{- if hasSuffix "m" $quantity -}} +{{- $n = divf (trimSuffix "m" $quantity | float64) 1000.0 -}} +{{- else if hasSuffix "k" $quantity -}} +{{- $n = trimSuffix "k" $quantity | int64 | mul 1000 -}} +{{- else if hasSuffix "M" $quantity -}} +{{- $n = trimSuffix "M" $quantity | int64 | mul 1000000 -}} +{{- else if hasSuffix "G" $quantity -}} +{{- $n = trimSuffix "G" $quantity | int64 | mul 1000000000 -}} +{{- else if hasSuffix "T" $quantity -}} +{{- $n = trimSuffix "T" $quantity | int64 | mul 1000000000000 -}} +{{- else if hasSuffix "P" $quantity -}} +{{- $n = trimSuffix "P" $quantity | int64 | mul 1000000000000000 -}} +{{- else if hasSuffix "E" $quantity -}} +{{- $n = trimSuffix "E" $quantity | int64 | mul 1000000000000000000 -}} +{{- else if hasSuffix "ki" $quantity -}} +{{- $n = trimSuffix "ki" $quantity | int64 | mul 1024 -}} +{{- else if hasSuffix "Mi" $quantity -}} +{{- $n = trimSuffix "Mi" $quantity | int64 | mul 1048576 -}} +{{- else if hasSuffix "Gi" $quantity -}} +{{- $n = trimSuffix "Gi" $quantity | int64 | mul 1073741824 -}} +{{- else if hasSuffix "Ti" $quantity -}} +{{- $n = trimSuffix "Ti" $quantity | int64 | mul 1099511627776 -}} +{{- else if hasSuffix "Pi" $quantity -}} +{{- $n = trimSuffix "Pi" $quantity | int64 | mul 1125899906842624 -}} +{{- else if hasSuffix "Ei" $quantity -}} +{{- $n = trimSuffix "Ei" $quantity | int64 | mul 1152921504606846976 -}} +{{- end -}} +{{- end -}} +{{- if le ($n | float64) 0.0 -}} +{{- fail (print "invalid quantity: " $quantity) -}} +{{- end -}} +{{- if kindIs "float64" $n -}} +{{- printf "%f" $n -}} +{{- else -}} +{{- printf "%v" $n -}} +{{- end -}} +{{- end -}} + +{{/* +Prints the ports section of the container spec. Also validates all port names to ensure +that they are unique. +*/}} +{{- define "polaris.containerPorts" -}} +{{- $ports := dict -}} +{{- $protocols := dict -}} +{{- /* Main service ports */ -}} +{{- range $i, $port := .Values.service.ports -}} +{{- if hasKey $ports $port.name -}} +{{- fail (printf "service.ports[%d]: port name already taken: %v" $i $port.name) -}} +{{- end -}} +{{- $portNumber := coalesce $port.targetPort $port.port -}} +{{- $_ := set $ports $port.name $portNumber -}} +{{- $_ = set $protocols $port.name ($port.protocol | default "TCP") -}} +{{- end -}} +{{- /* Management service ports */ -}} +{{- range $i, $port := .Values.managementService.ports -}} +{{- if hasKey $ports $port.name -}} +{{- fail (printf "managementService.ports[%d]: port name already taken: %v" $i $port.name) -}} +{{- end -}} +{{- $portNumber := coalesce $port.targetPort $port.port -}} +{{- $_ := set $ports $port.name $portNumber }} +{{- $_ = set $protocols $port.name ($port.protocol | default "TCP") -}} +{{- end -}} +{{- /* Extra service ports */ -}} +{{- range $i, $svc := .Values.extraServices -}} +{{- range $j, $port := $svc.ports -}} +{{- $portNumber := coalesce $port.targetPort $port.port -}} +{{- if hasKey $ports $port.name -}} +{{- if ne $portNumber (get $ports $port.name) -}} +{{- fail (printf "extraServices[%d].ports[%d]: wrong port number for port %s, expected %v, got %v" $i $j $port.name (get $ports $port.name) $portNumber) -}} +{{- end -}} +{{- end -}} +{{- if hasKey $protocols $port.name -}} +{{- if ne ($port.protocol | default "TCP") (get $protocols $port.name) -}} +{{- fail (printf "extraServices[%d].ports[%d]: wrong protocol for port %s, expected %v, got %v" $i $j $port.name (get $protocols $port.name) $port.protocol) -}} +{{- end -}} +{{- end -}} +{{- $_ := set $ports $port.name $portNumber -}} +{{- $_ = set $protocols $port.name ($port.protocol | default "TCP") -}} +{{- end -}} +{{- end }} +ports: +{{- range $portName, $portNumber := $ports }} + - name: {{ $portName }} + containerPort: {{ $portNumber }} + protocol: {{ get $protocols $portName }} +{{- end }} +{{- end -}} diff --git a/helm/polaris/templates/configmap.yaml b/helm/polaris/templates/configmap.yaml index 97bc983e57..8433e19c72 100644 --- a/helm/polaris/templates/configmap.yaml +++ b/helm/polaris/templates/configmap.yaml @@ -28,5 +28,176 @@ metadata: {{- tpl (toYaml .Values.configMapLabels) . | nindent 4 }} {{- end }} data: - polaris-server.yml: |- -{{ toYaml .Values.polarisServerConfig | indent 4 }} \ No newline at end of file + application.properties: |- + {{- $map := dict -}} + + {{- /* Realm Context */ -}} + {{- $_ := set $map "polaris.realm-context.type" .Values.realmContext.type -}} + {{- $_ = set $map "polaris.realm-context.realms" (join "," .Values.realmContext.realms) -}} + + {{- /* Features */ -}} + {{- range $k, $v := .Values.features.defaults -}} + {{- $_ = set $map (printf "polaris.features.defaults.\"%s\"" $k) (toJson $v) -}} + {{- end -}} + {{- range $realm, $overrides := .Values.features.realmOverrides -}} + {{- range $k, $v := $overrides -}} + {{- $_ = set $map (printf "polaris.config.realm-overrides.\"%s\".\"%s\"" $realm $k) (toJson $v) -}} + {{- end -}} + {{- end -}} + + {{- /* Persistence */ -}} + {{- $_ = set $map "polaris.persistence.type" .Values.persistence.type -}} + {{- if and ( eq .Values.persistence.type "eclipse-link" ) .Values.persistence.eclipseLink.secret.name -}} + {{- $_ = set $map "polaris.persistence.eclipselink.persistence-unit" .Values.persistence.eclipseLink.persistenceUnit -}} + {{- $_ = set $map "polaris.persistence.eclipselink.configuration-file" (printf "%s/persistence.xml" .Values.image.configDir ) -}} + {{- end -}} + + {{- /* File IO */ -}} + {{- $_ = set $map "polaris.file-io.type" .Values.fileIo.type -}} + + {{- /* Storage */ -}} + {{- if .Values.storage.secret.gcpTokenLifespan -}} + {{- $_ = set $map "polaris.storage.gcp.lifespan" .Values.storage.secret.gcpTokenLifespan -}} + {{- end -}} + + {{- /* Rate Limiter */ -}} + {{- $_ = set $map "polaris.rate-limiter.filter.type" .Values.rateLimiter.type -}} + {{- if ne .Values.rateLimiter.type "no-op" -}} + {{- $_ = set $map "polaris.rate-limiter.token-bucket.type" .Values.rateLimiter.tokenBucket.type -}} + {{- $_ = set $map "polaris.rate-limiter.token-bucket.requests-per-second" .Values.rateLimiter.tokenBucket.requestsPerSecond -}} + {{- $_ = set $map "polaris.rate-limiter.token-bucket.window" .Values.rateLimiter.tokenBucket.window -}} + {{- end -}} + + {{- /* Tasks */ -}} + {{- if .Values.tasks.maxConcurrentTasks -}} + {{- $_ = set $map "polaris.tasks.max-concurrent-tasks" .Values.tasks.maxConcurrentTasks -}} + {{- end -}} + {{- if .Values.tasks.maxQueuedTasks -}} + {{- $_ = set $map "polaris.tasks.max-queued-tasks" .Values.tasks.maxQueuedTasks -}} + {{- end -}} + + {{- /* Authentication */ -}} + {{- $_ = set $map "polaris.authentication.authenticator.type" .Values.authentication.authenticator.type -}} + {{- $_ = set $map "polaris.authentication.token-service.type" .Values.authentication.tokenService.type -}} + {{- $_ = set $map "polaris.authentication.token-broker.type" .Values.authentication.tokenBroker.type -}} + {{- $_ = set $map "polaris.authentication.token-broker.max-token-generation" .Values.authentication.tokenBroker.maxTokenGeneration -}} + {{- if .Values.authentication.tokenBroker.secret.name -}} + {{- if eq .Values.authentication.tokenBroker.type "rsa-key-pair" -}} + {{- $_ = set $map "polaris.authentication.token-broker.rsa-key-pair.public-key-file" (printf "%s/public.pem" .Values.image.configDir ) -}} + {{- $_ = set $map "polaris.authentication.token-broker.rsa-key-pair.private-key-file" (printf "%s/private.pem" .Values.image.configDir ) -}} + {{- end -}} + {{- if eq .Values.authentication.tokenBroker.type "symmetric-key" -}} + {{- $_ = set $map "polaris.authentication.token-broker.symmetric-key.file" (printf "%s/symmetric.key" .Values.image.configDir ) -}} + {{- end -}} + {{- end -}} + + {{- /* HTTP ports */ -}} + {{- $_ = set $map "quarkus.http.port" (get (first .Values.service.ports) "port") -}} + {{- $_ = set $map "quarkus.management.port" (get (first .Values.managementService.ports) "port") -}} + + {{- /* CORS */ -}} + {{- if .Values.cors.allowedOrigins -}} + {{- $_ = set $map "quarkus.http.cors.origins" (join "," .Values.cors.allowedOrigins) -}} + {{- end -}} + {{- if .Values.cors.allowedMethods -}} + {{- $_ = set $map "quarkus.http.cors.methods" (join "," .Values.cors.allowedMethods) -}} + {{- end -}} + {{- if .Values.cors.allowedHeaders -}} + {{- $_ = set $map "quarkus.http.cors.headers" (join "," .Values.cors.allowedHeaders) -}} + {{- end -}} + {{- if .Values.cors.exposedHeaders -}} + {{- $_ = set $map "quarkus.http.cors.exposed-headers" (join "," .Values.cors.exposedHeaders) -}} + {{- end -}} + {{- if .Values.cors.accessControlMaxAge -}} + {{- $_ = set $map "quarkus.http.cors.access-control-max-age" .Values.cors.accessControlMaxAge -}} + {{- end -}} + {{- if ne .Values.cors.accessControlAllowCredentials nil -}} + {{- $_ = set $map "quarkus.http.cors.access-control-allow-credentials" .Values.cors.accessControlAllowCredentials -}} + {{- end -}} + + {{- /* Logging */ -}} + {{- $_ = set $map "quarkus.log.level" .Values.logging.level -}} + {{- if .Values.logging.console.enabled -}} + {{- $_ = set $map "quarkus.log.console.enable" "true" -}} + {{- $_ = set $map "quarkus.log.console.level" .Values.logging.console.threshold -}} + {{- if .Values.logging.console.json -}} + {{- $_ = set $map "quarkus.log.console.json" "true" -}} + {{- else -}} + {{- $_ = set $map "quarkus.log.console.format" .Values.logging.console.format -}} + {{- end -}} + {{- else -}} + {{- $_ = set $map "quarkus.log.console.enable" "false" -}} + {{- end -}} + {{- if .Values.logging.file.enabled -}} + {{- $_ = set $map "quarkus.log.file.enable" "true" -}} + {{- $_ = set $map "quarkus.log.file.level" .Values.logging.file.threshold -}} + {{- $_ = set $map "quarkus.log.file.path" (printf "%s/%s" .Values.logging.file.logsDir .Values.logging.file.fileName) -}} + {{- $_ = set $map "quarkus.log.file.rotation.max-file-size" (include "polaris.quantity" .Values.logging.file.rotation.maxFileSize) -}} + {{- $_ = set $map "quarkus.log.file.rotation.max-backup-index" .Values.logging.file.rotation.maxBackupIndex -}} + {{- if .Values.logging.file.rotation.fileSuffix -}} + {{- $_ = set $map "quarkus.log.file.rotation.file-suffix" .Values.logging.file.rotation.fileSuffix -}} + {{- end -}} + {{- if .Values.logging.file.json -}} + {{- $_ = set $map "quarkus.log.file.json" "true" -}} + {{- else -}} + {{- $_ = set $map "quarkus.log.file.format" .Values.logging.file.format -}} + {{- end -}} + {{- else -}} + {{- $_ = set $map "quarkus.log.file.enable" "false" -}} + {{- end -}} + {{- $categories := dict -}} + {{- list .Values.logging.categories "" $categories | include "polaris.mergeConfigTree" -}} + {{- range $k, $v := $categories -}} + {{- $_ = set $map (printf "quarkus.log.category.\"%s\".level" $k) $v -}} + {{- end -}} + {{- $_ = set $map "polaris.log.request-id-header-name" .Values.logging.requestIdHeaderName -}} + {{- $mdc := dict -}} + {{- list .Values.logging.mdc "" $mdc | include "polaris.mergeConfigTree" -}} + {{- range $k, $v := $mdc -}} + {{- $_ = set $map (printf "polaris.log.mdc.\"%s\"" $k) $v -}} + {{- end -}} + + {{- /* Telemetry */ -}} + {{- if .Values.tracing.enabled -}} + {{- $_ = set $map "quarkus.otel.exporter.otlp.endpoint" .Values.tracing.endpoint -}} + {{- if .Values.tracing.attributes -}} + {{- $attributes := dict -}} + {{- list .Values.tracing.attributes "" $attributes | include "polaris.mergeConfigTree" -}} + {{- $i := 0 -}} + {{- range $k, $v := $attributes -}} + {{- $_ = set $map (printf "quarkus.otel.resource.attributes[%d]" $i) (printf "%s=%s" $k $v) -}} + {{- $i = add1 $i -}} + {{- end -}} + {{- end -}} + {{- if .Values.tracing.sample -}} + {{- $sample := toString .Values.tracing.sample -}} + {{ if eq $sample "all" -}} + {{- $_ = set $map "quarkus.otel.traces.sampler" "parentbased_always_on" -}} + {{- else if eq $sample "none" -}} + {{- $_ = set $map "quarkus.otel.traces.sampler" "always_off" -}} + {{- else -}} + {{- $_ = set $map "quarkus.otel.traces.sampler" "parentbased_traceidratio" -}} + {{- $_ = set $map "quarkus.otel.traces.sampler.arg" $sample -}} + {{- end -}} + {{- end -}} + {{- else -}} + {{- $_ = set $map "quarkus.otel.sdk.disabled" true -}} + {{- end -}} + + {{- /* Metrics */ -}} + {{- if .Values.metrics.enabled -}} + {{- range $name, $value := .Values.metrics.tags -}} + {{- $_ = set $map (print "polaris.metrics.tags." $name) $value -}} + {{- end -}} + {{- else -}} + {{- $_ = set $map "quarkus.micrometer.enabled" "false" -}} + {{- end -}} + + {{- /* Advanced Configuration (must be done last since it can override any of the settings above) */ -}} + {{- list .Values.advancedConfig "" $map | include "polaris.mergeConfigTree" -}} + + {{- /* Print the resulting configmap; each configuration option is templatized */ -}} + {{- $global := . -}} + {{- range $k, $v := $map }} + {{ include "polaris.appendConfigOption" (list $k $v $global) }} + {{- end }} diff --git a/helm/polaris/templates/deployment.yaml b/helm/polaris/templates/deployment.yaml index 9d688e6ac8..a444cc5076 100644 --- a/helm/polaris/templates/deployment.yaml +++ b/helm/polaris/templates/deployment.yaml @@ -49,23 +49,6 @@ spec: {{- tpl (toYaml .Values.podLabels) . | nindent 8 }} {{- end }} spec: - {{- if and .Values.persistenceConfigSecret (index .Values.polarisServerConfig.metaStoreManager "conf-file") }} - initContainers: - - name: init-config - image: "{{ tpl .Values.toolsImage.repository . }}:{{ tpl .Values.toolsImage.tag . }}" - imagePullPolicy: {{ tpl .Values.toolsImage.pullPolicy . }} - command: ["jar"] - args: ["-cf", "/eclipselink-config/conf.jar", "-C", "/secret", "persistence.xml"] - {{- if .Values.securityContext}} - securityContext: - {{- tpl (toYaml .Values.securityContext) . | nindent 12 }} - {{- end }} - volumeMounts: - - name: eclipselink-config-volume - mountPath: /eclipselink-config - - name: secret-volume - mountPath: /secret - {{- end }} {{- if .Values.imagePullSecrets }} imagePullSecrets: {{- range .Values.imagePullSecrets }} @@ -77,36 +60,47 @@ spec: securityContext: {{- tpl (toYaml .Values.podSecurityContext) . | nindent 8 }} {{- end }} + {{- if .Values.extraInitContainers }} + initContainers: + {{- tpl (toYaml .Values.extraInitContainers) . | nindent 8 }} + {{- end }} containers: - name: {{ .Chart.Name }} - {{- if .Values.securityContext}} + {{- if .Values.containerSecurityContext }} securityContext: - {{- tpl (toYaml .Values.securityContext) . | nindent 12 }} + {{- tpl (toYaml .Values.containerSecurityContext) . | nindent 12 }} {{- end }} image: "{{ tpl .Values.image.repository . }}:{{ tpl .Values.image.tag . | default .Chart.Version }}" imagePullPolicy: {{ tpl .Values.image.pullPolicy . }} - {{- if .Values.extraEnv }} + {{ if or .Values.storage.secret.name .Values.extraEnv -}} env: - {{- tpl (toYaml .Values.extraEnv) . | nindent 12 }} + {{- include "polaris.secretToEnv" (list .Values.storage.secret "awsAccessKeyId" "polaris.storage.aws.access-key") | indent 12 -}} + {{- include "polaris.secretToEnv" (list .Values.storage.secret "awsSecretAccessKey" "polaris.storage.aws.secret-key") | indent 12 -}} + {{- include "polaris.secretToEnv" (list .Values.storage.secret "gcpToken" "polaris.storage.gcp.token") | indent 12 -}} + {{- if .Values.extraEnv -}} + {{- tpl (toYaml .Values.extraEnv) . | nindent 12 -}} + {{- end -}} {{- end }} volumeMounts: - name: config-volume - mountPath: /app/config/polaris-server.yml - subPath: polaris-server.yml - {{- if and .Values.persistenceConfigSecret (index .Values.polarisServerConfig.metaStoreManager "conf-file") }} - - name: eclipselink-config-volume - mountPath: /eclipselink-config + mountPath: {{ trimSuffix "/" .Values.image.configDir }} + readOnly: true + {{- if .Values.logging.file.enabled }} + - name: logs-storage + mountPath: {{ .Values.logging.file.logsDir }} + readOnly: false {{- end }} - ports: - {{- range $portName, $portNumber := .Values.service.ports }} - - name: {{ $portName }} - containerPort: {{ $portNumber }} - protocol: TCP + - name: temp-dir + mountPath: /tmp + readOnly: false + {{- if .Values.extraVolumeMounts }} + {{- tpl (toYaml .Values.extraVolumeMounts) . | nindent 12 }} {{- end }} + {{- include "polaris.containerPorts" . | trim | nindent 10 }} livenessProbe: httpGet: path: /q/health/live - port: "polaris-metrics" + port: {{ get (first .Values.managementService.ports) "name" }} scheme: HTTP initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.livenessProbe.periodSeconds }} @@ -117,7 +111,7 @@ spec: readinessProbe: httpGet: path: /q/health/ready - port: "polaris-metrics" + port: {{ get (first .Values.managementService.ports) "name" }} scheme: HTTP initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.readinessProbe.periodSeconds }} @@ -129,15 +123,16 @@ spec: {{- tpl (toYaml .Values.resources) . | nindent 12 }} {{- end }} volumes: - - name: config-volume - configMap: - name: {{ include "polaris.fullname" . }} - {{- if and .Values.persistenceConfigSecret (index .Values.polarisServerConfig.metaStoreManager "conf-file") }} - - name: eclipselink-config-volume + {{- include "polaris.configVolume" . | nindent 8 }} + {{- if .Values.logging.file.enabled }} + - name: logs-storage + persistentVolumeClaim: + claimName: {{ include "polaris.fullnameWithSuffix" (list . "logs") }} + {{- end }} + - name: temp-dir emptyDir: {} - - name: secret-volume - secret: - secretName: {{ tpl .Values.persistenceConfigSecret . }} + {{- if .Values.extraVolumes }} + {{- tpl (toYaml .Values.extraVolumes) . | nindent 8 }} {{- end }} {{- if .Values.nodeSelector }} nodeSelector: diff --git a/helm/polaris/templates/ingress.yaml b/helm/polaris/templates/ingress.yaml index 7495be5b53..f1909cc625 100644 --- a/helm/polaris/templates/ingress.yaml +++ b/helm/polaris/templates/ingress.yaml @@ -19,7 +19,7 @@ {{- if .Values.ingress.enabled }} {{- $fullName := include "polaris.fullname" . }} -{{- $svcPort := index .Values.service.ports "polaris-service" }} +{{- $svcPort := get (first .Values.service.ports) "port" }} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: diff --git a/helm/polaris/templates/job.yaml b/helm/polaris/templates/job.yaml index 5dc54b2bba..bfbbc4e273 100644 --- a/helm/polaris/templates/job.yaml +++ b/helm/polaris/templates/job.yaml @@ -17,11 +17,11 @@ under the License. */}} -{{- if .Values.bootstrapMetastoreManager }} +{{- if .Values.bootstrap.enabled }} apiVersion: batch/v1 kind: Job metadata: - name: {{ include "polaris.fullname" . }} + name: {{ include "polaris.fullnameWithSuffix" (list . "bootstrap") }} namespace: {{ .Release.Namespace }} labels: {{- include "polaris.labels" . | nindent 4 }} @@ -43,23 +43,6 @@ spec: {{- tpl (toYaml .Values.podLabels) . | nindent 8 }} {{- end }} spec: - {{- if and .Values.persistenceConfigSecret (index .Values.polarisServerConfig.metaStoreManager "conf-file") }} - initContainers: - - name: init-config - image: "{{ tpl .Values.toolsImage.repository . }}:{{ tpl .Values.toolsImage.tag . }}" - imagePullPolicy: {{ tpl .Values.toolsImage.pullPolicy . }} - command: ["jar"] - args: ["-cf", "/eclipselink-config/conf.jar", "-C", "/secret", "persistence.xml"] - {{- if .Values.securityContext}} - securityContext: - {{- tpl (toYaml .Values.securityContext) . | nindent 12 }} - {{- end }} - volumeMounts: - - name: eclipselink-config-volume - mountPath: /eclipselink-config - - name: secret-volume - mountPath: /secret - {{- end }} {{- if .Values.imagePullSecrets }} imagePullSecrets: {{- range .Values.imagePullSecrets }} @@ -67,47 +50,50 @@ spec: {{- end }} {{- end }} serviceAccountName: {{ include "polaris.serviceAccountName" . }} - {{- if .Values.podSecurityContext}} + {{- if .Values.podSecurityContext }} securityContext: {{- tpl (toYaml .Values.podSecurityContext) . | nindent 8 }} {{- end }} containers: - - name: {{ .Chart.Name }} - {{- if .Values.securityContext}} + - name: "polaris-bootstrap" + {{- if .Values.containerSecurityContext }} securityContext: - {{- tpl (toYaml .Values.securityContext) . | nindent 12 }} + {{- tpl (toYaml .Values.containerSecurityContext) . | nindent 12 }} {{- end }} - image: "{{ tpl .Values.image.repository . }}:{{ tpl .Values.image.tag . | default .Chart.Version }}" - imagePullPolicy: {{ tpl .Values.image.pullPolicy . }} - command: ["/app/bin/polaris-service"] - args: ["bootstrap", "/app/config/polaris-server.yml"] - {{- if .Values.bootstrapExtraEnv }} + image: "{{ tpl .Values.bootstrap.image.repository . }}:{{ tpl .Values.bootstrap.image.tag . | default .Chart.Version }}" + imagePullPolicy: {{ tpl .Values.bootstrap.image.pullPolicy . }} + args: + - "bootstrap" + {{- range $realm := .Values.bootstrap.realms }} + - --realm={{ tpl $realm $ }} + {{- end }} + {{- range $credential := .Values.bootstrap.credentials }} + - --credential={{ tpl $credential $ }} + {{- end }} env: - {{- tpl (toYaml .Values.bootstrapExtraEnv) . | nindent 12 }} - {{- end }} + {{- if .Values.bootstrap.extraEnv }} + {{- tpl (toYaml .Values.bootstrap.extraEnv) . | nindent 12 }} + {{- end }} + - name: "quarkus.log.file.enable" + value: "false" volumeMounts: - name: config-volume - mountPath: /app/config/polaris-server.yml - subPath: polaris-server.yml - {{- if and .Values.persistenceConfigSecret (index .Values.polarisServerConfig.metaStoreManager "conf-file") }} - - name: eclipselink-config-volume - mountPath: /eclipselink-config - {{- end }} + mountPath: {{ trimSuffix "/" .Values.bootstrap.image.configDir }} + readOnly: true + - name: temp-dir + mountPath: /tmp + readOnly: false {{- if .Values.resources }} resources: {{- tpl (toYaml .Values.resources) . | nindent 12 }} {{- end }} restartPolicy: Never volumes: - - name: config-volume - configMap: - name: {{ include "polaris.fullname" . }} - {{- if and .Values.persistenceConfigSecret (index .Values.polarisServerConfig.metaStoreManager "conf-file") }} - - name: eclipselink-config-volume + {{- include "polaris.configVolume" . | nindent 8 }} + - name: temp-dir emptyDir: {} - - name: secret-volume - secret: - secretName: {{ tpl .Values.persistenceConfigSecret . }} + {{- if .Values.extraVolumes }} + {{- tpl (toYaml .Values.extraVolumes) . | nindent 8 }} {{- end }} {{- if .Values.nodeSelector }} nodeSelector: diff --git a/helm/polaris/templates/service-extra.yaml b/helm/polaris/templates/service-extra.yaml new file mode 100644 index 0000000000..ab4d00baa8 --- /dev/null +++ b/helm/polaris/templates/service-extra.yaml @@ -0,0 +1,69 @@ +{{/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/}} + +{{- range $i, $svc := .Values.extraServices }} +{{- if not $svc.nameSuffix }} +{{- fail (printf "extraServices[%d]: missing required nameSuffix" $i) }} +{{- else if or (eq $svc.nameSuffix "-mgmt") (eq $svc.nameSuffix "mgmt") }} +{{- fail (printf "extraServices[%d]: invalid nameSuffix" $i) }} +{{- end }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "polaris.fullnameWithSuffix" (list $ $svc.nameSuffix) }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "polaris.labels" $ | nindent 4 }} + {{- with $svc.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ $svc.type }} + selector: + {{- include "polaris.selectorLabels" $ | nindent 4 }} + ports: + {{- range $svc.ports }} + - name: {{ .name }} + port: {{ .port }} + {{- if .targetPort }} + targetPort: {{ .targetPort }} + {{- end }} + {{- if .nodePort }} + nodePort: {{ .nodePort }} + {{- end }} + protocol: {{ default "TCP" .protocol }} + {{- end }} + {{- if $svc.sessionAffinity }} + sessionAffinity: {{ $svc.sessionAffinity }} + {{- end }} + {{- if $svc.clusterIP }} + clusterIP: {{ $svc.clusterIP }} + {{- end }} + {{- if and $svc.externalTrafficPolicy (or (eq $svc.type "LoadBalancer") (eq $svc.type "NodePort")) }} + externalTrafficPolicy: {{ $svc.externalTrafficPolicy }} + {{- end }} + {{- if $svc.internalTrafficPolicy }} + internalTrafficPolicy: {{ $svc.internalTrafficPolicy }} + {{- end }} + {{- if and $svc.trafficDistribution (ge (int $.Capabilities.KubeVersion.Minor) 31) }} + trafficDistribution: {{ $svc.trafficDistribution }} + {{- end }} +{{- end }} diff --git a/helm/polaris/templates/service-mgmt.yaml b/helm/polaris/templates/service-mgmt.yaml new file mode 100644 index 0000000000..797632457c --- /dev/null +++ b/helm/polaris/templates/service-mgmt.yaml @@ -0,0 +1,61 @@ +{{/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "polaris.fullnameWithSuffix" (list . "mgmt") }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "polaris.labels" . | nindent 4 }} + {{- with .Values.managementService.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.managementService.type }} + selector: + {{- include "polaris.selectorLabels" . | nindent 4 }} + ports: + {{- range .Values.managementService.ports }} + - name: {{ .name }} + port: {{ .port }} + {{- if .targetPort }} + targetPort: {{ .targetPort }} + {{- end }} + {{- if .nodePort }} + nodePort: {{ .nodePort }} + {{- end }} + protocol: {{ default "TCP" .protocol }} + {{- end }} + {{- if .Values.managementService.sessionAffinity }} + sessionAffinity: {{ .Values.managementService.sessionAffinity }} + {{- end }} + {{- if .Values.managementService.clusterIP }} + clusterIP: {{ .Values.managementService.clusterIP }} + {{- end }} + {{- if and .Values.managementService.externalTrafficPolicy (or (eq .Values.managementService.type "LoadBalancer") (eq .Values.managementService.type "NodePort")) }} + externalTrafficPolicy: {{ .Values.managementService.externalTrafficPolicy }} + {{- end }} + {{- if .Values.managementService.internalTrafficPolicy }} + internalTrafficPolicy: {{ .Values.managementService.internalTrafficPolicy }} + {{- end }} + {{- if and .Values.managementService.trafficDistribution (ge (int $.Capabilities.KubeVersion.Minor) 31) }} + trafficDistribution: {{ .Values.managementService.trafficDistribution }} + {{- end }} diff --git a/helm/polaris/templates/service.yaml b/helm/polaris/templates/service.yaml index 628cd47166..a44486a06c 100644 --- a/helm/polaris/templates/service.yaml +++ b/helm/polaris/templates/service.yaml @@ -24,19 +24,38 @@ metadata: namespace: {{ .Release.Namespace }} labels: {{- include "polaris.labels" . | nindent 4 }} - {{- if .Values.service.annotations }} + {{- with .Values.service.annotations }} annotations: - {{- tpl (toYaml .Values.service.annotations) . | nindent 4 }} + {{- toYaml . | nindent 4 }} {{- end }} spec: type: {{ .Values.service.type }} selector: {{- include "polaris.selectorLabels" . | nindent 4 }} ports: - {{- range $portName, $portNumber := .Values.service.ports }} - - port: {{ $portNumber }} - targetPort: {{ $portNumber }} - protocol: TCP - name: {{ $portName }} + {{- range .Values.service.ports }} + - name: {{ .name }} + port: {{ .port }} + {{- if .targetPort }} + targetPort: {{ .targetPort }} + {{- end }} + {{- if .nodePort }} + nodePort: {{ .nodePort }} + {{- end }} + protocol: {{ default "TCP" .protocol }} {{- end }} + {{- if .Values.service.sessionAffinity }} sessionAffinity: {{ .Values.service.sessionAffinity }} + {{- end }} + {{- if .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if and .Values.service.externalTrafficPolicy (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy }} + {{- end }} + {{- if .Values.service.internalTrafficPolicy }} + internalTrafficPolicy: {{ .Values.service.internalTrafficPolicy }} + {{- end }} + {{- if and .Values.service.trafficDistribution (ge (int .Capabilities.KubeVersion.Minor) 31) }} + trafficDistribution: {{ .Values.service.trafficDistribution }} + {{- end }} diff --git a/helm/polaris/templates/servicemonitor.yaml b/helm/polaris/templates/servicemonitor.yaml new file mode 100644 index 0000000000..14dd2ee095 --- /dev/null +++ b/helm/polaris/templates/servicemonitor.yaml @@ -0,0 +1,49 @@ +{{/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +**/}} + +{{- if and ( .Capabilities.APIVersions.Has "monitoring.coreos.com/v1" ) .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "polaris.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "polaris.labels" . | nindent 4 }} + {{- if .Values.serviceMonitor.labels }} + {{ toYaml .Values.serviceMonitor.labels | nindent 4 }} + {{- end }} +spec: + endpoints: + - port: {{ get (first .Values.managementService.ports) "name" }} + scheme: http + {{- if .Values.serviceMonitor.interval }} + interval: {{ .Values.serviceMonitor.interval }} + {{- end }} + path: /q/metrics + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + {{- include "polaris.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/helm/polaris/templates/storage.yaml b/helm/polaris/templates/storage.yaml new file mode 100644 index 0000000000..aee642ac1e --- /dev/null +++ b/helm/polaris/templates/storage.yaml @@ -0,0 +1,41 @@ +{{/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +**/}} + +{{- if .Values.logging.file.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "polaris.fullnameWithSuffix" (list . "logs") }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "polaris.labels" . | nindent 4 }} +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + storageClassName: {{ .Values.logging.file.storage.className }} + resources: + requests: + storage: "{{ .Values.logging.file.storage.size }}" +{{- if .Values.logging.file.storage.selectorLabels }} + selector: + matchLabels: + {{- toYaml .Values.logging.file.storage.selectorLabels | nindent 6 }} +{{- end }} +{{- end }} diff --git a/helm/polaris/templates/tests/test-connection.yaml b/helm/polaris/templates/tests/test-connection.yaml index d60b9726a8..02941182f0 100644 --- a/helm/polaris/templates/tests/test-connection.yaml +++ b/helm/polaris/templates/tests/test-connection.yaml @@ -32,8 +32,13 @@ metadata: "helm.sh/hook": test spec: containers: - - name: wget + - name: check-connection image: busybox - command: ['wget'] - args: ['{{ include "polaris.fullname" . }}:{{ index .Values.service.ports "polaris-metrics" }}/q/health'] + command: ['sh', '-c'] + args: + - | + for i in $(seq 1 10); do + wget --spider '{{ include "polaris.fullnameWithSuffix" (list . "mgmt") }}:{{ get (first .Values.managementService.ports) "port" }}/q/health/ready' && exit 0 || sleep 3; + done; + exit 1 restartPolicy: Never \ No newline at end of file diff --git a/helm/polaris/tests/configmap_test.yaml b/helm/polaris/tests/configmap_test.yaml index 859ae1992d..ef725ec4f3 100644 --- a/helm/polaris/tests/configmap_test.yaml +++ b/helm/polaris/tests/configmap_test.yaml @@ -79,212 +79,263 @@ tests: content: app.kubernetes.io/component: polaris - # data - ## there is an auto newline for logFormat in the config map - ## auto newline of long string is reported in https://github.com/helm/helm/issues/5568 and due to https://github.com/go-yaml/yaml/issues/166 - - it: should set config map default data + - it: should configure realm context + set: + realmContext: { type: "custom", realms: [ "realm1", "realm2" ] } asserts: - - equal: - path: data - value: - polaris-server.yml: |- - authenticator: - class: org.apache.polaris.service.auth.TestInlineBearerTokenPolarisAuthenticator - callContextResolver: - type: default - cors: - allowed-credentials: true - allowed-headers: - - '*' - allowed-methods: - - PATCH - - POST - - DELETE - - GET - - PUT - allowed-origins: - - http://localhost:8080 - allowed-timing-origins: - - http://localhost:8080 - exposed-headers: - - '*' - preflight-max-age: 600 - defaultRealms: - - default-realm - featureConfiguration: - ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING: false - SUPPORTED_CATALOG_STORAGE_TYPES: - - S3 - - GCS - - AZURE - - FILE - io: - factoryType: default - logging: - appenders: - - logFormat: '%-5p [%d{ISO8601} - %-6r] [%t] [%X{aid}%X{sid}%X{tid}%X{wid}%X{oid}%X{srv}%X{job}%X{rid}] - %c{30}: %m %kvp%n%ex' - threshold: ALL - type: console - level: INFO - loggers: - org.apache.iceberg.rest: DEBUG - org.apache.polaris: DEBUG - maxRequestBodyBytes: -1 - metaStoreManager: - type: in-memory - oauth2: - type: test - rateLimiter: - type: no-op - realmContextResolver: - type: default - server: - adminConnectors: - - port: 8182 - type: http - applicationConnectors: - - port: 8181 - type: http - maxThreads: 200 - minThreads: 10 - requestLog: - appenders: - - type: console - - it: should set config map data (auto sorted) + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.realm-context.type=custom" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.realm-context.realms=realm1,realm2" } + + - it: should configure features set: - polarisServerConfig: - server: - maxThreads: 200 - minThreads: 10 - applicationConnectors: - - type: http - port: 8181 - adminConnectors: - - type: http - port: 8182 - requestLog: - appenders: - - type: console - featureConfiguration: - ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING: false - SUPPORTED_CATALOG_STORAGE_TYPES: - - S3 - callContextResolver: - type: default - realmContextResolver: - type: default - defaultRealms: - - default-realm - metaStoreManager: - type: eclipse-link - persistence-unit: polaris - conf-file: /eclipselink-config/conf.jar!/persistence.xml - io: - factoryType: default - oauth2: - type: default - tokenBroker: - type: symmetric-key - secret: polaris - authenticator: - class: org.apache.polaris.service.auth.DefaultPolarisAuthenticator - cors: - allowed-origins: - - http://localhost:8080 - allowed-timing-origins: - - http://localhost:8080 - allowed-methods: - - PATCH - - POST - - DELETE - - GET - - PUT - allowed-headers: - - "*" - exposed-headers: - - "*" - preflight-max-age: 600 - allowed-credentials: true - logging: - level: INFO - loggers: - org.apache.iceberg.rest: INFO - org.apache.polaris: INFO - appenders: - - type: console - threshold: ALL - logFormat: "%-5p [%d{ISO8601} - %-6r] [%t] [%X{aid}%X{sid}%X{tid}%X{wid}%X{oid}%X{srv}%X{job}%X{rid}] %c{30}: %m %kvp%n%ex" - maxRequestBodyBytes: -1 - rateLimiter: - type: no-op + features: + defaults: + feature1: true + feature2: 42 + realmOverrides: + realm1: + feature1: false + realm2: + feature2: 43 asserts: - - equal: - path: data - value: - polaris-server.yml: |- - authenticator: - class: org.apache.polaris.service.auth.DefaultPolarisAuthenticator - callContextResolver: - type: default - cors: - allowed-credentials: true - allowed-headers: - - '*' - allowed-methods: - - PATCH - - POST - - DELETE - - GET - - PUT - allowed-origins: - - http://localhost:8080 - allowed-timing-origins: - - http://localhost:8080 - exposed-headers: - - '*' - preflight-max-age: 600 - defaultRealms: - - default-realm - featureConfiguration: - ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING: false - SUPPORTED_CATALOG_STORAGE_TYPES: - - S3 - io: - factoryType: default - logging: - appenders: - - logFormat: '%-5p [%d{ISO8601} - %-6r] [%t] [%X{aid}%X{sid}%X{tid}%X{wid}%X{oid}%X{srv}%X{job}%X{rid}] - %c{30}: %m %kvp%n%ex' - threshold: ALL - type: console - level: INFO - loggers: - org.apache.iceberg.rest: INFO - org.apache.polaris: INFO - maxRequestBodyBytes: -1 - metaStoreManager: - conf-file: /eclipselink-config/conf.jar!/persistence.xml - persistence-unit: polaris - type: eclipse-link - oauth2: - type: default - rateLimiter: - type: no-op - realmContextResolver: - type: default - server: - adminConnectors: - - port: 8182 - type: http - applicationConnectors: - - port: 8181 - type: http - maxThreads: 200 - minThreads: 10 - requestLog: - appenders: - - type: console - tokenBroker: - secret: polaris - type: symmetric-key + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.features.defaults.\"feature1\"=true" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.features.defaults.\"feature2\"=42" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.config.realm-overrides.\"realm1\".\"feature1\"=false" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.config.realm-overrides.\"realm2\".\"feature2\"=43" } + + - it: should configure persistence + set: + persistence: { type: "eclipse-link", eclipseLink: { persistenceUnit: "polaris", secret: { name: "polaris-persistence" } } } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.persistence.type=eclipse-link" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.persistence.eclipselink.persistence-unit=polaris" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.persistence.eclipselink.configuration-file=/deployments/config/persistence.xml" } + + - it: should configure file-io + set: + fileIo.type: "custom" + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.file-io.type=custom" } + + - it: should configure GCP token lifespan + set: + storage: { secret: { gcpTokenLifespan: "PT2H" } } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.storage.gcp.lifespan=PT2H" } + + - it: should configure authentication with RSA key pair + set: + authentication: { authenticator: { type: custom }, tokenService: { type: custom }, tokenBroker: { type: rsa-key-pair, maxTokenGeneration: PT2H, secret: { name: polaris-auth } } } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.authentication.authenticator.type=custom" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.authentication.token-service.type=custom" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.authentication.token-broker.type=rsa-key-pair" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.authentication.token-broker.max-token-generation=PT2H" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.authentication.token-broker.rsa-key-pair.public-key-file=/deployments/config/public.pem" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.authentication.token-broker.rsa-key-pair.private-key-file=/deployments/config/private.pem" } + + - it: should configure authentication with symmetric key + set: + authentication: { tokenBroker: { type: symmetric-key, secret: { name: polaris-auth } } } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.authentication.authenticator.type=default" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.authentication.token-service.type=default" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.authentication.token-broker.type=symmetric-key" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.authentication.token-broker.max-token-generation=PT1H" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.authentication.token-broker.symmetric-key.file=/deployments/config/symmetric.key" } + + - it: should derive HTTP ports from service configuration + set: + service: { ports: [ { port: 8080 } ] } + managementService: { ports: [ { port: 8081 } ] } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.http.port=8080" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.management.port=8081" } + + - it: should configure console logging + set: + logging: { level: DEBUG, console: { enabled: true, threshold: INFO, format: custom } } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.level=DEBUG" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.console.enable=true" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.console.level=INFO" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.console.format=custom" } + + - it: should configure file logging + set: + logging: { file: { enabled: true, threshold: DEBUG, format: custom, logsDir: /mnt/logs, fileName: custom.log, rotation: { maxFileSize: 50Mi, maxBackupIndex: 2, fileSuffix: .yyyy-MM-dd } } } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.file.enable=true" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.file.level=DEBUG" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.file.path=/mnt/logs/custom.log" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.file.rotation.max-file-size=52428800" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.file.rotation.max-backup-index=2" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.file.rotation.file-suffix=.yyyy-MM-dd" } + + - it: should disable logging + set: + logging: { file: { enabled: false }, console: { enabled: false } } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.file.enable=false" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.console.enable=false" } + + - it: should enable JSON logging + set: + logging: { file: { enabled: true, json: true }, console: { enabled: true, json: true } } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.file.enable=true" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.console.enable=true" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.file.json=true" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.console.json=true" } + + - it: should include logging categories + set: + logging: + categories: + # compact style + org.acme: DEBUG + # expanded style + org: + acme: + service: INFO + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.category.\"org.acme\".level=DEBUG" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.log.category.\"org.acme.service\".level=INFO" } + + - it: should include MDC context + set: + logging: + mdc: + # compact style + org.acme: foo + # expanded style + org: + acme: + service: foo + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.log.mdc.\"org.acme\"=foo" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.log.mdc.\"org.acme.service\"=foo" } + + - it: should include telemetry configuration + set: + tracing: { enabled: true, endpoint: http://custom:4317, attributes: { service.name: custom, foo: bar } } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.otel.exporter.otlp.endpoint=http://custom:4317" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.otel.resource.attributes\\[\\d\\]=service.name=custom" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.otel.resource.attributes\\[\\d\\]=foo=bar" } + + - it: should include set sample rate numeric + set: + tracing: { enabled: true, sample: "0.123" } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.otel.traces.sampler=parentbased_traceidratio" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.otel.traces.sampler.arg=0.123" } + + - it: should include set sample rate "all" + set: + tracing: { enabled: true, sample: "all" } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.otel.traces.sampler=parentbased_always_on" } + + - it: should include set sample rate "none" + set: + tracing: { enabled: true, sample: "none" } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.otel.traces.sampler=always_off" } + + - it: should disable tracing by default + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.otel.sdk.disabled=true" } + + - it: should disable tracing + set: + tracing: { enabled: false } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.otel.sdk.disabled=true" } + + - it: should include custom metrics + set: + metrics: { enabled: true, tags: { app: custom, foo: bar } } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.metrics.tags.app=custom" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.metrics.tags.foo=bar" } + + - it: should disable metrics + set: + metrics: { enabled: false } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.micrometer.enabled=false" } + + - it: should include advanced configuration + set: + advancedConfig: + # compact style + quarkus.compact.custom: true + # expanded style + quarkus: + expanded: + custom: foo + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.compact.custom=true" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.expanded.custom=foo" } + + - it: should not include CORS configuration by default + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.http.cors" } + not: true + + - it: should include CORS configuration if defined + set: + cors: { allowedOrigins: [ "http://localhost:3000", "https://localhost:4000" ], allowedMethods: [ "GET", "POST" ], allowedHeaders: [ "X-Custom1", "X-Custom2" ], exposedHeaders: [ "X-Exposed-Custom1", "X-Exposed-Custom2" ], accessControlMaxAge: "PT1H", accessControlAllowCredentials: false } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.http.cors.origins=http://localhost:3000,https://localhost:4000" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.http.cors.methods=GET,POST" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.http.cors.headers=X-Custom1,X-Custom2" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.http.cors.exposed-headers=X-Exposed-Custom1,X-Exposed-Custom2" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.http.cors.access-control-max-age=PT1H" } + - matchRegex: { path: 'data["application.properties"]', pattern: "quarkus.http.cors.access-control-allow-credentials=false" } + + - it: should configure rate-limiter with default values + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.rate-limiter.filter.type=no-op" } + + - it: should configure rate-limiter no-op + set: + rateLimiter.type: no-op + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.rate-limiter.filter.type=no-op" } + + - it: should configure rate-limiter with default token bucket values + set: + rateLimiter.type: default + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.rate-limiter.filter.type=default" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.rate-limiter.token-bucket.type=default" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.rate-limiter.token-bucket.requests-per-second=9999" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.rate-limiter.token-bucket.window=PT10S" } + + - it: should configure rate-limiter with custom token bucket values + set: + rateLimiter: + type: custom + tokenBucket: + type: custom + requestsPerSecond: 1234 + window: PT5S + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.rate-limiter.filter.type=custom" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.rate-limiter.token-bucket.type=custom" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.rate-limiter.token-bucket.requests-per-second=1234" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.rate-limiter.token-bucket.window=PT5S" } + + - it: should not include tasks configuration by default + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.tasks" } + not: true + + - it: should include tasks configuration if defined + set: + tasks: { maxConcurrentTasks: 10, maxQueuedTasks: 20 } + asserts: + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.tasks.max-concurrent-tasks=10" } + - matchRegex: { path: 'data["application.properties"]', pattern: "polaris.tasks.max-queued-tasks=20" } diff --git a/helm/polaris/tests/deployment_test.yaml b/helm/polaris/tests/deployment_test.yaml index 161f273832..802ada10bb 100644 --- a/helm/polaris/tests/deployment_test.yaml +++ b/helm/polaris/tests/deployment_test.yaml @@ -175,37 +175,6 @@ tests: content: foo: bar - # spec.template.spec.initContainers - - it: should not set initContainers by default - asserts: - - notExists: - path: spec.template.spec.initContainers - - it: should set initContainers if persistence is enabled - set: - persistenceConfigSecret: polaris-persistence-secret - polarisServerConfig: - metaStoreManager: - conf-file: /eclipselink-config/conf.jar!/persistence.xml - toolsImage: - repository: test-repo - pullPolicy: Always - asserts: - - exists: - path: spec.template.spec.initContainers - - contains: - path: spec.template.spec.initContainers - content: - name: init-config - image: test-repo:latest - imagePullPolicy: Always - command: [ "jar" ] - args: [ "-cf", "/eclipselink-config/conf.jar", "-C", "/secret", "persistence.xml" ] - volumeMounts: - - name: eclipselink-config-volume - mountPath: /eclipselink-config - - name: secret-volume - mountPath: /secret - # spec.template.spec.imagePullSecrets - it: should not set imagePullSecrets by default asserts: @@ -291,7 +260,7 @@ tests: path: spec.template.spec.containers[0].securityContext - it: should set container securityContext set: - securityContext: + containerSecurityContext: runAsUser: 1000 asserts: - isSubset: @@ -299,30 +268,6 @@ tests: content: runAsUser: 1000 - # spec.template.spec.containers[0].securityContext - - it: should not set initContainer securityContext by default - set: - persistenceConfigSecret: polaris-persistence-secret - polarisServerConfig: - metaStoreManager: - conf-file: /eclipselink-config/conf.jar!/persistence.xml - asserts: - - notExists: - path: spec.template.spec.initContainers[0].securityContext - - it: should set initContainer securityContext - set: - persistenceConfigSecret: polaris-persistence-secret - polarisServerConfig: - metaStoreManager: - conf-file: /eclipselink-config/conf.jar!/persistence.xml - securityContext: - runAsUser: 1000 - asserts: - - isSubset: - path: spec.template.spec.initContainers[0].securityContext - content: - runAsUser: 1000 - # spec.template.spec.containers[0].image - it: should set container image set: @@ -384,61 +329,187 @@ tests: asserts: - lengthEqual: path: spec.template.spec.volumes - count: 1 + count: 2 # config-volume + temp-dir - lengthEqual: path: spec.template.spec.containers[0].volumeMounts - count: 1 + count: 2 # config-volume + temp-dir - contains: path: spec.template.spec.containers[0].volumeMounts content: name: config-volume - mountPath: /app/config/polaris-server.yml - subPath: polaris-server.yml - - it: should set persistence volumes if persistence is enabled + mountPath: /deployments/config + readOnly: true + + - it: should evaluate template expressions in persistence secret name set: - persistenceConfigSecret: polaris-persistence-secret - polarisServerConfig: - metaStoreManager: - conf-file: /eclipselink-config/conf.jar!/persistence.xml + persistence: + type: eclipse-link + eclipseLink: + secret: + name: "{{ .Release.Name }}-persistence-secret" asserts: - - lengthEqual: + - contains: path: spec.template.spec.volumes - count: 3 + content: + name: config-volume + projected: + sources: + - configMap: + items: + - key: application.properties + path: application.properties + name: polaris-release + - secret: + items: + - key: persistence.xml + path: persistence.xml + name: polaris-release-persistence-secret + + # spec.template.spec.containers[0].ports + - it: should set container ports by default + asserts: - lengthEqual: - path: spec.template.spec.containers[0].volumeMounts + path: spec.template.spec.containers[0].ports count: 2 - contains: - path: spec.template.spec.volumes + path: spec.template.spec.containers[0].ports content: - name: eclipselink-config-volume - emptyDir: { } + name: polaris-http + containerPort: 8181 + protocol: TCP - contains: - path: spec.template.spec.volumes + path: spec.template.spec.containers[0].ports content: - name: secret-volume - secret: - secretName: polaris-persistence-secret + name: polaris-mgmt + containerPort: 8182 + protocol: TCP + + - it: should set custom container ports + set: + service: + ports: + - name: polaris-custom + port: 18181 + managementService: + ports: + - name: mgmt-custom + port: 18182 + extraServices: + - nameSuffix: "-extra" + type: LoadBalancer + ports: + - name: extra-port + port: 18183 + asserts: + - lengthEqual: + path: spec.template.spec.containers[0].ports + count: 3 - contains: - path: spec.template.spec.containers[0].volumeMounts + path: spec.template.spec.containers[0].ports content: - name: eclipselink-config-volume - mountPath: /eclipselink-config - - it: should evaluate template expressions in persistence secret name + name: polaris-custom + containerPort: 18181 + protocol: TCP + - contains: + path: spec.template.spec.containers[0].ports + content: + name: mgmt-custom + containerPort: 18182 + protocol: TCP + - contains: + path: spec.template.spec.containers[0].ports + content: + name: extra-port + containerPort: 18183 + protocol: TCP + + - it: should use targetPort if defined set: - persistenceConfigSecret: '{{ .Release.Name }}-persistence-secret' - polarisServerConfig: - metaStoreManager: - conf-file: /eclipselink-config/conf.jar!/persistence.xml + service: + ports: + - name: polaris-custom + port: 18181 + targetPort: 8181 + managementService: + ports: + - name: mgmt-custom + port: 18182 + targetPort: 8182 + extraServices: + - nameSuffix: "-extra" + ports: + - name: extra-port + port: 18183 + targetPort: 8183 asserts: + - lengthEqual: + path: spec.template.spec.containers[0].ports + count: 3 - contains: - path: spec.template.spec.volumes + path: spec.template.spec.containers[0].ports + content: + name: polaris-custom + containerPort: 8181 + protocol: TCP + - contains: + path: spec.template.spec.containers[0].ports + content: + name: mgmt-custom + containerPort: 8182 + protocol: TCP + - contains: + path: spec.template.spec.containers[0].ports content: - name: secret-volume - secret: - secretName: polaris-release-persistence-secret + name: extra-port + containerPort: 8183 + protocol: TCP - # spec.template.spec.containers[0].ports - - it: should set container ports by default + - it: should fail if port name is not unique (#1) + set: + service: + ports: + - name: polaris-http + port: 8181 + - name: polaris-http + port: 18181 + asserts: + - failedTemplate: + errorPattern: "service.ports\\[\\d\\]: port name already taken: polaris-http" + + - it: should fail if port name is not unique (#2) + set: + managementService: + ports: + - name: polaris-mgmt + port: 8182 + - name: polaris-mgmt + port: 18182 + asserts: + - failedTemplate: + errorPattern: "managementService.ports\\[\\d\\]: port name already taken: polaris-mgmt" + + - it: should fail if port name is not unique (#3) + set: + service: + ports: + - name: polaris + port: 8181 + managementService: + ports: + - name: polaris + port: 8182 + asserts: + - failedTemplate: + errorPattern: "managementService.ports\\[\\d\\]: port name already taken: polaris" + + - it: should not fail when extra service references the same port name and number + set: + extraServices: + - nameSuffix: "-extra" + type: LoadBalancer + ports: + - name: polaris-http + port: 8181 asserts: - lengthEqual: path: spec.template.spec.containers[0].ports @@ -446,38 +517,203 @@ tests: - contains: path: spec.template.spec.containers[0].ports content: - name: polaris-service + name: polaris-http containerPort: 8181 protocol: TCP - contains: path: spec.template.spec.containers[0].ports content: - name: polaris-metrics + name: polaris-mgmt containerPort: 8182 protocol: TCP + - it: should fail when extra service references the same port name with different number (#1) + set: + extraServices: + - nameSuffix: "-extra" + type: LoadBalancer + ports: + - name: polaris-http + port: 9999 + asserts: + - failedTemplate: + errorPattern: "extraServices\\[\\d\\].ports\\[\\d\\]: wrong port number for port polaris-http, expected 8181, got 9999" + + - it: should fail when extra service references the same port name with different number (#2) + set: + extraServices: + - nameSuffix: "-extra" + type: LoadBalancer + ports: + - name: polaris-mgmt + port: 9999 + asserts: + - failedTemplate: + errorPattern: "extraServices\\[\\d\\].ports\\[\\d\\]: wrong port number for port polaris-mgmt, expected 8182, got 9999" + + - it: should fail when extra service references the same port name with different number (#3) + set: + service: + ports: + - name: polaris-http + port: 8181 + - name: polaris-https + port: 8043 + extraServices: + - nameSuffix: "-extra" + type: LoadBalancer + ports: + - name: polaris-https + port: 9999 + asserts: + - failedTemplate: + errorPattern: "extraServices\\[\\d\\].ports\\[\\d\\]: wrong port number for port polaris-https, expected 8043, got 9999" + + - it: should fail when extra service references the same port name with different protocol + set: + service: + ports: + - name: polaris-http + port: 8181 + extraServices: + - nameSuffix: "-extra" + type: LoadBalancer + ports: + - name: polaris-http + port: 8181 + protocol: UDP + asserts: + - failedTemplate: + errorPattern: "extraServices\\[\\d\\].ports\\[\\d\\]: wrong protocol for port polaris-http, expected TCP, got UDP" + + - it: should create 2 ports with same number + set: + service: + ports: + - name: polaris-http + port: 8181 + - name: polaris-http2 + port: 8181 + asserts: + - lengthEqual: + path: spec.template.spec.containers[0].ports + count: 3 + - contains: + path: spec.template.spec.containers[0].ports + content: + name: polaris-http + containerPort: 8181 + protocol: TCP + - contains: + path: spec.template.spec.containers[0].ports + content: + name: polaris-http2 + containerPort: 8181 + protocol: TCP + - it: should create 2 ports with same number using targetPort + set: + service: + ports: + - name: polaris-http + port: 18181 + targetPort: 8181 + - name: polaris-http2 + port: 18181 + targetPort: 8181 + asserts: + - lengthEqual: + path: spec.template.spec.containers[0].ports + count: 3 + - contains: + path: spec.template.spec.containers[0].ports + content: + name: polaris-http + containerPort: 8181 + protocol: TCP + - contains: + path: spec.template.spec.containers[0].ports + content: + name: polaris-http2 + containerPort: 8181 + protocol: TCP + - it: should set port protocols + set: + service: + ports: + - name: polaris-http + port: 8181 + protocol: UDP + managementService: + ports: + - name: polaris-mgmt + port: 8182 + protocol: UDP + extraServices: + - nameSuffix: "-extra" + type: LoadBalancer + ports: + - name: polaris-extra + port: 8183 + protocol: UDP + asserts: + - lengthEqual: + path: spec.template.spec.containers[0].ports + count: 3 + - contains: + path: spec.template.spec.containers[0].ports + content: + name: polaris-http + containerPort: 8181 + protocol: UDP + - contains: + path: spec.template.spec.containers[0].ports + content: + name: polaris-mgmt + containerPort: 8182 + protocol: UDP + - contains: + path: spec.template.spec.containers[0].ports + content: + name: polaris-extra + containerPort: 8183 + protocol: UDP + # spec.template.spec.containers[0].livenessProbe - it: should set container livenessProbe by default set: + managementService: + ports: + - name: mgmt-custom + port: 9999 livenessProbe: initialDelaySeconds: 11 periodSeconds: 22 successThreshold: 33 failureThreshold: 44 timeoutSeconds: 55 + terminationGracePeriodSeconds: 66 asserts: - - isSubset: + - equal: path: spec.template.spec.containers[0].livenessProbe - content: + value: + httpGet: + path: /q/health/live + port: mgmt-custom + scheme: HTTP initialDelaySeconds: 11 periodSeconds: 22 successThreshold: 33 failureThreshold: 44 timeoutSeconds: 55 + terminationGracePeriodSeconds: 66 # spec.template.spec.containers[0].readinessProbe - it: should set container readinessProbe by default set: + managementService: + ports: + - name: mgmt-custom + port: 9999 readinessProbe: initialDelaySeconds: 11 periodSeconds: 22 @@ -485,9 +721,13 @@ tests: failureThreshold: 44 timeoutSeconds: 55 asserts: - - isSubset: + - equal: path: spec.template.spec.containers[0].readinessProbe - content: + value: + httpGet: + path: /q/health/ready + port: mgmt-custom + scheme: HTTP initialDelaySeconds: 11 periodSeconds: 22 successThreshold: 33 @@ -585,3 +825,221 @@ tests: operator: "Equal" value: "value" effect: "NoSchedule" + + - it: should set storage credentials + set: + storage: + secret: + name: polaris-storage-secret + awsAccessKeyId: awsAccessKeyId + awsSecretAccessKey: awsSecretAccessKey + gcpToken: gcpToken + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: polaris.storage.aws.access-key + valueFrom: + secretKeyRef: + name: polaris-storage-secret + key: awsAccessKeyId + - contains: + path: spec.template.spec.containers[0].env + content: + name: polaris.storage.aws.secret-key + valueFrom: + secretKeyRef: + name: polaris-storage-secret + key: awsSecretAccessKey + - contains: + path: spec.template.spec.containers[0].env + content: + name: polaris.storage.gcp.token + valueFrom: + secretKeyRef: + name: polaris-storage-secret + key: gcpToken + + - it: should set extra env + set: + extraEnv: + - name: foo + value: bar + - name: baz + valueFrom: + secretKeyRef: + name: secret + key: key + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: foo + value: bar + - contains: + path: spec.template.spec.containers[0].env + content: + name: baz + valueFrom: + secretKeyRef: + name: secret + key: key + + - it: should set extra env + storage credentials + set: + storage: + secret: + name: polaris-storage-secret + awsAccessKeyId: awsAccessKeyId + extraEnv: + - name: foo + value: bar + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: foo + value: bar + - contains: + path: spec.template.spec.containers[0].env + content: + name: polaris.storage.aws.access-key + valueFrom: + secretKeyRef: + name: polaris-storage-secret + key: awsAccessKeyId + + - it: should not set any environment variables by default + asserts: + - notExists: + path: spec.template.spec.containers[0].env + + - it: should configure config volume + set: + image.configDir: /config/dir + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: config-volume + mountPath: /config/dir + readOnly: true + - contains: + path: spec.template.spec.volumes + content: + name: config-volume + projected: + sources: + - configMap: + name: polaris-release + items: + - key: application.properties + path: application.properties + + - it: should configure config volume with token broker secret + set: + image.configDir: /config/dir + authentication: + tokenBroker: + secret: + name: polaris-token-broker + publicKey: public.key + privateKey: private.key + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: config-volume + mountPath: /config/dir + readOnly: true + - contains: + path: spec.template.spec.volumes + content: + name: config-volume + projected: + sources: + - configMap: + name: polaris-release + items: + - key: application.properties + path: application.properties + - secret: + name: polaris-token-broker + items: + - key: public.key + path: public.pem + - key: private.key + path: private.pem + + - it: should configure config volume with persistence secret + set: + image.configDir: /config/dir + persistence: + type: eclipse-link + eclipseLink: + secret: + name: polaris-persistence + key: custom.xml + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: config-volume + mountPath: /config/dir + readOnly: true + - contains: + path: spec.template.spec.volumes + content: + name: config-volume + projected: + sources: + - configMap: + name: polaris-release + items: + - key: application.properties + path: application.properties + - secret: + name: polaris-persistence + items: + - key: custom.xml + path: persistence.xml + + - it: should configure volume for file logging + set: + logging.file.enabled: true + logging.file.logsDir: /custom/logs + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: logs-storage + mountPath: /custom/logs + readOnly: false + - contains: + path: spec.template.spec.volumes + content: + name: logs-storage + persistentVolumeClaim: + claimName: polaris-release-logs + + - it: should include extra volumes and volume mounts + set: + extraVolumes: + - name: extra-volume + emptyDir: {} + extraVolumeMounts: + - name: extra-volume + mountPath: /extra + readOnly: false + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: extra-volume + mountPath: /extra + readOnly: false + - contains: + path: spec.template.spec.volumes + content: + name: extra-volume + emptyDir: {} diff --git a/helm/polaris/tests/ingress_test.yaml b/helm/polaris/tests/ingress_test.yaml index ba296fd668..d9613bf54d 100644 --- a/helm/polaris/tests/ingress_test.yaml +++ b/helm/polaris/tests/ingress_test.yaml @@ -45,7 +45,7 @@ tests: kind: Ingress apiVersion: networking.k8s.io/v1 - # metadata.name (with with ingress enabled) + # metadata.name (with ingress enabled) - it: should set ingress name set: ingress.enabled: true diff --git a/helm/polaris/tests/job_test.yaml b/helm/polaris/tests/job_test.yaml index 4c83e7e272..6eaee0e33d 100644 --- a/helm/polaris/tests/job_test.yaml +++ b/helm/polaris/tests/job_test.yaml @@ -39,50 +39,50 @@ tests: not: true - it: should create job when enabled set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - containsDocument: kind: Job apiVersion: batch/v1 - # metadata.name (with bootstrapMetastoreManager enabled) + # metadata.name (with bootstrap.enabled true) - it: should set job name set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - equal: path: metadata.name - value: polaris-release + value: polaris-release-bootstrap - it: should set job name with override set: - bootstrapMetastoreManager: true + bootstrap.enabled: true nameOverride: polaris-override asserts: - equal: path: metadata.name - value: polaris-release-polaris-override + value: polaris-release-polaris-override-bootstrap - it: should set job name with full override set: - bootstrapMetastoreManager: true + bootstrap.enabled: true fullnameOverride: polaris-override asserts: - equal: path: metadata.name - value: polaris-override + value: polaris-override-bootstrap - # metadata.namespace (with bootstrapMetastoreManager enabled) + # metadata.namespace (with bootstrap.enabled true) - it: should set job namespace set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - equal: path: metadata.namespace value: polaris-ns - # metadata.labels (with bootstrapMetastoreManager enabled) + # metadata.labels (with bootstrap.enabled true) - it: should set job default labels set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - isSubset: path: metadata.labels @@ -94,7 +94,7 @@ tests: helm.sh/chart: polaris-1.2.3 - it: should set podLabels in job labels set: - bootstrapMetastoreManager: true + bootstrap.enabled: true podLabels: app.kubernetes.io/component: polaris asserts: @@ -103,26 +103,26 @@ tests: content: app.kubernetes.io/component: polaris - # metadata.annotations (with bootstrapMetastoreManager enabled) + # metadata.annotations (with bootstrap.enabled true) - it: should set job annotations set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - equal: path: metadata.annotations value: "helm.sh/hook": post-install - # spec.template.metadata.annotations (with bootstrapMetastoreManager enabled) + # spec.template.metadata.annotations (with bootstrap.enabled true) - it: should not set pod annotations by default set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - notExists: path: spec.template.metadata.annotations - it: should set pod annotations set: - bootstrapMetastoreManager: true + bootstrap.enabled: true podAnnotations: foo: bar asserts: @@ -131,10 +131,10 @@ tests: content: foo: bar - # spec.template.metadata.labels (with bootstrapMetastoreManager enabled) + # spec.template.metadata.labels (with bootstrap.enabled true) - it: should set pod labels set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - isSubset: path: spec.template.metadata.labels @@ -143,7 +143,7 @@ tests: app.kubernetes.io/instance: polaris-release - it: should set podLabels in pod labels set: - bootstrapMetastoreManager: true + bootstrap.enabled: true podLabels: app.kubernetes.io/component: polaris asserts: @@ -152,50 +152,16 @@ tests: content: app.kubernetes.io/component: polaris - # spec.template.spec.initContainers (with bootstrapMetastoreManager enabled) - - it: should not set initContainers by default - set: - bootstrapMetastoreManager: true - asserts: - - notExists: - path: spec.template.spec.initContainers - - it: should set initContainers if persistence is enabled - set: - bootstrapMetastoreManager: true - persistenceConfigSecret: polaris-persistence-secret - polarisServerConfig: - metaStoreManager: - conf-file: /eclipselink-config/conf.jar!/persistence.xml - toolsImage: - repository: test-repo - pullPolicy: Always - asserts: - - exists: - path: spec.template.spec.initContainers - - contains: - path: spec.template.spec.initContainers - content: - name: init-config - image: test-repo:latest - imagePullPolicy: Always - command: [ "jar" ] - args: [ "-cf", "/eclipselink-config/conf.jar", "-C", "/secret", "persistence.xml" ] - volumeMounts: - - name: eclipselink-config-volume - mountPath: /eclipselink-config - - name: secret-volume - mountPath: /secret - - # spec.template.spec.imagePullSecrets (with bootstrapMetastoreManager enabled) + # spec.template.spec.imagePullSecrets (with bootstrap.enabled true) - it: should not set imagePullSecrets by default set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - notExists: path: spec.template.spec.imagePullSecrets - it: should set imagePullSecrets set: - bootstrapMetastoreManager: true + bootstrap.enabled: true imagePullSecrets: - test-secret asserts: @@ -204,17 +170,17 @@ tests: content: name: test-secret - # spec.template.spec.serviceAccountName (with bootstrapMetastoreManager enabled) + # spec.template.spec.serviceAccountName (with bootstrap.enabled true) - it: should set default service account name set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - equal: path: spec.template.spec.serviceAccountName value: polaris-release - it: should set service account name when serviceAccount.create is true set: - bootstrapMetastoreManager: true + bootstrap.enabled: true serviceAccount: create: true asserts: @@ -223,7 +189,7 @@ tests: value: polaris-release - it: should set custom service account name when serviceAccount.create is true set: - bootstrapMetastoreManager: true + bootstrap.enabled: true serviceAccount: create: true name: polaris-sa @@ -233,7 +199,7 @@ tests: value: polaris-sa - it: should set service account name to default when serviceAccount.create is false set: - bootstrapMetastoreManager: true + bootstrap.enabled: true serviceAccount: create: false asserts: @@ -242,7 +208,7 @@ tests: value: default - it: should set custom service account name when serviceAccount.create is false set: - bootstrapMetastoreManager: true + bootstrap.enabled: true serviceAccount: create: false name: polaris-sa @@ -251,16 +217,16 @@ tests: path: spec.template.spec.serviceAccountName value: polaris-sa - # spec.template.spec.securityContext (with bootstrapMetastoreManager enabled) + # spec.template.spec.securityContext (with bootstrap.enabled true) - it: should not set securityContext by default set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - notExists: path: spec.template.spec.securityContext - it: should set securityContext set: - bootstrapMetastoreManager: true + bootstrap.enabled: true podSecurityContext: runAsUser: 1000 asserts: @@ -269,26 +235,26 @@ tests: content: runAsUser: 1000 - # spec.template.spec.containers (with bootstrapMetastoreManager enabled) + # spec.template.spec.containers (with bootstrap.enabled true) - it: should set container name set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - equal: path: spec.template.spec.containers[0].name - value: polaris + value: polaris-bootstrap - # spec.template.spec.containers[0].securityContext (with bootstrapMetastoreManager enabled) + # spec.template.spec.containers[0].securityContext (with bootstrap.enabled true) - it: should not set container securityContext by default set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - notExists: path: spec.template.spec.containers[0].securityContext - it: should set container securityContext set: - bootstrapMetastoreManager: true - securityContext: + bootstrap.enabled: true + containerSecurityContext: runAsUser: 1000 asserts: - isSubset: @@ -296,147 +262,63 @@ tests: content: runAsUser: 1000 - # spec.template.spec.containers[0].securityContext (with bootstrapMetastoreManager enabled) - - it: should not set initContainer securityContext by default - set: - bootstrapMetastoreManager: true - persistenceConfigSecret: polaris-persistence-secret - polarisServerConfig: - metaStoreManager: - conf-file: /eclipselink-config/conf.jar!/persistence.xml - asserts: - - notExists: - path: spec.template.spec.initContainers[0].securityContext - - it: should set initContainer securityContext - set: - bootstrapMetastoreManager: true - persistenceConfigSecret: polaris-persistence-secret - polarisServerConfig: - metaStoreManager: - conf-file: /eclipselink-config/conf.jar!/persistence.xml - securityContext: - runAsUser: 1000 - asserts: - - isSubset: - path: spec.template.spec.initContainers[0].securityContext - content: - runAsUser: 1000 - - # spec.template.spec.containers[0].image (with bootstrapMetastoreManager enabled) + # spec.template.spec.containers[0].image (with bootstrap.enabled true) - it: should set container image set: - bootstrapMetastoreManager: true - image: - repository: test-repo - tag: test-tag + bootstrap: + enabled: true + image: + repository: test-repo + tag: test-tag asserts: - equal: path: spec.template.spec.containers[0].image value: test-repo:test-tag - it: should set container image with template set: - bootstrapMetastoreManager: true - image: - repository: test-repo-{{ .Chart.Version }} - tag: test-tag-{{ .Release.Name }} + bootstrap: + enabled: true + image: + repository: test-repo-{{ .Chart.Version }} + tag: test-tag-{{ .Release.Name }} asserts: - equal: path: spec.template.spec.containers[0].image value: test-repo-1.2.3:test-tag-polaris-release - it: should set container image with chart version if no tag provided set: - bootstrapMetastoreManager: true - image: - repository: test-repo - tag: "" + bootstrap: + enabled: true + image: + repository: test-repo + tag: "" asserts: - equal: path: spec.template.spec.containers[0].image value: test-repo:1.2.3 - # spec.template.spec.containers[0].imagePullPolicy (with bootstrapMetastoreManager enabled) + # spec.template.spec.containers[0].imagePullPolicy (with bootstrap.enabled true) - it: should set container pull policy set: - bootstrapMetastoreManager: true - image: - pullPolicy: Always + bootstrap: + enabled: true + image: + pullPolicy: Always asserts: - equal: path: spec.template.spec.containers[0].imagePullPolicy value: Always - # spec.template.spec.containers[0].volumeMounts + spec.template.spec.volumes (with bootstrapMetastoreManager enabled) - - it: should not set persistence volumes by default - set: - bootstrapMetastoreManager: true - asserts: - - lengthEqual: - path: spec.template.spec.volumes - count: 1 - - lengthEqual: - path: spec.template.spec.containers[0].volumeMounts - count: 1 - - contains: - path: spec.template.spec.containers[0].volumeMounts - content: - name: config-volume - mountPath: /app/config/polaris-server.yml - subPath: polaris-server.yml - - it: should set persistence volumes if persistence is enabled - set: - bootstrapMetastoreManager: true - persistenceConfigSecret: polaris-persistence-secret - polarisServerConfig: - metaStoreManager: - conf-file: /eclipselink-config/conf.jar!/persistence.xml - asserts: - - lengthEqual: - path: spec.template.spec.volumes - count: 3 - - lengthEqual: - path: spec.template.spec.containers[0].volumeMounts - count: 2 - - contains: - path: spec.template.spec.volumes - content: - name: eclipselink-config-volume - emptyDir: { } - - contains: - path: spec.template.spec.volumes - content: - name: secret-volume - secret: - secretName: polaris-persistence-secret - - contains: - path: spec.template.spec.containers[0].volumeMounts - content: - name: eclipselink-config-volume - mountPath: /eclipselink-config - - it: should evaluate template expressions in persistence secret name - set: - bootstrapMetastoreManager: true - persistenceConfigSecret: '{{ .Release.Name }}-persistence-secret' - polarisServerConfig: - metaStoreManager: - conf-file: /eclipselink-config/conf.jar!/persistence.xml - asserts: - - contains: - path: spec.template.spec.volumes - content: - name: secret-volume - secret: - secretName: polaris-release-persistence-secret - - # spec.template.spec.containers[0].resources (with bootstrapMetastoreManager enabled) + # spec.template.spec.containers[0].resources (with bootstrap.enabled true) - it: should not set container resources by default set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - notExists: path: spec.template.spec.containers[0].resources - it: should set container resources set: - bootstrapMetastoreManager: true + bootstrap.enabled: true resources: requests: cpu: 100m @@ -455,19 +337,14 @@ tests: cpu: 200m memory: 256Mi - # spec.template.spec.containers[0].env (with bootstrapMetastoreManager enabled) - - it: should not set container env by default - set: - bootstrapMetastoreManager: true - asserts: - - notExists: - path: spec.template.spec.containers[0].env + # spec.template.spec.containers[0].env (with bootstrap.enabled true) - it: should set container env set: - bootstrapMetastoreManager: true - bootstrapExtraEnv: - - name: foo - value: bar + bootstrap: + enabled: true + extraEnv: + - name: foo + value: bar asserts: - contains: path: spec.template.spec.containers[0].env @@ -475,16 +352,16 @@ tests: name: foo value: bar - # spec.template.spec.nodeSelector (with bootstrapMetastoreManager enabled) + # spec.template.spec.nodeSelector (with bootstrap.enabled true) - it: should not set nodeSelector by default set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - notExists: path: spec.template.spec.nodeSelector - it: should set nodeSelector set: - bootstrapMetastoreManager: true + bootstrap.enabled: true nodeSelector: disktype: ssd asserts: @@ -493,16 +370,16 @@ tests: value: disktype: ssd - # spec.template.spec.affinity (with bootstrapMetastoreManager enabled) + # spec.template.spec.affinity (with bootstrap.enabled true) - it: should not set affinity by default set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - notExists: path: spec.template.spec.affinity - it: should set affinity set: - bootstrapMetastoreManager: true + bootstrap.enabled: true affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -527,16 +404,16 @@ tests: - zone1 - zone2 - # spec.template.spec.tolerations (with bootstrapMetastoreManager enabled) + # spec.template.spec.tolerations (with bootstrap.enabled true) - it: should not set tolerations by default set: - bootstrapMetastoreManager: true + bootstrap.enabled: true asserts: - notExists: path: spec.template.spec.tolerations - it: should set tolerations set: - bootstrapMetastoreManager: true + bootstrap.enabled: true tolerations: - key: "key" operator: "Equal" diff --git a/helm/polaris/tests/logging_storage_test.yaml b/helm/polaris/tests/logging_storage_test.yaml new file mode 100644 index 0000000000..0d777bf976 --- /dev/null +++ b/helm/polaris/tests/logging_storage_test.yaml @@ -0,0 +1,106 @@ +## +## Copyright (C) 2024 Dremio +## +## Licensed 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. +## + +release: + name: polaris + namespace: polaris-ns + +tests: + + - it: should create PVC for file logging + templates: + - storage.yaml + set: + logging.file.enabled: true + logging.file.logsDir: /var/log + logging.file.fileName: app.log + logging.file.storage.className: standard-rwo + logging.file.storage.size: 100Gi + asserts: + - containsDocument: + kind: PersistentVolumeClaim + apiVersion: v1 + name: polaris-logs + namespace: polaris-ns + - equal: + path: spec + value: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + storageClassName: standard-rwo + resources: + requests: + storage: 100Gi + - notExists: + path: spec.selector + + - it: should create PVC for file logging with selector labels + templates: + - storage.yaml + set: + logging.file.enabled: true + logging.file.logsDir: /var/log + logging.file.fileName: app.log + logging.file.storage.className: standard-rwo + logging.file.storage.size: 100Gi + logging.file.storage.selectorLabels: + app: polaris + documentSelector: + path: metadata.name + value: polaris-logs + asserts: + - containsDocument: + kind: PersistentVolumeClaim + apiVersion: v1 + name: polaris-logs + namespace: polaris-ns + - equal: + path: spec + value: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + storageClassName: standard-rwo + resources: + requests: + storage: 100Gi + selector: + matchLabels: + app: polaris + + - it: should mount PVC for file logging + templates: + - deployment.yaml + - configmap.yaml + set: + logging.file.enabled: true + logging.file.logsDir: /var/log + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: logs-storage + mountPath: /var/log + readOnly: false + template: deployment.yaml + - contains: + path: spec.template.spec.volumes + content: + name: logs-storage + persistentVolumeClaim: + claimName: polaris-logs + template: deployment.yaml diff --git a/helm/polaris/tests/quantity_test.yaml b/helm/polaris/tests/quantity_test.yaml new file mode 100644 index 0000000000..ca5ee25cee --- /dev/null +++ b/helm/polaris/tests/quantity_test.yaml @@ -0,0 +1,101 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +templates: + - configmap.yaml + +tests: + - it: should convert quantity 12345 + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"12345\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=12345" } } ] + - it: should convert quantity 12345.3456 + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"12345.3456\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=12345.3456" } } ] + - it: should convert quantity 123451234512345 + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"123451234512345\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=123451234512345" } } ] + - it: should convert quantity 1m + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1m\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=0.001" } } ] + - it: should convert quantity 100m + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"100m\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=0.1" } } ] + - it: should convert quantity 1000m + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1000m\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=1" } } ] + - it: should convert quantity 10000m + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"10000m\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=10" } } ] + - it: should convert quantity 1k + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1k\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=1000" } } ] + - it: should convert quantity 1ki + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1ki\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=1024" } } ] + - it: should convert quantity 100k + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"100k\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=100000" } } ] + - it: should convert quantity 100ki + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"100ki\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=102400" } } ] + - it: should convert quantity 1M + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1M\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=1000000" } } ] + - it: should convert quantity 1Mi + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1Mi\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=1048576" } } ] + - it: should convert quantity 1G + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1G\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=1000000000" } } ] + - it: should convert quantity 1Gi + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1Gi\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=1073741824" } } ] + - it: should convert quantity 1T + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1T\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=1000000000000" } } ] + - it: should convert quantity 1Ti + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1Ti\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=1099511627776" } } ] + - it: should convert quantity 1P + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1P\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=1000000000000000" } } ] + - it: should convert quantity 1Pi + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1Pi\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=1125899906842624" } } ] + - it: should convert quantity 1E + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1E\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=1000000000000000000" } } ] + - it: should convert quantity 1Ei + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1Ei\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=1152921504606846976" } } ] + - it: should fail on invalid quantity + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"invalid\" }}" }} + asserts: [ { failedTemplate: { errorMessage: "invalid quantity: invalid" } } ] + - it: should fail on zero quantity + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"0\" }}" }} + asserts: [ { failedTemplate: { errorMessage: "invalid quantity: 0" } } ] + - it: should fail on negative quantity + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"-1\" }}" }} + asserts: [ { failedTemplate: { errorMessage: "invalid quantity: -1" } } ] + - it: should convert quantity in scientific notation 123e2 + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"123e2\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=12300" } } ] + - it: should convert quantity in scientific notation 1.23e2 + set: { advancedConfig: { test: "{{ include \"polaris.quantity\" \"1.23e2\" }}" }} + asserts: [ { matchRegex: { path: "data[\"application.properties\"]", pattern: "test=123" } } ] diff --git a/helm/polaris/tests/service_extra_test.yaml b/helm/polaris/tests/service_extra_test.yaml new file mode 100644 index 0000000000..e34e77afc3 --- /dev/null +++ b/helm/polaris/tests/service_extra_test.yaml @@ -0,0 +1,349 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chart: + version: 1.2.3 + appVersion: 4.5.6 + +release: + name: polaris-release + namespace: polaris-ns + +templates: + - service-extra.yaml + +tests: + + - it: should not create extra service by default + asserts: + - containsDocument: + kind: Service + apiVersion: v1 + not: true + + - it: should fail to create extra service if suffix is not set + set: + extraServices: + - nameSuffix: "" + asserts: + - failedTemplate: + errorMessage: "extraServices[0]: missing required nameSuffix" + + - it: should fail to create extra service if suffix is invalid + set: + extraServices: + - nameSuffix: "mgmt" + asserts: + - failedTemplate: + errorMessage: "extraServices[0]: invalid nameSuffix" + - it: should fail to create extra service if suffix is invalid (#2) + set: + extraServices: + - nameSuffix: "-mgmt" + asserts: + - failedTemplate: + errorMessage: "extraServices[0]: invalid nameSuffix" + + # metadata.name + - it: should set service name + set: + extraServices: + - nameSuffix: "extra" + asserts: + - equal: + path: metadata.name + value: polaris-release-extra + - it: should set service name with override + set: + extraServices: + - nameSuffix: "extra" + nameOverride: polaris-override + asserts: + - equal: + path: metadata.name + value: polaris-release-polaris-override-extra + - it: should set service name with full override + set: + extraServices: + - nameSuffix: "extra" + fullnameOverride: polaris-override + asserts: + - equal: + path: metadata.name + value: polaris-override-extra + + # metadata.namespace + - it: should set service namespace + set: + extraServices: + - nameSuffix: "extra" + asserts: + - equal: + path: metadata.namespace + value: polaris-ns + + # metadata.labels + - it: should set service default labels + set: + extraServices: + - nameSuffix: "extra" + asserts: + - isSubset: + path: metadata.labels + content: + app.kubernetes.io/name: polaris + app.kubernetes.io/instance: polaris-release + app.kubernetes.io/version: 4.5.6 + app.kubernetes.io/managed-by: Helm + helm.sh/chart: polaris-1.2.3 + + # metadata.annotations + - it: should not set service annotations by default + set: + extraServices: + - nameSuffix: "extra" + asserts: + - notExists: + path: metadata.annotations + - it: should set service annotations + set: + extraServices: + - nameSuffix: "extra" + annotations: + foo: bar + asserts: + - isSubset: + path: metadata.annotations + content: + foo: bar + + # spec.type + - it: should set service default type + set: + extraServices: + - nameSuffix: "extra" + type: ClusterIP + asserts: + - equal: + path: spec.type + value: ClusterIP + - it: should set service type + set: + extraServices: + - nameSuffix: "extra" + type: NodePort + asserts: + - equal: + path: spec.type + value: NodePort + + # spec.selector + - it: should set service default selector + set: + extraServices: + - nameSuffix: "extra" + asserts: + - isSubset: + path: spec.selector + content: + app.kubernetes.io/name: polaris + app.kubernetes.io/instance: polaris-release + + # spec.ports + - it: should set service ports + set: + extraServices: + - nameSuffix: "extra" + ports: + - port: 18181 + targetPort: 18181 + name: polaris-http + - port: 28181 + targetPort: 28181 + name: polaris-http2 + nodePort: 28181 + protocol: UDP + asserts: + - equal: + path: spec.ports + value: + - port: 18181 + targetPort: 18181 + protocol: TCP + name: polaris-http + - port: 28181 + targetPort: 28181 + name: polaris-http2 + nodePort: 28181 + protocol: UDP + + # spec.sessionAffinity + - it: should not set service session affinity by default + set: + extraServices: + - nameSuffix: "extra" + asserts: + - notExists: + path: spec.sessionAffinity + - it: should set service session affinity + set: + extraServices: + - nameSuffix: "extra" + sessionAffinity: ClientIP + asserts: + - equal: + path: spec.sessionAffinity + value: ClientIP + + # spec.clusterIP + - it: should not set service cluster IP by default + set: + extraServices: + - nameSuffix: "extra" + asserts: + - notExists: + path: spec.clusterIP + - it: should set service cluster IP + set: + extraServices: + - nameSuffix: "extra" + clusterIP: 1.2.3.4 + asserts: + - equal: + path: spec.clusterIP + value: 1.2.3.4 + + # spec.externalTrafficPolicy + - it: should not set service external traffic policy by default + set: + extraServices: + - nameSuffix: "extra" + asserts: + - notExists: + path: spec.externalTrafficPolicy + - it: should set service external traffic policy if LoadBalancer + set: + extraServices: + - nameSuffix: "extra" + externalTrafficPolicy: Local + type: LoadBalancer + asserts: + - equal: + path: spec.externalTrafficPolicy + value: Local + - it: should set service external traffic policy if NodePort + set: + extraServices: + - nameSuffix: "extra" + externalTrafficPolicy: Local + type: NodePort + asserts: + - equal: + path: spec.externalTrafficPolicy + value: Local + - it: should set service external traffic policy if ClusterIP + set: + extraServices: + - nameSuffix: "extra" + externalTrafficPolicy: Local + type: ClusterIP + asserts: + - notExists: + path: spec.externalTrafficPolicy + + # spec.internalTrafficPolicy + - it: should not set service internal traffic policy by default + set: + extraServices: + - nameSuffix: "extra" + asserts: + - notExists: + path: spec.internalTrafficPolicy + - it: should set service internal traffic policy + set: + extraServices: + - nameSuffix: "extra" + internalTrafficPolicy: Local + asserts: + - equal: + path: spec.internalTrafficPolicy + value: Local + + # spec.trafficDistribution + - it: should not set service traffic distribution by default + set: + extraServices: + - nameSuffix: "extra" + asserts: + - notExists: + path: spec.trafficDistribution + - it: should set service traffic distribution if Kubernetes version >= 1.31 + capabilities: + majorVersion: 1 + minorVersion: 31 + set: + extraServices: + - nameSuffix: "extra" + trafficDistribution: Local + asserts: + - equal: + path: spec.trafficDistribution + value: Local + - it: should not set service traffic distribution if Kubernetes version < 1.31 + capabilities: + majorVersion: 1 + minorVersion: 30 + set: + extraServices: + - nameSuffix: "extra" + trafficDistribution: Local + asserts: + - notExists: + path: spec.trafficDistribution + + - it: should define many extra services + set: + extraServices: + - nameSuffix: "extra1" + annotations: + foo: bar + - nameSuffix: "extra2" + annotations: + bar: baz + asserts: + - hasDocuments: + count: 2 + - equal: + path: metadata.name + value: polaris-release-extra1 + documentIndex: 0 + - equal: + path: metadata.name + value: polaris-release-extra2 + documentIndex: 1 + - equal: + path: metadata.annotations + value: + foo: bar + documentIndex: 0 + - equal: + path: metadata.annotations + value: + bar: baz + documentIndex: 1 diff --git a/helm/polaris/tests/service_mgmt_test.yaml b/helm/polaris/tests/service_mgmt_test.yaml new file mode 100644 index 0000000000..6b6c9eea4c --- /dev/null +++ b/helm/polaris/tests/service_mgmt_test.yaml @@ -0,0 +1,253 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chart: + version: 1.2.3 + appVersion: 4.5.6 + +release: + name: polaris-release + namespace: polaris-ns + +templates: + - service-mgmt.yaml + +tests: + + # metadata.name + - it: should set service name + asserts: + - equal: + path: metadata.name + value: polaris-release-mgmt + - it: should set service name with override + set: + nameOverride: polaris-override + asserts: + - equal: + path: metadata.name + value: polaris-release-polaris-override-mgmt + - it: should set service name with full override + set: + fullnameOverride: polaris-override + asserts: + - equal: + path: metadata.name + value: polaris-override-mgmt + + # metadata.namespace + - it: should set service namespace + asserts: + - equal: + path: metadata.namespace + value: polaris-ns + + # metadata.labels + - it: should set service default labels + asserts: + - isSubset: + path: metadata.labels + content: + app.kubernetes.io/name: polaris + app.kubernetes.io/instance: polaris-release + app.kubernetes.io/version: 4.5.6 + app.kubernetes.io/managed-by: Helm + helm.sh/chart: polaris-1.2.3 + + # metadata.annotations + - it: should not set service annotations by default + asserts: + - notExists: + path: metadata.annotations + - it: should set service annotations + set: + managementService.annotations: + foo: bar + asserts: + - isSubset: + path: metadata.annotations + content: + foo: bar + + # spec.type + - it: should set service default type + asserts: + - equal: + path: spec.type + value: ClusterIP + - it: should set service type + set: + managementService.type: NodePort + asserts: + - equal: + path: spec.type + value: NodePort + + # spec.selector + - it: should set service default selector + asserts: + - isSubset: + path: spec.selector + content: + app.kubernetes.io/name: polaris + app.kubernetes.io/instance: polaris-release + + # spec.ports + - it: should set service default ports + asserts: + - equal: + path: spec.ports + value: + - port: 8182 + protocol: TCP + name: polaris-mgmt + - it: should set service ports + set: + managementService: + ports: + - port: 18182 + targetPort: 18182 + name: polaris-mgmt + asserts: + - equal: + path: spec.ports + value: + - port: 18182 + targetPort: 18182 + protocol: TCP + name: polaris-mgmt + - it: should set many service ports + set: + managementService: + ports: + - port: 18182 + targetPort: 18182 + name: polaris-mgmt + - port: 28182 + targetPort: 28182 + name: polaris-mgmt2 + nodePort: 28182 + protocol: UDP + asserts: + - equal: + path: spec.ports + value: + - port: 18182 + targetPort: 18182 + protocol: TCP + name: polaris-mgmt + - port: 28182 + targetPort: 28182 + name: polaris-mgmt2 + nodePort: 28182 + protocol: UDP + + # spec.sessionAffinity + - it: should not set service session affinity by default + asserts: + - notExists: + path: spec.sessionAffinity + - it: should set service session affinity + set: + managementService.sessionAffinity: ClientIP + asserts: + - equal: + path: spec.sessionAffinity + value: ClientIP + + # spec.clusterIP + - it: should not set service cluster IP by default + asserts: + - notExists: + path: spec.clusterIP + - it: should set service cluster IP + set: + managementService.clusterIP: 1.2.3.4 + asserts: + - equal: + path: spec.clusterIP + value: 1.2.3.4 + + + # spec.externalTrafficPolicy + - it: should not set service external traffic policy by default + asserts: + - notExists: + path: spec.externalTrafficPolicy + - it: should set service external traffic policy if LoadBalancer + set: + managementService.externalTrafficPolicy: Local + managementService.type: LoadBalancer + asserts: + - equal: + path: spec.externalTrafficPolicy + value: Local + - it: should set service external traffic policy if NodePort + set: + managementService.externalTrafficPolicy: Local + managementService.type: NodePort + asserts: + - equal: + path: spec.externalTrafficPolicy + value: Local + - it: should set service external traffic policy if ClusterIP + set: + managementService.externalTrafficPolicy: Local + managementService.type: ClusterIP + asserts: + - notExists: + path: spec.externalTrafficPolicy + + # spec.internalTrafficPolicy + - it: should not set service internal traffic policy by default + asserts: + - notExists: + path: spec.internalTrafficPolicy + - it: should set service internal traffic policy + set: + managementService.internalTrafficPolicy: Local + asserts: + - equal: + path: spec.internalTrafficPolicy + value: Local + + # spec.trafficDistribution + - it: should not set service traffic distribution by default + asserts: + - notExists: + path: spec.trafficDistribution + - it: should set service traffic distribution if Kubernetes version >= 1.31 + capabilities: + majorVersion: 1 + minorVersion: 31 + set: + managementService.trafficDistribution: Local + asserts: + - equal: + path: spec.trafficDistribution + value: Local + - it: should not set service traffic distribution if Kubernetes version < 1.31 + capabilities: + majorVersion: 1 + minorVersion: 30 + set: + managementService.trafficDistribution: Local + asserts: + - notExists: + path: spec.trafficDistribution diff --git a/helm/polaris/tests/service_monitor_test.yaml b/helm/polaris/tests/service_monitor_test.yaml new file mode 100644 index 0000000000..772d1ad5a3 --- /dev/null +++ b/helm/polaris/tests/service_monitor_test.yaml @@ -0,0 +1,76 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +release: + name: polaris + namespace: polaris-ns + +capabilities: + apiVersions: + - monitoring.coreos.com/v1 + +templates: + - servicemonitor.yaml + +tests: + + - it: should create ServiceMonitor if enabled + set: + serviceMonitor: + enabled: true + asserts: + - containsDocument: + kind: ServiceMonitor + apiVersion: monitoring.coreos.com/v1 + name: polaris + namespace: polaris-ns + + - it: should not create ServiceMonitor if disabled + set: + serviceMonitor: + enabled: false + asserts: + - containsDocument: + kind: ServiceMonitor + apiVersion: monitoring.coreos.com/v1 + name: polaris + namespace: polaris-ns + not: true + + - it: should add metrics relabelings + set: + serviceMonitor: + enabled: true + metricRelabelings: + - source_labels: [ __meta_kubernetes_namespace ] + separator: ; + regex: (.*) + target_label: namespace + replacement: $1 + action: replace + asserts: + - equal: + path: spec.endpoints[ 0].metricRelabelings + value: + - source_labels: [ __meta_kubernetes_namespace ] + separator: ; + regex: (.*) + target_label: namespace + replacement: $1 + action: replace \ No newline at end of file diff --git a/helm/polaris/tests/service_test.yaml b/helm/polaris/tests/service_test.yaml index b7e3057ab5..41ff599faa 100644 --- a/helm/polaris/tests/service_test.yaml +++ b/helm/polaris/tests/service_test.yaml @@ -114,45 +114,140 @@ tests: - equal: path: spec.ports value: - - port: 8182 - targetPort: 8182 - protocol: TCP - name: polaris-metrics - port: 8181 - targetPort: 8181 protocol: TCP - name: polaris-service + name: polaris-http - it: should set service ports set: service: ports: - polaris-service: 18181 - polaris-metrics: 18182 + - port: 18181 + targetPort: 18181 + name: polaris-http asserts: - equal: path: spec.ports value: - - port: 18182 - targetPort: 18182 + - port: 18181 + targetPort: 18181 protocol: TCP - name: polaris-metrics + name: polaris-http + - it: should set many service ports + set: + service: + ports: + - port: 18181 + targetPort: 18181 + name: polaris-http + - port: 28181 + targetPort: 28181 + name: polaris-http2 + nodePort: 28181 + protocol: UDP + asserts: + - equal: + path: spec.ports + value: - port: 18181 targetPort: 18181 protocol: TCP - name: polaris-service + name: polaris-http + - port: 28181 + targetPort: 28181 + name: polaris-http2 + nodePort: 28181 + protocol: UDP # spec.sessionAffinity - - it: should set service default session affinity + - it: should not set service session affinity by default asserts: - - equal: + - notExists: path: spec.sessionAffinity - value: - None - it: should set service session affinity set: service.sessionAffinity: ClientIP asserts: - equal: path: spec.sessionAffinity - value: - ClientIP + value: ClientIP + + # spec.clusterIP + - it: should not set service cluster IP by default + asserts: + - notExists: + path: spec.clusterIP + - it: should set service cluster IP + set: + service.clusterIP: 1.2.3.4 + asserts: + - equal: + path: spec.clusterIP + value: 1.2.3.4 + + + # spec.externalTrafficPolicy + - it: should not set service external traffic policy by default + asserts: + - notExists: + path: spec.externalTrafficPolicy + - it: should set service external traffic policy if LoadBalancer + set: + service.externalTrafficPolicy: Local + service.type: LoadBalancer + asserts: + - equal: + path: spec.externalTrafficPolicy + value: Local + - it: should set service external traffic policy if NodePort + set: + service.externalTrafficPolicy: Local + service.type: NodePort + asserts: + - equal: + path: spec.externalTrafficPolicy + value: Local + - it: should set service external traffic policy if ClusterIP + set: + service.externalTrafficPolicy: Local + service.type: ClusterIP + asserts: + - notExists: + path: spec.externalTrafficPolicy + + # spec.internalTrafficPolicy + - it: should not set service internal traffic policy by default + asserts: + - notExists: + path: spec.internalTrafficPolicy + - it: should set service internal traffic policy + set: + service.internalTrafficPolicy: Local + asserts: + - equal: + path: spec.internalTrafficPolicy + value: Local + + # spec.trafficDistribution + - it: should not set service traffic distribution by default + asserts: + - notExists: + path: spec.trafficDistribution + - it: should set service traffic distribution if Kubernetes version >= 1.31 + capabilities: + majorVersion: 1 + minorVersion: 31 + set: + service.trafficDistribution: Local + asserts: + - equal: + path: spec.trafficDistribution + value: Local + - it: should not set service traffic distribution if Kubernetes version < 1.31 + capabilities: + majorVersion: 1 + minorVersion: 30 + set: + service.trafficDistribution: Local + asserts: + - notExists: + path: spec.trafficDistribution diff --git a/helm/polaris/values.yaml b/helm/polaris/values.yaml index c365bf0812..34f83746f7 100644 --- a/helm/polaris/values.yaml +++ b/helm/polaris/values.yaml @@ -28,14 +28,9 @@ image: pullPolicy: IfNotPresent # -- The image tag. tag: "latest" - -toolsImage: - # -- The image repository to pull from (must have jar binary included). - repository: registry.access.redhat.com/ubi9/openjdk-21 - # -- The image pull policy. - pullPolicy: IfNotPresent - # -- The image tag. - tag: "latest" + # -- The path to the directory where the application.properties file, and other configuration + # files, if any, should be mounted. + configDir: /deployments/config # -- References to secrets in the same namespace to use for pulling any of the images used by this # chart. Each entry is a LocalObjectReference to an existing secret in the namespace. The secret @@ -74,7 +69,7 @@ podSecurityContext: # fsGroup: 2000 # -- Security context for the polaris container. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/. -securityContext: +containerSecurityContext: {} # capabilities: # drop: @@ -83,28 +78,121 @@ securityContext: # runAsNonRoot: true # runAsUser: 1000 -# Polaris service settings. +# -- Polaris main service settings. service: - # -- The type of service to create. + # -- The type of service to create. Valid values are: ExternalName, ClusterIP, NodePort, and LoadBalancer. + # The default value is ClusterIP. type: ClusterIP - # -- The ports the service will listen on. Two ports are required: one for the Polaris service and - # one for the metrics API. + # -- The ports the service will listen on. + # At least one port is required; the first port implicitly becomes the HTTP port that the + # application will use for serving API requests. By default, it's 8181. # Note: port names must be unique and no more than 15 characters long. ports: - # polaris-server: The port the Polaris server listens on for API requests. - polaris-service: 8181 - # polaris-metrics: The port the Polaris server listens on for metrics API requests (health checks, metrics, etc.). - polaris-metrics: 8182 - # -- The session affinity for the service. Valid values are: None, ClientIP. + # -- The name of the port. Required. + - name: polaris-http + # -- The port the service listens on. By default, the HTTP port is 8181. + port: 8181 + # -- Number or name of the port to access on the pods targeted by the service. + # If this is a string, it will be looked up as a named port in the target Pod's container ports. + # If this is not specified, the value of the 'port' field is used. + targetPort: ~ # polaris-service + # -- The port on each node on which this service is exposed when type is NodePort or LoadBalancer. + # Usually assigned by the system. If not specified, a port will be allocated if this Service requires one. If this field is specified when creating a Service which does not need it, creation will fail. + nodePort: ~ # 30000 + # -- The IP protocol for this port. Supports "TCP", "UDP", and "SCTP". Default is TCP. + protocol: ~ + # - name: polaris-https + # port: 18181 + # -- The session affinity for the service. Valid values are: None, ClientIP. The default value is None. # ClientIP enables sticky sessions based on the client's IP address. # This is generally beneficial to Polaris deployments, but some testing may be # required in order to make sure that the load is distributed evenly among the pods. # Also, this setting affects only internal clients, not external ones. # If Ingress is enabled, it is recommended to set sessionAffinity to None. - sessionAffinity: None + sessionAffinity: ~ + # -- You can specify your own cluster IP address + # If you define a Service that has the .spec.clusterIP set to "None" then Kubernetes does not assign an IP address. + # Instead, DNS records for the service will return the IP addresses of each pod targeted by the server. This is + # called a headless service. + # See https://kubernetes.io/docs/concepts/services-networking/service/#headless-services + clusterIP: ~ + # -- Controls how traffic from internal sources is routed. + # Valid values are Cluster and Local. The default value is Cluster. + # Set the field to Cluster to route traffic to all ready endpoints. + # Set the field to Local to only route to ready node-local endpoints. + # If the traffic policy is Local and there are no node-local endpoints, traffic is dropped by kube-proxy. + internalTrafficPolicy: ~ + # -- Controls how traffic from external sources is routed. + # Valid values are Cluster and Local. The default value is Cluster. + # Set the field to Cluster to route traffic to all ready endpoints. + # Set the field to Local to only route to ready node-local endpoints. + # If the traffic policy is Local and there are no node-local endpoints, traffic is dropped by kube-proxy. + externalTrafficPolicy: ~ + # -- The traffic distribution field provides another way to influence traffic routing within a Kubernetes Service. + # While traffic policies focus on strict semantic guarantees, traffic distribution allows you to express preferences + # such as routing to topologically closer endpoints. + # The only valid value is: PreferClose. The default value is implementation-specific. + trafficDistribution: ~ + # -- Annotations to add to the service. + annotations: {} + +# -- Management service settings. These settings are used to configure liveness and readiness probes, +# and to configure the dedicated headless service that will expose health checks and metrics, e.g. +# for metrics scraping and service monitoring. +managementService: + # -- The type of service to create. Valid values are: ExternalName, ClusterIP, NodePort, and LoadBalancer. + # The default value is ClusterIP. + type: ClusterIP + # -- The ports the management service will listen on. + # At least one port is required; the first port implicitly becomes the HTTP port that the + # application will use for serving management requests. By default, it's 8182. + # Note: port names must be unique and no more than 15 characters long. + ports: + # -- The name of the management port. Required. + - name: polaris-mgmt + # -- The port the management service listens on. By default, the management interface is exposed + # on HTTP port 8182. + port: 8182 + # -- Number or name of the port to access on the pods targeted by the service. + # If this is a string, it will be looked up as a named port in the target Pod's container ports. + # If this is not specified, the value of the 'port' field is used. + targetPort: ~ # polaris-service + # -- The port on each node on which this service is exposed when type is NodePort or LoadBalancer. + # Usually assigned by the system. If not specified, a port will be allocated if this Service requires one. If this field is specified when creating a Service which does not need it, creation will fail. + nodePort: ~ # 30000 + # -- The IP protocol for this port. Supports "TCP", "UDP", and "SCTP". Default is TCP. + protocol: ~ + clusterIP: ~ + sessionAffinity: ~ + internalTrafficPolicy: ~ + externalTrafficPolicy: ~ + trafficDistribution: ~ # -- Annotations to add to the service. annotations: {} +# -- Additional service definitions. All service definitions always select all Polaris pods. Use +# this if you need to expose specific ports with different configurations, e.g. expose polaris-http +# with an alternate LoadBalancer service instead of ClusterIP. +extraServices: [] + # - # -- The suffix to append to the service name. Required. It must be unique. If it does not + # # start with a hyphen, a hyphen will be inserted between the base service name and the suffix. + # nameSuffix: "ext" + # # -- The type of service to create. + # type: LoadBalancer + # # -- The ports the service will listen on. + # ports: + # - name: polaris-http + # number: 8181 + # targetPort: 8181 + # nodePort: 30000 + # protocol: TCP + # sessionAffinity: None + # clusterIP: "" + # internalTrafficPolicy: Cluster + # externalTrafficPolicy: Cluster + # trafficDistribution: PreferClose + # annotations: {} + # Polaris Ingress settings. # These settings generate an Ingress resource that routes external traffic to the Polaris service # using the "polaris-service" port described above. @@ -213,6 +301,36 @@ readinessProbe: # -- Number of seconds after which the probe times out. Minimum value is 1. timeoutSeconds: 10 +# -- Advanced configuration. +# You can pass here any valid Polaris or Quarkus configuration property. +# Any property that is defined here takes precedence over all the other configuration values generated by this chart. +# Properties can be passed "flattened" or as nested YAML objects (see examples below). +# Note: values should be strings; avoid using numbers, booleans, or other types. +advancedConfig: +# # Disable access log: +# quarkus.http.access-log.enabled: "true" +# # Reverse Proxy Settings +# # ---------------------- +# # +# # These config options are mentioned only for documentation purposes. Consult the +# # Quarkus documentation for "Running behind a reverse proxy" and configure those +# # depending on your actual needs. +# +# # See https://quarkus.io/guides/http-reference#reverse-proxy +# +# # Do NOT enable these option unless your reverse proxy (for example istio or nginx) +# # is properly setup to set these headers but also filter those from incoming requests. +# +# quarkus: +# http: +# proxy: +# proxy-address-forwarding: "true" +# allow-x-forwarded: "true" +# enable-forwarded-host: "true" +# enable-forwarded-prefix: "true" +# trusted-proxies: "127.0.0.1" + {} + # -- Advanced configuration via Environment Variables. # Extra environment variables to add to the Polaris server container. # You can pass here any valid EnvVar object: @@ -233,170 +351,291 @@ extraEnv: # name: aws-secret # key: secret_access_key -# -- Configures whether to enable the bootstrap metastore manager job -bootstrapMetastoreManager: false - -# -- Extra environment variables to add to the bootstrap metastore manager job (see `extraEnv` for an example) -bootstrapExtraEnv: [] - -# -- The secret name to pull persistence.xml from (ensure the key name is 'persistence.xml') -persistenceConfigSecret: ~ - -# -- Configures for polaris-server.yml -polarisServerConfig: - server: - # Maximum number of threads. - maxThreads: 200 - - # Minimum number of thread to keep alive. - minThreads: 10 - applicationConnectors: - # HTTP-specific options. - - type: http - - # The port on which the HTTP server listens for service requests. - port: 8181 - - adminConnectors: - - type: http - port: 8182 - - # The hostname of the interface to which the HTTP server socket wil be found. If omitted, the - # socket will listen on all interfaces. - # bindHost: localhost - - # ssl: - # keyStore: ./example.keystore - # keyStorePassword: example - # - # keyStoreType: JKS # (optional, JKS is default) - - # HTTP request log settings - requestLog: - appenders: - # Settings for logging to stdout. - - type: console - - # # Settings for logging to a file. - # - type: file - - # # The file to which statements will be logged. - # currentLogFilename: ./logs/request.log - - # # When the log file rolls over, the file will be archived to requests-2012-03-15.log.gz, - # # requests.log will be truncated, and new statements written to it. - # archivedLogFilenamePattern: ./logs/requests-%d.log.gz - - # # The maximum number of log files to archive. - # archivedFileCount: 14 - - # # Enable archiving if the request log entries go to the their own file - # archive: true - - featureConfiguration: - ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING: false - SUPPORTED_CATALOG_STORAGE_TYPES: - - S3 - - GCS - - AZURE - - FILE - - callContextResolver: +# -- Extra volumes to add to the polaris pod. See https://kubernetes.io/docs/concepts/storage/volumes/. +extraVolumes: [] + # - name: extra-volume + # emptyDir: {} + +# -- Extra volume mounts to add to the polaris container. See https://kubernetes.io/docs/concepts/storage/volumes/. +extraVolumeMounts: [] + # - name: extra-volume + # mountPath: /usr/share/extra-volume + +# -- Add additional init containers to the polaris pod(s) See https://kubernetes.io/docs/concepts/workloads/pods/init-containers/. +extraInitContainers: [] + # - name: your-image-name + # image: your-image + # imagePullPolicy: Always + # command: ['sh', '-c', 'echo "hello world"'] + +# -- Configures whether to enable the bootstrap metastore manager job. +# It is recommended to bootstrap realms using the Polaris Admin Tool; use this only if you need to +# bootstrap realms while deploying Polaris at the same time. +bootstrap: + # -- Specifies whether the bootstrap metastore manager job should be enabled. + enabled: false + # -- The names of the realms to bootstrap. + realms: [] + # -- The root credentials to create during the bootstrap. If you don't provide credentials for the + # root principal of each realm to bootstrap, random credentials will be generated. + # Each entry in the array must be of the form: realm,clientId,clientSecret + credentials: [] + # - realm1,root,s3cr3t + # - realm2,root,s3cr3t + # -- The image to use for the bootstrap metastore manager job. + image: + # -- The image repository to pull from. + repository: apache/polaris-admin-tool + # -- The image pull policy. + pullPolicy: IfNotPresent + # -- The image tag. + tag: "latest" + # -- The path to the directory where the application.properties file, and other configuration + # files, if any, should be mounted. + configDir: /deployments/config + # -- Extra environment variables to add to the bootstrap metastore manager job (see `extraEnv` for an example) + extraEnv: [] + +tracing: + # -- Specifies whether tracing for the polaris server should be enabled. + enabled: false + # -- The collector endpoint URL to connect to (required). + # The endpoint URL must have either the http:// or the https:// scheme. + # The collector must talk the OpenTelemetry protocol (OTLP) and the port must be its gRPC port (by default 4317). + # See https://quarkus.io/guides/opentelemetry for more information. + endpoint: "http://otlp-collector:4317" + # -- Which requests should be sampled. Valid values are: "all", "none", or a ratio between 0.0 and + # "1.0d" (inclusive). E.g. "0.5d" means that 50% of the requests will be sampled. + # Note: avoid entering numbers here, always prefer a string representation of the ratio. + sample: "1.0d" + # -- Resource attributes to identify the polaris service among other tracing sources. + # See https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/#service. + # If left empty, traces will be attached to a service named "Apache Polaris"; to change this, + # provide a service.name attribute here. + attributes: + {} + # service.name: my-polaris + +metrics: + # -- Specifies whether metrics for the polaris server should be enabled. + enabled: true + # -- Additional tags (dimensional labels) to add to the metrics. + tags: + {} + # service: polaris + # environment: production + +serviceMonitor: + # -- Specifies whether a ServiceMonitor for Prometheus operator should be created. + enabled: true + # -- The scrape interval; leave empty to let Prometheus decide. Must be a valid duration, e.g. 1d, 1h30m, 5m, 10s. + interval: "" + # -- Labels for the created ServiceMonitor so that Prometheus operator can properly pick it up. + labels: + {} + # release: prometheus + # -- Relabeling rules to apply to metrics. Ref https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config. + metricRelabelings: [] + # - source_labels: [ __meta_kubernetes_namespace ] + # separator: ; + # regex: (.*) + # target_label: namespace + # replacement: $1 + # action: replace + +# -- Logging configuration. +logging: + # -- The log level of the root category, which is used as the default log level for all categories. + level: INFO + # -- The header name to use for the request ID. + requestIdHeaderName: Polaris-Request-Id + # -- Configuration for the console appender. + console: + # -- Whether to enable the console appender. + enabled: true + # -- The log level of the console appender. + threshold: ALL + # -- Whether to log in JSON format. + json: false + # -- The log format to use. Ignored if JSON format is enabled. See + # https://quarkus.io/guides/logging#logging-format for details. + format: "%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] [%X{requestId},%X{realmId}] [%X{traceId},%X{parentId},%X{spanId},%X{sampled}] (%t) %s%e%n" + # -- Configuration for the file appender. + file: + # -- Whether to enable the file appender. + enabled: false + # -- The log level of the file appender. + threshold: ALL + # -- Whether to log in JSON format. + json: false + # -- The log format to use. Ignored if JSON format is enabled. See + # https://quarkus.io/guides/logging#logging-format for details. + format: "%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] [%X{requestId},%X{realmId}] [%X{traceId},%X{parentId},%X{spanId},%X{sampled}] (%t) %s%e%n" + # -- The local directory where log files are stored. The persistent volume claim will be mounted + # here. + logsDir: /deployments/logs + # -- The log file name. + fileName: polaris.log + # -- Log rotation configuration. + rotation: + # -- The maximum size of the log file before it is rotated. Should be expressed as a Kubernetes quantity. + maxFileSize: 100Mi + # -- The maximum number of backup files to keep. + maxBackupIndex: 5 + # -- An optional suffix to append to the rotated log files. If present, the rotated log files + # will be grouped in time buckets, and each bucket will contain at most maxBackupIndex files. + # The suffix must be in a date-time format that is understood by DateTimeFormatter. If the + # suffix ends with .gz or .zip, the rotated files will also be compressed using the + # corresponding algorithm. + fileSuffix: ~ # .yyyy-MM-dd.gz + # -- The log storage configuration. A persistent volume claim will be created using these + # settings. + storage: + # -- The storage class name of the persistent volume claim to create. + className: standard + # -- The size of the persistent volume claim to create. + size: 512Gi + # -- Labels to add to the persistent volume claim spec selector; a persistent volume with + # matching labels must exist. Leave empty if using dynamic provisioning. + selectorLabels: {} + # app.kubernetes.io/name: polaris + # app.kubernetes.io/instance: RELEASE-NAME + # -- Configuration for specific log categories. + categories: + org.apache.polaris: INFO + org.apache.iceberg.rest: INFO + # Useful to debug configuration issues: + # io.smallrye.config: DEBUG + # -- Configuration for MDC (Mapped Diagnostic Context). Values specified here will be added to the + # log context of all incoming requests and can be used in log patterns. + mdc: + # aid=polaris + # sid=polaris-service + {} + +# -- Realm context resolver configuration. +realmContext: + # -- The type of realm context resolver to use. Two built-in types are supported: default and test; + # test is not recommended for production as it does not perform any realm validation. + type: default + # -- List of valid realms, for use with the default realm context resolver. The first realm in + # the list is the default realm. Realms not in this list will be rejected. + realms: + - POLARIS + +# -- Polaris features configuration. +features: + # -- Features to enable or disable globally. If a feature is not present in the map, the default + # built-in value is used. + defaults: {} + # ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING: false + # SUPPORTED_CATALOG_STORAGE_TYPES: + # - S3 + # - GCS + # - AZURE + # - FILE + # -- Features to enable or disable per realm. This field is a map of maps. The realm name is the key, and the value is a map of + # feature names to values. If a feature is not present in the map, the default value from the 'defaults' field is used. + realmOverrides: {} + # my-realm: + # ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING: true + +# -- Polaris persistence configuration. +persistence: + # -- The type of persistence to use. Two built-in types are supported: in-memory and eclipse-link. + type: eclipse-link # in-memory + # -- The configuration for the eclipse-link persistence manager. + eclipseLink: + # -- The secret name to pull persistence.xml from. + secret: + # -- The name of the secret to pull persistence.xml from. + # If not provided, the default built-in persistence.xml will be used. This is probably not what you want. + name: ~ + # -- The key in the secret to pull persistence.xml from. + key: persistence.xml + # -- The persistence unit name to use. + persistenceUnit: polaris + +# -- Polaris FileIO configuration. +fileIo: + # -- The type of file IO to use. Two built-in types are supported: default and wasb. The wasb one translates WASB paths to ABFS ones. + type: default + +# -- Storage credentials for the server. If the following properties are unset, default +# credentials will be used, in which case the pod must have the necessary permissions to access the storage. +storage: + # -- The secret to pull storage credentials from. + secret: + # -- The name of the secret to pull storage credentials from. + name: ~ + # -- The key in the secret to pull the AWS access key ID from. Only required when using AWS. + awsAccessKeyId: ~ + # -- The key in the secret to pull the AWS secret access key from. Only required when using AWS. + awsSecretAccessKey: ~ + # -- The key in the secret to pull the GCP token from. Only required when using GCP. + gcpToken: ~ + # -- The key in the secret to pull the GCP token expiration time from. Only required when using GCP. Must be a valid ISO 8601 duration. The default is PT1H (1 hour). + gcpTokenLifespan: ~ + +# -- Polaris authentication configuration. +authentication: + # -- The type of authentication to use. Two built-in types are supported: default and test; + # test is not recommended for production. + authenticator: type: default - - realmContextResolver: + # -- The type of token service to use. Two built-in types are supported: default and test; + # test is not recommended for production. + tokenService: type: default - - defaultRealms: - - default-realm - - metaStoreManager: - type: in-memory - # uncomment below to use eclipse-link as metastore - # type: eclipse-link - # persistence-unit: polaris - # conf-file: /eclipselink-config/conf.jar!/persistence.xml - - io: - factoryType: default - - # TODO - avoid duplicating token broker config - oauth2: - type: test - # type: default # - uncomment to support Auth0 JWT tokens -# tokenBroker: -# type: symmetric-key -# secret: polaris - - authenticator: - class: org.apache.polaris.service.auth.TestInlineBearerTokenPolarisAuthenticator - # class: org.apache.polaris.service.auth.DefaultPolarisAuthenticator # - uncomment to support Auth0 JWT tokens - # tokenBroker: - # type: symmetric-key - # secret: polaris - - cors: - allowed-origins: - - http://localhost:8080 - allowed-timing-origins: - - http://localhost:8080 - allowed-methods: - - PATCH - - POST - - DELETE - - GET - - PUT - allowed-headers: - - "*" - exposed-headers: - - "*" - preflight-max-age: 600 - allowed-credentials: true - - # Logging settings. - - logging: - - # The default level of all loggers. Can be OFF, ERROR, WARN, INFO, DEBUG, TRACE, or ALL. - level: INFO - - # Logger-specific levels. - loggers: - org.apache.iceberg.rest: DEBUG - org.apache.polaris: DEBUG - - appenders: - - - type: console - # If true, write log statements to stdout. - # enabled: true - # Do not display log statements below this threshold to stdout. - threshold: ALL - # Custom Logback PatternLayout with threadname. - logFormat: "%-5p [%d{ISO8601} - %-6r] [%t] [%X{aid}%X{sid}%X{tid}%X{wid}%X{oid}%X{srv}%X{job}%X{rid}] %c{30}: %m %kvp%n%ex" - - # # Settings for logging to a file. - # - type: file - # # If true, write log statements to a file. - # # enabled: true - # # Do not write log statements below this threshold to the file. - # threshold: ALL - # layout: - # type: polaris - # flattenKeyValues: false - # includeKeyValues: true - - # # The file to which statements will be logged. - # currentLogFilename: ./logs/polaris.log - # # When the log file rolls over, the file will be archived to polaris-2012-03-15.log.gz, - # # polaris.log will be truncated, and new statements written to it. - # archivedLogFilenamePattern: ./logs/polaris-%d.log.gz - # # The maximum number of log files to archive. - # archivedFileCount: 14 - - # Limits the size of request bodies sent to Polaris. -1 means no limit. - maxRequestBodyBytes: -1 - - # Optional, not specifying a "rateLimiter" section also means no rate limiter - rateLimiter: - type: no-op + # -- The type of token broker to use. Two built-in types are supported: rsa-key-pair and symmetric-key. + tokenBroker: + type: rsa-key-pair # symmetric-key + maxTokenGeneration: PT1H + # -- The secret name to pull the public and private keys, or the symmetric key secret from. + secret: + # -- The name of the secret to pull the keys from. If not provided, a key pair will be generated. + # This is not recommended for production. + name: ~ + # -- The public key file to use for RSA key pair token broker. Only required when using rsa-key-pair. + publicKey: public.pem + # -- The private key file to use for RSA key pair token broker. Only required when using rsa-key-pair. + privateKey: private.pem + # -- The symmetric key file to use for symmetric key token broker. Only required when using symmetric-key. + secretKey: secret + +# -- Polaris CORS configuration. +cors: + # -- Origins allowed for CORS, e.g. http://polaris.io, http://localhost:8181. In case an entry of the list is surrounded by forward slashes, it is interpreted as a regular expression. + allowedOrigins: [] + # -- HTTP methods allowed for CORS, ex: GET, PUT, POST. If this is not set or empty, all requested methods are considered allowed. + allowedMethods: [] + # -- HTTP headers allowed for CORS, ex: X-Custom, Content-Disposition. If this is not set or empty, all requested headers are considered allowed. + allowedHeaders: [] + # -- HTTP headers exposed to the client, ex: X-Custom, Content-Disposition. The default is an empty list. + exposedHeaders: [] + # -- The `Access-Control-Max-Age` response header value indicating how long the results of a pre-flight request can be cached. Must be a valid duration. + accessControlMaxAge: ~ # PT10M + # -- The `Access-Control-Allow-Credentials` response header. + # The value of this header will default to `true` if `allowedOrigins` property is set and there is a match with the precise `Origin` header. + accessControlAllowCredentials: ~ # true + +# -- Polaris rate limiter configuration. +rateLimiter: + # -- The type of rate limiter filter to use. Two built-in types are supported: default and no-op. + type: no-op + # -- The configuration for the default rate limiter, which uses the token bucket algorithm with + # one bucket per realm. + tokenBucket: + # -- The type of the token bucket rate limiter. Only the default type is supported out of the box. + type: default + # -- The maximum number of requests per second allowed for each realm. + requestsPerSecond: 9999 + # -- The time window. + window: PT10S + +# -- Polaris asynchronous task executor configuration. +tasks: + # -- The maximum number of concurrent tasks that can be executed at the same time. The default is the number of available cores. + maxConcurrentTasks: ~ # 100 + # -- The maximum number of tasks that can be queued up for execution. The default is Integer.MAX_VALUE. + maxQueuedTasks: ~ # 1000 From bac622df6fd4e77c1c3cb634bebd7a6a36f6a7ee Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Mon, 3 Feb 2025 14:16:03 +0100 Subject: [PATCH 2/8] remove bootstrap job --- helm/polaris/README.md | 10 - helm/polaris/ci/persistence-values.yaml | 9 - helm/polaris/ci/simple-values.yaml | 4 - helm/polaris/templates/job.yaml | 110 ------ helm/polaris/tests/job_test.yaml | 429 ------------------------ helm/polaris/values.yaml | 28 -- 6 files changed, 590 deletions(-) delete mode 100644 helm/polaris/templates/job.yaml delete mode 100644 helm/polaris/tests/job_test.yaml diff --git a/helm/polaris/README.md b/helm/polaris/README.md index d3756e06a1..3b9887c066 100644 --- a/helm/polaris/README.md +++ b/helm/polaris/README.md @@ -149,16 +149,6 @@ helm uninstall --namespace polaris polaris | autoscaling.minReplicas | int | `1` | The minimum number of replicas to maintain. | | autoscaling.targetCPUUtilizationPercentage | int | `80` | Optional; set to zero or empty to disable. | | autoscaling.targetMemoryUtilizationPercentage | string | `nil` | Optional; set to zero or empty to disable. | -| bootstrap | object | `{"credentials":[],"enabled":false,"extraEnv":[],"image":{"configDir":"/deployments/config","pullPolicy":"IfNotPresent","repository":"apache/polaris-admin-tool","tag":"latest"},"realms":[]}` | Configures whether to enable the bootstrap metastore manager job. It is recommended to bootstrap realms using the Polaris Admin Tool; use this only if you need to bootstrap realms while deploying Polaris at the same time. | -| bootstrap.credentials | list | `[]` | The root credentials to create during the bootstrap. If you don't provide credentials for the root principal of each realm to bootstrap, random credentials will be generated. Each entry in the array must be of the form: realm,clientId,clientSecret | -| bootstrap.enabled | bool | `false` | Specifies whether the bootstrap metastore manager job should be enabled. | -| bootstrap.extraEnv | list | `[]` | Extra environment variables to add to the bootstrap metastore manager job (see `extraEnv` for an example) | -| bootstrap.image | object | `{"configDir":"/deployments/config","pullPolicy":"IfNotPresent","repository":"apache/polaris-admin-tool","tag":"latest"}` | The image to use for the bootstrap metastore manager job. | -| bootstrap.image.configDir | string | `"/deployments/config"` | The path to the directory where the application.properties file, and other configuration files, if any, should be mounted. | -| bootstrap.image.pullPolicy | string | `"IfNotPresent"` | The image pull policy. | -| bootstrap.image.repository | string | `"apache/polaris-admin-tool"` | The image repository to pull from. | -| bootstrap.image.tag | string | `"latest"` | The image tag. | -| bootstrap.realms | list | `[]` | The names of the realms to bootstrap. | | configMapLabels | object | `{}` | Additional Labels to apply to polaris configmap. | | containerSecurityContext | object | `{}` | Security context for the polaris container. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/. | | cors | object | `{"accessControlAllowCredentials":null,"accessControlMaxAge":null,"allowedHeaders":[],"allowedMethods":[],"allowedOrigins":[],"exposedHeaders":[]}` | Polaris CORS configuration. | diff --git a/helm/polaris/ci/persistence-values.yaml b/helm/polaris/ci/persistence-values.yaml index ff97a5ecc8..3d83874399 100644 --- a/helm/polaris/ci/persistence-values.yaml +++ b/helm/polaris/ci/persistence-values.yaml @@ -37,12 +37,3 @@ persistence: eclipseLink: secret: name: polaris-persistence - -bootstrap: - enabled: true - realms: - - POLARIS - credentials: - - POLARIS,root,secret - image: - pullPolicy: Never diff --git a/helm/polaris/ci/simple-values.yaml b/helm/polaris/ci/simple-values.yaml index e3e7c41da2..4daf85ddf9 100644 --- a/helm/polaris/ci/simple-values.yaml +++ b/helm/polaris/ci/simple-values.yaml @@ -25,7 +25,3 @@ storage: name: polaris-storage awsAccessKeyId: access-key awsSecretAccessKey: secret-key - -extraEnv: - - name: POLARIS_BOOTSTRAP_CREDENTIALS - value: root,root,secret diff --git a/helm/polaris/templates/job.yaml b/helm/polaris/templates/job.yaml deleted file mode 100644 index bfbbc4e273..0000000000 --- a/helm/polaris/templates/job.yaml +++ /dev/null @@ -1,110 +0,0 @@ -{{/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/}} - -{{- if .Values.bootstrap.enabled }} -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ include "polaris.fullnameWithSuffix" (list . "bootstrap") }} - namespace: {{ .Release.Namespace }} - labels: - {{- include "polaris.labels" . | nindent 4 }} - {{- if .Values.podLabels }} - {{- tpl (toYaml .Values.podLabels) . | nindent 4 }} - {{- end }} - annotations: - "helm.sh/hook": post-install -spec: - template: - metadata: - {{- if .Values.podAnnotations }} - annotations: - {{- tpl (toYaml .Values.podAnnotations) . | nindent 8 }} - {{- end }} - labels: - {{- include "polaris.selectorLabels" . | nindent 8 }} - {{- if .Values.podLabels }} - {{- tpl (toYaml .Values.podLabels) . | nindent 8 }} - {{- end }} - spec: - {{- if .Values.imagePullSecrets }} - imagePullSecrets: - {{- range .Values.imagePullSecrets }} - - name: {{ . | quote }} - {{- end }} - {{- end }} - serviceAccountName: {{ include "polaris.serviceAccountName" . }} - {{- if .Values.podSecurityContext }} - securityContext: - {{- tpl (toYaml .Values.podSecurityContext) . | nindent 8 }} - {{- end }} - containers: - - name: "polaris-bootstrap" - {{- if .Values.containerSecurityContext }} - securityContext: - {{- tpl (toYaml .Values.containerSecurityContext) . | nindent 12 }} - {{- end }} - image: "{{ tpl .Values.bootstrap.image.repository . }}:{{ tpl .Values.bootstrap.image.tag . | default .Chart.Version }}" - imagePullPolicy: {{ tpl .Values.bootstrap.image.pullPolicy . }} - args: - - "bootstrap" - {{- range $realm := .Values.bootstrap.realms }} - - --realm={{ tpl $realm $ }} - {{- end }} - {{- range $credential := .Values.bootstrap.credentials }} - - --credential={{ tpl $credential $ }} - {{- end }} - env: - {{- if .Values.bootstrap.extraEnv }} - {{- tpl (toYaml .Values.bootstrap.extraEnv) . | nindent 12 }} - {{- end }} - - name: "quarkus.log.file.enable" - value: "false" - volumeMounts: - - name: config-volume - mountPath: {{ trimSuffix "/" .Values.bootstrap.image.configDir }} - readOnly: true - - name: temp-dir - mountPath: /tmp - readOnly: false - {{- if .Values.resources }} - resources: - {{- tpl (toYaml .Values.resources) . | nindent 12 }} - {{- end }} - restartPolicy: Never - volumes: - {{- include "polaris.configVolume" . | nindent 8 }} - - name: temp-dir - emptyDir: {} - {{- if .Values.extraVolumes }} - {{- tpl (toYaml .Values.extraVolumes) . | nindent 8 }} - {{- end }} - {{- if .Values.nodeSelector }} - nodeSelector: - {{- tpl (toYaml .Values.nodeSelector) . | nindent 8 }} - {{- end }} - {{- if .Values.affinity }} - affinity: - {{- tpl (toYaml .Values.affinity) . | nindent 8 }} - {{- end }} - {{- if .Values.tolerations }} - tolerations: - {{- tpl (toYaml .Values.tolerations) . | nindent 8 }} - {{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/polaris/tests/job_test.yaml b/helm/polaris/tests/job_test.yaml deleted file mode 100644 index 6eaee0e33d..0000000000 --- a/helm/polaris/tests/job_test.yaml +++ /dev/null @@ -1,429 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -chart: - version: 1.2.3 - appVersion: 4.5.6 - -release: - name: polaris-release - namespace: polaris-ns - -templates: - - job.yaml - -tests: - - # kind - - it: should not create job by default - asserts: - - containsDocument: - kind: Job - apiVersion: batch/v1 - not: true - - it: should create job when enabled - set: - bootstrap.enabled: true - asserts: - - containsDocument: - kind: Job - apiVersion: batch/v1 - - # metadata.name (with bootstrap.enabled true) - - it: should set job name - set: - bootstrap.enabled: true - asserts: - - equal: - path: metadata.name - value: polaris-release-bootstrap - - it: should set job name with override - set: - bootstrap.enabled: true - nameOverride: polaris-override - asserts: - - equal: - path: metadata.name - value: polaris-release-polaris-override-bootstrap - - it: should set job name with full override - set: - bootstrap.enabled: true - fullnameOverride: polaris-override - asserts: - - equal: - path: metadata.name - value: polaris-override-bootstrap - - # metadata.namespace (with bootstrap.enabled true) - - it: should set job namespace - set: - bootstrap.enabled: true - asserts: - - equal: - path: metadata.namespace - value: polaris-ns - - # metadata.labels (with bootstrap.enabled true) - - it: should set job default labels - set: - bootstrap.enabled: true - asserts: - - isSubset: - path: metadata.labels - content: - app.kubernetes.io/name: polaris - app.kubernetes.io/instance: polaris-release - app.kubernetes.io/version: 4.5.6 - app.kubernetes.io/managed-by: Helm - helm.sh/chart: polaris-1.2.3 - - it: should set podLabels in job labels - set: - bootstrap.enabled: true - podLabels: - app.kubernetes.io/component: polaris - asserts: - - isSubset: - path: metadata.labels - content: - app.kubernetes.io/component: polaris - - # metadata.annotations (with bootstrap.enabled true) - - it: should set job annotations - set: - bootstrap.enabled: true - asserts: - - equal: - path: metadata.annotations - value: - "helm.sh/hook": post-install - - # spec.template.metadata.annotations (with bootstrap.enabled true) - - it: should not set pod annotations by default - set: - bootstrap.enabled: true - asserts: - - notExists: - path: spec.template.metadata.annotations - - it: should set pod annotations - set: - bootstrap.enabled: true - podAnnotations: - foo: bar - asserts: - - isSubset: - path: spec.template.metadata.annotations - content: - foo: bar - - # spec.template.metadata.labels (with bootstrap.enabled true) - - it: should set pod labels - set: - bootstrap.enabled: true - asserts: - - isSubset: - path: spec.template.metadata.labels - content: - app.kubernetes.io/name: polaris - app.kubernetes.io/instance: polaris-release - - it: should set podLabels in pod labels - set: - bootstrap.enabled: true - podLabels: - app.kubernetes.io/component: polaris - asserts: - - isSubset: - path: spec.template.metadata.labels - content: - app.kubernetes.io/component: polaris - - # spec.template.spec.imagePullSecrets (with bootstrap.enabled true) - - it: should not set imagePullSecrets by default - set: - bootstrap.enabled: true - asserts: - - notExists: - path: spec.template.spec.imagePullSecrets - - it: should set imagePullSecrets - set: - bootstrap.enabled: true - imagePullSecrets: - - test-secret - asserts: - - contains: - path: spec.template.spec.imagePullSecrets - content: - name: test-secret - - # spec.template.spec.serviceAccountName (with bootstrap.enabled true) - - it: should set default service account name - set: - bootstrap.enabled: true - asserts: - - equal: - path: spec.template.spec.serviceAccountName - value: polaris-release - - it: should set service account name when serviceAccount.create is true - set: - bootstrap.enabled: true - serviceAccount: - create: true - asserts: - - equal: - path: spec.template.spec.serviceAccountName - value: polaris-release - - it: should set custom service account name when serviceAccount.create is true - set: - bootstrap.enabled: true - serviceAccount: - create: true - name: polaris-sa - asserts: - - equal: - path: spec.template.spec.serviceAccountName - value: polaris-sa - - it: should set service account name to default when serviceAccount.create is false - set: - bootstrap.enabled: true - serviceAccount: - create: false - asserts: - - equal: - path: spec.template.spec.serviceAccountName - value: default - - it: should set custom service account name when serviceAccount.create is false - set: - bootstrap.enabled: true - serviceAccount: - create: false - name: polaris-sa - asserts: - - equal: - path: spec.template.spec.serviceAccountName - value: polaris-sa - - # spec.template.spec.securityContext (with bootstrap.enabled true) - - it: should not set securityContext by default - set: - bootstrap.enabled: true - asserts: - - notExists: - path: spec.template.spec.securityContext - - it: should set securityContext - set: - bootstrap.enabled: true - podSecurityContext: - runAsUser: 1000 - asserts: - - isSubset: - path: spec.template.spec.securityContext - content: - runAsUser: 1000 - - # spec.template.spec.containers (with bootstrap.enabled true) - - it: should set container name - set: - bootstrap.enabled: true - asserts: - - equal: - path: spec.template.spec.containers[0].name - value: polaris-bootstrap - - # spec.template.spec.containers[0].securityContext (with bootstrap.enabled true) - - it: should not set container securityContext by default - set: - bootstrap.enabled: true - asserts: - - notExists: - path: spec.template.spec.containers[0].securityContext - - it: should set container securityContext - set: - bootstrap.enabled: true - containerSecurityContext: - runAsUser: 1000 - asserts: - - isSubset: - path: spec.template.spec.containers[0].securityContext - content: - runAsUser: 1000 - - # spec.template.spec.containers[0].image (with bootstrap.enabled true) - - it: should set container image - set: - bootstrap: - enabled: true - image: - repository: test-repo - tag: test-tag - asserts: - - equal: - path: spec.template.spec.containers[0].image - value: test-repo:test-tag - - it: should set container image with template - set: - bootstrap: - enabled: true - image: - repository: test-repo-{{ .Chart.Version }} - tag: test-tag-{{ .Release.Name }} - asserts: - - equal: - path: spec.template.spec.containers[0].image - value: test-repo-1.2.3:test-tag-polaris-release - - it: should set container image with chart version if no tag provided - set: - bootstrap: - enabled: true - image: - repository: test-repo - tag: "" - asserts: - - equal: - path: spec.template.spec.containers[0].image - value: test-repo:1.2.3 - - # spec.template.spec.containers[0].imagePullPolicy (with bootstrap.enabled true) - - it: should set container pull policy - set: - bootstrap: - enabled: true - image: - pullPolicy: Always - asserts: - - equal: - path: spec.template.spec.containers[0].imagePullPolicy - value: Always - - # spec.template.spec.containers[0].resources (with bootstrap.enabled true) - - it: should not set container resources by default - set: - bootstrap.enabled: true - asserts: - - notExists: - path: spec.template.spec.containers[0].resources - - it: should set container resources - set: - bootstrap.enabled: true - resources: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 200m - memory: 256Mi - asserts: - - equal: - path: spec.template.spec.containers[0].resources - value: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 200m - memory: 256Mi - - # spec.template.spec.containers[0].env (with bootstrap.enabled true) - - it: should set container env - set: - bootstrap: - enabled: true - extraEnv: - - name: foo - value: bar - asserts: - - contains: - path: spec.template.spec.containers[0].env - content: - name: foo - value: bar - - # spec.template.spec.nodeSelector (with bootstrap.enabled true) - - it: should not set nodeSelector by default - set: - bootstrap.enabled: true - asserts: - - notExists: - path: spec.template.spec.nodeSelector - - it: should set nodeSelector - set: - bootstrap.enabled: true - nodeSelector: - disktype: ssd - asserts: - - equal: - path: spec.template.spec.nodeSelector - value: - disktype: ssd - - # spec.template.spec.affinity (with bootstrap.enabled true) - - it: should not set affinity by default - set: - bootstrap.enabled: true - asserts: - - notExists: - path: spec.template.spec.affinity - - it: should set affinity - set: - bootstrap.enabled: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: zone - operator: In - values: - - zone1 - - zone2 - asserts: - - equal: - path: spec.template.spec.affinity - value: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: zone - operator: In - values: - - zone1 - - zone2 - - # spec.template.spec.tolerations (with bootstrap.enabled true) - - it: should not set tolerations by default - set: - bootstrap.enabled: true - asserts: - - notExists: - path: spec.template.spec.tolerations - - it: should set tolerations - set: - bootstrap.enabled: true - tolerations: - - key: "key" - operator: "Equal" - value: "value" - effect: "NoSchedule" - asserts: - - equal: - path: spec.template.spec.tolerations - value: - - key: "key" - operator: "Equal" - value: "value" - effect: "NoSchedule" \ No newline at end of file diff --git a/helm/polaris/values.yaml b/helm/polaris/values.yaml index 34f83746f7..fcbc99a1bc 100644 --- a/helm/polaris/values.yaml +++ b/helm/polaris/values.yaml @@ -368,34 +368,6 @@ extraInitContainers: [] # imagePullPolicy: Always # command: ['sh', '-c', 'echo "hello world"'] -# -- Configures whether to enable the bootstrap metastore manager job. -# It is recommended to bootstrap realms using the Polaris Admin Tool; use this only if you need to -# bootstrap realms while deploying Polaris at the same time. -bootstrap: - # -- Specifies whether the bootstrap metastore manager job should be enabled. - enabled: false - # -- The names of the realms to bootstrap. - realms: [] - # -- The root credentials to create during the bootstrap. If you don't provide credentials for the - # root principal of each realm to bootstrap, random credentials will be generated. - # Each entry in the array must be of the form: realm,clientId,clientSecret - credentials: [] - # - realm1,root,s3cr3t - # - realm2,root,s3cr3t - # -- The image to use for the bootstrap metastore manager job. - image: - # -- The image repository to pull from. - repository: apache/polaris-admin-tool - # -- The image pull policy. - pullPolicy: IfNotPresent - # -- The image tag. - tag: "latest" - # -- The path to the directory where the application.properties file, and other configuration - # files, if any, should be mounted. - configDir: /deployments/config - # -- Extra environment variables to add to the bootstrap metastore manager job (see `extraEnv` for an example) - extraEnv: [] - tracing: # -- Specifies whether tracing for the polaris server should be enabled. enabled: false From 8d5737bc795ebeb0f5debcafe3d9d9feb4c38f56 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Mon, 3 Feb 2025 14:59:42 +0100 Subject: [PATCH 3/8] set connection pool size to 1 --- helm/polaris/ci/fixtures/persistence.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/helm/polaris/ci/fixtures/persistence.yaml b/helm/polaris/ci/fixtures/persistence.yaml index 18731d7046..5f888bc54a 100644 --- a/helm/polaris/ci/fixtures/persistence.yaml +++ b/helm/polaris/ci/fixtures/persistence.yaml @@ -46,6 +46,9 @@ stringData: + + + \ No newline at end of file From ba5882d8dfce9e49ab3e5946f96f7adfa3820469 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Mon, 3 Feb 2025 15:05:46 +0100 Subject: [PATCH 4/8] review --- helm/polaris/templates/configmap.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/polaris/templates/configmap.yaml b/helm/polaris/templates/configmap.yaml index 8433e19c72..58ba96c0b6 100644 --- a/helm/polaris/templates/configmap.yaml +++ b/helm/polaris/templates/configmap.yaml @@ -199,5 +199,5 @@ data: {{- /* Print the resulting configmap; each configuration option is templatized */ -}} {{- $global := . -}} {{- range $k, $v := $map }} - {{ include "polaris.appendConfigOption" (list $k $v $global) }} + {{ include "polaris.appendConfigOption" (list $k $v $global) }} {{- end }} From 8c45ee0b0fce338043e5c2b07aa9cd2546be0c67 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Mon, 3 Feb 2025 15:07:05 +0100 Subject: [PATCH 5/8] add comment about EclipseLink --- helm/polaris/README.md | 2 +- helm/polaris/values.yaml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/helm/polaris/README.md b/helm/polaris/README.md index 3b9887c066..c529012444 100644 --- a/helm/polaris/README.md +++ b/helm/polaris/README.md @@ -168,7 +168,7 @@ helm uninstall --namespace polaris polaris | features.realmOverrides | object | `{}` | Features to enable or disable per realm. This field is a map of maps. The realm name is the key, and the value is a map of feature names to values. If a feature is not present in the map, the default value from the 'defaults' field is used. | | fileIo | object | `{"type":"default"}` | Polaris FileIO configuration. | | fileIo.type | string | `"default"` | The type of file IO to use. Two built-in types are supported: default and wasb. The wasb one translates WASB paths to ABFS ones. | -| image.configDir | string | `"/deployments/config"` | The path to the directory where the application.properties file, and other configuration files, if any, should be mounted. | +| image.configDir | string | `"/deployments/config"` | The path to the directory where the application.properties file, and other configuration files, if any, should be mounted. Note: if you are using EclipseLink, then this value must be at least two folders down to the root folder, e.g. `/deployments/config` is OK, whereas `/deployments` is not. | | image.pullPolicy | string | `"IfNotPresent"` | The image pull policy. | | image.repository | string | `"apache/polaris"` | The image repository to pull from. | | image.tag | string | `"latest"` | The image tag. | diff --git a/helm/polaris/values.yaml b/helm/polaris/values.yaml index fcbc99a1bc..a1d120c6e8 100644 --- a/helm/polaris/values.yaml +++ b/helm/polaris/values.yaml @@ -30,6 +30,8 @@ image: tag: "latest" # -- The path to the directory where the application.properties file, and other configuration # files, if any, should be mounted. + # Note: if you are using EclipseLink, then this value must be at least two folders down to the + # root folder, e.g. `/deployments/config` is OK, whereas `/deployments` is not. configDir: /deployments/config # -- References to secrets in the same namespace to use for pulling any of the images used by this From cd330f8055546ed8ba8511ac97bde9d8ee2d0cb1 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Tue, 4 Feb 2025 13:41:31 +0100 Subject: [PATCH 6/8] remove workaround for noisy warning during helm unittest --- .github/workflows/helm.yml | 2 +- helm/polaris/README.md | 2 +- helm/polaris/README.md.gotmpl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/helm.yml b/.github/workflows/helm.yml index e03ad3d829..7939c03123 100644 --- a/.github/workflows/helm.yml +++ b/.github/workflows/helm.yml @@ -79,7 +79,7 @@ jobs: if: steps.list-changed.outputs.changed == 'true' run: | helm plugin install https://github.com/helm-unittest/helm-unittest.git || true - helm unittest helm/polaris 2> >(grep -v 'found symbolic link' >&2) + helm unittest helm/polaris - name: Run chart-testing (lint) if: steps.list-changed.outputs.changed == 'true' diff --git a/helm/polaris/README.md b/helm/polaris/README.md index c529012444..f714949a5a 100644 --- a/helm/polaris/README.md +++ b/helm/polaris/README.md @@ -59,7 +59,7 @@ Helm unit tests do not require a Kubernetes cluster. To run the unit tests from root: ```bash -helm unittest helm/polaris 2> >(grep -v 'found symbolic link' >&2) +helm unittest helm/polaris ``` Note: the `grep` command is used to filter out the annoying warning messages about symbolic links; diff --git a/helm/polaris/README.md.gotmpl b/helm/polaris/README.md.gotmpl index 97a1dbdb2c..973d0b2efd 100644 --- a/helm/polaris/README.md.gotmpl +++ b/helm/polaris/README.md.gotmpl @@ -60,7 +60,7 @@ Helm unit tests do not require a Kubernetes cluster. To run the unit tests from root: ```bash -helm unittest helm/polaris 2> >(grep -v 'found symbolic link' >&2) +helm unittest helm/polaris ``` Note: the `grep` command is used to filter out the annoying warning messages about symbolic links; From 80cc4d4f783cdc009bbdebb396ab84b0a600257c Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Thu, 6 Feb 2025 12:50:52 +0100 Subject: [PATCH 7/8] review --- helm/polaris/ci/fixtures/storage.yaml | 2 +- helm/polaris/ci/fixtures/token-broker.yaml | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/helm/polaris/ci/fixtures/storage.yaml b/helm/polaris/ci/fixtures/storage.yaml index 85aca71076..5f6fdae073 100644 --- a/helm/polaris/ci/fixtures/storage.yaml +++ b/helm/polaris/ci/fixtures/storage.yaml @@ -24,4 +24,4 @@ metadata: type: Opaque stringData: access-key: "my-key" - secret-key: "my-secret" \ No newline at end of file + secret-key: "my-secret" diff --git a/helm/polaris/ci/fixtures/token-broker.yaml b/helm/polaris/ci/fixtures/token-broker.yaml index 5a10fbc083..50399c3d4b 100644 --- a/helm/polaris/ci/fixtures/token-broker.yaml +++ b/helm/polaris/ci/fixtures/token-broker.yaml @@ -22,6 +22,10 @@ kind: Secret metadata: name: polaris-token-broker type: Opaque +# The following values were generated using the following commands: +# openssl genrsa -out private.pem 2048 +# openssl rsa -in private.pem -pubout -out public.pem +# They do not contain any sensitive information and are used for testing purposes only. stringData: private.pem: |- -----BEGIN PRIVATE KEY----- From c64771b4edd558516c817e0faac79de2d41c0932 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Thu, 6 Feb 2025 12:51:47 +0100 Subject: [PATCH 8/8] switch management service to headless (oversight) --- helm/polaris/README.md | 3 ++- helm/polaris/tests/service_mgmt_test.yaml | 5 +++-- helm/polaris/values.yaml | 5 ++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/helm/polaris/README.md b/helm/polaris/README.md index f714949a5a..06927d636c 100644 --- a/helm/polaris/README.md +++ b/helm/polaris/README.md @@ -210,8 +210,9 @@ helm uninstall --namespace polaris polaris | logging.level | string | `"INFO"` | The log level of the root category, which is used as the default log level for all categories. | | logging.mdc | object | `{}` | Configuration for MDC (Mapped Diagnostic Context). Values specified here will be added to the log context of all incoming requests and can be used in log patterns. | | logging.requestIdHeaderName | string | `"Polaris-Request-Id"` | The header name to use for the request ID. | -| managementService | object | `{"annotations":{},"clusterIP":null,"externalTrafficPolicy":null,"internalTrafficPolicy":null,"ports":[{"name":"polaris-mgmt","nodePort":null,"port":8182,"protocol":null,"targetPort":null}],"sessionAffinity":null,"trafficDistribution":null,"type":"ClusterIP"}` | Management service settings. These settings are used to configure liveness and readiness probes, and to configure the dedicated headless service that will expose health checks and metrics, e.g. for metrics scraping and service monitoring. | +| managementService | object | `{"annotations":{},"clusterIP":"None","externalTrafficPolicy":null,"internalTrafficPolicy":null,"ports":[{"name":"polaris-mgmt","nodePort":null,"port":8182,"protocol":null,"targetPort":null}],"sessionAffinity":null,"trafficDistribution":null,"type":"ClusterIP"}` | Management service settings. These settings are used to configure liveness and readiness probes, and to configure the dedicated headless service that will expose health checks and metrics, e.g. for metrics scraping and service monitoring. | | managementService.annotations | object | `{}` | Annotations to add to the service. | +| managementService.clusterIP | string | `"None"` | By default, the management service is headless, i.e. it does not have a cluster IP. This is generally the right option for exposing health checks and metrics, e.g. for metrics scraping and service monitoring. | | managementService.ports | list | `[{"name":"polaris-mgmt","nodePort":null,"port":8182,"protocol":null,"targetPort":null}]` | The ports the management service will listen on. At least one port is required; the first port implicitly becomes the HTTP port that the application will use for serving management requests. By default, it's 8182. Note: port names must be unique and no more than 15 characters long. | | managementService.ports[0] | object | `{"name":"polaris-mgmt","nodePort":null,"port":8182,"protocol":null,"targetPort":null}` | The name of the management port. Required. | | managementService.ports[0].nodePort | string | `nil` | The port on each node on which this service is exposed when type is NodePort or LoadBalancer. Usually assigned by the system. If not specified, a port will be allocated if this Service requires one. If this field is specified when creating a Service which does not need it, creation will fail. | diff --git a/helm/polaris/tests/service_mgmt_test.yaml b/helm/polaris/tests/service_mgmt_test.yaml index 6b6c9eea4c..9e37fae860 100644 --- a/helm/polaris/tests/service_mgmt_test.yaml +++ b/helm/polaris/tests/service_mgmt_test.yaml @@ -172,10 +172,11 @@ tests: value: ClientIP # spec.clusterIP - - it: should not set service cluster IP by default + - it: should set service cluster IP to None (headless) by default asserts: - - notExists: + - equal: path: spec.clusterIP + value: None - it: should set service cluster IP set: managementService.clusterIP: 1.2.3.4 diff --git a/helm/polaris/values.yaml b/helm/polaris/values.yaml index a1d120c6e8..3a1fb7ebf8 100644 --- a/helm/polaris/values.yaml +++ b/helm/polaris/values.yaml @@ -164,7 +164,10 @@ managementService: nodePort: ~ # 30000 # -- The IP protocol for this port. Supports "TCP", "UDP", and "SCTP". Default is TCP. protocol: ~ - clusterIP: ~ + # -- By default, the management service is headless, i.e. it does not have a cluster IP. + # This is generally the right option for exposing health checks and metrics, e.g. for metrics + # scraping and service monitoring. + clusterIP: None sessionAffinity: ~ internalTrafficPolicy: ~ externalTrafficPolicy: ~