commit 152c286448db608fc64c19789fcab419d443f18f Author: Markus Pesch Date: Mon Nov 25 11:53:09 2024 +0100 Initial Commit diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b53e68c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = false + +[Makefile] +indent_style = tab \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba69fff --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +charts +node_modules +target +values2.yml +values2.yaml +*.tgz diff --git a/.helmignore b/.helmignore new file mode 100644 index 0000000..e4d5f3e --- /dev/null +++ b/.helmignore @@ -0,0 +1,49 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store + +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ + +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ + +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ + +# drone +.drone.ya?ml + +# editorconfig +.editorconfig + +# customized values +values2.yml +values2.yaml + +# helm packages +*.tgz + +# markdownlint +.markdownlint.yml +.markdownlint.yaml + +# maven +target + +# serviceDescriptor (uctl-cluster) +serviceDescriptor.yaml \ No newline at end of file diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 0000000..d898196 --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,154 @@ +# markdownlint YAML configuration +# https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.yaml + +# Default state for all rules +default: true + +# Path to configuration file to extend +extends: null + +# MD003/heading-style/header-style - Heading style +MD003: + # Heading style + style: "atx" + +# MD004/ul-style - Unordered list style +MD004: + style: "dash" + +# MD007/ul-indent - Unordered list indentation +MD007: + # Spaces for indent + indent: 2 + # Whether to indent the first level of the list + start_indented: false + +# MD009/no-trailing-spaces - Trailing spaces +MD009: + # Spaces for line break + br_spaces: 2 + # Allow spaces for empty lines in list items + list_item_empty_lines: false + # Include unnecessary breaks + strict: false + +# MD010/no-hard-tabs - Hard tabs +MD010: + # Include code blocks + code_blocks: true + +# MD012/no-multiple-blanks - Multiple consecutive blank lines +MD012: + # Consecutive blank lines + maximum: 1 + +# MD013/line-length - Line length +MD013: + # Number of characters + line_length: 120 + # Number of characters for headings + heading_line_length: 120 + # Number of characters for code blocks + code_block_line_length: 80 + # Include code blocks + code_blocks: false + # Include tables + tables: false + # Include headings + headings: true + # Strict length checking + strict: false + # Stern length checking + stern: false + +# MD022/blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines +MD022: + # Blank lines above heading + lines_above: 1 + # Blank lines below heading + lines_below: 1 + +# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content +MD024: + # Only check sibling headings + siblings_only: true + +# MD025/single-title/single-h1 - Multiple top-level headings in the same document +MD025: + # Heading level + level: 1 + # RegExp for matching title in front matter + front_matter_title: "^\\s*title\\s*[:=]" + +# MD026/no-trailing-punctuation - Trailing punctuation in heading +MD026: + # Punctuation characters + punctuation: ".,;:!。,;:!" + +# MD029/ol-prefix - Ordered list item prefix +MD029: + # List style + style: "one_or_ordered" + +# MD030/list-marker-space - Spaces after list markers +MD030: + # Spaces for single-line unordered list items + ul_single: 1 + # Spaces for single-line ordered list items + ol_single: 1 + # Spaces for multi-line unordered list items + ul_multi: 1 + # Spaces for multi-line ordered list items + ol_multi: 1 + +# MD033/no-inline-html - Inline HTML +MD033: + # Allowed elements + allowed_elements: [] + +# MD035/hr-style - Horizontal rule style +MD035: + # Horizontal rule style + style: "---" + +# MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading +MD036: + # Punctuation characters + punctuation: ".,;:!?。,;:!?" + +# MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading +MD041: + # Heading level + level: 1 + # RegExp for matching title in front matter + front_matter_title: "^\\s*title\\s*[:=]" + +# MD044/proper-names - Proper names should have the correct capitalization +MD044: + # List of proper names + names: + - Git + - Gitea + - GitDevOps + - GitHub + - GitLab + - GitOps + - Memcached + - Oracle + - ORBIS U + - PostgreSQL + - Prometheus + - SSL + - TLS + # Include code blocks + code_blocks: false + +# MD046/code-block-style - Code block style +MD046: + # Block style + style: "fenced" + +# MD048/code-fence-style - Code fence style +MD048: + # Code fence syle + style: "backtick" diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 0000000..9fe4803 --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1,4 @@ +.github/ +Chart.lock +charts/ +node_modules/ \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..b6f27f1 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..fafeafa --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +Chart.lock \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..08a5b51 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + "recommendations": [ + "DavidAnson.vscode-markdownlint", + "esbenp.prettier-vscode", + "Tim-Koehler.helm-intellisense", + "yzhang.markdown-all-in-one" + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7ed7716 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "yaml.schemas": { + "https://raw.githubusercontent.com/helm-unittest/helm-unittest/v0.5.2/schema/helm-testsuite.json": [ + "/unittests/**/*.yaml" + ] + }, + "yaml.schemaStore.enable": true +} \ No newline at end of file diff --git a/.yamllint.yaml b/.yamllint.yaml new file mode 100644 index 0000000..90128be --- /dev/null +++ b/.yamllint.yaml @@ -0,0 +1,20 @@ +--- +extends: default + +ignore: | + .yamllint + node_modules + templates + + +rules: + truthy: + allowed-values: ['true', 'false'] + check-keys: False + level: error + line-length: disable + document-start: disable + comments: + min-spaces-from-content: 1 + braces: + max-spaces-inside: 2 \ No newline at end of file diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..af45fc8 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @volker.raschek diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..8a1b9f1 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1 @@ +# Contribution Guidelines diff --git a/Chart.yaml b/Chart.yaml new file mode 100644 index 0000000..31c314f --- /dev/null +++ b/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +name: prometheus-postgres-exporter +description: Prometheus metric exporter for PostgreSQL +type: application +kubeVersion: ">=1.20.0" +version: "0.1.0" +appVersion: "0.15.0" + +# icon: https://annotations.example.com/icon.png + +keywords: +- prometheus +- prometheus exporter +- postgres + +sources: +- https://github.com/prometheus-community/postgres_exporter +- https://git.cryptic.systems/volker.raschek/prometheus-postgres-exporter \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d4e5db8 --- /dev/null +++ b/Makefile @@ -0,0 +1,108 @@ +# CONTAINER_RUNTIME +CONTAINER_RUNTIME?=$(shell which podman) + +# HELM_IMAGE +HELM_IMAGE_REGISTRY_HOST?=docker.io +HELM_IMAGE_REPOSITORY=volkerraschek/helm +HELM_IMAGE_VERSION?=3.16.1 # renovate: datasource=docker registryUrl=https://docker.io depName=volkerraschek/helm +HELM_IMAGE_FULLY_QUALIFIED=${HELM_IMAGE_REGISTRY_HOST}/${HELM_IMAGE_REPOSITORY}:${HELM_IMAGE_VERSION} + +# MARKDOWNLINKCHECKER_IMAGE +MARKDOWNLINKCHECK_IMAGE_REGISTRY_HOST?=ghcr.io +MARKDOWNLINKCHECK_IMAGE_REPOSITORY=tcort/markdown-link-check +MARKDOWNLINKCHECK_IMAGE_VERSION?=3.12.2 # renovate: datasource=docker registryUrl=https://ghcr.io depName=tcort/markdown-link-check +MARKDOWNLINKCHECK_IMAGE_FULLY_QUALIFIED=${MARKDOWNLINT_IMAGE_REGISTRY_HOST}/${MARKDOWNLINT_IMAGE_REPOSITORY}:${MARKDOWNLINT_IMAGE_VERSION} + +# NODE_IMAGE +NODE_IMAGE_REGISTRY_HOST?=docker.io +NODE_IMAGE_REPOSITORY=library/node +NODE_IMAGE_VERSION?=22.9.0-alpine # renovate: datasource=docker registryUrl=https://docker.io depName=library/node +NODE_IMAGE_FULLY_QUALIFIED=${NODE_IMAGE_REGISTRY_HOST}/${NODE_IMAGE_REPOSITORY}:${NODE_IMAGE_VERSION} + +# CHART_SERVER +CHART_SERVER_HOST?=charts.u.orbis-healthcare.com +CHART_SERVER_NAMESPACE?=orbis-u +CHART_SERVER_REPOSITORY?=qu-seed +CHART_VERSION?=0.1.0 + +# MISSING DOT +# ============================================================================== +missing-dot: + grep --perl-regexp '## @(param|skip).*[^.]$$' values.yaml + +# CONTAINER RUN - PREPARE ENVIRONMENT +# ============================================================================== +PHONY+=container-run/readme +container-run/readme: + ${CONTAINER_RUNTIME} run \ + --rm \ + --volume $(shell pwd):$(shell pwd) \ + --workdir $(shell pwd) \ + ${NODE_IMAGE_FULLY_QUALIFIED} \ + npm install && npm run readme:parameters && npm run readme:lint + +# CONTAINER RUN - HELM UNITTESTS +# ============================================================================== +PHONY+=container-run/helm-unittests +container-run/helm-unittests: + ${CONTAINER_RUNTIME} run \ + --env HELM_REPO_PASSWORD=${CHART_SERVER_PASSWORD} \ + --env HELM_REPO_USERNAME=${CHART_SERVER_USERNAME} \ + --rm \ + --volume $(shell pwd):$(shell pwd) \ + --workdir $(shell pwd) \ + ${HELM_IMAGE_FULLY_QUALIFIED} \ + unittest --strict --file 'unittests/**/*.yaml' ./ + +# CONTAINER RUN - HELM UPDATE DEPENDENCIES +# ============================================================================== +PHONY+=container-run/helm-update-dependencies +container-run/helm-update-dependencies: + ${CONTAINER_RUNTIME} run \ + --env HELM_REPO_PASSWORD=${CHART_SERVER_PASSWORD} \ + --env HELM_REPO_USERNAME=${CHART_SERVER_USERNAME} \ + --rm \ + --volume $(shell pwd):$(shell pwd) \ + --workdir $(shell pwd) \ + ${HELM_IMAGE_FULLY_QUALIFIED} \ + dependency update + +# CONTAINER RUN - DEPLOY2CHART-REPO +# ============================================================================== +container-run/deploy2chart-repo: + ${CONTAINER_RUNTIME} run \ + --env HELM_REPO_PASSWORD=${CHART_SERVER_PASSWORD} \ + --env HELM_REPO_USERNAME=${CHART_SERVER_USERNAME} \ + --entrypoint /bin/bash \ + --rm \ + --volume $(shell pwd):$(shell pwd) \ + --workdir $(shell pwd) \ + ${HELM_IMAGE_FULLY_QUALIFIED} \ + -c "helm repo add ${CHART_SERVER_NAMESPACE} http://${CHART_SERVER_HOST}/${CHART_SERVER_NAMESPACE} && helm package --version ${CHART_VERSION} . && helm cm-push ./${CHART_SERVER_REPOSITORY}-${CHART_VERSION}.tgz ${CHART_SERVER_NAMESPACE}" + +# CONTAINER RUN - MARKDOWN-LINT +# ============================================================================== +PHONY+=container-run/helm-lint +container-run/helm-lint: + ${CONTAINER_RUNTIME} run \ + --rm \ + --volume $(shell pwd):$(shell pwd) \ + --workdir $(shell pwd) \ + ${HELM_IMAGE_FULLY_QUALIFIED} \ + lint --values values.yaml . + +# CONTAINER RUN - MARKDOWN-LINK-CHECK +# ============================================================================== +PHONY+=container-run/markdown-link-check +container-run/markdown-link-check: + ${CONTAINER_RUNTIME} run \ + --rm \ + --volume $(shell pwd):/work \ + ${MARKDOWNLINKCHECK_IMAGE_FULLY_QUALIFIED} \ + *.md + +# PHONY +# ============================================================================== +# Declare the contents of the PHONY variable as phony. We keep that information +# in a variable so we can use it in if_changed. +.PHONY: ${PHONY} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..a33ef1e --- /dev/null +++ b/README.md @@ -0,0 +1,263 @@ +# Prometheus PostgreSQL exporter + +This helm chart enables the deployment of a Prometheus metrics exporter for PostgreSQL databases and allows the +individual configuration of additional containers/initContainers, mounting of volumes, defining additional environment +variables, apply a user-defined web-config.yaml and much more. + +Chapter [configuration and installation](#helm-configuration-and-installation) describes the basics how to configure helm +and use it to deploy the exporter. It also contains further configuration examples. + +Furthermore, this helm chart unit tests to detect regressions and stabilize the deployment. Additionally, this helm +chart is tested for deployment scenarios with ArgoCD. + +> ![NOTE] +> This is not the official *community* helm chart of the Prometheus metric exporter for PostgreSQL databases. You can +> find the official community chart [here](https://github.com/prometheus-community/helm-charts). + +## Helm: configuration and installation + +1. A helm chart repository must be configured, to pull the helm charts from. +2. All available parameters are [here](#parameters). The parameters can be defined via the helm `--set` flag or directly + as part of a `values.yaml` file. The following example defines the `prometheus-exporter` repository and use the + `--set` flag for a basic deployment. + +```bash +helm repo add prometheus-exporter https://charts.cryptic.systems/prometheus-exporter +helm repo update +helm install prometheus-exporter/prometheus-postgres-exporter prometheus-postgres-exporter \ + --set 'config.database.secret.databaseUsername=postgres' \ + --set 'config.database.secret.databasePassword=postgres' \ + --set 'config.database.secret.databaseConnectionUrl="postgres.example.local:5432/postgres?ssl=disable"' +``` + +Instead of passing all parameters via the *set* flag, it is also possible to define them as part of the `values.yaml`. +The following command downloads the `values.yaml` for a specific version of this chart. Please keep in mind, that the +version of the chart must be in sync with the `values.yaml`. Newer *minor* versions can have new features. New *major* +versions can break something! + +```bash +helm show values prometheus-exporter/prometheus-postgres-exporter --version 0.1.0 > values.yaml +``` + +A complete list of available helm chart versions can be displayed via the following command: + +```bash +helm search repo prometheus-postgres-exporter --versions +``` + +### Examples + +The following examples serve as individual configurations and as inspiration for how deployment problems can be solved. + +### TLS authentication and encryption + +The first example shows how to deploy the metric exporter with TLS encryption. The verification of the custom TLS +certification will be skipped by Prometheus. + +> [!WARN] +> A TLS secret with the name `prometheus-postgresql-exporter-http` containing a `ca.crt`, `tls.key` and `tls.crt` is +> already present. + +```bash +helm install prometheus-exporter/prometheus-postgres-exporter prometheus-postgres-exporter \ + --set 'config.database.secret.databaseUsername=postgres' \ + --set 'config.database.secret.databasePassword=postgres' \ + --set 'config.database.secret.databaseConnectionUrl="postgres.example.local:5432/postgres?ssl=disable"' \ + --set 'config.webConfig.secret.webConfig.cert_file=/etc/prometheus-postgres-exporter/tls/tls.crt' \ + --set 'config.webConfig.secret.webConfig.client_ca_file=/etc/prometheus-postgres-exporter/tls/ca.crt' \ + --set 'config.webConfig.secret.webConfig.key_file=/etc/prometheus-postgres-exporter/tls/tls.key' + --set 'deployment.volumes[0].name=tls' \ + --set 'deployment.volumes[0].secret.secretName=prometheus-postgresql-exporter-http' \ + --set 'deployment.postgresExporter.volumeMounts[0].name=tls' \ + --set 'deployment.postgresExporter.volumeMounts[0].mountPath=/etc/prometheus-postgres-exporter/tls' \ + --set 'deployment.postgresExporter.volumeMounts[0].readOnly=true' \ + --set 'prometheus.serviceMonitor.enabled=true' \ + --set 'prometheus.serviceMonitor.scheme=https' \ + --set 'prometheus.serviceMonitor.tlsConfig.insecureSkipVerify=true' +``` + +If the Prometheus pod has a TLS certificate mounted and is also signed by the private key of the CA which issued the TLS +certificate for the metrics exporter - TLS certificate verification can be enabled. The following flags must be +replaced: + +```diff + helm install prometheus-exporter/prometheus-postgres-exporter prometheus-postgres-exporter \ + --set 'config.database.secret.databaseUsername=postgres' \ + --set 'config.database.secret.databasePassword=postgres' \ + --set 'config.database.secret.databaseConnectionUrl="postgres.example.local:5432/postgres?ssl=disable"' \ + --set 'config.webConfig.secret.webConfig.cert_file=/etc/prometheus-postgres-exporter/tls/tls.crt' \ + --set 'config.webConfig.secret.webConfig.client_ca_file=/etc/prometheus-postgres-exporter/tls/ca.crt' \ + --set 'config.webConfig.secret.webConfig.key_file=/etc/prometheus-postgres-exporter/tls/tls.key' + --set 'deployment.volumes[0].name=tls' \ + --set 'deployment.volumes[0].secret.secretName=prometheus-postgresql-exporter-http' \ + --set 'deployment.postgresExporter.volumeMounts[0].name=tls' \ + --set 'deployment.postgresExporter.volumeMounts[0].mountPath=/etc/prometheus-postgres-exporter/tls' \ + --set 'deployment.postgresExporter.volumeMounts[0].readOnly=true' \ + --set 'prometheus.serviceMonitor.enabled=true' \ + --set 'prometheus.serviceMonitor.scheme=https' \ +- --set 'prometheus.serviceMonitor.tlsConfig.insecureSkipVerify=true' \ ++ --set 'prometheus.serviceMonitor.tlsConfig.caFile=/etc/prometheus/tls/ca.crt' \ ++ --set 'prometheus.serviceMonitor.tlsConfig.certFile=/etc/prometheus/tls/tls.crt' \ ++ --set 'prometheus.serviceMonitor.tlsConfig.keyFile=/etc/prometheus/tls/tls.key' +``` + +## Parameters + +### Global + +| Name | Description | Value | +| ------------------ | ----------------------------------------- | ----- | +| `nameOverride` | Individual release name suffix. | `""` | +| `fullnameOverride` | Override the complete release name logic. | `""` | + +### Configuration + +| Name | Description | Value | +| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `config.database.existingSecret.enabled` | Mount an existing secret containing the application specific `DATA_SOURCE_` prefixed environment variables. | `false` | +| `config.database.existingSecret.secretName` | Name of the existing secret containing the application specific `DATA_SOURCE_` prefixed environment variables. | `""` | +| `config.database.secret.annotations` | Additional annotations of the secret containing the database credentials. | `{}` | +| `config.database.secret.labels` | Additional labels of the secret containing the database credentials. | `{}` | +| `config.database.secret.databaseUsername` | Database username. Will be defined as env `DATA_SOURCE_USER` as part of a secret. | `""` | +| `config.database.secret.databasePassword` | Database password. Will be defined as env `DATA_SOURCE_PASS` as part of a secret. | `""` | +| `config.database.secret.databaseConnectionUrl` | Complex database connection URL. Will be defined as env `DATA_SOURCE_URI` as part of a secret. | `""` | +| `config.exporterConfig.existingSecret.enabled` | Mount an existing secret containing the key `exporter_config.yaml`. | `false` | +| `config.exporterConfig.existingSecret.secretName` | Name of the existing secret containing the key `exporter_config.yaml`. | `""` | +| `config.exporterConfig.secret.annotations` | Additional annotations of the secret containing the `exporterConfig.yaml`. | `{}` | +| `config.exporterConfig.secret.labels` | Additional labels of the secret containing the `exporterConfig.yaml`. | `{}` | +| `config.exporterConfig.secret.exporterConfig` | Content of the `exporterConfig.yaml`. Further information can be found [here](https://prometheus.io/docs/prometheus/latest/configuration/https/). | `{}` | +| `config.webConfig.existingSecret.enabled` | Mount an existing secret containing the key `webConfig.yaml`. | `false` | +| `config.webConfig.existingSecret.secretName` | Name of the existing secret containing the key `webConfig.yaml`. | `""` | +| `config.webConfig.secret.annotations` | Additional annotations of the secret containing the `webConfig.yaml`. | `{}` | +| `config.webConfig.secret.labels` | Additional labels of the secret containing the `webConfig.yaml`. | `{}` | +| `config.webConfig.secret.webConfig` | Content of the `webConfig.yaml`. Further information can be found [here](https://prometheus.io/docs/prometheus/latest/configuration/https/). | `{}` | + +### Deployment + +| Name | Description | Value | +| -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | --------------------------------------- | +| `deployment.annotations` | Additional deployment annotations. | `{}` | +| `deployment.labels` | Additional ingress labels. | `{}` | +| `deployment.additionalContainers` | List of additional containers. | `[]` | +| `deployment.affinity` | Affinity for the postgres-exporter deployment. | `{}` | +| `deployment.initContainers` | List of additional init containers. | `[]` | +| `deployment.dnsConfig` | dnsConfig of the postgres-exporter deployment. | `{}` | +| `deployment.dnsPolicy` | dnsPolicy of the postgres-exporter deployment. | `""` | +| `deployment.hostname` | Individual hostname of the pod. | `""` | +| `deployment.subdomain` | Individual domain of the pod. | `""` | +| `deployment.hostNetwork` | Use the kernel network namespace of the host system. | `false` | +| `deployment.imagePullSecrets` | Secret to use for pulling the image. | `[]` | +| `deployment.postgresExporter.args` | Arguments passed to the postgres-exporter container. | `[]` | +| `deployment.postgresExporter.env` | List of environment variables for the postgres-exporter container. | `[]` | +| `deployment.postgresExporter.envFrom` | List of environment variables mounted from configMaps or secrets for the postgres-exporter container. | `[]` | +| `deployment.postgresExporter.image.registry` | Image registry, eg. `docker.io`. | `quay.io` | +| `deployment.postgresExporter.image.repository` | Image repository, eg. `library/busybox`. | `prometheuscommunity/postgres-exporter` | +| `deployment.postgresExporter.image.tag` | Custom image tag, eg. `0.1.0`. Defaults to `appVersion`. | `""` | +| `deployment.postgresExporter.image.pullPolicy` | Image pull policy. | `IfNotPresent` | +| `deployment.postgresExporter.resources` | CPU and memory resources of the pod. | `{}` | +| `deployment.postgresExporter.securityContext` | Security context of the container of the deployment. | `{}` | +| `deployment.postgresExporter.volumeMounts` | Additional volume mounts. | `{}` | +| `deployment.nodeSelector` | NodeSelector of the postgres-exporter deployment. | `{}` | +| `deployment.priorityClassName` | PriorityClassName of the postgres-exporter deployment. | `""` | +| `deployment.replicaCount` | Number of replicas for the postgres-exporter deployment. | `1` | +| `deployment.securityContext` | Security context of the postgres-exporter deployment. | `{}` | +| `deployment.strategy.type` | Strategy type - `Recreate` or `Rollingupdate`. | `Recreate` | +| `deployment.strategy.rollingUpdate.maxSurge` | The maximum number of pods that can be scheduled above the desired number of pods during a rolling update. | `1` | +| `deployment.strategy.rollingUpdate.maxUnavailable` | The maximum number of pods that can be unavailable during a rolling update. | `1` | +| `deployment.terminationGracePeriodSeconds` | How long to wait until forcefully kill the pod. | `60` | +| `deployment.tolerations` | Tolerations of the postgres-exporter deployment. | `[]` | +| `deployment.topologySpreadConstraints` | TopologySpreadConstraints of the postgres-exporter deployment. | `[]` | +| `deployment.volumes` | Additional volumes to mount into the pods of the Prometheus-exporter deployment. | `[]` | + +### Grafana + +| Name | Description | Value | +| ------------------------------------ | --------------------------------------------------------- | ------- | +| `grafana.enabled` | Enable integration into Grafana. | `false` | +| `grafana.dashboards.businessMetrics` | Enable deployment of Grafana dashboard `businessMetrics`. | `true` | + +### Ingress + +| Name | Description | Value | +| --------------------- | -------------------------------------------------------------------------------------------------------------------- | ------- | +| `ingress.enabled` | Enable creation of an ingress resource. Requires, that the http service is also enabled. | `false` | +| `ingress.className` | Ingress class. | `nginx` | +| `ingress.annotations` | Additional ingress annotations. | `{}` | +| `ingress.labels` | Additional ingress labels. | `{}` | +| `ingress.hosts` | Ingress specific configuration. Specification only required when another ingress controller is used instead of `t1k. | `[]` | +| `ingress.tls` | Ingress TLS settings. Specification only required when another ingress controller is used instead of `t1k``. | `[]` | + +### Pod disruption + +| Name | Description | Value | +| --------------------- | ---------------------- | ----- | +| `podDisruptionBudget` | Pod disruption budget. | `{}` | + +### Network + +| Name | Description | Value | +| ----------------- | ------------------------------------------------------------------------------------------------------------------ | ----- | +| `networkPolicies` | Deploy network policies based on the used container network interface (CNI) implementation - like calico or weave. | `{}` | + +### Prometheus + +| Name | Description | Value | +| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | +| `prometheus.metrics.enabled` | Enable of scraping metrics by Prometheus. | `true` | +| `prometheus.metrics.podMonitor.enabled` | Enable creation of a podMonitor. Excludes the existence of a serviceMonitor resource. | `false` | +| `prometheus.metrics.podMonitor.annotations` | Additional podMonitor annotations. | `{}` | +| `prometheus.metrics.podMonitor.enableHttp2` | Enable HTTP2. | `false` | +| `prometheus.metrics.podMonitor.followRedirects` | FollowRedirects configures whether scrape requests follow HTTP 3xx redirects. | `false` | +| `prometheus.metrics.podMonitor.honorLabels` | Honor labels. | `false` | +| `prometheus.metrics.podMonitor.labels` | Additional podMonitor labels. | `{}` | +| `prometheus.metrics.podMonitor.interval` | Interval at which metrics should be scraped. If not specified Prometheus' global scrape interval is used. | `60s` | +| `prometheus.metrics.podMonitor.path` | HTTP path for scraping Prometheus metrics. | `/metrics` | +| `prometheus.metrics.podMonitor.relabelings` | RelabelConfigs to apply to samples before scraping. Prometheus Operator automatically adds relabelings for a few standard Kubernetes fields. | `[]` | +| `prometheus.metrics.podMonitor.scrapeTimeout` | Timeout after which the scrape is ended. If not specified, global Prometheus scrape timeout is used. | `30s` | +| `prometheus.metrics.podMonitor.scheme` | HTTP scheme to use for scraping. For example `http` or `https`. | `http` | +| `prometheus.metrics.podMonitor.tlsConfig` | TLS configuration to use when scraping the metric endpoint by Prometheus. | `{}` | +| `prometheus.metrics.serviceMonitor.enabled` | Enable creation of a serviceMonitor. Excludes the existence of a podMonitor resource. | `false` | +| `prometheus.metrics.serviceMonitor.annotations` | Additional serviceMonitor annotations. | `{}` | +| `prometheus.metrics.serviceMonitor.labels` | Additional serviceMonitor labels. | `{}` | +| `prometheus.metrics.serviceMonitor.enableHttp2` | Enable HTTP2. | `false` | +| `prometheus.metrics.serviceMonitor.followRedirects` | FollowRedirects configures whether scrape requests follow HTTP 3xx redirects. | `false` | +| `prometheus.metrics.serviceMonitor.honorLabels` | Honor labels. | `false` | +| `prometheus.metrics.serviceMonitor.interval` | Interval at which metrics should be scraped. If not specified Prometheus' global scrape interval is used. | `60s` | +| `prometheus.metrics.serviceMonitor.path` | HTTP path for scraping Prometheus metrics. | `/metrics` | +| `prometheus.metrics.serviceMonitor.port` | HTTP port for scraping Prometheus metrics. | `9187` | +| `prometheus.metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping. Prometheus Operator automatically adds relabelings for a few standard Kubernetes fields. | `[]` | +| `prometheus.metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended. If not specified, global Prometheus scrape timeout is used. | `30s` | +| `prometheus.metrics.serviceMonitor.scheme` | HTTP scheme to use for scraping. For example `http` or `https`. | `http` | +| `prometheus.metrics.serviceMonitor.tlsConfig` | TLS configuration to use when scraping the metric endpoint by Prometheus. | `{}` | +| `prometheus.rules` | Array of Prometheus rules for monitoring the application and triggering alerts. | `[]` | + +### Service + +| Name | Description | Value | +| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | +| `services.http.enabled` | Enable the service. | `true` | +| `services.http.annotations` | Additional service annotations. | `{}` | +| `services.http.externalIPs` | External IPs for the service. | `[]` | +| `services.http.externalTrafficPolicy` | If `service.type` is `NodePort` or `LoadBalancer`, set this to `Local` to tell kube-proxy to only use node local endpoints for cluster external traffic. Furthermore, this enables source IP preservation. | `Cluster` | +| `services.http.internalTrafficPolicy` | If `service.type` is `NodePort` or `LoadBalancer`, set this to `Local` to tell kube-proxy to only use node local endpoints for cluster internal traffic. | `Cluster` | +| `services.http.ipFamilies` | IPFamilies is list of IP families (e.g. `IPv4`, `IPv6`) assigned to this service. This field is usually assigned automatically based on cluster configuration and only required for customization. | `[]` | +| `services.http.labels` | Additional service labels. | `{}` | +| `services.http.loadBalancerClass` | LoadBalancerClass is the class of the load balancer implementation this Service belongs to. Requires service from type `LoadBalancer`. | `""` | +| `services.http.loadBalancerIP` | LoadBalancer will get created with the IP specified in this field. Requires service from type `LoadBalancer`. | `""` | +| `services.http.loadBalancerSourceRanges` | Source range filter for LoadBalancer. Requires service from type `LoadBalancer`. | `[]` | +| `services.http.port` | Port to forward the traffic to. | `9187` | +| `services.http.sessionAffinity` | Supports `ClientIP` and `None`. Enable client IP based session affinity via `ClientIP`. | `None` | +| `services.http.sessionAffinityConfig` | Contains the configuration of the session affinity. | `{}` | +| `services.http.type` | Kubernetes service type for the traffic. | `ClusterIP` | + +### ServiceAccount + +| Name | Description | Value | +| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `serviceAccount.existing.enabled` | Use an existing service account instead of creating a new one. Assumes that the user has all the necessary kubernetes API authorizations. | `false` | +| `serviceAccount.existing.serviceAccountName` | Name of the existing service account. | `""` | +| `serviceAccount.new.annotations` | Additional service account annotations. | `{}` | +| `serviceAccount.new.labels` | Additional service account labels. | `{}` | +| `serviceAccount.new.automountServiceAccountToken` | Enable/disable auto mounting of the service account token. | `true` | +| `serviceAccount.new.imagePullSecrets` | ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images in pods that reference this serviceAccount. | `[]` | +| `serviceAccount.new.secrets` | Secrets is the list of secrets allowed to be used by pods running using this ServiceAccount. | `[]` | diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..455c3b6 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,919 @@ +{ + "name": "qu-seed-chart", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "qu-seed-chart", + "license": "MIT", + "devDependencies": { + "@bitnami/readme-generator-for-helm": "^2.5.0", + "markdownlint-cli": "^0.41.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + } + }, + "node_modules/@bitnami/readme-generator-for-helm": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@bitnami/readme-generator-for-helm/-/readme-generator-for-helm-2.6.1.tgz", + "integrity": "sha512-rN0m0sfbOuaNdCmQWBfSj9o4kgzz+Dw67Dl1ssDVqghv/UpLkrDmNuTxhD1CWu+sesGL66UYJ2VplGz9KxlAdg==", + "dev": true, + "dependencies": { + "commander": "^7.1.0", + "dot-object": "^2.1.4", + "lodash": "^4.17.21", + "markdown-table": "^2.0.0", + "yaml": "^2.0.0-3" + }, + "bin": { + "readme-generator": "bin/index.js" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/dot-object": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/dot-object/-/dot-object-2.1.4.tgz", + "integrity": "sha512-7FXnyyCLFawNYJ+NhkqyP9Wd2yzuo+7n9pGiYpkmXCTYa8Ci2U0eUNDVg5OuO5Pm6aFXI2SWN8/N/w7SJWu1WA==", + "dev": true, + "dependencies": { + "commander": "^4.0.0", + "glob": "^7.1.5" + }, + "bin": { + "dot-object": "bin/dot-object" + } + }, + "node_modules/dot-object/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.1.2.tgz", + "integrity": "sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", + "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", + "dev": true, + "dependencies": { + "repeat-string": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/markdownlint": { + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.34.0.tgz", + "integrity": "sha512-qwGyuyKwjkEMOJ10XN6OTKNOVYvOIi35RNvDLNxTof5s8UmyGHlCdpngRHoRGNvQVGuxO3BJ7uNSgdeX166WXw==", + "dev": true, + "dependencies": { + "markdown-it": "14.1.0", + "markdownlint-micromark": "0.1.9" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + } + }, + "node_modules/markdownlint-cli": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.41.0.tgz", + "integrity": "sha512-kp29tKrMKdn+xonfefjp3a/MsNzAd9c5ke0ydMEI9PR98bOjzglYN4nfMSaIs69msUf1DNkgevAIAPtK2SeX0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "~12.1.0", + "get-stdin": "~9.0.0", + "glob": "~10.4.1", + "ignore": "~5.3.1", + "js-yaml": "^4.1.0", + "jsonc-parser": "~3.2.1", + "jsonpointer": "5.0.1", + "markdownlint": "~0.34.0", + "minimatch": "~9.0.4", + "run-con": "~1.3.2", + "smol-toml": "~1.2.0" + }, + "bin": { + "markdownlint": "markdownlint.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/markdownlint-cli/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/markdownlint-cli/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/markdownlint-cli/node_modules/glob": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/markdownlint-cli/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/markdownlint-micromark": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.9.tgz", + "integrity": "sha512-5hVs/DzAFa8XqYosbEAEg6ok6MF2smDj89ztn9pKkCtdKHVdPQuGMH7frFfYL9mLkvfFe4pTyAMffLbjf3/EyA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/run-con": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/run-con/-/run-con-1.3.2.tgz", + "integrity": "sha512-CcfE+mYiTcKEzg0IqS08+efdnH0oJ3zV0wSUFBNrMHMuxCtXvBCLzCJHatwuXDcu/RlhjTziTo/a1ruQik6/Yg==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~4.1.0", + "minimist": "^1.2.8", + "strip-json-comments": "~3.1.1" + }, + "bin": { + "run-con": "cli.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.1.tgz", + "integrity": "sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/smol-toml": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.2.0.tgz", + "integrity": "sha512-KObxdQANC/xje3OoatMbSwQf2XAvJ0RbK+4nmQRszFNZptbNRnMWqbLF/zb4sMi9xJ6HNyhWXeuZ9zC/I/XY7w==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18", + "pnpm": ">= 9" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", + "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==", + "dev": true, + "engines": { + "node": ">= 14" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..361cd38 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "qu-seed-chart", + "homepage": "https://github.com/dedalus-cis4u/qu-seed-chart.git", + "license": "MIT", + "private": true, + "engineStrict": true, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "scripts": { + "readme:lint": "markdownlint *.md -f", + "readme:parameters": "readme-generator -v values.yaml -r README.md" + }, + "devDependencies": { + "@bitnami/readme-generator-for-helm": "^2.5.0", + "markdownlint-cli": "^0.41.0" + } +} diff --git a/templates/prometheus-postgres-exporter/_common.tpl b/templates/prometheus-postgres-exporter/_common.tpl new file mode 100644 index 0000000..e8c23c4 --- /dev/null +++ b/templates/prometheus-postgres-exporter/_common.tpl @@ -0,0 +1,58 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "prometheus-postgres-exporter.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "prometheus-postgres-exporter.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "prometheus-postgres-exporter.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common annotations +*/}} +{{- define "prometheus-postgres-exporter.annotations" -}} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "prometheus-postgres-exporter.labels" -}} +{{ include "prometheus-postgres-exporter.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +helm.sh/chart: {{ include "prometheus-postgres-exporter.chart" . }} +{{- end }} + +{{/* +Common selector labels +*/}} +{{- define "prometheus-postgres-exporter.selectorLabels" -}} +app.kubernetes.io/name: {{ include "prometheus-postgres-exporter.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/templates/prometheus-postgres-exporter/_deployment.tpl b/templates/prometheus-postgres-exporter/_deployment.tpl new file mode 100644 index 0000000..55da6a2 --- /dev/null +++ b/templates/prometheus-postgres-exporter/_deployment.tpl @@ -0,0 +1,70 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* annotations */}} + +{{- define "prometheus-postgres-exporter.deployment.annotations" -}} +{{ include "prometheus-postgres-exporter.annotations" . }} +{{- if .Values.deployment.annotations }} +{{ toYaml .Values.deployment.annotations }} +{{- end }} +{{- end }} + +{{/* envFrom */}} + +{{- define "prometheus-postgres-exporter.deployment.envFrom" -}} +{{- $envFrom := dict "envFrom" (.Values.deployment.postgresExporter.envFrom | default (list) ) }} +{{- $secretName := .Values.config.database.existingSecret.secretName -}} +{{- if not .Values.config.database.existingSecret.enabled }} +{{- $secretName = printf "%s-database-env" (include "prometheus-postgres-exporter.fullname" . ) }} +{{- end }} +{{- $envFrom = merge $envFrom (dict "envFrom" (list (dict "secretRef" (dict "name" $secretName)))) }} +{{ toYaml $envFrom }} +{{- end -}} + +{{/* image */}} + +{{- define "prometheus-postgres-exporter.deployment.images.postgres-exporter.fqin" -}} +{{- $registry := .Values.deployment.postgresExporter.image.registry -}} +{{- $repository := .Values.deployment.postgresExporter.image.repository -}} +{{- $tag := default .Chart.AppVersion .Values.deployment.postgresExporter.image.tag -}} +{{- printf "%s/%s:v%s" $registry $repository $tag -}} +{{- end -}} + +{{/* labels */}} + +{{- define "prometheus-postgres-exporter.deployment.labels" -}} +{{ include "prometheus-postgres-exporter.labels" . }} +{{- if .Values.deployment.labels }} +{{ toYaml .Values.deployment.labels }} +{{- end }} +{{- end }} + +{{/* serviceAccount */}} + +{{- define "prometheus-postgres-exporter.deployment.serviceAccount" -}} +{{- if .Values.serviceAccount.existing.enabled -}} +{{- printf "%s" .Values.serviceAccount.existing.serviceAccountName -}} +{{- else -}} +{{- include "prometheus-postgres-exporter.fullname" . -}} +{{- end -}} +{{- end }} + +{{/* volumeMounts */}} + +{{- define "prometheus-postgres-exporter.deployment.volumeMounts" -}} +{{- $volumeMounts := dict "volumeMounts" (.Values.deployment.postgresExporter.volumeMounts | default (list) ) }} +{{- $volumeMounts = merge $volumeMounts (dict "volumeMounts" (list (dict "name" "exporter-config" "mountPath" "/etc/prometheus-postgres-exporter/config.d" ))) }} +{{ toYaml $volumeMounts }} +{{- end -}} + +{{/* volumes */}} + +{{- define "prometheus-postgres-exporter.deployment.volumes" -}} +{{- $volumes := dict "volumes" (.Values.deployment.volumes | default (list) ) }} +{{- $secretName := .Values.config.exporterConfig.existingSecret.secretName -}} +{{- if not .Values.config.exporterConfig.existingSecret.enabled }} +{{- $secretName = printf "%s-exporter-config" (include "prometheus-postgres-exporter.fullname" . ) }} +{{- end }} +{{- $volumes = merge $volumes (dict "volumes" (list (dict "name" "exporter-config" "secret" (dict "secretName" $secretName)))) }} +{{ toYaml $volumes }} +{{- end -}} \ No newline at end of file diff --git a/templates/prometheus-postgres-exporter/_ingress.tpl b/templates/prometheus-postgres-exporter/_ingress.tpl new file mode 100644 index 0000000..bb2dfff --- /dev/null +++ b/templates/prometheus-postgres-exporter/_ingress.tpl @@ -0,0 +1,19 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* annotations */}} + +{{- define "prometheus-postgres-exporter.ingress.annotations" -}} +{{ include "prometheus-postgres-exporter.annotations" . }} +{{- if .Values.ingress.annotations }} +{{ toYaml .Values.ingress.annotations }} +{{- end }} +{{- end }} + +{{/* labels */}} + +{{- define "prometheus-postgres-exporter.ingress.labels" -}} +{{ include "prometheus-postgres-exporter.labels" . }} +{{- if .Values.ingress.labels }} +{{ toYaml .Values.ingress.labels }} +{{- end }} +{{- end }} diff --git a/templates/prometheus-postgres-exporter/_pod.tpl b/templates/prometheus-postgres-exporter/_pod.tpl new file mode 100644 index 0000000..c728c7f --- /dev/null +++ b/templates/prometheus-postgres-exporter/_pod.tpl @@ -0,0 +1,17 @@ +--- + +{{/* annotations */}} + +{{- define "prometheus-postgres-exporter.pod.annotations" -}} +{{ include "prometheus-postgres-exporter.annotations" . }} +{{- end }} + +{{/* labels */}} + +{{- define "prometheus-postgres-exporter.pod.labels" -}} +{{ include "prometheus-postgres-exporter.labels" . }} +{{- end }} + +{{- define "prometheus-postgres-exporter.pod.selectorLabels" -}} +{{ include "prometheus-postgres-exporter.pod.labels" . }} +{{- end }} \ No newline at end of file diff --git a/templates/prometheus-postgres-exporter/_podMonitors.tpl b/templates/prometheus-postgres-exporter/_podMonitors.tpl new file mode 100644 index 0000000..e1cc7f3 --- /dev/null +++ b/templates/prometheus-postgres-exporter/_podMonitors.tpl @@ -0,0 +1,19 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* annotations */}} + +{{- define "prometheus-postgres-exporter.podMonitors.http.annotations" -}} +{{ include "prometheus-postgres-exporter.annotations" . }} +{{- if .Values.prometheus.metrics.podMonitor.annotations }} +{{ toYaml .Values.prometheus.metrics.podMonitor.annotations }} +{{- end }} +{{- end }} + +{{/* labels */}} + +{{- define "prometheus-postgres-exporter.podMonitors.http.labels" -}} +{{ include "prometheus-postgres-exporter.labels" . }} +{{- if .Values.prometheus.metrics.podMonitor.labels }} +{{ toYaml .Values.prometheus.metrics.podMonitor.labels }} +{{- end }} +{{- end }} diff --git a/templates/prometheus-postgres-exporter/_prometheusRules.tpl b/templates/prometheus-postgres-exporter/_prometheusRules.tpl new file mode 100644 index 0000000..3043c09 --- /dev/null +++ b/templates/prometheus-postgres-exporter/_prometheusRules.tpl @@ -0,0 +1,13 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* annotations */}} + +{{- define "prometheus-postgres-exporter.prometheusRules.annotations" -}} +{{ include "prometheus-postgres-exporter.annotations" . }} +{{- end }} + +{{/* labels */}} + +{{- define "prometheus-postgres-exporter.prometheusRules.labels" -}} +{{ include "prometheus-postgres-exporter.labels" . }} +{{- end }} diff --git a/templates/prometheus-postgres-exporter/_secrets.tpl b/templates/prometheus-postgres-exporter/_secrets.tpl new file mode 100644 index 0000000..99354f9 --- /dev/null +++ b/templates/prometheus-postgres-exporter/_secrets.tpl @@ -0,0 +1,48 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* annotations */}} + +{{- define "prometheus-postgres-exporter.secrets.database.annotations" -}} +{{ include "prometheus-postgres-exporter.annotations" . }} +{{- if .Values.config.database.secret.annotations }} +{{ toYaml .Values.config.database.secret.annotations }} +{{- end }} +{{- end }} + +{{- define "prometheus-postgres-exporter.secrets.exporterConfig.annotations" -}} +{{ include "prometheus-postgres-exporter.annotations" . }} +{{- if .Values.config.exporterConfig.secret.annotations }} +{{ toYaml .Values.config.exporterConfig.secret.annotations }} +{{- end }} +{{- end }} + +{{- define "prometheus-postgres-exporter.secrets.webConfig.annotations" -}} +{{ include "prometheus-postgres-exporter.annotations" . }} +{{- if .Values.config.webConfig.secret.annotations }} +{{ toYaml .Values.config.webConfig.secret.annotations }} +{{- end }} +{{- end }} + +{{/* labels */}} + +{{- define "prometheus-postgres-exporter.secrets.database.labels" -}} +{{ include "prometheus-postgres-exporter.labels" . }} +{{- if .Values.config.database.secret.labels }} +{{ toYaml .Values.config.database.secret.labels }} +{{- end }} +{{- end }} + +{{- define "prometheus-postgres-exporter.secrets.exporterConfig.labels" -}} +{{ include "prometheus-postgres-exporter.labels" . }} +{{- if .Values.config.exporterConfig.secret.labels }} +{{ toYaml .Values.config.exporterConfig.secret.labels }} +{{- end }} +{{- end }} + + +{{- define "prometheus-postgres-exporter.secrets.webConfig.labels" -}} +{{ include "prometheus-postgres-exporter.labels" . }} +{{- if .Values.config.webConfig.secret.labels }} +{{ toYaml .Values.config.webConfig.secret.labels }} +{{- end }} +{{- end }} diff --git a/templates/prometheus-postgres-exporter/_serviceAccount.tpl b/templates/prometheus-postgres-exporter/_serviceAccount.tpl new file mode 100644 index 0000000..66f09fd --- /dev/null +++ b/templates/prometheus-postgres-exporter/_serviceAccount.tpl @@ -0,0 +1,17 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* annotations */}} + +{{- define "prometheus-postgres-exporter.serviceAccount.annotations" -}} +{{- if .Values.serviceAccount.new.annotations }} +{{ toYaml .Values.serviceAccount.new.annotations }} +{{- end }} +{{- end }} + +{{/* labels */}} + +{{- define "prometheus-postgres-exporter.serviceAccount.labels" -}} +{{- if .Values.serviceAccount.new.labels }} +{{ toYaml .Values.serviceAccount.new.labels }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/templates/prometheus-postgres-exporter/_serviceMonitors.tpl b/templates/prometheus-postgres-exporter/_serviceMonitors.tpl new file mode 100644 index 0000000..24c0344 --- /dev/null +++ b/templates/prometheus-postgres-exporter/_serviceMonitors.tpl @@ -0,0 +1,25 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* annotations */}} + +{{- define "prometheus-postgres-exporter.serviceMonitors.http.annotations" -}} +{{ include "prometheus-postgres-exporter.annotations" . }} +{{- if .Values.prometheus.metrics.serviceMonitor.annotations }} +{{ toYaml .Values.prometheus.metrics.serviceMonitor.annotations }} +{{- end }} +{{- end }} + +{{/* labels */}} + +{{- define "prometheus-postgres-exporter.serviceMonitors.http.labels" -}} +{{ include "prometheus-postgres-exporter.labels" . }} +{{- if .Values.prometheus.metrics.serviceMonitor.labels }} +{{ toYaml .Values.prometheus.metrics.serviceMonitor.labels }} +{{- end }} +{{- end }} + +{{- define "prometheus-postgres-exporter.serviceMonitors.http.selectorLabels" -}} +{{ include "prometheus-postgres-exporter.selectorLabels" . }} +{{/* Add label to select the correct service via `selector.matchLabels` of the serviceMonitor resource. */}} +app.kubernetes.io/service-name: http +{{- end }} \ No newline at end of file diff --git a/templates/prometheus-postgres-exporter/_services.tpl b/templates/prometheus-postgres-exporter/_services.tpl new file mode 100644 index 0000000..54128cc --- /dev/null +++ b/templates/prometheus-postgres-exporter/_services.tpl @@ -0,0 +1,29 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* annotations */}} + +{{- define "prometheus-postgres-exporter.services.http.annotations" -}} +{{ include "prometheus-postgres-exporter.annotations" . }} +{{- if .Values.services.http.annotations }} +{{ toYaml .Values.services.http.annotations }} +{{- end }} +{{- end }} + +{{/* labels */}} + +{{- define "prometheus-postgres-exporter.services.http.labels" -}} +{{ include "prometheus-postgres-exporter.labels" . }} +{{/* Add label to select the correct service via `selector.matchLabels` of the serviceMonitor resource. */}} +app.kubernetes.io/service-name: http +{{- if .Values.services.http.labels }} +{{ toYaml .Values.services.http.labels }} +{{- end }} +{{- end }} + +{{/* names */}} + +{{- define "prometheus-postgres-exporter.services.http.name" -}} +{{- if .Values.services.http.enabled -}} +{{ include "prometheus-postgres-exporter.fullname" . }}-http +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/templates/prometheus-postgres-exporter/deployment.yaml b/templates/prometheus-postgres-exporter/deployment.yaml new file mode 100644 index 0000000..60b3390 --- /dev/null +++ b/templates/prometheus-postgres-exporter/deployment.yaml @@ -0,0 +1,119 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + {{- with (include "prometheus-postgres-exporter.deployment.annotations" . | fromYaml) }} + annotations: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + {{- with (include "prometheus-postgres-exporter.deployment.labels" . | fromYaml) }} + labels: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus-postgres-exporter.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: + selector: + matchLabels: + {{- include "prometheus-postgres-exporter.pod.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "prometheus-postgres-exporter.pod.labels" . | nindent 8 }} + spec: + containers: + - name: postgres-exporter + args: + - "--config.file=/etc/prometheus-postgres-exporter/config.d/exporterConfig.yaml" + - "--web.listen-address=:9187" + {{- range .Values.deployment.postgresExporter.args }} + - {{ . | quote }} + {{- end }} + {{- with .Values.deployment.postgresExporter.env }} + env: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- $envFrom := (include "prometheus-postgres-exporter.deployment.envFrom" . | fromYaml) }} + {{- if hasKey $envFrom "envFrom" }} + envFrom: + {{- toYaml $envFrom.envFrom | nindent 8 }} + {{- end }} + image: {{ include "prometheus-postgres-exporter.deployment.images.postgres-exporter.fqin" . | quote }} + imagePullPolicy: {{ .Values.deployment.postgresExporter.image.pullPolicy }} + livenessProbe: + tcpSocket: + port: 9187 + failureThreshold: 3 + initialDelaySeconds: 5 + periodSeconds: 60 + successThreshold: 1 + timeoutSeconds: 3 + readinessProbe: + tcpSocket: + port: 9187 + failureThreshold: 3 + initialDelaySeconds: 5 + periodSeconds: 15 + successThreshold: 1 + timeoutSeconds: 3 + ports: + - name: http + containerPort: 9187 + protocol: TCP + {{- with .Values.deployment.containerResources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.deployment.postgresExporter.securityContext }} + securityContext: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- $volumeMounts := (include "prometheus-postgres-exporter.deployment.volumeMounts" . | fromYaml) }} + {{- if hasKey $volumeMounts "volumeMounts" }} + volumeMounts: + {{- toYaml $volumeMounts.volumeMounts | nindent 8 }} + {{- end }} + {{- with .Values.deployment.dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.deployment.dnsPolicy }} + dnsPolicy: {{ .Values.deployment.dnsPolicy }} + {{- end }} + {{- if .Values.deployment.hostname }} + hostname: {{ .Values.batch.dbUpdate.hostname }} + {{- end }} + hostNetwork: {{ .Values.deployment.hostNetwork }} + {{- with .Values.deployment.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.deployment.priorityClassName }} + priorityClassName: {{ .Values.deployment.priorityClassName }} + {{- end }} + restartPolicy: {{ .Values.deployment.restartPolicy }} + {{- with .Values.deployment.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccount: {{ include "prometheus-postgres-exporter.deployment.serviceAccount" . }} + {{- if .Values.deployment.subdomain }} + subdomain: {{ .Values.deployment.subdomain }} + {{- end }} + terminationGracePeriodSeconds: {{ .Values.deployment.terminationGracePeriodSeconds }} + {{- with .Values.deployment.tolerations }} + tolerations: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.deployment.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- $volumes := (include "prometheus-postgres-exporter.deployment.volumes" . | fromYaml) }} + {{- if hasKey $volumes "volumes" }} + volumes: + {{- toYaml $volumes.volumes | nindent 6 }} + {{- end }} diff --git a/templates/prometheus-postgres-exporter/ingress.yaml b/templates/prometheus-postgres-exporter/ingress.yaml new file mode 100644 index 0000000..d36bda4 --- /dev/null +++ b/templates/prometheus-postgres-exporter/ingress.yaml @@ -0,0 +1,45 @@ +{{- if and .Values.services.http.enabled .Values.ingress.enabled }} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + {{- with (include "prometheus-postgres-exporter.ingress.annotations" . | fromYaml) }} + annotations: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + {{- with (include "prometheus-postgres-exporter.ingress.labels" . | fromYaml) }} + labels: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus-postgres-exporter.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: + ingressClassName: {{ .Values.ingress.className }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ tpl .host $ | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if .pathType }} + pathType: {{ .pathType }} + {{- end }} + backend: + service: + name: {{ include "prometheus-postgres-exporter.fullname" $ }} + port: + number: {{ $.Values.services.http.port }} + {{- end }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ tpl . $ | quote }} + {{- end }} + secretName: {{ .secretName | quote }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/templates/prometheus-postgres-exporter/podMonitor.yaml b/templates/prometheus-postgres-exporter/podMonitor.yaml new file mode 100644 index 0000000..6140828 --- /dev/null +++ b/templates/prometheus-postgres-exporter/podMonitor.yaml @@ -0,0 +1,40 @@ +{{- if and .Values.prometheus.metrics.enabled .Values.prometheus.metrics.podMonitor.enabled (not .Values.prometheus.metrics.serviceMonitor.enabled) }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + {{- with (include "prometheus-postgres-exporter.podMonitors.http.annotations" . | fromYaml) }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with (include "prometheus-postgres-exporter.podMonitors.http.labels" . | fromYaml) }} + labels: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus-postgres-exporter.fullname" . }}-http + namespace: {{ .Release.Namespace }} +spec: + podMetricsEndpoints: + - enableHttp2: {{ required "The enableHttp2 option of the podMonitor is not defined!" .Values.prometheus.metrics.podMonitor.enableHttp2 }} + followRedirects: {{ required "The followRedirects option of the podMonitor is not defined!" .Values.prometheus.metrics.podMonitor.followRedirects }} + honorLabels: {{ required "The honorLabels option of the podMonitor is not defined!" .Values.prometheus.metrics.podMonitor.honorLabels }} + interval: {{ required "The scrape interval of the podMonitor is not defined!" .Values.prometheus.metrics.podMonitor.interval }} + path: {{ required "The metric path of the podMonitor is not defined!" .Values.prometheus.metrics.podMonitor.path }} + port: "http" + {{- with .Values.prometheus.metrics.podMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + scrapeTimeout: {{ required "The scrape timeout of the podMonitor is not defined!" .Values.prometheus.metrics.podMonitor.scrapeTimeout }} + scheme: {{ required "The scheme of the podMonitor is not defined!" .Values.prometheus.metrics.podMonitor.scheme}} + {{- with .Values.prometheus.metrics.podMonitor.tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 6 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + {{- include "prometheus-postgres-exporter.pod.selectorLabels" . | nindent 6 }} +{{- end }} \ No newline at end of file diff --git a/templates/prometheus-postgres-exporter/prometheusRules.yaml b/templates/prometheus-postgres-exporter/prometheusRules.yaml new file mode 100644 index 0000000..0ef225a --- /dev/null +++ b/templates/prometheus-postgres-exporter/prometheusRules.yaml @@ -0,0 +1,23 @@ +{{- if gt (len .Values.prometheus.rules) 0 }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + {{- with (include "prometheus-postgres-exporter.prometheusRules.annotations" . | fromYaml) }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with (include "prometheus-postgres-exporter.prometheusRules.labels" . | fromYaml) }} + labels: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus-postgres-exporter.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: +{{- with .Values.prometheus.rules }} + groups: + - name: {{ template "prometheus-postgres-exporter.name" $ }} + rules: + {{ toYaml . | nindent 4 }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/templates/prometheus-postgres-exporter/secretDatabase.yaml b/templates/prometheus-postgres-exporter/secretDatabase.yaml new file mode 100644 index 0000000..a1483c0 --- /dev/null +++ b/templates/prometheus-postgres-exporter/secretDatabase.yaml @@ -0,0 +1,20 @@ +{{- if not (.Values.config.database.existingSecret.enabled) }} +--- +apiVersion: v1 +kind: Secret +metadata: + {{- with (include "prometheus-postgres-exporter.secrets.database.annotations" . | fromYaml) }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with (include "prometheus-postgres-exporter.secrets.database.labels" . | fromYaml) }} + labels: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus-postgres-exporter.fullname" . }}-database-env + namespace: {{ .Release.Namespace }} +stringData: + DATA_SOURCE_URI: {{ required "No `databaseConnectionUrl` defined!" .Values.config.database.secret.databaseConnectionUrl }} + DATA_SOURCE_USER: {{ required "No `databaseUsername` defined!" .Values.config.database.secret.databaseUsername }} + DATA_SOURCE_PASS: {{ required "No `databasePassword` defined!" .Values.config.database.secret.databasePassword }} +{{- end }} diff --git a/templates/prometheus-postgres-exporter/secretExporterConfig.yaml b/templates/prometheus-postgres-exporter/secretExporterConfig.yaml new file mode 100644 index 0000000..7c9e30d --- /dev/null +++ b/templates/prometheus-postgres-exporter/secretExporterConfig.yaml @@ -0,0 +1,19 @@ +{{- if not .Values.config.exporterConfig.existingSecret.enabled }} +--- +apiVersion: v1 +kind: Secret +metadata: + {{- with (include "prometheus-postgres-exporter.secrets.exporterConfig.annotations" . | fromYaml) }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with (include "prometheus-postgres-exporter.secrets.exporterConfig.labels" . | fromYaml) }} + labels: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus-postgres-exporter.fullname" . }}-exporter-config + namespace: {{ .Release.Namespace }} +stringData: + exporterConfig.yaml: | + {{- toYaml .Values.config.exporterConfig.secret.exporterConfig | nindent 4 }} +{{- end }} diff --git a/templates/prometheus-postgres-exporter/secretWebConfig.yaml b/templates/prometheus-postgres-exporter/secretWebConfig.yaml new file mode 100644 index 0000000..dfe9f87 --- /dev/null +++ b/templates/prometheus-postgres-exporter/secretWebConfig.yaml @@ -0,0 +1,19 @@ +{{- if and (not (.Values.config.webConfig.existingSecret.enabled)) .Values.config.webConfig.secret.webConfig }} +--- +apiVersion: v1 +kind: Secret +metadata: + {{- with (include "prometheus-postgres-exporter.secrets.webConfig.annotations" . | fromYaml) }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with (include "prometheus-postgres-exporter.secrets.webConfig.labels" . | fromYaml) }} + labels: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus-postgres-exporter.fullname" . }}-webconfig + namespace: {{ .Release.Namespace }} +stringData: + webConfig.yaml: | + {{- toYaml .Values.config.webConfig.secret.webConfig | nindent 4 }} +{{- end }} diff --git a/templates/prometheus-postgres-exporter/serviceAccount.yaml b/templates/prometheus-postgres-exporter/serviceAccount.yaml new file mode 100644 index 0000000..a395fea --- /dev/null +++ b/templates/prometheus-postgres-exporter/serviceAccount.yaml @@ -0,0 +1,26 @@ +{{- if not .Values.serviceAccount.existing.enabled }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + {{- with (include "prometheus-postgres-exporter.serviceAccount.annotations" . | fromYaml) }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with (include "prometheus-postgres-exporter.serviceAccount.labels" . | fromYaml) }} + labels: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus-postgres-exporter.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: + automountServiceAccountToken: {{ .Values.serviceAccount.new.automountServiceAccountToken }} + {{- with .Values.serviceAccount.new.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.serviceAccount.new.secrets }} + secrets: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/templates/prometheus-postgres-exporter/serviceHTTP.yaml b/templates/prometheus-postgres-exporter/serviceHTTP.yaml new file mode 100644 index 0000000..ba4614e --- /dev/null +++ b/templates/prometheus-postgres-exporter/serviceHTTP.yaml @@ -0,0 +1,57 @@ +{{- if .Values.services.http.enabled }} +--- +apiVersion: v1 +kind: Service +metadata: + {{- with (include "prometheus-postgres-exporter.services.http.annotations" . | fromYaml) }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with (include "prometheus-postgres-exporter.services.http.labels" . | fromYaml) }} + labels: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus-postgres-exporter.services.http.name" . }} + namespace: {{ .Release.Namespace }} +spec: + {{- if not (empty .Values.services.http.externalIPs) }} + externalIPs: + {{- range .Values.services.http.externalIPs }} + - {{ . }} + {{- end }} + {{- end }} + {{- if and (or (eq .Values.services.http.type "LoadBalancer") (eq .Values.services.http.type "NodePort") ) .Values.services.http.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.services.http.externalTrafficPolicy }} + {{- end }} + internalTrafficPolicy: {{ required "No internal traffic policy defined!" .Values.services.http.internalTrafficPolicy }} + {{- if .Values.services.http.ipFamilies }} + ipFamilies: + {{- range .Values.services.http.ipFamilies }} + - {{ . }} + {{- end }} + {{- end }} + {{- if and (eq .Values.services.http.type "LoadBalancer") .Values.services.http.loadBalancerClass }} + loadBalancerClass: {{ .Values.services.http.loadBalancerClass }} + {{- end }} + {{- if and (eq .Values.services.http.type "LoadBalancer") .Values.services.http.loadBalancerIP }} + loadBalancerIP: {{ .Values.services.http.loadBalancerIP }} + {{- end }} + {{- if eq .Values.services.http.type "LoadBalancer" }} + loadBalancerSourceRanges: + {{- range .Values.services.http.loadBalancerSourceRanges }} + - {{ . }} + {{- end }} + {{- end }} + ports: + - name: http + protocol: TCP + port: {{ required "No service port defined!" .Values.services.http.port }} + selector: + {{- include "prometheus-postgres-exporter.pod.selectorLabels" . | nindent 4 }} + sessionAffinity: {{ required "No session affinity defined!" .Values.services.http.sessionAffinity }} + {{- with .Values.services.http.sessionAffinityConfig }} + sessionAffinityConfig: + {{- toYaml . | nindent 4}} + {{- end }} + type: {{ required "No service type defined!" .Values.services.http.type }} +{{- end }} \ No newline at end of file diff --git a/templates/prometheus-postgres-exporter/serviceMonitorHTTP.yaml b/templates/prometheus-postgres-exporter/serviceMonitorHTTP.yaml new file mode 100644 index 0000000..82c09b5 --- /dev/null +++ b/templates/prometheus-postgres-exporter/serviceMonitorHTTP.yaml @@ -0,0 +1,40 @@ +{{- if and .Values.services.http.enabled .Values.prometheus.metrics.enabled .Values.prometheus.metrics.serviceMonitor.enabled (not .Values.prometheus.metrics.podMonitor.enabled)}} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + {{- with (include "prometheus-postgres-exporter.serviceMonitors.http.annotations" . | fromYaml) }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with (include "prometheus-postgres-exporter.serviceMonitors.http.labels" . | fromYaml) }} + labels: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus-postgres-exporter.fullname" . }}-http + namespace: {{ .Release.Namespace }} +spec: + endpoints: + - enableHttp2: {{ required "The enableHttp2 option of the serviceMonitor is not defined!" .Values.prometheus.metrics.serviceMonitor.enableHttp2 }} + followRedirects: {{ required "The followRedirects option of the serviceMonitor is not defined!" .Values.prometheus.metrics.serviceMonitor.followRedirects }} + honorLabels: {{ required "The honorLabels option of the serviceMonitor is not defined!" .Values.prometheus.metrics.serviceMonitor.honorLabels }} + interval: {{ required "The scrape interval of the serviceMonitor is not defined!" .Values.prometheus.metrics.serviceMonitor.interval }} + path: {{ required "The metric path of the serviceMonitor is not defined!" .Values.prometheus.metrics.serviceMonitor.path }} + {{- with .Values.prometheus.metrics.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + scrapeTimeout: {{ required "The scrape timeout of the serviceMonitor is not defined!" .Values.prometheus.metrics.serviceMonitor.scrapeTimeout }} + scheme: {{ required "The scheme of the serviceMonitor is not defined!" .Values.prometheus.metrics.serviceMonitor.scheme}} + targetPort: {{ required "The port of the serviceMonitor is not defined!" .Values.prometheus.metrics.serviceMonitor.port }} + {{- with .Values.prometheus.metrics.serviceMonitor.tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 6 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + {{- include "prometheus-postgres-exporter.serviceMonitors.http.selectorLabels" . | nindent 6 }} +{{- end }} \ No newline at end of file diff --git a/unittests/deployment/deployment.yaml b/unittests/deployment/deployment.yaml new file mode 100644 index 0000000..8872f5f --- /dev/null +++ b/unittests/deployment/deployment.yaml @@ -0,0 +1,45 @@ +chart: + appVersion: 0.1.0 + version: 0.1.0 +suite: Deployment template (basic) +release: + name: prometheus-postgres-exporter-unittest + namespace: testing +templates: +- templates/prometheus-postgres-exporter/deployment.yaml +tests: +- it: Rendering default + asserts: + - hasDocuments: + count: 1 + - containsDocument: + apiVersion: apps/v1 + kind: Deployment + name: prometheus-postgres-exporter-unittest + namespace: testing + - notExists: + path: metadata.annotations + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: prometheus-postgres-exporter-0.1.0 + - contains: + path: spec.template.spec.containers[0].envFrom + content: + secretRef: + name: prometheus-postgres-exporter-unittest-database-env + +- it: Test custom database secret + set: + config.database.existingSecret.enabled: true + config.database.existingSecret.secretName: custom-database-secret + asserts: + - contains: + path: spec.template.spec.containers[0].envFrom + content: + secretRef: + name: custom-database-secret diff --git a/unittests/ingress/ingress.yaml b/unittests/ingress/ingress.yaml new file mode 100644 index 0000000..5f63bcf --- /dev/null +++ b/unittests/ingress/ingress.yaml @@ -0,0 +1,140 @@ +chart: + appVersion: 0.1.0 + version: 0.1.0 +suite: Ingress template (basic) +release: + name: prometheus-postgres-exporter-unittest + namespace: testing +templates: +- templates/prometheus-postgres-exporter/ingress.yaml +tests: +- it: Skip ingress by default. + asserts: + - hasDocuments: + count: 0 + +- it: Skip ingress, when service is disabled. + set: + services.http.enabled: false + ingress.enabled: true + asserts: + - hasDocuments: + count: 0 + +- it: Render ingress with default values. + set: + ingress.enabled: true + ingress.hosts: + - host: postgres-exporter.example.local + paths: + - path: / + pathType: Prefix + ingress.tls: + - secretName: postgres-exporter-http-tls + hosts: + - postgres-exporter.example.local + + asserts: + - hasDocuments: + count: 1 + - containsDocument: + apiVersion: networking.k8s.io/v1 + kind: Ingress + name: prometheus-postgres-exporter-unittest + namespace: testing + - notExists: + path: metadata.annotations + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: prometheus-postgres-exporter-0.1.0 + - equal: + path: spec.ingressClassName + value: nginx + - contains: + path: spec.rules + content: + host: postgres-exporter.example.local + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: prometheus-postgres-exporter-unittest + port: + number: 9187 + - contains: + path: spec.tls + content: + hosts: + - postgres-exporter.example.local + secretName: postgres-exporter-http-tls + +- it: Render ingress with custom values. + set: + ingress.enabled: true + ingress.annotations: + foo: bar + ingress.className: nginx + ingress.labels: + bar: foo + ingress.hosts: + - host: postgres-exporter.example.local + paths: + - path: / + pathType: Prefix + ingress.tls: + - secretName: postgres-exporter-http-tls + hosts: + - postgres-exporter.example.local + + services.http.port: 8080 + + asserts: + - hasDocuments: + count: 1 + - containsDocument: + apiVersion: networking.k8s.io/v1 + kind: Ingress + name: prometheus-postgres-exporter-unittest + namespace: testing + - equal: + path: metadata.annotations + value: + foo: bar + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: prometheus-postgres-exporter-0.1.0 + bar: foo + - equal: + path: spec.ingressClassName + value: nginx + - contains: + path: spec.rules + content: + host: postgres-exporter.example.local + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: prometheus-postgres-exporter-unittest + port: + number: 8080 + - contains: + path: spec.tls + content: + hosts: + - postgres-exporter.example.local + secretName: postgres-exporter-http-tls diff --git a/unittests/podMonitors/podMonitorHTTP.yaml b/unittests/podMonitors/podMonitorHTTP.yaml new file mode 100644 index 0000000..b634455 --- /dev/null +++ b/unittests/podMonitors/podMonitorHTTP.yaml @@ -0,0 +1,172 @@ +chart: + appVersion: 0.1.0 + version: 0.1.0 +suite: PodMonitor http template (basic) +release: + name: prometheus-postgres-exporter-unittest + namespace: testing +templates: +- templates/prometheus-postgres-exporter/podMonitor.yaml +tests: +- it: Skip podMonitor when metrics are disabled. + set: + prometheus.metrics.enabled: false + prometheus.metrics.podMonitor.enabled: true + prometheus.metrics.serviceMonitor.enabled: true + asserts: + - hasDocuments: + count: 0 + +- it: Skip podMonitor when podMonitor is disabled. + set: + prometheus.metrics.enabled: true + prometheus.metrics.podMonitor.enabled: false + asserts: + - hasDocuments: + count: 0 + +- it: Skip podMonitor when both monitor types are enabled. + set: + prometheus.metrics.enabled: true + prometheus.metrics.podMonitor.enabled: true + prometheus.metrics.serviceMonitor.enabled: true + asserts: + - hasDocuments: + count: 0 + +- it: Rendering podMonitor with default values - enabled manually. + set: + prometheus.metrics.enabled: true + prometheus.metrics.podMonitor.enabled: true + asserts: + - hasDocuments: + count: 1 + - containsDocument: + apiVersion: monitoring.coreos.com/v1 + kind: PodMonitor + name: prometheus-postgres-exporter-unittest-http + namespace: testing + - notExists: + path: metadata.annotations + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: prometheus-postgres-exporter-0.1.0 + - equal: + path: spec.podMetricsEndpoints[0].enableHttp2 + value: false + - equal: + path: spec.podMetricsEndpoints[0].followRedirects + value: false + - equal: + path: spec.podMetricsEndpoints[0].honorLabels + value: false + - equal: + path: spec.podMetricsEndpoints[0].interval + value: 60s + - equal: + path: spec.podMetricsEndpoints[0].path + value: /metrics + - equal: + path: spec.podMetricsEndpoints[0].port + value: http + - notExists: + path: spec.podMetricsEndpoints[0].relabelings + - equal: + path: spec.podMetricsEndpoints[0].scrapeTimeout + value: 30s + - equal: + path: spec.podMetricsEndpoints[0].scheme + value: http + - contains: + path: spec.namespaceSelector.matchNames + content: + testing + - equal: + path: spec.selector.matchLabels + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: prometheus-postgres-exporter-0.1.0 + +- it: Render podMonitor with custom annotations and labels. + set: + prometheus.metrics.enabled: true + prometheus.metrics.podMonitor.enabled: true + prometheus.metrics.podMonitor.annotations: + foo: bar + prometheus.metrics.podMonitor.labels: + bar: foo + asserts: + - equal: + path: metadata.annotations + value: + foo: bar + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/version: 0.1.0 + bar: foo + helm.sh/chart: prometheus-postgres-exporter-0.1.0 + +- it: Change defaults + set: + prometheus.metrics.enabled: true + prometheus.metrics.podMonitor.enabled: true + prometheus.metrics.podMonitor.enableHttp2: true + prometheus.metrics.podMonitor.followRedirects: true + prometheus.metrics.podMonitor.honorLabels: true + prometheus.metrics.podMonitor.interval: "180s" + prometheus.metrics.podMonitor.path: "/my-metrics" + prometheus.metrics.podMonitor.relabelings: + - sourceLabels: [ container ] + separator: ";" + regex: "app" + replacement: "$1" + action: "drop" + prometheus.metrics.podMonitor.scrapeTimeout: "5s" + prometheus.metrics.podMonitor.scheme: "http" + asserts: + - hasDocuments: + count: 1 + - equal: + path: spec.podMetricsEndpoints[0].enableHttp2 + value: true + - equal: + path: spec.podMetricsEndpoints[0].followRedirects + value: true + - equal: + path: spec.podMetricsEndpoints[0].honorLabels + value: true + - equal: + path: spec.podMetricsEndpoints[0].interval + value: 180s + - equal: + path: spec.podMetricsEndpoints[0].path + value: /my-metrics + - equal: + path: spec.podMetricsEndpoints[0].port + value: http + - contains: + path: spec.podMetricsEndpoints[0].relabelings + content: + sourceLabels: [ container ] + separator: ";" + regex: "app" + replacement: "$1" + action: "drop" + - equal: + path: spec.podMetricsEndpoints[0].scrapeTimeout + value: 5s + - equal: + path: spec.podMetricsEndpoints[0].scheme + value: http \ No newline at end of file diff --git a/unittests/secrets/database.yaml b/unittests/secrets/database.yaml new file mode 100644 index 0000000..e288fee --- /dev/null +++ b/unittests/secrets/database.yaml @@ -0,0 +1,104 @@ +chart: + appVersion: 0.1.0 + version: 0.1.0 +suite: Secret database template (basic) +release: + name: prometheus-postgres-exporter-unittest + namespace: testing +templates: +- templates/prometheus-postgres-exporter/secretDatabase.yaml +tests: +- it: Skip rendering by using existing secret. + set: + config.database.existingSecret.enabled: true + asserts: + - hasDocuments: + count: 0 + +- it: Expect error when no variable is defined. + asserts: + - failedTemplate: + errorMessage: No `databaseConnectionUrl` defined! + +- it: Expect error when variable `databaseUsername` is not defined. + set: + # config.database.secret.databaseUsername: "" + config.database.secret.databasePassword: "postgres" + config.database.secret.databaseConnectionUrl: "localhost:5432/postgres?sslmode=disable" + asserts: + - failedTemplate: + errorMessage: No `databaseUsername` defined! + +- it: Expect error when variable `databasePassword` is not defined. + set: + config.database.secret.databaseUsername: "postgres" + # config.database.secret.databasePassword: "postgres" + config.database.secret.databaseConnectionUrl: "localhost:5432/postgres?sslmode=disable" + asserts: + - failedTemplate: + errorMessage: No `databasePassword` defined! + +- it: Expect error when variable `databaseConnectionUrl` is not defined. + set: + config.database.secret.databaseUsername: "postgres" + config.database.secret.databasePassword: "postgres" + # config.database.secret.databaseConnectionUrl: "localhost:5432/postgres?sslmode=disable" + asserts: + - failedTemplate: + errorMessage: No `databaseConnectionUrl` defined! + +- it: Rendering database secret. + set: + config.database.secret.databaseUsername: "postgres" + config.database.secret.databasePassword: "postgres" + config.database.secret.databaseConnectionUrl: "localhost:5432/postgres?sslmode=disable" + asserts: + - hasDocuments: + count: 1 + - containsDocument: + apiVersion: v1 + kind: Secret + name: prometheus-postgres-exporter-unittest-database-env + namespace: testing + - notExists: + path: metadata.annotations + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: prometheus-postgres-exporter-0.1.0 + - equal: + path: stringData.DATA_SOURCE_URI + value: "localhost:5432/postgres?sslmode=disable" + - equal: + path: stringData.DATA_SOURCE_USER + value: "postgres" + - equal: + path: stringData.DATA_SOURCE_PASS + value: "postgres" + +- it: Rendering custom annotations and labels. + set: + config.database.secret.annotations: + foo: bar + bar: foo + config.database.secret.databaseUsername: "postgres" + config.database.secret.databasePassword: "postgres" + config.database.secret.databaseConnectionUrl: "localhost:5432/postgres?sslmode=disable" + config.database.secret.labels: + foo: bar + bar: foo + asserts: + - equal: + path: metadata.annotations + value: + foo: bar + bar: foo + - isSubset: + path: metadata.labels + content: + foo: bar + bar: foo \ No newline at end of file diff --git a/unittests/secrets/exporterConfig.yaml b/unittests/secrets/exporterConfig.yaml new file mode 100644 index 0000000..f82fb93 --- /dev/null +++ b/unittests/secrets/exporterConfig.yaml @@ -0,0 +1,86 @@ +chart: + appVersion: 0.1.0 + version: 0.1.0 +suite: Secret database template (basic) +release: + name: prometheus-postgres-exporter-unittest + namespace: testing +templates: +- templates/prometheus-postgres-exporter/secretExporterConfig.yaml +tests: +- it: Skip rendering by using existing secret. + set: + config.exporterConfig.existingSecret.enabled: true + asserts: + - hasDocuments: + count: 0 + +- it: Render secret, but with no value. + asserts: + - hasDocuments: + count: 1 + - equal: + path: stringData["exporterConfig.yaml"] + value: | + {} + +- it: Rendering exporter config secret. + set: + config.exporterConfig.secret.exporterConfig: + auth_modules: + first: + type: userpass + userpass: + username: first_username + password: first_password + options: + sslmode: disable + asserts: + - hasDocuments: + count: 1 + - containsDocument: + apiVersion: v1 + kind: Secret + name: prometheus-postgres-exporter-unittest-exporter-config + namespace: testing + - notExists: + path: metadata.annotations + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: prometheus-postgres-exporter-0.1.0 + - equal: + path: stringData["exporterConfig.yaml"] + value: | + auth_modules: + first: + options: + sslmode: disable + type: userpass + userpass: + password: first_password + username: first_username + +- it: Rendering custom annotations and labels. + set: + config.exporterConfig.secret.annotations: + foo: bar + bar: foo + config.exporterConfig.secret.labels: + foo: bar + bar: foo + asserts: + - equal: + path: metadata.annotations + value: + foo: bar + bar: foo + - isSubset: + path: metadata.labels + content: + foo: bar + bar: foo \ No newline at end of file diff --git a/unittests/secrets/webconfig.yaml b/unittests/secrets/webconfig.yaml new file mode 100644 index 0000000..f70cf57 --- /dev/null +++ b/unittests/secrets/webconfig.yaml @@ -0,0 +1,81 @@ +chart: + appVersion: 0.1.0 + version: 0.1.0 +suite: Secret database template (basic) +release: + name: prometheus-postgres-exporter-unittest + namespace: testing +templates: +- templates/prometheus-postgres-exporter/secretWebConfig.yaml +tests: +- it: Skip rendering by using existing secret. + set: + config.webConfig.existingSecret.enabled: true + asserts: + - hasDocuments: + count: 0 + +- it: Skip rendering when no webConfig.yaml is defined. + set: + config.webConfig.existingSecret.enabled: false + asserts: + - hasDocuments: + count: 0 + +- it: Rendering database secret. + set: + config.webConfig.secret.webConfig: + tls_server_config: + cert_file: /path/to/cert.pem + client_ca_file: /path/to/ca.pem + key_file: /path/to/key.pem + asserts: + - hasDocuments: + count: 1 + - containsDocument: + apiVersion: v1 + kind: Secret + name: prometheus-postgres-exporter-unittest-webconfig + namespace: testing + - notExists: + path: metadata.annotations + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: prometheus-postgres-exporter-0.1.0 + - equal: + path: stringData["webConfig.yaml"] + value: | + tls_server_config: + cert_file: /path/to/cert.pem + client_ca_file: /path/to/ca.pem + key_file: /path/to/key.pem + +- it: Rendering custom annotations and labels. + set: + config.webConfig.secret.annotations: + foo: bar + bar: foo + config.webConfig.secret.labels: + foo: bar + bar: foo + config.webConfig.secret.webConfig: + tls_server_config: + cert_file: /path/to/cert.pem + key_file: /path/to/key.pem + client_ca_file: /path/to/ca.pem + asserts: + - equal: + path: metadata.annotations + value: + foo: bar + bar: foo + - isSubset: + path: metadata.labels + content: + foo: bar + bar: foo \ No newline at end of file diff --git a/unittests/serviceAccounts/serviceAccount.yaml b/unittests/serviceAccounts/serviceAccount.yaml new file mode 100644 index 0000000..5f1d4cf --- /dev/null +++ b/unittests/serviceAccounts/serviceAccount.yaml @@ -0,0 +1,79 @@ +chart: + appVersion: 0.1.0 + version: 0.1.0 +suite: ServiceAccount prometheus-postgres-exporter template (basic) +release: + name: prometheus-postgres-exporter-unittest + namespace: testing +templates: +- templates/prometheus-postgres-exporter/serviceAccount.yaml +tests: +- it: Skip rendering. + set: + serviceAccount.existing.enabled: true + asserts: + - hasDocuments: + count: 0 + +- it: Rendering serviceAccount with default values. + asserts: + - hasDocuments: + count: 1 + - containsDocument: + apiVersion: v1 + kind: ServiceAccount + name: prometheus-postgres-exporter-unittest + namespace: testing + - notExists: + path: metadata.annotations + - notExists: + path: metadata.labels + - equal: + path: spec.automountServiceAccountToken + value: true + - notExists: + path: spec.imagePullSecrets + - notExists: + path: spec.secrets + + +- it: Rendering serviceAccount with custom values. + set: + serviceAccount.new.annotations: + foo: bar + serviceAccount.new.labels: + bar: foo + serviceAccount.new.automountServiceAccountToken: false + serviceAccount.new.imagePullSecrets: + - name: "my-pull-secret" + serviceAccount.new.secrets: + - name: "my-secret" + namespace: "my-namespace" + fieldPath: "my-path" + asserts: + - hasDocuments: + count: 1 + - exists: + path: metadata.annotations + value: + foo: bar + - exists: + path: metadata.labels + value: + bar: foo + - equal: + path: metadata.name + value: prometheus-postgres-exporter-unittest + - equal: + path: spec.automountServiceAccountToken + value: false + - equal: + path: spec.imagePullSecrets + value: + - name: "my-pull-secret" + - equal: + path: spec.secrets + value: + - name: "my-secret" + namespace: "my-namespace" + fieldPath: "my-path" diff --git a/unittests/serviceMonitors/serviceMonitorHTTP.yaml b/unittests/serviceMonitors/serviceMonitorHTTP.yaml new file mode 100644 index 0000000..3f481b7 --- /dev/null +++ b/unittests/serviceMonitors/serviceMonitorHTTP.yaml @@ -0,0 +1,172 @@ +chart: + appVersion: 0.1.0 + version: 0.1.0 +suite: ServiceMonitor http template (basic) +release: + name: prometheus-postgres-exporter-unittest + namespace: testing +templates: +- templates/prometheus-postgres-exporter/serviceMonitorHTTP.yaml +tests: +- it: Skip serviceMonitor when service is disabled. + set: + prometheus.metrics.enabled: true + prometheus.metrics.serviceMonitor.enabled: true + services.http.enabled: false + asserts: + - hasDocuments: + count: 0 + +- it: Skip serviceMonitor when metrics are disabled. + set: + prometheus.metrics.enabled: false + prometheus.metrics.serviceMonitor.enabled: true + services.http.enabled: true + asserts: + - hasDocuments: + count: 0 + +- it: Skip serviceMonitor when serviceMonitor is disabled. + set: + prometheus.metrics.enabled: true + prometheus.metrics.serviceMonitor.enabled: false + services.http.enabled: true + asserts: + - hasDocuments: + count: 0 + +- it: Rendering serviceMonitor with default values - enabled manually. + set: + prometheus.metrics.enabled: true + prometheus.metrics.serviceMonitor.enabled: true + asserts: + - hasDocuments: + count: 1 + - containsDocument: + apiVersion: monitoring.coreos.com/v1 + kind: ServiceMonitor + name: prometheus-postgres-exporter-unittest-http + namespace: testing + - notExists: + path: metadata.annotations + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: prometheus-postgres-exporter-0.1.0 + - equal: + path: spec.endpoints[0].enableHttp2 + value: false + - equal: + path: spec.endpoints[0].followRedirects + value: false + - equal: + path: spec.endpoints[0].honorLabels + value: false + - equal: + path: spec.endpoints[0].interval + value: 60s + - equal: + path: spec.endpoints[0].path + value: /metrics + - notExists: + path: spec.endpoints[0].relabelings + - equal: + path: spec.endpoints[0].scrapeTimeout + value: 30s + - equal: + path: spec.endpoints[0].scheme + value: http + - equal: + path: spec.endpoints[0].targetPort + value: 9187 + - contains: + path: spec.namespaceSelector.matchNames + content: + testing + - equal: + path: spec.selector.matchLabels + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/service-name: http + +- it: Render serviceMonitor with custom annotations and labels. + set: + prometheus.metrics.enabled: true + prometheus.metrics.serviceMonitor.enabled: true + prometheus.metrics.serviceMonitor.annotations: + foo: bar + prometheus.metrics.serviceMonitor.labels: + bar: foo + asserts: + - equal: + path: metadata.annotations + value: + foo: bar + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/version: 0.1.0 + bar: foo + helm.sh/chart: prometheus-postgres-exporter-0.1.0 + +- it: Change defaults + set: + prometheus.metrics.enabled: true + prometheus.metrics.serviceMonitor.enabled: true + prometheus.metrics.serviceMonitor.enableHttp2: true + prometheus.metrics.serviceMonitor.followRedirects: true + prometheus.metrics.serviceMonitor.honorLabels: true + prometheus.metrics.serviceMonitor.interval: "180s" + prometheus.metrics.serviceMonitor.path: "/my-metrics" + prometheus.metrics.serviceMonitor.relabelings: + - sourceLabels: [ container ] + separator: ";" + regex: "app" + replacement: "$1" + action: "drop" + prometheus.metrics.serviceMonitor.scrapeTimeout: "5s" + prometheus.metrics.serviceMonitor.scheme: "http" + prometheus.metrics.serviceMonitor.port: 10443 + asserts: + - hasDocuments: + count: 1 + - equal: + path: spec.endpoints[0].enableHttp2 + value: true + - equal: + path: spec.endpoints[0].followRedirects + value: true + - equal: + path: spec.endpoints[0].honorLabels + value: true + - equal: + path: spec.endpoints[0].interval + value: 180s + - equal: + path: spec.endpoints[0].path + value: /my-metrics + - contains: + path: spec.endpoints[0].relabelings + content: + sourceLabels: [ container ] + separator: ";" + regex: "app" + replacement: "$1" + action: "drop" + - equal: + path: spec.endpoints[0].scrapeTimeout + value: 5s + - equal: + path: spec.endpoints[0].scheme + value: http + - equal: + path: spec.endpoints[0].targetPort + value: 10443 \ No newline at end of file diff --git a/unittests/services/http.yaml b/unittests/services/http.yaml new file mode 100644 index 0000000..dc9b251 --- /dev/null +++ b/unittests/services/http.yaml @@ -0,0 +1,177 @@ +chart: + appVersion: 0.1.0 + version: 0.1.0 +suite: Service http template (basic) +release: + name: prometheus-postgres-exporter-unittest + namespace: testing +templates: +- templates/prometheus-postgres-exporter/serviceHTTP.yaml +tests: +- it: Skip service when disabled. + set: + services.http.enabled: false + asserts: + - hasDocuments: + count: 0 + +- it: Rendering service with default values. + asserts: + - hasDocuments: + count: 1 + - containsDocument: + apiVersion: v1 + kind: Service + name: prometheus-postgres-exporter-unittest-http + namespace: testing + - notExists: + path: metadata.annotations + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/service-name: http + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: prometheus-postgres-exporter-0.1.0 + - notExists: + path: spec.externalIPs + - notExists: + path: spec.externalTrafficPolicy + - equal: + path: spec.internalTrafficPolicy + value: Cluster + - notExists: + path: spec.ipFamilies + - notExists: + path: spec.loadBalancerClass + - notExists: + path: spec.loadBalancerIP + - notExists: + path: spec.loadBalancerSourceRanges + - equal: + path: spec.ports[0].name + value: http + - equal: + path: spec.ports[0].protocol + value: TCP + - equal: + path: spec.ports[0].port + value: 9187 + - equal: + path: spec.selector + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: prometheus-postgres-exporter-0.1.0 + - equal: + path: spec.sessionAffinity + value: None + - notExists: + path: spec.sessionAffinityConfig + - equal: + path: spec.type + value: ClusterIP + +- it: Require internalTrafficPolicy. + set: + services.http.internalTrafficPolicy: "" + asserts: + - failedTemplate: + errorMessage: No internal traffic policy defined! + +- it: Require port. + set: + services.http.port: "" + asserts: + - failedTemplate: + errorMessage: No service port defined! + +- it: Require sessionAffinity. + set: + services.http.sessionAffinity: "" + asserts: + - failedTemplate: + errorMessage: No session affinity defined! + +- it: Require service type. + set: + services.http.type: "" + asserts: + - failedTemplate: + errorMessage: No service type defined! + +- it: Render service with custom annotations and labels. + set: + services.http.annotations: + foo: bar + services.http.labels: + bar: foo + asserts: + - equal: + path: metadata.annotations + value: + foo: bar + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: prometheus-postgres-exporter-unittest + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: prometheus-postgres-exporter + app.kubernetes.io/service-name: http + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: prometheus-postgres-exporter-0.1.0 + bar: foo + +- it: Change defaults + set: + services.http.externalIPs: + - "10.11.12.13/32" + services.http.externalTrafficPolicy: Local + services.http.internalTrafficPolicy: Local + services.http.ipFamilies: + - IPv4 + services.http.loadBalancerClass: aws + services.http.loadBalancerIP: "11.12.13.14" + services.http.loadBalancerSourceRanges: + - "11.12.0.0/17" + services.http.port: 10443 + services.http.sessionAffinity: ClientIP + services.http.type: LoadBalancer + asserts: + - equal: + path: spec.externalIPs + value: + - 10.11.12.13/32 + - equal: + path: spec.externalTrafficPolicy + value: Local + - equal: + path: spec.internalTrafficPolicy + value: Local + - equal: + path: spec.ipFamilies + value: + - IPv4 + - equal: + path: spec.loadBalancerClass + value: aws + - equal: + path: spec.loadBalancerIP + value: "11.12.13.14" + - equal: + path: spec.loadBalancerSourceRanges + value: + - "11.12.0.0/17" + - equal: + path: spec.ports[0].port + value: 10443 + - equal: + path: spec.sessionAffinity + value: ClientIP + - equal: + path: spec.type + value: LoadBalancer \ No newline at end of file diff --git a/values.yaml b/values.yaml new file mode 100644 index 0000000..96aa82d --- /dev/null +++ b/values.yaml @@ -0,0 +1,521 @@ +# Default values for qu-seed. +# This is a YAML-formatted file. + +# Declare variables to be passed into your templates. +## @section Global +## @param nameOverride Individual release name suffix. +## @param fullnameOverride Override the complete release name logic. +nameOverride: "" +fullnameOverride: "" + +## @section Configuration +config: + database: + ## @param config.database.existingSecret.enabled Mount an existing secret containing the application specific `DATA_SOURCE_` prefixed environment variables. + ## @param config.database.existingSecret.secretName Name of the existing secret containing the application specific `DATA_SOURCE_` prefixed environment variables. + existingSecret: + enabled: false + secretName: "" + + ## @param config.database.secret.annotations Additional annotations of the secret containing the database credentials. + ## @param config.database.secret.labels Additional labels of the secret containing the database credentials. + ## @param config.database.secret.databaseUsername Database username. Will be defined as env `DATA_SOURCE_USER` as part of a secret. + ## @param config.database.secret.databasePassword Database password. Will be defined as env `DATA_SOURCE_PASS` as part of a secret. + ## @param config.database.secret.databaseConnectionUrl Complex database connection URL. Will be defined as env `DATA_SOURCE_URI` as part of a secret. + secret: + annotations: {} + labels: {} + databaseUsername: "" + databasePassword: "" + databaseConnectionUrl: "" + + exporterConfig: + ## @param config.exporterConfig.existingSecret.enabled Mount an existing secret containing the key `exporter_config.yaml`. + ## @param config.exporterConfig.existingSecret.secretName Name of the existing secret containing the key `exporter_config.yaml`. + existingSecret: + enabled: false + secretName: "" + + ## @param config.exporterConfig.secret.annotations Additional annotations of the secret containing the `exporterConfig.yaml`. + ## @param config.exporterConfig.secret.labels Additional labels of the secret containing the `exporterConfig.yaml`. + ## @param config.exporterConfig.secret.exporterConfig Content of the `exporterConfig.yaml`. Further information can be found [here](https://prometheus.io/docs/prometheus/latest/configuration/https/). + ## @skip config.exporterConfig.secret.exporterConfig Skip individual postgres exporter configuration. + secret: + annotations: {} + labels: {} + exporterConfig: {} + # auth_modules: + # first: + # options: + # sslmode: disable + # type: userpass + # userpass: + # password: first_password + # username: first_username + + webConfig: + ## @param config.webConfig.existingSecret.enabled Mount an existing secret containing the key `webConfig.yaml`. + ## @param config.webConfig.existingSecret.secretName Name of the existing secret containing the key `webConfig.yaml`. + existingSecret: + enabled: false + secretName: "" + + ## @param config.webConfig.secret.annotations Additional annotations of the secret containing the `webConfig.yaml`. + ## @param config.webConfig.secret.labels Additional labels of the secret containing the `webConfig.yaml`. + ## @param config.webConfig.secret.webConfig Content of the `webConfig.yaml`. Further information can be found [here](https://prometheus.io/docs/prometheus/latest/configuration/https/). + ## @skip config.webConfig.secret.webConfig Skip individual web configuration. + secret: + annotations: {} + labels: {} + webConfig: {} + # basic_auth_users: + # prom: + # http_server_config: + # http2: true + # tls_server_config: + # cert_file: /path/to/cert.pem + # client_allowed_sans: + # - postgres.example.local + # client_ca_file: /path/to/ca.pem + # key_file: /path/to/key.pem + # max_version: TLS13 + # min_version: TLS12 + +## @section Deployment +deployment: + ## @param deployment.annotations Additional deployment annotations. + ## @param deployment.labels Additional ingress labels. + annotations: {} + labels: {} + + ## @param deployment.additionalContainers List of additional containers. + additionalContainers: [] + # - command: [ "sh", "-c", "echo hello world" ] + # image: "docker.io/library/busybox:latest" + # name: side-car + + ## @param deployment.affinity Affinity for the postgres-exporter deployment. + affinity: {} + + ## @param deployment.initContainers List of additional init containers. + initContainers: [] + # - command: [ "sh", "-c", "echo hello world" ] + # image: "docker.io/library/busybox:latest" + # name: init + + ## @param deployment.dnsConfig dnsConfig of the postgres-exporter deployment. + dnsConfig: {} + # nameservers: + # - 192.0.2.1 # this is an example + # searches: + # - ns1.svc.cluster-domain.example + # - my.dns.search.suffix + # options: + # - name: ndots + # value: "2" + # - name: edns0 + + ## @param deployment.dnsPolicy dnsPolicy of the postgres-exporter deployment. + dnsPolicy: "" + + ## @param deployment.hostname Individual hostname of the pod. + ## @param deployment.subdomain Individual domain of the pod. + hostname: "" + subdomain: "" + + ## @param deployment.hostNetwork Use the kernel network namespace of the host system. + hostNetwork: false + + ## @param deployment.imagePullSecrets Secret to use for pulling the image. + imagePullSecrets: [] + # - name: "my-custom-secret" + + postgresExporter: + ## @param deployment.postgresExporter.args Arguments passed to the postgres-exporter container. + args: [] + + ## @param deployment.postgresExporter.env List of environment variables for the postgres-exporter container. + env: [] + # - name: SPECIAL_ENV_A + # value: special-key + # - name: SPECIAL_ENV + # valueFrom: + # configMapKeyRef: + # name: special-config + # key: special-key + # - name: SPECIAL_ENV + # valueFrom: + # secretKeyRef: + # name: special-secret + # key: special-key + + ## @param deployment.postgresExporter.envFrom List of environment variables mounted from configMaps or secrets for the postgres-exporter container. + envFrom: [] + # - configMapRef: + # name: special-config + # - secretRef: + # name: special-secret + + ## @param deployment.postgresExporter.image.registry Image registry, eg. `docker.io`. + ## @param deployment.postgresExporter.image.repository Image repository, eg. `library/busybox`. + ## @param deployment.postgresExporter.image.tag Custom image tag, eg. `0.1.0`. Defaults to `appVersion`. + ## @param deployment.postgresExporter.image.pullPolicy Image pull policy. + image: + registry: quay.io + repository: prometheuscommunity/postgres-exporter + tag: "" + pullPolicy: IfNotPresent + + ## @param deployment.postgresExporter.resources CPU and memory resources of the pod. + resources: {} + # limits: + # cpu: + # ephemeral-storage: + # memory: + # requests: + # cpu: + # ephemeral-storage: + # memory: + + ## @param deployment.postgresExporter.securityContext Security context of the container of the deployment. + securityContext: {} + # capabilities: + # add: + # - NET_RAW + # drop: + # - ALL + # privileged: false + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + + ## @param deployment.postgresExporter.volumeMounts Additional volume mounts. + volumeMounts: {} + # - name: my-configmap-volume + # mountPath: /configmap + # readOnly: true + + ## @param deployment.nodeSelector NodeSelector of the postgres-exporter deployment. + nodeSelector: {} + + ## @param deployment.priorityClassName PriorityClassName of the postgres-exporter deployment. + priorityClassName: "" + + ## @param deployment.replicaCount Number of replicas for the postgres-exporter deployment. + replicaCount: 1 + + ## @param deployment.securityContext Security context of the postgres-exporter deployment. + securityContext: {} + # fsGroup: 2000 + + ## @param deployment.strategy.type Strategy type - `Recreate` or `Rollingupdate`. + ## @param deployment.strategy.rollingUpdate.maxSurge The maximum number of pods that can be scheduled above the desired number of pods during a rolling update. + ## @param deployment.strategy.rollingUpdate.maxUnavailable The maximum number of pods that can be unavailable during a rolling update. + strategy: + type: "Recreate" + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + + ## @param deployment.terminationGracePeriodSeconds How long to wait until forcefully kill the pod. + terminationGracePeriodSeconds: 60 + + ## @param deployment.tolerations Tolerations of the postgres-exporter deployment. + tolerations: [] + + ## @param deployment.topologySpreadConstraints TopologySpreadConstraints of the postgres-exporter deployment. + topologySpreadConstraints: [] + # - topologyKey: kubernetes.io/hostname + # whenUnsatisfiable: DoNotSchedule + # labelSelector: + # matchLabels: + # app.kubernetes.io/instance: prometheus-postgres-exporter + + ## @param deployment.volumes Additional volumes to mount into the pods of the prometheus-exporter deployment. + volumes: [] + # - name: my-configmap-volume + # config: + # name: my-configmap + # - name: my-secret-volume + # secret: + # secretName: my-secret + +## @section Grafana +## @param grafana.enabled Enable integration into Grafana. +## @param grafana.dashboards.businessMetrics Enable deployment of Grafana dashboard `businessMetrics`. +grafana: + enabled: false + dashboards: + businessMetrics: true + +## @section Ingress +ingress: + ## @param ingress.enabled Enable creation of an ingress resource. Requires, that the http service is also enabled. + ## @param ingress.className Ingress class. + ## @param ingress.annotations Additional ingress annotations. + ## @param ingress.labels Additional ingress labels. + enabled: false + className: "nginx" + annotations: {} + labels: {} + + ## @param ingress.hosts Ingress specific configuration. Specification only required when another ingress controller is used instead of `t1k. + ## @skip ingress.hosts Skip individual host configuration. + hosts: [] + # - host: postgres-exporter.example.local + # paths: + # - path: / + # pathType: Prefix + + ## @param ingress.tls Ingress TLS settings. Specification only required when another ingress controller is used instead of `t1k``. + ## @skip ingress.tls Skip individual TLS configuration. + tls: [] + # - secretName: postgres-exporter-http-tls + # hosts: + # - postgres-exporter.example.local + +## @section Pod disruption +## @param podDisruptionBudget Pod disruption budget. +podDisruptionBudget: {} +# maxUnavailable: 1 +# minAvailable: 1 + +## @section Network +## @param networkPolicies Deploy network policies based on the used container network interface (CNI) implementation - like calico or weave. +networkPolicies: {} + +## @section Prometheus +prometheus: + ## @param prometheus.metrics.enabled Enable of scraping metrics by Prometheus. + metrics: + enabled: true + + ## @param prometheus.metrics.podMonitor.enabled Enable creation of a podMonitor. Excludes the existence of a serviceMonitor resource. + ## @param prometheus.metrics.podMonitor.annotations Additional podMonitor annotations. + ## @param prometheus.metrics.podMonitor.enableHttp2 Enable HTTP2. + ## @param prometheus.metrics.podMonitor.followRedirects FollowRedirects configures whether scrape requests follow HTTP 3xx redirects. + ## @param prometheus.metrics.podMonitor.honorLabels Honor labels. + ## @param prometheus.metrics.podMonitor.labels Additional podMonitor labels. + ## @param prometheus.metrics.podMonitor.interval Interval at which metrics should be scraped. If not specified Prometheus' global scrape interval is used. + ## @param prometheus.metrics.podMonitor.path HTTP path for scraping prometheus metrics. + ## @param prometheus.metrics.podMonitor.relabelings RelabelConfigs to apply to samples before scraping. Prometheus Operator automatically adds relabelings for a few standard Kubernetes fields. + ## @param prometheus.metrics.podMonitor.scrapeTimeout Timeout after which the scrape is ended. If not specified, global Prometheus scrape timeout is used. + ## @param prometheus.metrics.podMonitor.scheme HTTP scheme to use for scraping. For example `http` or `https`. + ## @param prometheus.metrics.podMonitor.tlsConfig TLS configuration to use when scraping the metric endpoint by Prometheus. + ## @skip prometheus.metrics.podMonitor.tlsConfig Skip individual TLS configuration. + podMonitor: + enabled: false + annotations: {} + enableHttp2: false + followRedirects: false + honorLabels: false + labels: {} + interval: "60s" + path: "/metrics" + relabelings: [] + scrapeTimeout: "30s" + scheme: "http" + tlsConfig: {} + + ## @param prometheus.metrics.serviceMonitor.enabled Enable creation of a serviceMonitor. Excludes the existence of a podMonitor resource. + ## @param prometheus.metrics.serviceMonitor.annotations Additional serviceMonitor annotations. + ## @param prometheus.metrics.serviceMonitor.labels Additional serviceMonitor labels. + ## @param prometheus.metrics.serviceMonitor.enableHttp2 Enable HTTP2. + ## @param prometheus.metrics.serviceMonitor.followRedirects FollowRedirects configures whether scrape requests follow HTTP 3xx redirects. + ## @param prometheus.metrics.serviceMonitor.honorLabels Honor labels. + ## @param prometheus.metrics.serviceMonitor.interval Interval at which metrics should be scraped. If not specified Prometheus' global scrape interval is used. + ## @param prometheus.metrics.serviceMonitor.path HTTP path for scraping prometheus metrics. + ## @param prometheus.metrics.serviceMonitor.port HTTP port for scraping prometheus metrics. + ## @param prometheus.metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping. Prometheus Operator automatically adds relabelings for a few standard Kubernetes fields. + ## @param prometheus.metrics.serviceMonitor.scrapeTimeout Timeout after which the scrape is ended. If not specified, global Prometheus scrape timeout is used. + ## @param prometheus.metrics.serviceMonitor.scheme HTTP scheme to use for scraping. For example `http` or `https`. + ## @param prometheus.metrics.serviceMonitor.tlsConfig TLS configuration to use when scraping the metric endpoint by Prometheus. + ## @skip prometheus.metrics.serviceMonitor.tlsConfig Skip individual TLS configuration. + serviceMonitor: + enabled: false + annotations: {} + labels: {} + enableHttp2: false + followRedirects: false + honorLabels: false + interval: "60s" + path: "/metrics" + port: 9187 + relabelings: [] + scrapeTimeout: "30s" + scheme: "http" + tlsConfig: {} + + ## @param prometheus.rules Array of prometheus rules for monitoring the application and triggering alerts. + ## @skip prometheus.rules Skip individual prometheus rules. + rules: [] + # - alert: ExporterErrors + # expr: pg_exporter_last_scrape_error == 1 + # for: 10m + # labels: + # service: PostgreSQL + # severity: critical + # annotations: + # description: The Postgres Exporter is not running or it is showing errors {{ $labels.instance }} + # summary: Postgres Exporter is down or is showing errors + # - alert: InstanceDown + # expr: pg_up == 0 + # for: 1m + # labels: + # service: PostgreSQL + # severity: critical + # annotations: + # description: Postgres server has not been responding for the past 1 minutes on {{ $labels.instance }} + # summary: Postgres server instance is down + # title: Postgres server instance {{ $labels.instance}} is down + # - alert: InactiveReplicationSlots + # expr: pg_replication_slots_active == 0 + # for: 30m + # labels: + # severity: warning + # service: PostgreSQL + # annotations: + # summary: There are inactive replications slots + # description: The are some inactive replication slots on {{$labels.instance}} in cluster {{$labels.cluster_name}} + # - alert: NotEnoughConnections + # expr: sum by (datname) (pg_stat_activity_count{datname!~"template.*|postgres"}) < 5 + # for: 5m + # labels: + # severity: warning + # annotations: + # summary: Postgresql not enough connections (instance {{ $labels.instance }} in cluster {{$labels.cluster_name}}) + # description: "PostgreSQL instance should have more connections (> 5)\n VALUE = {{ $value }}\n LABELS: {{ $labels }}" + # - alert: PromotedNode + # expr: pg_replication_is_replica and changes(pg_replication_is_replica[1m]) > 0 + # for: 5m + # labels: + # severity: warning + # annotations: + # summary: Postgresql promoted node (instance {{ $labels.instance }}, cluster {{ $labels.cluster_name }}) + # description: "Postgresql standby server has been promoted as primary node\n VALUE = {{ $value }}\n LABELS: {{ $labels }}" + # - alert: ReplicationLagSizeTooLarge + # expr: pg_replication_status_lag_size > 1e+09 + # for: 5m + # labels: + # service: PostgreSQL + # severity: critical + # annotations: + # summary: Postgres replication lag size is to large + # description: Replication lag size on server {{ $labels.instance }} ({{ $labels.application_name }}) is currently {{ $value }} behind the leader in cluster {{ $labels.cluster_name }} + # - alert: TooManyDeadTuples + # expr: ((pg_stat_user_tables_n_dead_tup > 1e+06) / (pg_stat_user_tables_n_live_tup + pg_stat_user_tables_n_dead_tup)) >= 0.05 + # for: 30m + # labels: + # service: PostgreSQL + # severity: warning + # annotations: + # description: The dead tuple ratio of {{ $labels.relname }} on database {{ $labels.datname }} is greater than 5% in cluster {{ $labels.cluster_name }} + # summary: PostgreSQL dead tuples is too large + # - alert: TooManyConnections + # expr: sum by (datname) (pg_stat_activity_count{datname!~"template.*|postgres"}) > pg_settings_max_connections * 0.9 + # for: 5m + # labels: + # severity: warning + # annotations: + # summary: Postgresql too many connections (instance {{ $labels.instance }} in cluster {{$labels.cluster_name}}) + # description: "PostgreSQL instance has too many connections\n VALUE = {{ $value }}\n LABELS: {{ $labels }}" + + ## Connection Pooling alerts + #### + + # - alert: BouncerAvgWaitTimeTooHigh + # expr: pgbouncer_show_stats_avg_wait_time > 1e+6 + # for: 5m + # labels: + # severity: warning + # annotations: + # description: "PgBouncer wait for a server connections is too high = {{ $value }}" + # summary: PgBouncer time spent by clients waiting for a connections is too high on {{ $labels.instance }} in cluster {{$labels.cluster_name}}) + # - alert: BouncerNotEnoughConnections + # expr: (sum by (database,instance) (pgbouncer_show_pools_cl_active{database!~"template.*|postgres|pgbouncer"}) + sum by (database, instance) (pgbouncer_show_pools_cl_waiting{database!~"template.*|postgres|pgbouncer"})) - on (database,instance) (pgbouncer_show_databases_pool_size{database!~"template.*|postgres|pgbouncer"}) > 0 + # for: 10m + # labels: + # severity: critical + # annotations: + # description: "PgBouncer is getting more connections than the pool size, extra connections = {{ $value }}" + # summary: PgBouncer pool size is not enough for the current connections on {{ $labels.instance }} in cluster {{$labels.cluster_name}}) + # - alert: BouncerPoolFillingUp + # expr: (sum by (database,instance) (pgbouncer_show_databases_pool_size{database!~"template.*|postgres|pgbouncer"}) - on (database,instance) pgbouncer_show_databases_current_connections) <= 15 + # for: 5m + # labels: + # severity: warning + # annotations: + # description: "PgBouncer pool is filling up, remaining connections = {{ $value }}" + # summary: PgBouncer pool is filling up on {{ $labels.instance }} in cluster {{$labels.cluster_name}}) + # - alert: BouncerQueryTimeTooHigh + # expr: pgbouncer_show_stats_avg_query_time > 5e+6 + # for: 5m + # labels: + # severity: warning + # annotations: + # description: "PgBouncer average query duration more than 5 seconds = {{ $value }}" + # summary: PgBouncer average query duration more than 5 seconds on {{ $labels.instance }} in cluster {{$labels.cluster_name}}) + # - alert: BouncerWaitingClients + # expr: pgbouncer_show_pools_cl_waiting > 0 + # for: 5m + # labels: + # severity: warning + # annotations: + # description: "PgBouncer instance has waiting clients\n VALUE = {{ $value }}\n LABELS: {{ $labels }}" + # summary: PgBouncer has waiting clients on instance {{ $labels.instance }} in cluster {{$labels.cluster_name}}) + +## @section Service +## @param services.http.enabled Enable the service. +## @param services.http.annotations Additional service annotations. +## @param services.http.externalIPs External IPs for the service. +## @param services.http.externalTrafficPolicy If `service.type` is `NodePort` or `LoadBalancer`, set this to `Local` to tell kube-proxy to only use node local endpoints for cluster external traffic. Furthermore, this enables source IP preservation. +## @param services.http.internalTrafficPolicy If `service.type` is `NodePort` or `LoadBalancer`, set this to `Local` to tell kube-proxy to only use node local endpoints for cluster internal traffic. +## @param services.http.ipFamilies IPFamilies is list of IP families (e.g. `IPv4`, `IPv6`) assigned to this service. This field is usually assigned automatically based on cluster configuration and only required for customization. +## @param services.http.labels Additional service labels. +## @param services.http.loadBalancerClass LoadBalancerClass is the class of the load balancer implementation this Service belongs to. Requires service from type `LoadBalancer`. +## @param services.http.loadBalancerIP LoadBalancer will get created with the IP specified in this field. Requires service from type `LoadBalancer`. +## @param services.http.loadBalancerSourceRanges Source range filter for LoadBalancer. Requires service from type `LoadBalancer`. +## @param services.http.port Port to forward the traffic to. +## @param services.http.sessionAffinity Supports `ClientIP` and `None`. Enable client IP based session affinity via `ClientIP`. +## @param services.http.sessionAffinityConfig Contains the configuration of the session affinity. +## @param services.http.type Kubernetes service type for the traffic. +services: + http: + enabled: true + annotations: {} + externalIPs: [] + externalTrafficPolicy: "Cluster" + internalTrafficPolicy: "Cluster" + ipFamilies: [] + labels: {} + loadBalancerClass: "" + loadBalancerIP: "" + loadBalancerSourceRanges: [] + port: 9187 + sessionAffinity: "None" + sessionAffinityConfig: {} + type: "ClusterIP" + +## @section ServiceAccount +serviceAccount: + ## @param serviceAccount.existing.enabled Use an existing service account instead of creating a new one. Assumes that the user has all the necessary kubernetes API authorizations. + ## @param serviceAccount.existing.serviceAccountName Name of the existing service account. + existing: + enabled: false + serviceAccountName: "" + + ## @param serviceAccount.new.annotations Additional service account annotations. + ## @param serviceAccount.new.labels Additional service account labels. + ## @param serviceAccount.new.automountServiceAccountToken Enable/disable auto mounting of the service account token. + ## @param serviceAccount.new.imagePullSecrets ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images in pods that reference this serviceAccount. + ## @param serviceAccount.new.secrets Secrets is the list of secrets allowed to be used by pods running using this ServiceAccount. + new: + annotations: {} + labels: {} + automountServiceAccountToken: true + imagePullSecrets: [] + # - name: "my-image-pull-secret" + secrets: [] + # - name: "my-secret" + # namespace: "my-namespace" + # fieldPath: "my-field"