This commit is contained in:
dvirlabs 2026-06-04 11:46:59 +03:00
parent 1de2ecee92
commit aa51c3f9ca
76 changed files with 19427 additions and 0 deletions

23
argocd-apps/nifi.yaml Normal file
View File

@ -0,0 +1,23 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: nifi
namespace: argocd
labels:
env: dev-tools
spec:
project: dev-tools
source:
repoURL: ssh://git@gitea-ssh.dev-tools.svc.cluster.local:2222/dvirlabs/dev-tools.git
targetRevision: HEAD
path: charts/nifi
helm:
valueFiles:
- ../../manifests/nifi/values.yaml
destination:
server: https://kubernetes.default.svc
namespace: dev-tools
syncPolicy:
automated:
prune: true
selfHeal: true

View File

@ -0,0 +1,364 @@
name: 🚀 Publish Helm Chart (Enhanced)
on:
push:
branches:
- main
paths:
- 'Chart.yaml'
- 'values.yaml'
- 'templates/**'
- 'examples/**'
pull_request:
branches:
- main
paths:
- 'Chart.yaml'
- 'values.yaml'
- 'templates/**'
- 'examples/**'
workflow_dispatch:
inputs:
version_bump:
description: 'Version bump type'
required: true
default: 'patch'
type: choice
options:
- patch
- minor
- major
force_publish:
description: 'Force publish even if version unchanged'
required: false
default: false
type: boolean
env:
CHART_PATH: .
REPO_URL: https://sakkiii.github.io/apache-nifi-helm
REGISTRY: ghcr.io
CHART_NAME: apache-nifi-helm
jobs:
# ==========================================
# VALIDATION & TESTING JOB
# ==========================================
# This job runs on both PRs and main branch pushes
# - On PRs: Only validates and tests (no publishing)
# - On main: Validates and provides outputs for publishing
validate:
name: 🔍 Validate & Test Chart
runs-on: ubuntu-22.04
outputs:
chart-version: ${{ steps.chart-info.outputs.version }}
app-version: ${{ steps.chart-info.outputs.app-version }}
version-changed: ${{ steps.version-check.outputs.changed }}
steps:
- name: 📥 Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for version comparison
- name: 🛠️ Set up Helm
uses: azure/setup-helm@v4.2.0
with:
version: '3.14.0' # Pin to specific version for reproducibility
- name: 📊 Extract Chart Information
id: chart-info
run: |
VERSION=$(yq eval '.version' Chart.yaml)
APP_VERSION=$(yq eval '.appVersion' Chart.yaml)
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "app-version=$APP_VERSION" >> $GITHUB_OUTPUT
echo "📋 Chart Version: $VERSION"
echo "📋 App Version: $APP_VERSION"
- name: 🔄 Check Version Changes
id: version-check
run: |
CURRENT_VERSION="${{ steps.chart-info.outputs.version }}"
# Check if this version already exists in releases
if git tag --list | grep -q "^v$CURRENT_VERSION$"; then
echo "changed=false" >> $GITHUB_OUTPUT
echo "⚠️ Version $CURRENT_VERSION already exists"
else
echo "changed=true" >> $GITHUB_OUTPUT
echo "✅ New version $CURRENT_VERSION detected"
fi
- name: 🔍 Lint Helm Chart
run: |
echo "🔍 Linting Helm chart..."
helm lint "${{ env.CHART_PATH }}"
- name: 📦 Update Dependencies
run: |
echo "📦 Updating Helm dependencies..."
helm dependency update "${{ env.CHART_PATH }}"
- name: 🧪 Template Validation
run: |
echo "🧪 Validating Helm templates..."
# Test with different value files if examples directory exists
if [ -d "examples" ]; then
for values_file in examples/values-*.yaml; do
if [ -f "$values_file" ]; then
echo "Testing with $values_file"
helm template test-release . -f "$values_file" --debug > /dev/null
fi
done
else
echo " Examples directory not found, skipping example value file tests"
fi
# Test default values
helm template test-release . --debug > /dev/null
echo "✅ All template validations passed"
- name: 🔒 Security Scan with Checkov
uses: bridgecrewio/checkov-action@master
with:
directory: .
framework: kubernetes
output_format: sarif
output_file_path: checkov-results.sarif
continue-on-error: true
- name: 📤 Upload Security Results
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: checkov-results.sarif
continue-on-error: true
- name: 🔍 Kubeconform Validation
run: |
echo "🔍 Installing kubeconform..."
curl -L https://github.com/yannh/kubeconform/releases/latest/download/kubeconform-linux-amd64.tar.gz | tar xz
sudo mv kubeconform /usr/local/bin
echo "🧪 Validating Kubernetes manifests..."
# Use -skip to skip custom resources that don't have schemas
# This prevents failures on cert-manager resources like Certificate and Issuer
# Also use -ignore-missing-schemas to be more permissive
helm template test-release . | kubeconform -skip Certificate,Issuer -ignore-missing-schemas -summary
echo "✅ Kubeconform validation completed (custom resources skipped)"
# ==========================================
# PUBLISH JOB (Only on main branch)
# ==========================================
# This job only runs on main branch pushes when:
# - Version has changed (new chart version)
# - Force publish is requested via workflow_dispatch
# PRs will NOT trigger this job (only validation)
publish:
name: 📦 Package & Publish Chart
runs-on: ubuntu-22.04
needs: validate
if: |
github.ref == 'refs/heads/main' &&
(needs.validate.outputs.version-changed == 'true' ||
github.event.inputs.force_publish == 'true')
permissions:
contents: write
pages: write
packages: write
id-token: write
steps:
- name: 📥 Checkout Repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: 🛠️ Set up Helm
uses: azure/setup-helm@v4.2.0
with:
version: '3.14.0'
- name: 🔑 Install Helm Plugins
run: |
helm plugin install https://github.com/chartmuseum/helm-push || true
helm plugin install https://github.com/helm/helm-2to3 || true
- name: 📦 Update Dependencies
run: |
helm dependency update "${{ env.CHART_PATH }}"
- name: 📦 Package Helm Chart
run: |
mkdir -p packaged-charts
helm package "${{ env.CHART_PATH }}" -d packaged-charts/
# List packaged files
ls -la packaged-charts/
- name: 🔐 Sign Chart (Optional)
if: env.GPG_PRIVATE_KEY != ''
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
echo "$GPG_PRIVATE_KEY" | gpg --import --batch --yes
for chart in packaged-charts/*.tgz; do
helm package --sign --key "Helm Chart Signing" --keyring ~/.gnupg/secring.gpg "$chart"
done
- name: 🐳 Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 📦 Push to GitHub Packages (OCI)
run: |
VERSION="${{ needs.validate.outputs.chart-version }}"
CHART_FILE=$(find packaged-charts/ -name "*.tgz" | head -1)
echo "📦 Pushing chart to GitHub Packages as OCI artifact..."
echo "🔗 Registry: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.CHART_NAME }}"
echo "🏷️ Version: $VERSION"
# Push chart as OCI artifact
helm push "$CHART_FILE" oci://${{ env.REGISTRY }}/${{ github.repository_owner }}
echo "✅ Successfully pushed to GitHub Packages!"
echo "📋 Install command:"
echo "helm install my-nifi oci://${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.CHART_NAME }} --version $VERSION"
- name: 📋 Generate Helm Index
run: |
helm repo index packaged-charts/ --url "${{ env.REPO_URL }}"
# Add metadata to index.yaml
cat >> packaged-charts/index.yaml << EOF
# Generated on: $(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Chart Version: ${{ needs.validate.outputs.chart-version }}
# App Version: ${{ needs.validate.outputs.app-version }}
# Commit: ${{ github.sha }}
# OCI Registry: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.CHART_NAME }}
EOF
- name: 🏷️ Create Git Tag
run: |
VERSION="${{ needs.validate.outputs.chart-version }}"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -a "v$VERSION" -m "Release version $VERSION"
git push origin "v$VERSION"
- name: 📝 Generate Release Notes
id: release-notes
run: |
VERSION="${{ needs.validate.outputs.chart-version }}"
APP_VERSION="${{ needs.validate.outputs.app-version }}"
cat > release-notes.md << EOF
# Apache NiFi Helm Chart v$VERSION
## 📋 Chart Information
- **Chart Version**: $VERSION
- **App Version**: $APP_VERSION (Apache NiFi)
- **Release Date**: $(date -u +"%Y-%m-%d")
## 🚀 Installation Options
### Option 1: GitHub Pages (Traditional Helm Repository)
\`\`\`bash
helm repo add apache-nifi-helm https://sakkiii.github.io/apache-nifi-helm
helm repo update
helm install my-nifi apache-nifi-helm/nifi --version $VERSION
\`\`\`
### Option 2: GitHub Packages (OCI Registry)
\`\`\`bash
helm install my-nifi oci://ghcr.io/sakkiii/apache-nifi-helm --version $VERSION
\`\`\`
## 🔐 Authentication Methods Supported
- ✅ **Basic Authentication** (Single User) - Default
- ✅ **OIDC Authentication** - Enterprise SSO
- ✅ **LDAP Authentication** - Directory Integration
## 📦 What's Included
- Multi-node clustering support
- Automatic TLS certificate management
- Persistent storage configuration
- Monitoring and metrics integration
- Production-ready security defaults
## 📚 Documentation
- [Chart README](https://github.com/sakkiii/apache-nifi-helm/blob/main/README.md)
- [Authentication Guide](https://github.com/sakkiii/apache-nifi-helm/blob/main/examples/)
- [Configuration Examples](https://github.com/sakkiii/apache-nifi-helm/tree/main/examples)
## 🔄 Upgrade Instructions
### From GitHub Pages Repository:
\`\`\`bash
helm upgrade my-nifi apache-nifi-helm/nifi --version $VERSION
\`\`\`
### From GitHub Packages (OCI):
\`\`\`bash
helm upgrade my-nifi oci://ghcr.io/sakkiii/apache-nifi-helm --version $VERSION
\`\`\`
---
**Full Changelog**: https://github.com/sakkiii/apache-nifi-helm/compare/v$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "0.0.0")...v$VERSION
EOF
- name: 🚀 Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: packaged-charts
publish_branch: gh-pages
user_name: "github-actions[bot]"
user_email: "github-actions[bot]@users.noreply.github.com"
commit_message: "📦 Publish chart version ${{ needs.validate.outputs.chart-version }}"
- name: 🎉 Create GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: "v${{ needs.validate.outputs.chart-version }}"
name: "Apache NiFi Helm Chart v${{ needs.validate.outputs.chart-version }}"
body_path: release-notes.md
files: |
packaged-charts/*.tgz
packaged-charts/*.tgz.prov
draft: false
prerelease: false
# ==========================================
# NOTIFICATION JOB
# ==========================================
notify:
name: 📢 Notify Success
runs-on: ubuntu-22.04
needs: [validate, publish]
if: always() && needs.publish.result == 'success'
steps:
- name: 🎉 Success Notification
run: |
echo "🎉 Successfully published Apache NiFi Helm Chart!"
echo "📦 Version: ${{ needs.validate.outputs.chart-version }}"
echo ""
echo "📍 Available from multiple sources:"
echo "🔗 GitHub Pages: https://sakkiii.github.io/apache-nifi-helm"
echo "📦 GitHub Packages: ghcr.io/${{ github.repository_owner }}/${{ env.CHART_NAME }}"
echo "📋 Release: https://github.com/sakkiii/apache-nifi-helm/releases/tag/v${{ needs.validate.outputs.chart-version }}"
echo ""
echo "📋 Installation commands:"
echo "helm repo add apache-nifi-helm https://sakkiii.github.io/apache-nifi-helm && helm install my-nifi apache-nifi-helm/nifi"
echo "helm install my-nifi oci://ghcr.io/${{ github.repository_owner }}/${{ env.CHART_NAME }}"

View File

@ -0,0 +1,74 @@
name: 🏷️ Version Bump
on:
workflow_dispatch:
inputs:
bump_type:
description: 'Version bump type'
required: true
default: 'patch'
type: choice
options:
- patch
- minor
- major
nifi_version:
description: 'NiFi version (optional)'
required: false
type: string
jobs:
bump-version:
name: 🏷️ Bump Version
runs-on: ubuntu-22.04
steps:
- name: 📥 Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: 🔧 Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: 📦 Install semver
run: npm install -g semver
- name: 🏷️ Bump Chart Version
id: bump
run: |
CURRENT_VERSION=$(yq eval '.version' Chart.yaml)
NEW_VERSION=$(semver -i ${{ github.event.inputs.bump_type }} $CURRENT_VERSION)
echo "current-version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
echo "new-version=$NEW_VERSION" >> $GITHUB_OUTPUT
# Update Chart.yaml
yq eval ".version = \"$NEW_VERSION\"" -i Chart.yaml
# Update NiFi version if provided
if [ -n "${{ github.event.inputs.nifi_version }}" ]; then
yq eval ".appVersion = \"${{ github.event.inputs.nifi_version }}\"" -i Chart.yaml
echo "nifi-version=${{ github.event.inputs.nifi_version }}" >> $GITHUB_OUTPUT
fi
- name: 📝 Commit Changes
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Chart.yaml
git commit -m "chore: bump version to ${{ steps.bump.outputs.new-version }}"
git push
- name: 📊 Summary
run: |
echo "## 🏷️ Version Bump Summary" >> $GITHUB_STEP_SUMMARY
echo "- **Previous Version**: ${{ steps.bump.outputs.current-version }}" >> $GITHUB_STEP_SUMMARY
echo "- **New Version**: ${{ steps.bump.outputs.new-version }}" >> $GITHUB_STEP_SUMMARY
if [ -n "${{ steps.bump.outputs.nifi-version }}" ]; then
echo "- **NiFi Version**: ${{ steps.bump.outputs.nifi-version }}" >> $GITHUB_STEP_SUMMARY
fi
echo "- **Bump Type**: ${{ github.event.inputs.bump_type }}" >> $GITHUB_STEP_SUMMARY

23
charts/nifi/.helmignore Normal file
View File

@ -0,0 +1,23 @@
# 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/

6
charts/nifi/Chart.lock Normal file
View File

@ -0,0 +1,6 @@
dependencies:
- name: zookeeper
repository: https://charts.bitnami.com/bitnami
version: 13.4.14
digest: sha256:bb25612769fe7a40262235b3a4393d5071b235f81056ab56e6862318114a8e0d
generated: "2025-09-04T04:05:44.385666856Z"

38
charts/nifi/Chart.yaml Normal file
View File

@ -0,0 +1,38 @@
annotations:
category: Analytics
images: |
- name: nifi
image: apache/nifi:1.28.1
- name: zookeeper
image: bitnami/zookeeper:3.9.2-debian-12-r7
licenses: Apache-2.0
apiVersion: v2
appVersion: 1.28.1
dependencies:
- condition: zookeeper.enabled
name: zookeeper
repository: https://charts.bitnami.com/bitnami
version: 13.4.14
description: Production-ready Apache NiFi Helm chart with enterprise authentication,
high availability, and advanced security features
home: https://github.com/sakkiii/apache-nifi-helm
keywords:
- nifi
- apache
- dataflow
- etl
- streaming
- data-processing
- enterprise
- authentication
- clustering
maintainers:
- email: saket@example.com
name: sakkiii
url: https://github.com/sakkiii
name: nifi
sources:
- https://github.com/sakkiii/apache-nifi-helm
- https://github.com/apache/nifi
type: application
version: 1.0.0

201
charts/nifi/LICENSE Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

827
charts/nifi/README.md Normal file
View File

@ -0,0 +1,827 @@
# Apache NiFi Helm Chart
[![Publish Helm Chart](https://github.com/sakkiii/apache-nifi-helm/actions/workflows/publish-chart.yml/badge.svg)](https://github.com/sakkiii/apache-nifi-helm/actions/workflows/publish-chart.yml)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Helm Version](https://img.shields.io/badge/Helm-v3+-green.svg)](https://helm.sh/)
[![Kubernetes Version](https://img.shields.io/badge/Kubernetes-v1.21+-blue.svg)](https://kubernetes.io/)
A production-ready Helm chart for deploying Apache NiFi on Kubernetes with enterprise-grade features including multiple authentication methods, high availability, monitoring, and advanced security configurations.
## ✨ Key Features
- 🔐 **Multiple Authentication Methods**: Basic Auth, LDAP, and OIDC with automatic fallback
- 🏗️ **High Availability**: Multi-node clustering with StatefulSets and Pod Disruption Budgets
- 🚀 **Smart State Management**: Kubernetes-native state management for NiFi 2.0+ with ZooKeeper fallback
- 🔒 **Enterprise Security**: TLS/SSL, cert-manager integration, and secure secret management
- 📊 **Monitoring & Observability**: Prometheus metrics, Grafana dashboards, and custom exporters
- 💾 **Flexible Storage**: Multiple persistent volume configurations for different repositories
- 🚀 **Production Ready**: Resource management, scaling, backup strategies, and upgrade support
- 🌐 **Advanced Networking**: Site-to-Site communication, ingress routing, and load balancing
## 📋 Table of Contents
- [Quick Start](#-quick-start)
- [Prerequisites](#-prerequisites)
- [Installation](#-installation)
- [State Management](#-state-management)
- [Authentication](#-authentication)
- [Configuration](#-configuration)
- [Advanced Configuration](#-advanced-configuration)
- [Storage Configuration](#-storage-configuration)
- [Monitoring & Observability](#-monitoring--observability)
- [Security](#-security)
- [Networking](#-networking)
- [Scaling & High Availability](#-scaling--high-availability)
- [Backup & Restore](#-backup--restore)
- [Troubleshooting](#-troubleshooting)
- [Contributing](#-contributing)
## 🚀 Quick Start
### Basic Deployment (Single Node)
```bash
# Add the Helm repository
helm repo add apache-nifi-helm https://sakkiii.github.io/apache-nifi-helm
helm repo update
# Install with default basic authentication
helm install my-nifi apache-nifi-helm/nifi
# Access NiFi (after port-forward)
kubectl port-forward svc/my-nifi-http 8443:8443
# Open https://localhost:8443/nifi
# Default credentials: admin / your32characterpasswordhere123
```
### Production Deployment (Multi-Node with OIDC)
```bash
# Install with OIDC authentication and 3 nodes
helm install my-nifi apache-nifi-helm/nifi \
--set global.nifi.nodeCount=3 \
--set global.oidc.enabled=true \
--set global.oidc.oidc_url="https://your-oidc-provider/.well-known/openid-configuration" \
--set global.oidc.client_id="nifi-client" \
--set global.oidc.client_secret="your-secret" \
--set global.oidc.initial_admin_identity="admin@company.com" \
--set ingress.enabled=true \
--set ingress.hostName="nifi.company.com"
```
## 📦 Prerequisites
- **Helm**: 3.x or higher
- **Kubernetes**: 1.21+ with RBAC enabled
- **Storage**: Persistent storage provisioner (e.g., AWS EBS, Azure Disk, GCP PD)
- **Cert-manager**: For automatic TLS certificate management (recommended)
- **Ingress Controller**: For external access (e.g., NGINX, AWS ALB, Traefik)
### Optional Dependencies
- **Prometheus**: For metrics collection
- **Grafana**: For visualization dashboards
- **External DNS**: For automatic DNS management
## 📥 Installation
### 1. Add Helm Repository
```bash
helm repo add apache-nifi-helm https://sakkiii.github.io/apache-nifi-helm
helm repo update
```
### 2. Create Namespace (Optional)
```bash
kubectl create namespace nifi
```
### 3. Install Chart
```bash
# Basic installation
helm install my-nifi apache-nifi-helm/nifi -n nifi
# With custom values file
helm install my-nifi apache-nifi-helm/nifi -f my-values.yaml -n nifi
# With inline overrides
helm install my-nifi apache-nifi-helm/nifi \
--set global.nifi.nodeCount=3 \
--set ingress.enabled=true \
--set ingress.hostName="nifi.example.com" \
-n nifi
```
### 4. Upgrade
```bash
helm upgrade my-nifi apache-nifi-helm/nifi -f my-values.yaml -n nifi
```
### 5. Uninstall
```bash
helm uninstall my-nifi -n nifi
```
## 🚀 State Management
This chart supports **both ZooKeeper and Kubernetes-native state management** with automatic version detection and backward compatibility.
### 📋 **Available Strategies**
| Strategy | NiFi Version | Description |
|----------|--------------|-------------|
| `auto` | All | **Recommended** - Automatically choose based on NiFi version |
| `kubernetes` | 2.0+ | Native Kubernetes state management (ConfigMaps + Leases) |
| `zookeeper` | All | Traditional ZooKeeper-based clustering |
### 🎯 **Quick Configuration**
```yaml
# values.yaml - Automatic strategy (recommended)
stateManagement:
strategy: "auto" # Kubernetes for NiFi 2.0+, ZooKeeper for older versions
```
```yaml
# values.yaml - Force Kubernetes state management (NiFi 2.0+)
stateManagement:
strategy: "kubernetes"
kubernetes:
leasePrefix: "nifi-lease"
statePrefix: "nifi-state"
# Note: Always uses release namespace
```
```yaml
# values.yaml - Force ZooKeeper state management
stateManagement:
strategy: "zookeeper"
zookeeper:
enabled: true
replicaCount: 3
```
### 📚 **Detailed Documentation**
For comprehensive state management documentation, examples, and migration guides, see:
**[📖 Kubernetes State Management Guide](./KUBERNETES_STATE_MANAGEMENT.md)**
## 🔐 Authentication
The chart supports **three authentication methods** with automatic priority-based selection:
### Priority Order
1. **OIDC** (highest priority) - if `global.oidc.enabled: true`
2. **LDAP** (second priority) - if OIDC disabled and `global.ldap.enabled: true`
3. **Basic Auth** (default fallback) - if both OIDC and LDAP disabled
### Basic Authentication (Default)
**Automatically enabled** when no other authentication method is configured.
```yaml
global:
nifi:
nodeCount: 1 # Basic auth only supports single-node
basic:
admin_username: "admin"
admin_password: "your32characterpasswordhere123" # Min 12 chars
```
**⚠️ Important**: Basic authentication only supports single-node deployment (`nodeCount: 1`).
### OIDC Authentication (Recommended for Production)
```yaml
global:
nifi:
nodeCount: 3 # Clustering supported
oidc:
enabled: true
oidc_url: "https://auth.company.com/.well-known/openid-configuration"
client_id: "nifi-client"
client_secret: "your-client-secret"
claim_identifying_user: "preferred_username"
initial_admin_identity: "admin@company.com"
```
### LDAP Authentication
```yaml
global:
nifi:
nodeCount: 3 # Clustering supported
ldap:
enabled: true
url: "ldaps://ldap.company.com:636"
tlsProtocol: "TLSv1.2"
authenticationStrategy: "LDAPS"
identityStrategy: "USE_USERNAME"
initialAdminIdentity: "CN=NiFi Admin,OU=Users,DC=company,DC=com"
manager:
distinguishedName: "CN=Service Account,OU=Services,DC=company,DC=com"
passwordSecretRef:
name: "ldap-manager-secret"
key: "password"
userSearchBase: "OU=Users,DC=company,DC=com"
userSearchFilter: "sAMAccountName={0}"
```
### Authentication Examples
See the [`examples/`](examples/) directory for complete configuration files:
- [`examples/values-auth-basic.yaml`](examples/values-auth-basic.yaml) - Basic authentication
- [`examples/values-auth-oidc.yaml`](examples/values-auth-oidc.yaml) - OIDC authentication
- [`examples/values-auth-ldap.yaml`](examples/values-auth-ldap.yaml) - LDAP authentication
## ⚙️ Configuration
### Core Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `global.nifi.nodeCount` | Number of NiFi nodes (1 for basic auth, 1+ for OIDC/LDAP) | `1` |
| `image.repository` | NiFi Docker image repository | `apache/nifi` |
| `image.tag` | NiFi Docker image tag | `""` (uses appVersion) |
| `ingress.enabled` | Enable ingress for external access | `true` |
| `ingress.hostName` | Hostname for NiFi web interface | `example.com` |
| `zookeeper.enabled` | Enable embedded Zookeeper (required for clustering) | `true` |
### Authentication Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `global.basic.admin_username` | Basic auth admin username | `admin` |
| `global.basic.admin_password` | Basic auth admin password (min 12 chars) | `your32characterpasswordhere123` |
| `global.oidc.enabled` | Enable OIDC authentication | `false` |
| `global.oidc.oidc_url` | OIDC discovery URL | `""` |
| `global.oidc.client_id` | OIDC client ID | `""` |
| `global.oidc.client_secret` | OIDC client secret | `""` |
| `global.ldap.enabled` | Enable LDAP authentication | `false` |
| `global.ldap.url` | LDAP server URL | `""` |
### Resource Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `resources.requests.cpu` | CPU request per pod | `500m` |
| `resources.requests.memory` | Memory request per pod | `2Gi` |
| `jvmHeap.min` | JVM minimum heap size | `512m` |
| `jvmHeap.max` | JVM maximum heap size | `1g` |
### Storage Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `volumeClaims.config.size` | Configuration volume size | `5Gi` |
| `volumeClaims.state.size` | State volume size | `10Gi` |
| `volumeClaims.content.size` | Content repository size | `15Gi` |
| `volumeClaims.provenance.size` | Provenance repository size | `10Gi` |
| `volumeClaims.flowfile.size` | FlowFile repository size | `10Gi` |
## 🔧 Advanced Configuration
### Multi-Environment Setup
#### Development Environment
```yaml
# values-dev.yaml
global:
nifi:
nodeCount: 1
basic:
admin_username: "admin"
admin_password: "devpassword123"
resources:
requests:
cpu: 200m
memory: 1Gi
jvmHeap:
min: 256m
max: 512m
volumeClaims:
config:
size: 1Gi
state:
size: 2Gi
content:
size: 5Gi
```
#### Production Environment
```yaml
# values-prod.yaml
global:
nifi:
nodeCount: 3
oidc:
enabled: true
oidc_url: "https://auth.company.com/.well-known/openid-configuration"
client_id: "nifi-prod"
client_secret: "prod-secret"
initial_admin_identity: "nifi-admin@company.com"
resources:
requests:
cpu: 2
memory: 8Gi
limits:
cpu: 4
memory: 16Gi
jvmHeap:
min: 4g
max: 6g
pdb:
enabled: true
maxUnavailable: 1
metrics:
serviceMonitor:
enabled: true
interval: 30s
nifiMonitor:
enabled: true
replicas: 2
```
### Custom NiFi Properties
```yaml
extraConfig:
nifiProperties:
nifi.cluster.node.connection.timeout: "10 secs"
nifi.cluster.node.read.timeout: "10 secs"
nifi.web.request.timeout: "60 secs"
nifi.administrative.yield.duration: "30 sec"
```
### External Zookeeper
```yaml
zookeeper:
enabled: false
url: "zk-cluster.company.com"
port: 2181
rootNode: "/nifi"
```
### Custom Storage Classes
```yaml
volumeClaims:
config:
storageClass: "fast-ssd"
size: "10Gi"
content:
storageClass: "bulk-storage"
size: "100Gi"
provenance:
storageClass: "archive-storage"
size: "500Gi"
```
## 💾 Storage Configuration
### Storage Architecture
NiFi uses multiple repositories for different types of data:
- **Config**: Configuration files and user settings
- **State**: Component state and cluster coordination
- **FlowFile**: Active data flow metadata
- **Content**: Actual data content
- **Provenance**: Data lineage and audit information
- **Logs**: Application and audit logs
### Storage Classes
```yaml
volumeClaims:
config:
storageClass: "gp3" # Fast access for configs
size: "5Gi"
state:
storageClass: "gp3" # Fast access for state
size: "10Gi"
flowfile:
storageClass: "gp3" # Fast access for active flows
size: "20Gi"
content:
storageClass: "gp3" # Balanced performance/cost
size: "100Gi"
provenance:
storageClass: "sc1" # Cold storage for archives
size: "500Gi"
logs:
storageClass: "gp3"
size: "10Gi"
```
### Backup Strategy
```yaml
# Enable log persistence for backup
persistence:
logs:
volumeMount:
name: "logs"
subPath: "nifi-logs"
# Custom backup paths
extraTakeOwnershipPaths:
- "/backup/flows"
- "/backup/templates"
extraVolumeMounts:
- mountPath: /backup
name: backup-volume
extraVolumes:
- name: backup-volume
persistentVolumeClaim:
claimName: nifi-backup-pvc
```
## 📊 Monitoring & Observability
### Prometheus Integration
```yaml
metrics:
serviceMonitor:
enabled: true
interval: 30s
scrapeTimeout: 10s
labels:
monitoring: "prometheus"
nifiMonitor:
enabled: true
image:
repository: ghcr.io/sakkiii/nifi_exporter
tag: latest
replicas: 2
resources:
requests:
cpu: 50m
memory: 128Mi
```
### Custom Metrics Ingress
```yaml
metrics:
ingress:
enabled: true
https: true
basePath: /metrics
requireClientCertificate: true
```
### Grafana Dashboards
The chart includes pre-built Grafana dashboards in the [`grafana/`](grafana/) directory:
- `nifi-cluster-health.json` - Cluster health and performance
- `zookeeper.json` - Zookeeper metrics and coordination
### Log Management
```yaml
logging:
levels:
org.apache.nifi.web.security: ERROR
org.apache.nifi.processors: WARN
org.apache.nifi.processors.standard.LogAttribute: WARN
totalSizeCap:
APP_FILE: 10GB
USER_FILE: 5GB
# Optional: Filebeat sidecar for log shipping
filebeat:
enabled: true
image:
repository: docker.elastic.co/beats/filebeat
tag: "8.8.0"
output:
type: elasticsearch
parameters:
hosts: ["elasticsearch.logging.svc.cluster.local:9200"]
index: "nifi-logs-%{+yyyy.MM.dd}"
```
## 🔒 Security
### TLS/SSL Configuration
```yaml
global:
tls:
certificate:
duration: 8760h # 1 year
renewBefore: 168h # 1 week
keystorePasswordSecretRef:
name: "nifi-keystore-password"
key: "password"
# Additional subject alternative names
tls:
subjectAltNames:
- "nifi.internal"
- "*.nifi.company.com"
```
### Secret Management
```yaml
global:
encryption:
sensitivePropertiesKey:
secretRef:
name: "nifi-sensitive-key" # Auto-generated if not exists
key: "sensitivekey"
# Repository encryption (optional)
encryption:
repository:
enabled: true
keyId: 1
secretRef:
name: "nifi-repo-encryption"
key: "repository.p12"
```
### Security Context
```yaml
securityContext:
runAsUser: 1000
runAsGroup: 1000
runAsNonRoot: true
# Custom umask
umask: "0002"
```
## 🌐 Networking
### Ingress Configuration
```yaml
ingress:
enabled: true
ingressClassName: "nginx" # or "alb", "traefik"
hostName: "nifi.company.com"
siteToSite:
subDomain: "s2s" # Creates s2s.company.com
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
```
### AWS Application Load Balancer
```yaml
ingress:
enabled: true
ingressClassName: "alb"
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/backend-protocol: HTTPS
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
alb.ingress.kubernetes.io/certificate-arn: "arn:aws:acm:region:account:certificate/cert-id"
```
### Site-to-Site Communication
```yaml
# Automatic configuration for S2S routing
# - Cluster-local communication via service
# - External communication via ingress
# - Proper hostname resolution and port mapping
```
### Extra Ports and Services
```yaml
extraPorts:
datafeed:
containerPort: 9443
protocol: TCP
nodePort: 30443 # For NodePort service
loadBalancerPort: 9443 # For LoadBalancer service
ingress:
path: /datafeed
pathType: Exact
service:
external:
type: LoadBalancer
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
```
## 📈 Scaling & High Availability
### Horizontal Scaling
```yaml
global:
nifi:
nodeCount: 5 # Scale to 5 nodes
# Pod Disruption Budget
pdb:
enabled: true
maxUnavailable: 1 # Allow only 1 pod down during disruptions
```
### Resource Scaling
```yaml
resources:
requests:
cpu: 2
memory: 8Gi
limits:
cpu: 4
memory: 16Gi
jvmHeap:
min: 4g
max: 6g
```
### Anti-Affinity Rules
```yaml
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- nifi
topologyKey: kubernetes.io/hostname
```
### Topology Spread Constraints
```yaml
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app.kubernetes.io/name: nifi
```
## 💾 Backup & Restore
### Automated Backup Strategy
```yaml
# 1. Use storage provider snapshots
# Example for AWS EBS
volumeClaims:
config:
storageClass: "gp3"
annotations:
volume.beta.kubernetes.io/storage-class: "gp3"
# Add backup annotations for automated snapshots
# 2. NiFi Registry integration
extraConfig:
nifiProperties:
nifi.registry.url: "https://nifi-registry.company.com"
nifi.registry.bucket.default: "production-flows"
```
### Manual Backup Process
```bash
# 1. Create consistent snapshot
kubectl exec -it nifi-0 -- /opt/nifi/nifi-current/bin/nifi.sh stop
# 2. Backup persistent volumes
kubectl get pvc -l app.kubernetes.io/name=nifi
# 3. Export flow definitions
kubectl exec -it nifi-0 -- curl -k https://localhost:8443/nifi-api/flow/download
# 4. Restart NiFi
kubectl exec -it nifi-0 -- /opt/nifi/nifi-current/bin/nifi.sh start
```
### Disaster Recovery
```yaml
# Multi-region deployment
global:
nifi:
nodeCount: 3
# Cross-region replication
extraConfig:
nifiProperties:
nifi.remote.input.host: "nifi-dr.company.com"
nifi.remote.input.port: "10443"
nifi.remote.input.secure: "true"
```
## 🔍 Troubleshooting
### Common Issues
#### 1. Authentication Problems
```bash
# Check authentication configuration
kubectl logs nifi-0 | grep -i auth
# Verify secrets exist
kubectl get secrets | grep nifi
# Check OIDC/LDAP connectivity
kubectl exec -it nifi-0 -- curl -k https://auth.company.com/.well-known/openid-configuration
```
#### 2. Clustering Issues
```bash
# Check Zookeeper connectivity
kubectl exec -it nifi-0 -- nc -zv nifi-zookeeper 2181
# Verify cluster status
kubectl exec -it nifi-0 -- curl -k https://localhost:8443/nifi-api/controller/cluster
# Check node communication
kubectl logs nifi-0 | grep -i cluster
```
#### 3. Storage Issues
```bash
# Check PVC status
kubectl get pvc -l app.kubernetes.io/name=nifi
# Verify permissions
kubectl exec -it nifi-0 -- ls -la /opt/nifi/nifi-current/
# Check disk space
kubectl exec -it nifi-0 -- df -h
```
#### 4. Performance Issues
```bash
# Check resource usage
kubectl top pods -l app.kubernetes.io/name=nifi
# Monitor JVM metrics
kubectl exec -it nifi-0 -- jstat -gc $(pgrep java)
# Check NiFi system diagnostics
kubectl exec -it nifi-0 -- curl -k https://localhost:8443/nifi-api/system-diagnostics
```
### Debug Mode
```yaml
# Enable debug startup
debugStartup: true
# Increase log levels
logging:
levels:
org.apache.nifi: DEBUG
org.apache.nifi.web.security: DEBUG
```
### Health Checks
```bash
# Check pod readiness
kubectl get pods -l app.kubernetes.io/name=nifi
# Test NiFi API
kubectl exec -it nifi-0 -- curl -k https://localhost:8443/nifi-api/system-diagnostics
# Verify ingress
curl -k https://nifi.company.com/nifi-api/system-diagnostics
```
## 🤝 Contributing
We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details.
### Development Setup
```bash
# Clone the repository
git clone https://github.com/sakkiii/apache-nifi-helm.git
cd apache-nifi-helm
# Test the chart
helm lint .
helm template test-release . -f examples/values-auth-oidc.yaml
# Run tests
helm test my-nifi
```
### Reporting Issues
Please use [GitHub Issues](https://github.com/sakkiii/apache-nifi-helm/issues) to report bugs or request features. Include:
- Chart version
- Helm version
- Kubernetes version
- Values file (sanitized)
- Error logs
## 📄 License
This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
## 🙏 Acknowledgments
- [Apache NiFi](https://nifi.apache.org/) community
- [Kubernetes](https://kubernetes.io/) project
- [Helm](https://helm.sh/) maintainers
- All [contributors](https://github.com/sakkiii/apache-nifi-helm/graphs/contributors)
---
**⭐ If this chart helped you, please consider giving it a star on GitHub!**

View File

@ -0,0 +1,25 @@
# 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
*~
# Various IDEs
.project
.idea/
*.tmproj
# img folder
img/
# Changelog
CHANGELOG.md

View File

@ -0,0 +1,6 @@
dependencies:
- name: common
repository: oci://registry-1.docker.io/bitnamicharts
version: 2.22.0
digest: sha256:a8fb2fc887ead658a89598a48acde5324196fbc0509503a3eaed50a710fbfe74
generated: "2024-08-30T16:58:39.028289094Z"

View File

@ -0,0 +1,29 @@
annotations:
category: Infrastructure
images: |
- name: os-shell
image: docker.io/bitnami/os-shell:12-debian-12-r28
- name: zookeeper
image: docker.io/bitnami/zookeeper:3.9.2-debian-12-r12
licenses: Apache-2.0
apiVersion: v2
appVersion: 3.9.2
dependencies:
- name: common
repository: oci://registry-1.docker.io/bitnamicharts
tags:
- bitnami-common
version: 2.x.x
description: Apache ZooKeeper provides a reliable, centralized register of configuration
data and services for distributed applications.
home: https://bitnami.com
icon: https://bitnami.com/assets/stacks/zookeeper/img/zookeeper-stack-220x234.png
keywords:
- zookeeper
maintainers:
- name: Broadcom, Inc. All Rights Reserved.
url: https://github.com/bitnami/charts
name: zookeeper
sources:
- https://github.com/bitnami/charts/tree/main/bitnami/zookeeper
version: 13.4.14

View File

@ -0,0 +1,558 @@
<!--- app-name: Apache ZooKeeper -->
# Bitnami package for Apache ZooKeeper
Apache ZooKeeper provides a reliable, centralized register of configuration data and services for distributed applications.
[Overview of Apache ZooKeeper](https://zookeeper.apache.org)
Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement.
## TL;DR
```console
helm install my-release oci://registry-1.docker.io/bitnamicharts/zookeeper
```
Looking to use Apache ZooKeeper in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog.
## Introduction
This chart bootstraps a [ZooKeeper](https://github.com/bitnami/containers/tree/main/bitnami/zookeeper) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters.
## Prerequisites
- Kubernetes 1.23+
- Helm 3.8.0+
- PV provisioner support in the underlying infrastructure
## Installing the Chart
To install the chart with the release name `my-release`:
```console
helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/zookeeper
```
> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`.
These commands deploy ZooKeeper on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation.
> **Tip**: List all releases using `helm list`
## Configuration and installation details
### Resource requests and limits
Bitnami charts allow setting resource requests and limits for all containers inside the chart deployment. These are inside the `resources` value (check parameter table). Setting requests is essential for production workloads and these should be adapted to your specific use case.
To make this process easier, the chart contains the `resourcesPreset` values, which automatically sets the `resources` section according to different presets. Check these presets in [the bitnami/common chart](https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15). However, in production workloads using `resourcePreset` is discouraged as it may not fully adapt to your specific needs. Find more information on container resource management in the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/).
### [Rolling vs Immutable tags](https://docs.vmware.com/en/VMware-Tanzu-Application-Catalog/services/tutorials/GUID-understand-rolling-tags-containers-index.html)
It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image.
Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist.
### Configure log level
You can configure the ZooKeeper log level using the `ZOO_LOG_LEVEL` environment variable or the parameter `logLevel`. By default, it is set to `ERROR` because each use of the liveness probe and the readiness probe produces an `INFO` message on connection and a `WARN` message on disconnection, generating a high volume of noise in your logs.
In order to remove that log noise so levels can be set to 'INFO', two changes must be made.
First, ensure that you are not getting metrics via the deprecated pattern of polling 'mntr' on the ZooKeeper client port. The preferred method of polling for Apache ZooKeeper metrics is the ZooKeeper metrics server. This is supported in this chart when setting `metrics.enabled` to `true`.
Second, to avoid the connection/disconnection messages from the probes, you can set custom values for these checks which direct them to the ZooKeeper Admin Server instead of the client port. By default, an Admin Server will be started that listens on `localhost` at port `8080`. The following is an example of this use of the Admin Server for probes:
```yaml
livenessProbe:
enabled: false
readinessProbe:
enabled: false
customLivenessProbe:
exec:
command: ['/bin/bash', '-c', 'curl -s -m 2 http://localhost:8080/commands/ruok | grep ruok']
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 6
customReadinessProbe:
exec:
command: ['/bin/bash', '-c', 'curl -s -m 2 http://localhost:8080/commands/ruok | grep error | grep null']
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 6
```
You can also set the log4j logging level and what log appenders are turned on, by using `ZOO_LOG4J_PROP` set inside of conf/log4j.properties as zookeeper.root.logger by default to
```console
zookeeper.root.logger=INFO, CONSOLE
```
the available appender is
- CONSOLE
- ROLLINGFILE
- RFAAUDIT
- TRACEFILE
## Persistence
The [Bitnami ZooKeeper](https://github.com/bitnami/containers/tree/main/bitnami/zookeeper) image stores the ZooKeeper data and configurations at the `/bitnami/zookeeper` path of the container.
Persistent Volume Claims are used to keep the data across deployments. This is known to work in GCE, AWS, and minikube. See the [Parameters](#parameters) section to configure the PVC or to disable persistence.
If you encounter errors when working with persistent volumes, refer to our [troubleshooting guide for persistent volumes](https://docs.bitnami.com/kubernetes/faq/troubleshooting/troubleshooting-persistence-volumes/).
### Adjust permissions of persistent volume mountpoint
As the image run as non-root by default, it is necessary to adjust the ownership of the persistent volume so that the container can write data into it.
By default, the chart is configured to use Kubernetes Security Context to automatically change the ownership of the volume. However, this feature does not work in all Kubernetes distributions.
As an alternative, this chart supports using an initContainer to change the ownership of the volume before mounting it in the final destination.
You can enable this initContainer by setting `volumePermissions.enabled` to `true`.
### Configure the data log directory
You can use a dedicated device for logs (instead of using the data directory) to help avoiding competition between logging and snaphots. To do so, set the `dataLogDir` parameter with the path to be used for writing transaction logs. Alternatively, set this parameter with an empty string and it will result in the log being written to the data directory (Zookeeper's default behavior).
When using a dedicated device for logs, you can use a PVC to persist the logs. To do so, set `persistence.enabled` to `true`. See the [Persistence Parameters](#persistence-parameters) section for more information.
### Set pod affinity
This chart allows you to set custom pod affinity using the `affinity` parameter. Find more information about pod affinity in the [Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity).
As an alternative, you can use any of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `podAffinityPreset`, `podAntiAffinityPreset`, or `nodeAffinityPreset` parameters.
## Parameters
### Global parameters
| Name | Description | Value |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| `global.imageRegistry` | Global Docker image registry | `""` |
| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` |
| `global.defaultStorageClass` | Global default StorageClass for Persistent Volume(s) | `""` |
| `global.storageClass` | DEPRECATED: use global.defaultStorageClass instead | `""` |
| `global.compatibility.openshift.adaptSecurityContext` | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) | `auto` |
### Common parameters
| Name | Description | Value |
| ------------------------ | -------------------------------------------------------------------------------------------- | --------------- |
| `kubeVersion` | Override Kubernetes version | `""` |
| `nameOverride` | String to partially override common.names.fullname template (will maintain the release name) | `""` |
| `fullnameOverride` | String to fully override common.names.fullname template | `""` |
| `clusterDomain` | Kubernetes Cluster Domain | `cluster.local` |
| `extraDeploy` | Extra objects to deploy (evaluated as a template) | `[]` |
| `commonLabels` | Add labels to all the deployed resources | `{}` |
| `commonAnnotations` | Add annotations to all the deployed resources | `{}` |
| `namespaceOverride` | Override namespace for ZooKeeper resources | `""` |
| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` |
| `diagnosticMode.command` | Command to override all containers in the statefulset | `["sleep"]` |
| `diagnosticMode.args` | Args to override all containers in the statefulset | `["infinity"]` |
### ZooKeeper chart parameters
| Name | Description | Value |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------- | --------------------------- |
| `image.registry` | ZooKeeper image registry | `REGISTRY_NAME` |
| `image.repository` | ZooKeeper image repository | `REPOSITORY_NAME/zookeeper` |
| `image.digest` | ZooKeeper image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` |
| `image.pullPolicy` | ZooKeeper image pull policy | `IfNotPresent` |
| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` |
| `image.debug` | Specify if debug values should be set | `false` |
| `auth.client.enabled` | Enable ZooKeeper client-server authentication. It uses SASL/Digest-MD5 | `false` |
| `auth.client.clientUser` | User that will use ZooKeeper clients to auth | `""` |
| `auth.client.clientPassword` | Password that will use ZooKeeper clients to auth | `""` |
| `auth.client.serverUsers` | Comma, semicolon or whitespace separated list of user to be created | `""` |
| `auth.client.serverPasswords` | Comma, semicolon or whitespace separated list of passwords to assign to users when created | `""` |
| `auth.client.existingSecret` | Use existing secret (ignores previous passwords) | `""` |
| `auth.quorum.enabled` | Enable ZooKeeper server-server authentication. It uses SASL/Digest-MD5 | `false` |
| `auth.quorum.learnerUser` | User that the ZooKeeper quorumLearner will use to authenticate to quorumServers. | `""` |
| `auth.quorum.learnerPassword` | Password that the ZooKeeper quorumLearner will use to authenticate to quorumServers. | `""` |
| `auth.quorum.serverUsers` | Comma, semicolon or whitespace separated list of users for the quorumServers. | `""` |
| `auth.quorum.serverPasswords` | Comma, semicolon or whitespace separated list of passwords to assign to users when created | `""` |
| `auth.quorum.existingSecret` | Use existing secret (ignores previous passwords) | `""` |
| `tickTime` | Basic time unit (in milliseconds) used by ZooKeeper for heartbeats | `2000` |
| `initLimit` | ZooKeeper uses to limit the length of time the ZooKeeper servers in quorum have to connect to a leader | `10` |
| `syncLimit` | How far out of date a server can be from a leader | `5` |
| `preAllocSize` | Block size for transaction log file | `65536` |
| `snapCount` | The number of transactions recorded in the transaction log before a snapshot can be taken (and the transaction log rolled) | `100000` |
| `maxClientCnxns` | Limits the number of concurrent connections that a single client may make to a single member of the ZooKeeper ensemble | `60` |
| `maxSessionTimeout` | Maximum session timeout (in milliseconds) that the server will allow the client to negotiate | `40000` |
| `heapSize` | Size (in MB) for the Java Heap options (Xmx and Xms) | `1024` |
| `fourlwCommandsWhitelist` | A list of comma separated Four Letter Words commands that can be executed | `srvr, mntr, ruok` |
| `minServerId` | Minimal SERVER_ID value, nodes increment their IDs respectively | `1` |
| `listenOnAllIPs` | Allow ZooKeeper to listen for connections from its peers on all available IP addresses | `false` |
| `autopurge.snapRetainCount` | The most recent snapshots amount (and corresponding transaction logs) to retain | `10` |
| `autopurge.purgeInterval` | The time interval (in hours) for which the purge task has to be triggered | `1` |
| `logLevel` | Log level for the ZooKeeper server. ERROR by default | `ERROR` |
| `jvmFlags` | Default JVM flags for the ZooKeeper process | `""` |
| `dataLogDir` | Dedicated data log directory | `""` |
| `configuration` | Configure ZooKeeper with a custom zoo.cfg file | `""` |
| `existingConfigmap` | The name of an existing ConfigMap with your custom configuration for ZooKeeper | `""` |
| `extraEnvVars` | Array with extra environment variables to add to ZooKeeper nodes | `[]` |
| `extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for ZooKeeper nodes | `""` |
| `extraEnvVarsSecret` | Name of existing Secret containing extra env vars for ZooKeeper nodes | `""` |
| `command` | Override default container command (useful when using custom images) | `["/scripts/setup.sh"]` |
| `args` | Override default container args (useful when using custom images) | `[]` |
### Statefulset parameters
| Name | Description | Value |
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
| `replicaCount` | Number of ZooKeeper nodes | `1` |
| `revisionHistoryLimit` | The number of old history to retain to allow rollback | `10` |
| `containerPorts.client` | ZooKeeper client container port | `2181` |
| `containerPorts.tls` | ZooKeeper TLS container port | `3181` |
| `containerPorts.follower` | ZooKeeper follower container port | `2888` |
| `containerPorts.election` | ZooKeeper election container port | `3888` |
| `containerPorts.adminServer` | ZooKeeper admin server container port | `8080` |
| `containerPorts.metrics` | ZooKeeper Prometheus Exporter container port | `9141` |
| `livenessProbe.enabled` | Enable livenessProbe on ZooKeeper containers | `true` |
| `livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` |
| `livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` |
| `livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` |
| `livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` |
| `livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` |
| `livenessProbe.probeCommandTimeout` | Probe command timeout for livenessProbe | `3` |
| `readinessProbe.enabled` | Enable readinessProbe on ZooKeeper containers | `true` |
| `readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` |
| `readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` |
| `readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` |
| `readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` |
| `readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` |
| `readinessProbe.probeCommandTimeout` | Probe command timeout for readinessProbe | `2` |
| `startupProbe.enabled` | Enable startupProbe on ZooKeeper containers | `false` |
| `startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `30` |
| `startupProbe.periodSeconds` | Period seconds for startupProbe | `10` |
| `startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `1` |
| `startupProbe.failureThreshold` | Failure threshold for startupProbe | `15` |
| `startupProbe.successThreshold` | Success threshold for startupProbe | `1` |
| `customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` |
| `customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` |
| `customStartupProbe` | Custom startupProbe that overrides the default one | `{}` |
| `lifecycleHooks` | for the ZooKeeper container(s) to automate configuration before or after startup | `{}` |
| `resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` |
| `resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` |
| `podSecurityContext.enabled` | Enabled ZooKeeper pods' Security Context | `true` |
| `podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` |
| `podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` |
| `podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` |
| `podSecurityContext.fsGroup` | Set ZooKeeper pod's Security Context fsGroup | `1001` |
| `containerSecurityContext.enabled` | Enabled containers' Security Context | `true` |
| `containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` |
| `containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` |
| `containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` |
| `containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` |
| `containerSecurityContext.privileged` | Set container's Security Context privileged | `false` |
| `containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` |
| `containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` |
| `containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` |
| `containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` |
| `automountServiceAccountToken` | Mount Service Account token in pod | `false` |
| `hostAliases` | ZooKeeper pods host aliases | `[]` |
| `podLabels` | Extra labels for ZooKeeper pods | `{}` |
| `podAnnotations` | Annotations for ZooKeeper pods | `{}` |
| `podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` |
| `podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` |
| `nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` |
| `nodeAffinityPreset.key` | Node label key to match Ignored if `affinity` is set. | `""` |
| `nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set. | `[]` |
| `affinity` | Affinity for pod assignment | `{}` |
| `nodeSelector` | Node labels for pod assignment | `{}` |
| `tolerations` | Tolerations for pod assignment | `[]` |
| `topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` |
| `podManagementPolicy` | StatefulSet controller supports relax its ordering guarantees while preserving its uniqueness and identity guarantees. There are two valid pod management policies: `OrderedReady` and `Parallel` | `Parallel` |
| `priorityClassName` | Name of the existing priority class to be used by ZooKeeper pods, priority class needs to be created beforehand | `""` |
| `schedulerName` | Kubernetes pod scheduler registry | `""` |
| `updateStrategy.type` | ZooKeeper statefulset strategy type | `RollingUpdate` |
| `updateStrategy.rollingUpdate` | ZooKeeper statefulset rolling update configuration parameters | `{}` |
| `extraVolumes` | Optionally specify extra list of additional volumes for the ZooKeeper pod(s) | `[]` |
| `extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the ZooKeeper container(s) | `[]` |
| `sidecars` | Add additional sidecar containers to the ZooKeeper pod(s) | `[]` |
| `initContainers` | Add additional init containers to the ZooKeeper pod(s) | `[]` |
| `pdb.create` | Deploy a pdb object for the ZooKeeper pod | `true` |
| `pdb.minAvailable` | Minimum available ZooKeeper replicas | `""` |
| `pdb.maxUnavailable` | Maximum unavailable ZooKeeper replicas. Defaults to `1` if both `pdb.minAvailable` and `pdb.maxUnavailable` are empty. | `""` |
| `enableServiceLinks` | Whether information about services should be injected into pod's environment variable | `true` |
| `dnsPolicy` | Specifies the DNS policy for the zookeeper pods | `""` |
| `dnsConfig` | allows users more control on the DNS settings for a Pod. Required if `dnsPolicy` is set to `None` | `{}` |
### Traffic Exposure parameters
| Name | Description | Value |
| ------------------------------------------- | --------------------------------------------------------------------------------------- | ----------- |
| `service.type` | Kubernetes Service type | `ClusterIP` |
| `service.ports.client` | ZooKeeper client service port | `2181` |
| `service.ports.tls` | ZooKeeper TLS service port | `3181` |
| `service.ports.follower` | ZooKeeper follower service port | `2888` |
| `service.ports.election` | ZooKeeper election service port | `3888` |
| `service.nodePorts.client` | Node port for clients | `""` |
| `service.nodePorts.tls` | Node port for TLS | `""` |
| `service.disableBaseClientPort` | Remove client port from service definitions. | `false` |
| `service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` |
| `service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` |
| `service.clusterIP` | ZooKeeper service Cluster IP | `""` |
| `service.loadBalancerIP` | ZooKeeper service Load Balancer IP | `""` |
| `service.loadBalancerSourceRanges` | ZooKeeper service Load Balancer sources | `[]` |
| `service.externalTrafficPolicy` | ZooKeeper service external traffic policy | `Cluster` |
| `service.annotations` | Additional custom annotations for ZooKeeper service | `{}` |
| `service.extraPorts` | Extra ports to expose in the ZooKeeper service (normally used with the `sidecar` value) | `[]` |
| `service.headless.annotations` | Annotations for the Headless Service | `{}` |
| `service.headless.publishNotReadyAddresses` | If the ZooKeeper headless service should publish DNS records for not ready pods | `true` |
| `service.headless.servicenameOverride` | String to partially override headless service name | `""` |
| `networkPolicy.enabled` | Specifies whether a NetworkPolicy should be created | `true` |
| `networkPolicy.allowExternal` | Don't require client label for connections | `true` |
| `networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` |
| `networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` |
| `networkPolicy.extraEgress` | Add extra ingress rules to the NetworkPolicy | `[]` |
| `networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces | `{}` |
| `networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces | `{}` |
### Other Parameters
| Name | Description | Value |
| --------------------------------------------- | ---------------------------------------------------------------------- | ------- |
| `serviceAccount.create` | Enable creation of ServiceAccount for ZooKeeper pod | `true` |
| `serviceAccount.name` | The name of the ServiceAccount to use. | `""` |
| `serviceAccount.automountServiceAccountToken` | Allows auto mount of ServiceAccountToken on the serviceAccount created | `false` |
| `serviceAccount.annotations` | Additional custom annotations for the ServiceAccount | `{}` |
### Persistence parameters
| Name | Description | Value |
| -------------------------------------- | ------------------------------------------------------------------------------ | ------------------- |
| `persistence.enabled` | Enable ZooKeeper data persistence using PVC. If false, use emptyDir | `true` |
| `persistence.existingClaim` | Name of an existing PVC to use (only when deploying a single replica) | `""` |
| `persistence.storageClass` | PVC Storage Class for ZooKeeper data volume | `""` |
| `persistence.accessModes` | PVC Access modes | `["ReadWriteOnce"]` |
| `persistence.size` | PVC Storage Request for ZooKeeper data volume | `8Gi` |
| `persistence.annotations` | Annotations for the PVC | `{}` |
| `persistence.labels` | Labels for the PVC | `{}` |
| `persistence.selector` | Selector to match an existing Persistent Volume for ZooKeeper's data PVC | `{}` |
| `persistence.dataLogDir.size` | PVC Storage Request for ZooKeeper's dedicated data log directory | `8Gi` |
| `persistence.dataLogDir.existingClaim` | Provide an existing `PersistentVolumeClaim` for ZooKeeper's data log directory | `""` |
| `persistence.dataLogDir.selector` | Selector to match an existing Persistent Volume for ZooKeeper's data log PVC | `{}` |
### Volume Permissions parameters
| Name | Description | Value |
| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |
| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume | `false` |
| `volumePermissions.image.registry` | Init container volume-permissions image registry | `REGISTRY_NAME` |
| `volumePermissions.image.repository` | Init container volume-permissions image repository | `REPOSITORY_NAME/os-shell` |
| `volumePermissions.image.digest` | Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` |
| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `IfNotPresent` |
| `volumePermissions.image.pullSecrets` | Init container volume-permissions image pull secrets | `[]` |
| `volumePermissions.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). | `nano` |
| `volumePermissions.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` |
| `volumePermissions.containerSecurityContext.enabled` | Enabled init container Security Context | `true` |
| `volumePermissions.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` |
| `volumePermissions.containerSecurityContext.runAsUser` | User ID for the init container | `0` |
### Metrics parameters
| Name | Description | Value |
| ------------------------------------------ | ------------------------------------------------------------------------------------- | ----------- |
| `metrics.enabled` | Enable Prometheus to access ZooKeeper metrics endpoint | `false` |
| `metrics.service.type` | ZooKeeper Prometheus Exporter service type | `ClusterIP` |
| `metrics.service.port` | ZooKeeper Prometheus Exporter service port | `9141` |
| `metrics.service.annotations` | Annotations for Prometheus to auto-discover the metrics endpoint | `{}` |
| `metrics.serviceMonitor.enabled` | Create ServiceMonitor Resource for scraping metrics using Prometheus Operator | `false` |
| `metrics.serviceMonitor.namespace` | Namespace for the ServiceMonitor Resource (defaults to the Release Namespace) | `""` |
| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped. | `""` |
| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `""` |
| `metrics.serviceMonitor.additionalLabels` | Additional labels that can be used so ServiceMonitor will be discovered by Prometheus | `{}` |
| `metrics.serviceMonitor.selector` | Prometheus instance selector labels | `{}` |
| `metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping | `[]` |
| `metrics.serviceMonitor.metricRelabelings` | MetricRelabelConfigs to apply to samples before ingestion | `[]` |
| `metrics.serviceMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` |
| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in prometheus. | `""` |
| `metrics.prometheusRule.enabled` | Create a PrometheusRule for Prometheus Operator | `false` |
| `metrics.prometheusRule.namespace` | Namespace for the PrometheusRule Resource (defaults to the Release Namespace) | `""` |
| `metrics.prometheusRule.additionalLabels` | Additional labels that can be used so PrometheusRule will be discovered by Prometheus | `{}` |
| `metrics.prometheusRule.rules` | PrometheusRule definitions | `[]` |
### TLS/SSL parameters
| Name | Description | Value |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| `tls.client.enabled` | Enable TLS for client connections | `false` |
| `tls.client.auth` | SSL Client auth. Can be "none", "want" or "need". | `none` |
| `tls.client.autoGenerated` | Generate automatically self-signed TLS certificates for ZooKeeper client communications | `false` |
| `tls.client.existingSecret` | Name of the existing secret containing the TLS certificates for ZooKeeper client communications | `""` |
| `tls.client.existingSecretKeystoreKey` | The secret key from the tls.client.existingSecret containing the Keystore. | `""` |
| `tls.client.existingSecretTruststoreKey` | The secret key from the tls.client.existingSecret containing the Truststore. | `""` |
| `tls.client.keystorePath` | Location of the KeyStore file used for Client connections | `/opt/bitnami/zookeeper/config/certs/client/zookeeper.keystore.jks` |
| `tls.client.truststorePath` | Location of the TrustStore file used for Client connections | `/opt/bitnami/zookeeper/config/certs/client/zookeeper.truststore.jks` |
| `tls.client.passwordsSecretName` | Existing secret containing Keystore and truststore passwords | `""` |
| `tls.client.passwordsSecretKeystoreKey` | The secret key from the tls.client.passwordsSecretName containing the password for the Keystore. | `""` |
| `tls.client.passwordsSecretTruststoreKey` | The secret key from the tls.client.passwordsSecretName containing the password for the Truststore. | `""` |
| `tls.client.keystorePassword` | Password to access KeyStore if needed | `""` |
| `tls.client.truststorePassword` | Password to access TrustStore if needed | `""` |
| `tls.quorum.enabled` | Enable TLS for quorum protocol | `false` |
| `tls.quorum.auth` | SSL Quorum Client auth. Can be "none", "want" or "need". | `none` |
| `tls.quorum.autoGenerated` | Create self-signed TLS certificates. Currently only supports PEM certificates. | `false` |
| `tls.quorum.existingSecret` | Name of the existing secret containing the TLS certificates for ZooKeeper quorum protocol | `""` |
| `tls.quorum.existingSecretKeystoreKey` | The secret key from the tls.quorum.existingSecret containing the Keystore. | `""` |
| `tls.quorum.existingSecretTruststoreKey` | The secret key from the tls.quorum.existingSecret containing the Truststore. | `""` |
| `tls.quorum.keystorePath` | Location of the KeyStore file used for Quorum protocol | `/opt/bitnami/zookeeper/config/certs/quorum/zookeeper.keystore.jks` |
| `tls.quorum.truststorePath` | Location of the TrustStore file used for Quorum protocol | `/opt/bitnami/zookeeper/config/certs/quorum/zookeeper.truststore.jks` |
| `tls.quorum.passwordsSecretName` | Existing secret containing Keystore and truststore passwords | `""` |
| `tls.quorum.passwordsSecretKeystoreKey` | The secret key from the tls.quorum.passwordsSecretName containing the password for the Keystore. | `""` |
| `tls.quorum.passwordsSecretTruststoreKey` | The secret key from the tls.quorum.passwordsSecretName containing the password for the Truststore. | `""` |
| `tls.quorum.keystorePassword` | Password to access KeyStore if needed | `""` |
| `tls.quorum.truststorePassword` | Password to access TrustStore if needed | `""` |
| `tls.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if tls.resources is set (tls.resources is recommended for production). | `nano` |
| `tls.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` |
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
```console
helm install my-release \
--set auth.clientUser=newUser \
oci://REGISTRY_NAME/REPOSITORY_NAME/zookeeper
```
> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`.
The above command sets the ZooKeeper user to `newUser`.
> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available.
Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example,
```console
helm install my-release -f values.yaml oci://REGISTRY_NAME/REPOSITORY_NAME/zookeeper
```
> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`.
> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/zookeeper/values.yaml)
## Troubleshooting
Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues).
## Upgrading
### To 13.0.0
This major bump changes the following security defaults:
- `runAsGroup` is changed from `0` to `1001`
- `readOnlyRootFilesystem` is set to `true`
- `resourcesPreset` is changed from `none` to the minimum size working in our test suites (NOTE: `resourcesPreset` is not meant for production usage, but `resources` adapted to your use case).
- `global.compatibility.openshift.adaptSecurityContext` is changed from `disabled` to `auto`.
This could potentially break any customization or init scripts used in your deployment. If this is the case, change the default values to the previous ones.
### To 12.0.0
This new version of the chart includes the new ZooKeeper major version 3.9.x. For more information, please refer to [Zookeeper 3.9.0 Release Notes](https://zookeeper.apache.org/doc/r3.9.0/releasenotes.html)
### To 11.0.0
This major version removes `commonAnnotations` and `commonLabels` from `volumeClaimTemplates`. Now annotations and labels can be set in volume claims using `persistence.annotations` and `persistence.labels` values. If the previous deployment has already set `commonAnnotations` and/or `commonLabels` values, to ensure a clean upgrade from previous version without loosing data, please set `persistence.annotations` and/or `persistence.labels` values with the same content as the common values.
### To 10.0.0
This new version of the chart adds support for server-server authentication.
The chart previously supported client-server authentication, to avoid confusion, the previous parameters have been renamed from `auth.*` to `auth.client.*`.
### To 9.0.0
This new version of the chart includes the new ZooKeeper major version 3.8.0. Upgrade compatibility is not guaranteed.
### To 8.0.0
This major release renames several values in this chart and adds missing features, in order to be inline with the rest of assets in the Bitnami charts repository.
Affected values:
- `allowAnonymousLogin` is deprecated.
- `containerPort`, `tlsContainerPort`, `followerContainerPort` and `electionContainerPort` have been regrouped under the `containerPorts` map.
- `service.port`, `service.tlsClientPort`, `service.followerPort`, and `service.electionPort` have been regrouped under the `service.ports` map.
- `updateStrategy` (string) and `rollingUpdatePartition` are regrouped under the `updateStrategy` map.
- `podDisruptionBudget.*` parameters are renamed to `pdb.*`.
### To 7.0.0
This new version renames the parameters used to configure TLS for both client and quorum.
- `service.tls.disable_base_client_port` is renamed to `service.disableBaseClientPort`
- `service.tls.client_port` is renamed to `service.tlsClientPort`
- `service.tls.client_enable` is renamed to `tls.client.enabled`
- `service.tls.client_keystore_path` is renamed to `tls.client.keystorePath`
- `service.tls.client_truststore_path` is renamed to `tls.client.truststorePath`
- `service.tls.client_keystore_password` is renamed to `tls.client.keystorePassword`
- `service.tls.client_truststore_password` is renamed to `tls.client.truststorePassword`
- `service.tls.quorum_enable` is renamed to `tls.quorum.enabled`
- `service.tls.quorum_keystore_path` is renamed to `tls.quorum.keystorePath`
- `service.tls.quorum_truststore_path` is renamed to `tls.quorum.truststorePath`
- `service.tls.quorum_keystore_password` is renamed to `tls.quorum.keystorePassword`
- `service.tls.quorum_truststore_password` is renamed to `tls.quorum.truststorePassword`
### To 6.1.0
This version introduces `bitnami/common`, a [library chart](https://helm.sh/docs/topics/library_charts/#helm) as a dependency. More documentation about this new utility could be found [here](https://github.com/bitnami/charts/tree/main/bitnami/common#bitnami-common-library-chart). Please, make sure that you have updated the chart dependencies before executing any upgrade.
### To 6.0.0
[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL.
### To 5.21.0
A couple of parameters related to Zookeeper metrics were renamed or disappeared in favor of new ones:
- `metrics.port` is renamed to `metrics.containerPort`.
- `metrics.annotations` is deprecated in favor of `metrics.service.annotations`.
### To 3.0.0
This new version of the chart includes the new ZooKeeper major version 3.5.5. Note that to perform an automatic upgrade
of the application, each node will need to have at least one snapshot file created in the data directory. If not, the
new version of the application won't be able to start the service. Please refer to [ZOOKEEPER-3056](https://issues.apache.org/jira/browse/ZOOKEEPER-3056)
in order to find ways to workaround this issue in case you are facing it.
### To 2.0.0
Backwards compatibility is not guaranteed unless you modify the labels used on the chart's statefulsets.
Use the workaround below to upgrade from versions previous to 2.0.0. The following example assumes that the release name is `zookeeper`:
```console
kubectl delete statefulset zookeeper-zookeeper --cascade=false
```
### To 1.0.0
Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments.
Use the workaround below to upgrade from versions previous to 1.0.0. The following example assumes that the release name is zookeeper:
```console
kubectl delete statefulset zookeeper-zookeeper --cascade=false
```
## License
Copyright &copy; 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
<http://www.apache.org/licenses/LICENSE-2.0>
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,26 @@
# 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
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
# img folder
img/
# Changelog
CHANGELOG.md

View File

@ -0,0 +1,23 @@
annotations:
category: Infrastructure
licenses: Apache-2.0
apiVersion: v2
appVersion: 2.22.0
description: A Library Helm Chart for grouping common logic between bitnami charts.
This chart is not deployable by itself.
home: https://bitnami.com
icon: https://bitnami.com/downloads/logos/bitnami-mark.png
keywords:
- common
- helper
- template
- function
- bitnami
maintainers:
- name: Broadcom, Inc. All Rights Reserved.
url: https://github.com/bitnami/charts
name: common
sources:
- https://github.com/bitnami/charts/tree/main/bitnami/common
type: library
version: 2.22.0

View File

@ -0,0 +1,235 @@
# Bitnami Common Library Chart
A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts.
## TL;DR
```yaml
dependencies:
- name: common
version: 2.x.x
repository: oci://registry-1.docker.io/bitnamicharts
```
```console
helm dependency update
```
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "common.names.fullname" . }}
data:
myvalue: "Hello World"
```
Looking to use our applications in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog.
## Introduction
This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager.
Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters.
## Prerequisites
- Kubernetes 1.23+
- Helm 3.8.0+
## Parameters
## Special input schemas
### ImageRoot
```yaml
registry:
type: string
description: Docker registry where the image is located
example: docker.io
repository:
type: string
description: Repository and image name
example: bitnami/nginx
tag:
type: string
description: image tag
example: 1.16.1-debian-10-r63
pullPolicy:
type: string
description: Specify a imagePullPolicy. Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent'
pullSecrets:
type: array
items:
type: string
description: Optionally specify an array of imagePullSecrets (evaluated as templates).
debug:
type: boolean
description: Set to true if you would like to see extra information on logs
example: false
## An instance would be:
# registry: docker.io
# repository: bitnami/nginx
# tag: 1.16.1-debian-10-r63
# pullPolicy: IfNotPresent
# debug: false
```
### Persistence
```yaml
enabled:
type: boolean
description: Whether enable persistence.
example: true
storageClass:
type: string
description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning.
example: "-"
accessMode:
type: string
description: Access mode for the Persistent Volume Storage.
example: ReadWriteOnce
size:
type: string
description: Size the Persistent Volume Storage.
example: 8Gi
path:
type: string
description: Path to be persisted.
example: /bitnami
## An instance would be:
# enabled: true
# storageClass: "-"
# accessMode: ReadWriteOnce
# size: 8Gi
# path: /bitnami
```
### ExistingSecret
```yaml
name:
type: string
description: Name of the existing secret.
example: mySecret
keyMapping:
description: Mapping between the expected key name and the name of the key in the existing secret.
type: object
## An instance would be:
# name: mySecret
# keyMapping:
# password: myPasswordKey
```
#### Example of use
When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets.
```yaml
# templates/secret.yaml
---
apiVersion: v1
kind: Secret
metadata:
name: {{ include "common.names.fullname" . }}
labels:
app: {{ include "common.names.fullname" . }}
type: Opaque
data:
password: {{ .Values.password | b64enc | quote }}
# templates/dpl.yaml
---
...
env:
- name: PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }}
key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }}
...
# values.yaml
---
name: mySecret
keyMapping:
password: myPasswordKey
```
### ValidateValue
#### NOTES.txt
```console
{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}}
{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}}
{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }}
```
If we force those values to be empty we will see some alerts
```console
helm install test mychart --set path.to.value00="",path.to.value01=""
'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value:
export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d)
'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value:
export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d)
```
## Upgrading
### To 1.0.0
[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL.
#### What changes were introduced in this major version?
- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field.
- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information.
- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts
#### Considerations when upgrading to this version
- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues
- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore
- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3
#### Useful links
- <https://docs.vmware.com/en/VMware-Tanzu-Application-Catalog/services/tutorials/GUID-resolve-helm2-helm3-post-migration-issues-index.html>
- <https://helm.sh/docs/topics/v2_v3_migration/>
- <https://helm.sh/blog/migrate-from-helm-v2-to-helm-v3/>
## License
Copyright &copy; 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
<http://www.apache.org/licenses/LICENSE-2.0>
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,139 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Return a soft nodeAffinity definition
{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}}
*/}}
{{- define "common.affinities.nodes.soft" -}}
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
- key: {{ .key }}
operator: In
values:
{{- range .values }}
- {{ . | quote }}
{{- end }}
weight: 1
{{- end -}}
{{/*
Return a hard nodeAffinity definition
{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}}
*/}}
{{- define "common.affinities.nodes.hard" -}}
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: {{ .key }}
operator: In
values:
{{- range .values }}
- {{ . | quote }}
{{- end }}
{{- end -}}
{{/*
Return a nodeAffinity definition
{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}}
*/}}
{{- define "common.affinities.nodes" -}}
{{- if eq .type "soft" }}
{{- include "common.affinities.nodes.soft" . -}}
{{- else if eq .type "hard" }}
{{- include "common.affinities.nodes.hard" . -}}
{{- end -}}
{{- end -}}
{{/*
Return a topologyKey definition
{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}}
*/}}
{{- define "common.affinities.topologyKey" -}}
{{ .topologyKey | default "kubernetes.io/hostname" -}}
{{- end -}}
{{/*
Return a soft podAffinity/podAntiAffinity definition
{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "context" $) -}}
*/}}
{{- define "common.affinities.pods.soft" -}}
{{- $component := default "" .component -}}
{{- $customLabels := default (dict) .customLabels -}}
{{- $extraMatchLabels := default (dict) .extraMatchLabels -}}
{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}}
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }}
{{- if not (empty $component) }}
{{ printf "app.kubernetes.io/component: %s" $component }}
{{- end }}
{{- range $key, $value := $extraMatchLabels }}
{{ $key }}: {{ $value | quote }}
{{- end }}
topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }}
weight: 1
{{- range $extraPodAffinityTerms }}
- podAffinityTerm:
labelSelector:
matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }}
{{- if not (empty $component) }}
{{ printf "app.kubernetes.io/component: %s" $component }}
{{- end }}
{{- range $key, $value := .extraMatchLabels }}
{{ $key }}: {{ $value | quote }}
{{- end }}
topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }}
weight: {{ .weight | default 1 -}}
{{- end -}}
{{- end -}}
{{/*
Return a hard podAffinity/podAntiAffinity definition
{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "context" $) -}}
*/}}
{{- define "common.affinities.pods.hard" -}}
{{- $component := default "" .component -}}
{{- $customLabels := default (dict) .customLabels -}}
{{- $extraMatchLabels := default (dict) .extraMatchLabels -}}
{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}}
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }}
{{- if not (empty $component) }}
{{ printf "app.kubernetes.io/component: %s" $component }}
{{- end }}
{{- range $key, $value := $extraMatchLabels }}
{{ $key }}: {{ $value | quote }}
{{- end }}
topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }}
{{- range $extraPodAffinityTerms }}
- labelSelector:
matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }}
{{- if not (empty $component) }}
{{ printf "app.kubernetes.io/component: %s" $component }}
{{- end }}
{{- range $key, $value := .extraMatchLabels }}
{{ $key }}: {{ $value | quote }}
{{- end }}
topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }}
{{- end -}}
{{- end -}}
{{/*
Return a podAffinity/podAntiAffinity definition
{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}}
*/}}
{{- define "common.affinities.pods" -}}
{{- if eq .type "soft" }}
{{- include "common.affinities.pods.soft" . -}}
{{- else if eq .type "hard" }}
{{- include "common.affinities.pods.hard" . -}}
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,229 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Return the target Kubernetes version
*/}}
{{- define "common.capabilities.kubeVersion" -}}
{{- default (default .Capabilities.KubeVersion.Version .Values.kubeVersion) ((.Values.global).kubeVersion) -}}
{{- end -}}
{{/*
Return the appropriate apiVersion for poddisruptionbudget.
*/}}
{{- define "common.capabilities.policy.apiVersion" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}}
{{- if and (not (empty $kubeVersion)) (semverCompare "<1.21-0" $kubeVersion) -}}
{{- print "policy/v1beta1" -}}
{{- else -}}
{{- print "policy/v1" -}}
{{- end -}}
{{- end -}}
{{/*
Return the appropriate apiVersion for networkpolicy.
*/}}
{{- define "common.capabilities.networkPolicy.apiVersion" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}}
{{- if and (not (empty $kubeVersion)) (semverCompare "<1.7-0" $kubeVersion) -}}
{{- print "extensions/v1beta1" -}}
{{- else -}}
{{- print "networking.k8s.io/v1" -}}
{{- end -}}
{{- end -}}
{{/*
Return the appropriate apiVersion for cronjob.
*/}}
{{- define "common.capabilities.cronjob.apiVersion" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}}
{{- if and (not (empty $kubeVersion)) (semverCompare "<1.21-0" $kubeVersion) -}}
{{- print "batch/v1beta1" -}}
{{- else -}}
{{- print "batch/v1" -}}
{{- end -}}
{{- end -}}
{{/*
Return the appropriate apiVersion for daemonset.
*/}}
{{- define "common.capabilities.daemonset.apiVersion" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}}
{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}}
{{- print "extensions/v1beta1" -}}
{{- else -}}
{{- print "apps/v1" -}}
{{- end -}}
{{- end -}}
{{/*
Return the appropriate apiVersion for deployment.
*/}}
{{- define "common.capabilities.deployment.apiVersion" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}}
{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}}
{{- print "extensions/v1beta1" -}}
{{- else -}}
{{- print "apps/v1" -}}
{{- end -}}
{{- end -}}
{{/*
Return the appropriate apiVersion for statefulset.
*/}}
{{- define "common.capabilities.statefulset.apiVersion" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}}
{{- if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}}
{{- print "apps/v1beta1" -}}
{{- else -}}
{{- print "apps/v1" -}}
{{- end -}}
{{- end -}}
{{/*
Return the appropriate apiVersion for ingress.
*/}}
{{- define "common.capabilities.ingress.apiVersion" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}}
{{- if (.Values.ingress).apiVersion -}}
{{- .Values.ingress.apiVersion -}}
{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.14-0" $kubeVersion) -}}
{{- print "extensions/v1beta1" -}}
{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.19-0" $kubeVersion) -}}
{{- print "networking.k8s.io/v1beta1" -}}
{{- else -}}
{{- print "networking.k8s.io/v1" -}}
{{- end }}
{{- end -}}
{{/*
Return the appropriate apiVersion for RBAC resources.
*/}}
{{- define "common.capabilities.rbac.apiVersion" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}}
{{- if and (not (empty $kubeVersion)) (semverCompare "<1.17-0" $kubeVersion) -}}
{{- print "rbac.authorization.k8s.io/v1beta1" -}}
{{- else -}}
{{- print "rbac.authorization.k8s.io/v1" -}}
{{- end -}}
{{- end -}}
{{/*
Return the appropriate apiVersion for CRDs.
*/}}
{{- define "common.capabilities.crd.apiVersion" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}}
{{- if and (not (empty $kubeVersion)) (semverCompare "<1.19-0" $kubeVersion) -}}
{{- print "apiextensions.k8s.io/v1beta1" -}}
{{- else -}}
{{- print "apiextensions.k8s.io/v1" -}}
{{- end -}}
{{- end -}}
{{/*
Return the appropriate apiVersion for APIService.
*/}}
{{- define "common.capabilities.apiService.apiVersion" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}}
{{- if and (not (empty $kubeVersion)) (semverCompare "<1.10-0" $kubeVersion) -}}
{{- print "apiregistration.k8s.io/v1beta1" -}}
{{- else -}}
{{- print "apiregistration.k8s.io/v1" -}}
{{- end -}}
{{- end -}}
{{/*
Return the appropriate apiVersion for Horizontal Pod Autoscaler.
*/}}
{{- define "common.capabilities.hpa.apiVersion" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}}
{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}}
{{- if .beta2 -}}
{{- print "autoscaling/v2beta2" -}}
{{- else -}}
{{- print "autoscaling/v2beta1" -}}
{{- end -}}
{{- else -}}
{{- print "autoscaling/v2" -}}
{{- end -}}
{{- end -}}
{{/*
Return the appropriate apiVersion for Vertical Pod Autoscaler.
*/}}
{{- define "common.capabilities.vpa.apiVersion" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}}
{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}}
{{- if .beta2 -}}
{{- print "autoscaling/v2beta2" -}}
{{- else -}}
{{- print "autoscaling/v2beta1" -}}
{{- end -}}
{{- else -}}
{{- print "autoscaling/v2" -}}
{{- end -}}
{{- end -}}
{{/*
Returns true if PodSecurityPolicy is supported
*/}}
{{- define "common.capabilities.psp.supported" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}}
{{- if or (empty $kubeVersion) (semverCompare "<1.25-0" $kubeVersion) -}}
{{- true -}}
{{- end -}}
{{- end -}}
{{/*
Returns true if AdmissionConfiguration is supported
*/}}
{{- define "common.capabilities.admissionConfiguration.supported" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}}
{{- if or (empty $kubeVersion) (not (semverCompare "<1.23-0" $kubeVersion)) -}}
{{- true -}}
{{- end -}}
{{- end -}}
{{/*
Return the appropriate apiVersion for AdmissionConfiguration.
*/}}
{{- define "common.capabilities.admissionConfiguration.apiVersion" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}}
{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}}
{{- print "apiserver.config.k8s.io/v1alpha1" -}}
{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}}
{{- print "apiserver.config.k8s.io/v1beta1" -}}
{{- else -}}
{{- print "apiserver.config.k8s.io/v1" -}}
{{- end -}}
{{- end -}}
{{/*
Return the appropriate apiVersion for PodSecurityConfiguration.
*/}}
{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}}
{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}}
{{- if and (not (empty $kubeVersion)) (semverCompare "<1.23-0" $kubeVersion) -}}
{{- print "pod-security.admission.config.k8s.io/v1alpha1" -}}
{{- else if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}}
{{- print "pod-security.admission.config.k8s.io/v1beta1" -}}
{{- else -}}
{{- print "pod-security.admission.config.k8s.io/v1" -}}
{{- end -}}
{{- end -}}
{{/*
Returns true if the used Helm version is 3.3+.
A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure.
This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error.
**To be removed when the catalog's minimun Helm version is 3.3**
*/}}
{{- define "common.capabilities.supportsHelmVersion" -}}
{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }}
{{- true -}}
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,42 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Return true if the detected platform is Openshift
Usage:
{{- include "common.compatibility.isOpenshift" . -}}
*/}}
{{- define "common.compatibility.isOpenshift" -}}
{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}}
{{- true -}}
{{- end -}}
{{- end -}}
{{/*
Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC
Usage:
{{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}}
*/}}
{{- define "common.compatibility.renderSecurityContext" -}}
{{- $adaptedContext := .secContext -}}
{{- if (((.context.Values.global).compatibility).openshift) -}}
{{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .context)) -}}
{{/* Remove incompatible user/group values that do not work in Openshift out of the box */}}
{{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}}
{{- if not .secContext.seLinuxOptions -}}
{{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}}
{{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/* Remove fields that are disregarded when running the container in privileged mode */}}
{{- if $adaptedContext.privileged -}}
{{- $adaptedContext = omit $adaptedContext "capabilities" "seLinuxOptions" -}}
{{- end -}}
{{- omit $adaptedContext "enabled" | toYaml -}}
{{- end -}}

View File

@ -0,0 +1,28 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Through error when upgrading using empty passwords values that must not be empty.
Usage:
{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}}
{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}}
{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }}
Required password params:
- validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error.
- context - Context - Required. Parent context.
*/}}
{{- define "common.errors.upgrade.passwords.empty" -}}
{{- $validationErrors := join "" .validationErrors -}}
{{- if and $validationErrors .context.Release.IsUpgrade -}}
{{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}}
{{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}}
{{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}}
{{- $errorString = print $errorString "\n%s" -}}
{{- printf $errorString $validationErrors | fail -}}
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,115 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Return the proper image name.
If image tag and digest are not defined, termination fallbacks to chart appVersion.
{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global "chart" .Chart ) }}
*/}}
{{- define "common.images.image" -}}
{{- $registryName := default .imageRoot.registry ((.global).imageRegistry) -}}
{{- $repositoryName := .imageRoot.repository -}}
{{- $separator := ":" -}}
{{- $termination := .imageRoot.tag | toString -}}
{{- if not .imageRoot.tag }}
{{- if .chart }}
{{- $termination = .chart.AppVersion | toString -}}
{{- end -}}
{{- end -}}
{{- if .imageRoot.digest }}
{{- $separator = "@" -}}
{{- $termination = .imageRoot.digest | toString -}}
{{- end -}}
{{- if $registryName }}
{{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}}
{{- else -}}
{{- printf "%s%s%s" $repositoryName $separator $termination -}}
{{- end -}}
{{- end -}}
{{/*
Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead)
{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }}
*/}}
{{- define "common.images.pullSecrets" -}}
{{- $pullSecrets := list }}
{{- range ((.global).imagePullSecrets) -}}
{{- if kindIs "map" . -}}
{{- $pullSecrets = append $pullSecrets .name -}}
{{- else -}}
{{- $pullSecrets = append $pullSecrets . -}}
{{- end }}
{{- end -}}
{{- range .images -}}
{{- range .pullSecrets -}}
{{- if kindIs "map" . -}}
{{- $pullSecrets = append $pullSecrets .name -}}
{{- else -}}
{{- $pullSecrets = append $pullSecrets . -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if (not (empty $pullSecrets)) -}}
imagePullSecrets:
{{- range $pullSecrets | uniq }}
- name: {{ . }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Return the proper Docker Image Registry Secret Names evaluating values as templates
{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }}
*/}}
{{- define "common.images.renderPullSecrets" -}}
{{- $pullSecrets := list }}
{{- $context := .context }}
{{- range (($context.Values.global).imagePullSecrets) -}}
{{- if kindIs "map" . -}}
{{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}}
{{- else -}}
{{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}}
{{- end -}}
{{- end -}}
{{- range .images -}}
{{- range .pullSecrets -}}
{{- if kindIs "map" . -}}
{{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}}
{{- else -}}
{{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if (not (empty $pullSecrets)) -}}
imagePullSecrets:
{{- range $pullSecrets | uniq }}
- name: {{ . }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion)
{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }}
*/}}
{{- define "common.images.version" -}}
{{- $imageTag := .imageRoot.tag | toString -}}
{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}}
{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}}
{{- $version := semver $imageTag -}}
{{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}}
{{- else -}}
{{- print .chart.AppVersion -}}
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,73 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Generate backend entry that is compatible with all Kubernetes API versions.
Usage:
{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }}
Params:
- serviceName - String. Name of an existing service backend
- servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer.
- context - Dict - Required. The context for the template evaluation.
*/}}
{{- define "common.ingress.backend" -}}
{{- $apiVersion := (include "common.capabilities.ingress.apiVersion" .context) -}}
{{- if or (eq $apiVersion "extensions/v1beta1") (eq $apiVersion "networking.k8s.io/v1beta1") -}}
serviceName: {{ .serviceName }}
servicePort: {{ .servicePort }}
{{- else -}}
service:
name: {{ .serviceName }}
port:
{{- if typeIs "string" .servicePort }}
name: {{ .servicePort }}
{{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }}
number: {{ .servicePort | int }}
{{- end }}
{{- end -}}
{{- end -}}
{{/*
Print "true" if the API pathType field is supported
Usage:
{{ include "common.ingress.supportsPathType" . }}
*/}}
{{- define "common.ingress.supportsPathType" -}}
{{- if (semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .)) -}}
{{- print "false" -}}
{{- else -}}
{{- print "true" -}}
{{- end -}}
{{- end -}}
{{/*
Returns true if the ingressClassname field is supported
Usage:
{{ include "common.ingress.supportsIngressClassname" . }}
*/}}
{{- define "common.ingress.supportsIngressClassname" -}}
{{- if semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .) -}}
{{- print "false" -}}
{{- else -}}
{{- print "true" -}}
{{- end -}}
{{- end -}}
{{/*
Return true if cert-manager required annotations for TLS signed
certificates are set in the Ingress annotations
Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations
Usage:
{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }}
*/}}
{{- define "common.ingress.certManagerRequest" -}}
{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }}
{{- true -}}
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,46 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Kubernetes standard labels
{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}}
*/}}
{{- define "common.labels.standard" -}}
{{- if and (hasKey . "customLabels") (hasKey . "context") -}}
{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}}
{{- with .context.Chart.AppVersion -}}
{{- $_ := set $default "app.kubernetes.io/version" . -}}
{{- end -}}
{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }}
{{- else -}}
app.kubernetes.io/name: {{ include "common.names.name" . }}
helm.sh/chart: {{ include "common.names.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- with .Chart.AppVersion }}
app.kubernetes.io/version: {{ . | quote }}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector
{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}}
We don't want to loop over custom labels appending them to the selector
since it's very likely that it will break deployments, services, etc.
However, it's important to overwrite the standard labels if the user
overwrote them on metadata.labels fields.
*/}}
{{- define "common.labels.matchLabels" -}}
{{- if and (hasKey . "customLabels") (hasKey . "context") -}}
{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }}
{{- else -}}
app.kubernetes.io/name: {{ include "common.names.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,71 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "common.names.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "common.names.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | 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 "common.names.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 a default fully qualified dependency 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.
Usage:
{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }}
*/}}
{{- define "common.names.dependency.fullname" -}}
{{- if .chartValues.fullnameOverride -}}
{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .chartName .chartValues.nameOverride -}}
{{- if contains $name .context.Release.Name -}}
{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Allow the release namespace to be overridden for multi-namespace deployments in combined charts.
*/}}
{{- define "common.names.namespace" -}}
{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a fully qualified app name adding the installation's namespace.
*/}}
{{- define "common.names.fullname.namespace" -}}
{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}}
{{- end -}}

View File

@ -0,0 +1,50 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Return a resource request/limit object based on a given preset.
These presets are for basic testing and not meant to be used in production
{{ include "common.resources.preset" (dict "type" "nano") -}}
*/}}
{{- define "common.resources.preset" -}}
{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}}
{{- $presets := dict
"nano" (dict
"requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi")
"limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi")
)
"micro" (dict
"requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi")
"limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi")
)
"small" (dict
"requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi")
"limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi")
)
"medium" (dict
"requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi")
"limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi")
)
"large" (dict
"requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi")
"limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi")
)
"xlarge" (dict
"requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi")
"limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi")
)
"2xlarge" (dict
"requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi")
"limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi")
)
}}
{{- if hasKey $presets .type -}}
{{- index $presets .type | toYaml -}}
{{- else -}}
{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" .type (join "," (keys $presets)) | fail -}}
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,185 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Generate secret name.
Usage:
{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }}
Params:
- existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user
to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility.
+info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret
- defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment.
- context - Dict - Required. The context for the template evaluation.
*/}}
{{- define "common.secrets.name" -}}
{{- $name := (include "common.names.fullname" .context) -}}
{{- if .defaultNameSuffix -}}
{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- with .existingSecret -}}
{{- if not (typeIs "string" .) -}}
{{- with .name -}}
{{- $name = . -}}
{{- end -}}
{{- else -}}
{{- $name = . -}}
{{- end -}}
{{- end -}}
{{- printf "%s" $name -}}
{{- end -}}
{{/*
Generate secret key.
Usage:
{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }}
Params:
- existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user
to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility.
+info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret
- key - String - Required. Name of the key in the secret.
*/}}
{{- define "common.secrets.key" -}}
{{- $key := .key -}}
{{- if .existingSecret -}}
{{- if not (typeIs "string" .existingSecret) -}}
{{- if .existingSecret.keyMapping -}}
{{- $key = index .existingSecret.keyMapping $.key -}}
{{- end -}}
{{- end }}
{{- end -}}
{{- printf "%s" $key -}}
{{- end -}}
{{/*
Generate secret password or retrieve one if already created.
Usage:
{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "context" $) }}
Params:
- secret - String - Required - Name of the 'Secret' resource where the password is stored.
- key - String - Required - Name of the key in the secret.
- providedValues - List<String> - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value.
- length - int - Optional - Length of the generated random password.
- strong - Boolean - Optional - Whether to add symbols to the generated random password.
- chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart.
- context - Context - Required - Parent context.
- failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets.
- skipB64enc - Boolean - Optional - Default to false. If set to true, no the secret will not be base64 encrypted.
- skipQuote - Boolean - Optional - Default to false. If set to true, no quotes will be added around the secret.
The order in which this function returns a secret password:
1. Already existing 'Secret' resource
(If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned)
2. Password provided via the values.yaml
(If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned)
3. Randomly generated secret password
(A new random secret password with the length specified in the 'length' parameter will be generated and returned)
*/}}
{{- define "common.secrets.passwords.manage" -}}
{{- $password := "" }}
{{- $subchart := "" }}
{{- $chartName := default "" .chartName }}
{{- $passwordLength := default 10 .length }}
{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }}
{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }}
{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }}
{{- if $secretData }}
{{- if hasKey $secretData .key }}
{{- $password = index $secretData .key | b64dec }}
{{- else if not (eq .failOnNew false) }}
{{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}}
{{- end -}}
{{- end }}
{{- if not $password }}
{{- if $providedPasswordValue }}
{{- $password = $providedPasswordValue | toString }}
{{- else }}
{{- if .context.Values.enabled }}
{{- $subchart = $chartName }}
{{- end -}}
{{- if not (eq .failOnNew false) }}
{{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}}
{{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}}
{{- $passwordValidationErrors := list $requiredPasswordError -}}
{{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}}
{{- end }}
{{- if .strong }}
{{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }}
{{- $password = randAscii $passwordLength }}
{{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }}
{{- $password = printf "%s%s" $subStr $password | toString | shuffle }}
{{- else }}
{{- $password = randAlphaNum $passwordLength }}
{{- end }}
{{- end -}}
{{- end -}}
{{- if not .skipB64enc }}
{{- $password = $password | b64enc }}
{{- end -}}
{{- if .skipQuote -}}
{{- printf "%s" $password -}}
{{- else -}}
{{- printf "%s" $password | quote -}}
{{- end -}}
{{- end -}}
{{/*
Reuses the value from an existing secret, otherwise sets its value to a default value.
Usage:
{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }}
Params:
- secret - String - Required - Name of the 'Secret' resource where the password is stored.
- key - String - Required - Name of the key in the secret.
- defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value.
- context - Context - Required - Parent context.
*/}}
{{- define "common.secrets.lookup" -}}
{{- $value := "" -}}
{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}}
{{- if and $secretData (hasKey $secretData .key) -}}
{{- $value = index $secretData .key -}}
{{- else if .defaultValue -}}
{{- $value = .defaultValue | toString | b64enc -}}
{{- end -}}
{{- if $value -}}
{{- printf "%s" $value -}}
{{- end -}}
{{- end -}}
{{/*
Returns whether a previous generated secret already exists
Usage:
{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }}
Params:
- secret - String - Required - Name of the 'Secret' resource where the password is stored.
- context - Context - Required - Parent context.
*/}}
{{- define "common.secrets.exists" -}}
{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }}
{{- if $secret }}
{{- true -}}
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,21 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Return the proper Storage Class
{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }}
*/}}
{{- define "common.storage.class" -}}
{{- $storageClass := (.global).storageClass | default .persistence.storageClass | default (.global).defaultStorageClass | default "" -}}
{{- if $storageClass -}}
{{- if (eq "-" $storageClass) -}}
{{- printf "storageClassName: \"\"" -}}
{{- else -}}
{{- printf "storageClassName: %s" $storageClass -}}
{{- end -}}
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,38 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Renders a value that contains template perhaps with scope if the scope is present.
Usage:
{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }}
{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }}
*/}}
{{- define "common.tplvalues.render" -}}
{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }}
{{- if contains "{{" (toJson .value) }}
{{- if .scope }}
{{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }}
{{- else }}
{{- tpl $value .context }}
{{- end }}
{{- else }}
{{- $value }}
{{- end }}
{{- end -}}
{{/*
Merge a list of values that contains template after rendering them.
Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge
Usage:
{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }}
*/}}
{{- define "common.tplvalues.merge" -}}
{{- $dst := dict -}}
{{- range .values -}}
{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}}
{{- end -}}
{{ $dst | toYaml }}
{{- end -}}

View File

@ -0,0 +1,77 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Print instructions to get a secret value.
Usage:
{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }}
*/}}
{{- define "common.utils.secret.getvalue" -}}
{{- $varname := include "common.utils.fieldToEnvVar" . -}}
export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d)
{{- end -}}
{{/*
Build env var name given a field
Usage:
{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }}
*/}}
{{- define "common.utils.fieldToEnvVar" -}}
{{- $fieldNameSplit := splitList "-" .field -}}
{{- $upperCaseFieldNameSplit := list -}}
{{- range $fieldNameSplit -}}
{{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}}
{{- end -}}
{{ join "_" $upperCaseFieldNameSplit }}
{{- end -}}
{{/*
Gets a value from .Values given
Usage:
{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }}
*/}}
{{- define "common.utils.getValueFromKey" -}}
{{- $splitKey := splitList "." .key -}}
{{- $value := "" -}}
{{- $latestObj := $.context.Values -}}
{{- range $splitKey -}}
{{- if not $latestObj -}}
{{- printf "please review the entire path of '%s' exists in values" $.key | fail -}}
{{- end -}}
{{- $value = ( index $latestObj . ) -}}
{{- $latestObj = $value -}}
{{- end -}}
{{- printf "%v" (default "" $value) -}}
{{- end -}}
{{/*
Returns first .Values key with a defined value or first of the list if all non-defined
Usage:
{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }}
*/}}
{{- define "common.utils.getKeyFromList" -}}
{{- $key := first .keys -}}
{{- $reverseKeys := reverse .keys }}
{{- range $reverseKeys }}
{{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }}
{{- if $value -}}
{{- $key = . }}
{{- end -}}
{{- end -}}
{{- printf "%s" $key -}}
{{- end -}}
{{/*
Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376).
Usage:
{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }}
*/}}
{{- define "common.utils.checksumTemplate" -}}
{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}}
{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }}
{{- end -}}

View File

@ -0,0 +1,109 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Warning about using rolling tag.
Usage:
{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }}
*/}}
{{- define "common.warnings.rollingTag" -}}
{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }}
WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment.
+info https://docs.vmware.com/en/VMware-Tanzu-Application-Catalog/services/tutorials/GUID-understand-rolling-tags-containers-index.html
{{- end }}
{{- end -}}
{{/*
Warning about replaced images from the original.
Usage:
{{ include "common.warnings.modifiedImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }}
*/}}
{{- define "common.warnings.modifiedImages" -}}
{{- $affectedImages := list -}}
{{- $printMessage := false -}}
{{- $originalImages := .context.Chart.Annotations.images -}}
{{- range .images -}}
{{- $fullImageName := printf (printf "%s/%s:%s" .registry .repository .tag) -}}
{{- if not (contains $fullImageName $originalImages) }}
{{- $affectedImages = append $affectedImages (printf "%s/%s:%s" .registry .repository .tag) -}}
{{- $printMessage = true -}}
{{- end -}}
{{- end -}}
{{- if $printMessage }}
⚠ SECURITY WARNING: Original containers have been substituted. This Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Tanzu Application Catalog containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables.
Substituted images detected:
{{- range $affectedImages }}
- {{ . }}
{{- end }}
{{- end -}}
{{- end -}}
{{/*
Warning about not setting the resource object in all deployments.
Usage:
{{ include "common.warnings.resources" (dict "sections" (list "path1" "path2") context $) }}
Example:
{{- include "common.warnings.resources" (dict "sections" (list "csiProvider.provider" "server" "volumePermissions" "") "context" $) }}
The list in the example assumes that the following values exist:
- csiProvider.provider.resources
- server.resources
- volumePermissions.resources
- resources
*/}}
{{- define "common.warnings.resources" -}}
{{- $values := .context.Values -}}
{{- $printMessage := false -}}
{{ $affectedSections := list -}}
{{- range .sections -}}
{{- if eq . "" -}}
{{/* Case where the resources section is at the root (one main deployment in the chart) */}}
{{- if not (index $values "resources") -}}
{{- $affectedSections = append $affectedSections "resources" -}}
{{- $printMessage = true -}}
{{- end -}}
{{- else -}}
{{/* Case where the are multiple resources sections (more than one main deployment in the chart) */}}
{{- $keys := split "." . -}}
{{/* We iterate through the different levels until arriving to the resource section. Example: a.b.c.resources */}}
{{- $section := $values -}}
{{- range $keys -}}
{{- $section = index $section . -}}
{{- end -}}
{{- if not (index $section "resources") -}}
{{/* If the section has enabled=false or replicaCount=0, do not include it */}}
{{- if and (hasKey $section "enabled") -}}
{{- if index $section "enabled" -}}
{{/* enabled=true */}}
{{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}}
{{- $printMessage = true -}}
{{- end -}}
{{- else if and (hasKey $section "replicaCount") -}}
{{/* We need a casting to int because number 0 is not treated as an int by default */}}
{{- if (gt (index $section "replicaCount" | int) 0) -}}
{{/* replicaCount > 0 */}}
{{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}}
{{- $printMessage = true -}}
{{- end -}}
{{- else -}}
{{/* Default case, add it to the affected sections */}}
{{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}}
{{- $printMessage = true -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if $printMessage }}
WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs:
{{- range $affectedSections }}
- {{ . }}
{{- end }}
+info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,77 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Validate Cassandra required passwords are not empty.
Usage:
{{ include "common.validations.values.cassandra.passwords" (dict "secret" "secretName" "subchart" false "context" $) }}
Params:
- secret - String - Required. Name of the secret where Cassandra values are stored, e.g: "cassandra-passwords-secret"
- subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false
*/}}
{{- define "common.validations.values.cassandra.passwords" -}}
{{- $existingSecret := include "common.cassandra.values.existingSecret" . -}}
{{- $enabled := include "common.cassandra.values.enabled" . -}}
{{- $dbUserPrefix := include "common.cassandra.values.key.dbUser" . -}}
{{- $valueKeyPassword := printf "%s.password" $dbUserPrefix -}}
{{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}}
{{- $requiredPasswords := list -}}
{{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "cassandra-password" -}}
{{- $requiredPasswords = append $requiredPasswords $requiredPassword -}}
{{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for existingSecret.
Usage:
{{ include "common.cassandra.values.existingSecret" (dict "context" $) }}
Params:
- subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false
*/}}
{{- define "common.cassandra.values.existingSecret" -}}
{{- if .subchart -}}
{{- .context.Values.cassandra.dbUser.existingSecret | quote -}}
{{- else -}}
{{- .context.Values.dbUser.existingSecret | quote -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for enabled cassandra.
Usage:
{{ include "common.cassandra.values.enabled" (dict "context" $) }}
*/}}
{{- define "common.cassandra.values.enabled" -}}
{{- if .subchart -}}
{{- printf "%v" .context.Values.cassandra.enabled -}}
{{- else -}}
{{- printf "%v" (not .context.Values.enabled) -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for the key dbUser
Usage:
{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }}
Params:
- subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false
*/}}
{{- define "common.cassandra.values.key.dbUser" -}}
{{- if .subchart -}}
cassandra.dbUser
{{- else -}}
dbUser
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,108 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Validate MariaDB required passwords are not empty.
Usage:
{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }}
Params:
- secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret"
- subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false
*/}}
{{- define "common.validations.values.mariadb.passwords" -}}
{{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}}
{{- $enabled := include "common.mariadb.values.enabled" . -}}
{{- $architecture := include "common.mariadb.values.architecture" . -}}
{{- $authPrefix := include "common.mariadb.values.key.auth" . -}}
{{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}}
{{- $valueKeyUsername := printf "%s.username" $authPrefix -}}
{{- $valueKeyPassword := printf "%s.password" $authPrefix -}}
{{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}}
{{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}}
{{- $requiredPasswords := list -}}
{{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}}
{{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}}
{{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }}
{{- if not (empty $valueUsername) -}}
{{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}}
{{- $requiredPasswords = append $requiredPasswords $requiredPassword -}}
{{- end -}}
{{- if (eq $architecture "replication") -}}
{{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}}
{{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}}
{{- end -}}
{{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for existingSecret.
Usage:
{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }}
Params:
- subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false
*/}}
{{- define "common.mariadb.values.auth.existingSecret" -}}
{{- if .subchart -}}
{{- .context.Values.mariadb.auth.existingSecret | quote -}}
{{- else -}}
{{- .context.Values.auth.existingSecret | quote -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for enabled mariadb.
Usage:
{{ include "common.mariadb.values.enabled" (dict "context" $) }}
*/}}
{{- define "common.mariadb.values.enabled" -}}
{{- if .subchart -}}
{{- printf "%v" .context.Values.mariadb.enabled -}}
{{- else -}}
{{- printf "%v" (not .context.Values.enabled) -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for architecture
Usage:
{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }}
Params:
- subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false
*/}}
{{- define "common.mariadb.values.architecture" -}}
{{- if .subchart -}}
{{- .context.Values.mariadb.architecture -}}
{{- else -}}
{{- .context.Values.architecture -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for the key auth
Usage:
{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }}
Params:
- subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false
*/}}
{{- define "common.mariadb.values.key.auth" -}}
{{- if .subchart -}}
mariadb.auth
{{- else -}}
auth
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,113 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Validate MongoDB&reg; required passwords are not empty.
Usage:
{{ include "common.validations.values.mongodb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }}
Params:
- secret - String - Required. Name of the secret where MongoDB&reg; values are stored, e.g: "mongodb-passwords-secret"
- subchart - Boolean - Optional. Whether MongoDB&reg; is used as subchart or not. Default: false
*/}}
{{- define "common.validations.values.mongodb.passwords" -}}
{{- $existingSecret := include "common.mongodb.values.auth.existingSecret" . -}}
{{- $enabled := include "common.mongodb.values.enabled" . -}}
{{- $authPrefix := include "common.mongodb.values.key.auth" . -}}
{{- $architecture := include "common.mongodb.values.architecture" . -}}
{{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}}
{{- $valueKeyUsername := printf "%s.username" $authPrefix -}}
{{- $valueKeyDatabase := printf "%s.database" $authPrefix -}}
{{- $valueKeyPassword := printf "%s.password" $authPrefix -}}
{{- $valueKeyReplicaSetKey := printf "%s.replicaSetKey" $authPrefix -}}
{{- $valueKeyAuthEnabled := printf "%s.enabled" $authPrefix -}}
{{- $authEnabled := include "common.utils.getValueFromKey" (dict "key" $valueKeyAuthEnabled "context" .context) -}}
{{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") (eq $authEnabled "true") -}}
{{- $requiredPasswords := list -}}
{{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mongodb-root-password" -}}
{{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}}
{{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }}
{{- $valueDatabase := include "common.utils.getValueFromKey" (dict "key" $valueKeyDatabase "context" .context) }}
{{- if and $valueUsername $valueDatabase -}}
{{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mongodb-password" -}}
{{- $requiredPasswords = append $requiredPasswords $requiredPassword -}}
{{- end -}}
{{- if (eq $architecture "replicaset") -}}
{{- $requiredReplicaSetKey := dict "valueKey" $valueKeyReplicaSetKey "secret" .secret "field" "mongodb-replica-set-key" -}}
{{- $requiredPasswords = append $requiredPasswords $requiredReplicaSetKey -}}
{{- end -}}
{{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for existingSecret.
Usage:
{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }}
Params:
- subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false
*/}}
{{- define "common.mongodb.values.auth.existingSecret" -}}
{{- if .subchart -}}
{{- .context.Values.mongodb.auth.existingSecret | quote -}}
{{- else -}}
{{- .context.Values.auth.existingSecret | quote -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for enabled mongodb.
Usage:
{{ include "common.mongodb.values.enabled" (dict "context" $) }}
*/}}
{{- define "common.mongodb.values.enabled" -}}
{{- if .subchart -}}
{{- printf "%v" .context.Values.mongodb.enabled -}}
{{- else -}}
{{- printf "%v" (not .context.Values.enabled) -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for the key auth
Usage:
{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }}
Params:
- subchart - Boolean - Optional. Whether MongoDB&reg; is used as subchart or not. Default: false
*/}}
{{- define "common.mongodb.values.key.auth" -}}
{{- if .subchart -}}
mongodb.auth
{{- else -}}
auth
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for architecture
Usage:
{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }}
Params:
- subchart - Boolean - Optional. Whether MongoDB&reg; is used as subchart or not. Default: false
*/}}
{{- define "common.mongodb.values.architecture" -}}
{{- if .subchart -}}
{{- .context.Values.mongodb.architecture -}}
{{- else -}}
{{- .context.Values.architecture -}}
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,108 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Validate MySQL required passwords are not empty.
Usage:
{{ include "common.validations.values.mysql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }}
Params:
- secret - String - Required. Name of the secret where MySQL values are stored, e.g: "mysql-passwords-secret"
- subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false
*/}}
{{- define "common.validations.values.mysql.passwords" -}}
{{- $existingSecret := include "common.mysql.values.auth.existingSecret" . -}}
{{- $enabled := include "common.mysql.values.enabled" . -}}
{{- $architecture := include "common.mysql.values.architecture" . -}}
{{- $authPrefix := include "common.mysql.values.key.auth" . -}}
{{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}}
{{- $valueKeyUsername := printf "%s.username" $authPrefix -}}
{{- $valueKeyPassword := printf "%s.password" $authPrefix -}}
{{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}}
{{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}}
{{- $requiredPasswords := list -}}
{{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mysql-root-password" -}}
{{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}}
{{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }}
{{- if not (empty $valueUsername) -}}
{{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mysql-password" -}}
{{- $requiredPasswords = append $requiredPasswords $requiredPassword -}}
{{- end -}}
{{- if (eq $architecture "replication") -}}
{{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mysql-replication-password" -}}
{{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}}
{{- end -}}
{{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for existingSecret.
Usage:
{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }}
Params:
- subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false
*/}}
{{- define "common.mysql.values.auth.existingSecret" -}}
{{- if .subchart -}}
{{- .context.Values.mysql.auth.existingSecret | quote -}}
{{- else -}}
{{- .context.Values.auth.existingSecret | quote -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for enabled mysql.
Usage:
{{ include "common.mysql.values.enabled" (dict "context" $) }}
*/}}
{{- define "common.mysql.values.enabled" -}}
{{- if .subchart -}}
{{- printf "%v" .context.Values.mysql.enabled -}}
{{- else -}}
{{- printf "%v" (not .context.Values.enabled) -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for architecture
Usage:
{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }}
Params:
- subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false
*/}}
{{- define "common.mysql.values.architecture" -}}
{{- if .subchart -}}
{{- .context.Values.mysql.architecture -}}
{{- else -}}
{{- .context.Values.architecture -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for the key auth
Usage:
{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }}
Params:
- subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false
*/}}
{{- define "common.mysql.values.key.auth" -}}
{{- if .subchart -}}
mysql.auth
{{- else -}}
auth
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,134 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Validate PostgreSQL required passwords are not empty.
Usage:
{{ include "common.validations.values.postgresql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }}
Params:
- secret - String - Required. Name of the secret where postgresql values are stored, e.g: "postgresql-passwords-secret"
- subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false
*/}}
{{- define "common.validations.values.postgresql.passwords" -}}
{{- $existingSecret := include "common.postgresql.values.existingSecret" . -}}
{{- $enabled := include "common.postgresql.values.enabled" . -}}
{{- $valueKeyPostgresqlPassword := include "common.postgresql.values.key.postgressPassword" . -}}
{{- $valueKeyPostgresqlReplicationEnabled := include "common.postgresql.values.key.replicationPassword" . -}}
{{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}}
{{- $requiredPasswords := list -}}
{{- $requiredPostgresqlPassword := dict "valueKey" $valueKeyPostgresqlPassword "secret" .secret "field" "postgresql-password" -}}
{{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlPassword -}}
{{- $enabledReplication := include "common.postgresql.values.enabled.replication" . -}}
{{- if (eq $enabledReplication "true") -}}
{{- $requiredPostgresqlReplicationPassword := dict "valueKey" $valueKeyPostgresqlReplicationEnabled "secret" .secret "field" "postgresql-replication-password" -}}
{{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlReplicationPassword -}}
{{- end -}}
{{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to decide whether evaluate global values.
Usage:
{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }}
Params:
- key - String - Required. Field to be evaluated within global, e.g: "existingSecret"
*/}}
{{- define "common.postgresql.values.use.global" -}}
{{- if .context.Values.global -}}
{{- if .context.Values.global.postgresql -}}
{{- index .context.Values.global.postgresql .key | quote -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for existingSecret.
Usage:
{{ include "common.postgresql.values.existingSecret" (dict "context" $) }}
*/}}
{{- define "common.postgresql.values.existingSecret" -}}
{{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}}
{{- if .subchart -}}
{{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}}
{{- else -}}
{{- default (.context.Values.existingSecret | quote) $globalValue -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for enabled postgresql.
Usage:
{{ include "common.postgresql.values.enabled" (dict "context" $) }}
*/}}
{{- define "common.postgresql.values.enabled" -}}
{{- if .subchart -}}
{{- printf "%v" .context.Values.postgresql.enabled -}}
{{- else -}}
{{- printf "%v" (not .context.Values.enabled) -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for the key postgressPassword.
Usage:
{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }}
Params:
- subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false
*/}}
{{- define "common.postgresql.values.key.postgressPassword" -}}
{{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}}
{{- if not $globalValue -}}
{{- if .subchart -}}
postgresql.postgresqlPassword
{{- else -}}
postgresqlPassword
{{- end -}}
{{- else -}}
global.postgresql.postgresqlPassword
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for enabled.replication.
Usage:
{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }}
Params:
- subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false
*/}}
{{- define "common.postgresql.values.enabled.replication" -}}
{{- if .subchart -}}
{{- printf "%v" .context.Values.postgresql.replication.enabled -}}
{{- else -}}
{{- printf "%v" .context.Values.replication.enabled -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for the key replication.password.
Usage:
{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }}
Params:
- subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false
*/}}
{{- define "common.postgresql.values.key.replicationPassword" -}}
{{- if .subchart -}}
postgresql.replication.password
{{- else -}}
replication.password
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,81 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Validate Redis&reg; required passwords are not empty.
Usage:
{{ include "common.validations.values.redis.passwords" (dict "secret" "secretName" "subchart" false "context" $) }}
Params:
- secret - String - Required. Name of the secret where redis values are stored, e.g: "redis-passwords-secret"
- subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false
*/}}
{{- define "common.validations.values.redis.passwords" -}}
{{- $enabled := include "common.redis.values.enabled" . -}}
{{- $valueKeyPrefix := include "common.redis.values.keys.prefix" . -}}
{{- $standarizedVersion := include "common.redis.values.standarized.version" . }}
{{- $existingSecret := ternary (printf "%s%s" $valueKeyPrefix "auth.existingSecret") (printf "%s%s" $valueKeyPrefix "existingSecret") (eq $standarizedVersion "true") }}
{{- $existingSecretValue := include "common.utils.getValueFromKey" (dict "key" $existingSecret "context" .context) }}
{{- $valueKeyRedisPassword := ternary (printf "%s%s" $valueKeyPrefix "auth.password") (printf "%s%s" $valueKeyPrefix "password") (eq $standarizedVersion "true") }}
{{- $valueKeyRedisUseAuth := ternary (printf "%s%s" $valueKeyPrefix "auth.enabled") (printf "%s%s" $valueKeyPrefix "usePassword") (eq $standarizedVersion "true") }}
{{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}}
{{- $requiredPasswords := list -}}
{{- $useAuth := include "common.utils.getValueFromKey" (dict "key" $valueKeyRedisUseAuth "context" .context) -}}
{{- if eq $useAuth "true" -}}
{{- $requiredRedisPassword := dict "valueKey" $valueKeyRedisPassword "secret" .secret "field" "redis-password" -}}
{{- $requiredPasswords = append $requiredPasswords $requiredRedisPassword -}}
{{- end -}}
{{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right value for enabled redis.
Usage:
{{ include "common.redis.values.enabled" (dict "context" $) }}
*/}}
{{- define "common.redis.values.enabled" -}}
{{- if .subchart -}}
{{- printf "%v" .context.Values.redis.enabled -}}
{{- else -}}
{{- printf "%v" (not .context.Values.enabled) -}}
{{- end -}}
{{- end -}}
{{/*
Auxiliary function to get the right prefix path for the values
Usage:
{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }}
Params:
- subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false
*/}}
{{- define "common.redis.values.keys.prefix" -}}
{{- if .subchart -}}redis.{{- else -}}{{- end -}}
{{- end -}}
{{/*
Checks whether the redis chart's includes the standarizations (version >= 14)
Usage:
{{ include "common.redis.values.standarized.version" (dict "context" $) }}
*/}}
{{- define "common.redis.values.standarized.version" -}}
{{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}}
{{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }}
{{- if $standarizedAuthValues -}}
{{- true -}}
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,51 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Validate values must not be empty.
Usage:
{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}}
{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}}
{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }}
Validate value params:
- valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password"
- secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret"
- field - String - Optional. Name of the field in the secret data, e.g: "mysql-password"
*/}}
{{- define "common.validations.values.multiple.empty" -}}
{{- range .required -}}
{{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}}
{{- end -}}
{{- end -}}
{{/*
Validate a value must not be empty.
Usage:
{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }}
Validate value params:
- valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password"
- secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret"
- field - String - Optional. Name of the field in the secret data, e.g: "mysql-password"
- subchart - String - Optional - Name of the subchart that the validated password is part of.
*/}}
{{- define "common.validations.values.single.empty" -}}
{{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }}
{{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }}
{{- if not $value -}}
{{- $varname := "my-value" -}}
{{- $getCurrentValue := "" -}}
{{- if and .secret .field -}}
{{- $varname = include "common.utils.fieldToEnvVar" . -}}
{{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}}
{{- end -}}
{{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}}
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,8 @@
# Copyright Broadcom, Inc. All Rights Reserved.
# SPDX-License-Identifier: APACHE-2.0
## bitnami/common
## It is required by CI/CD tools and processes.
## @skip exampleValue
##
exampleValue: common-chart

View File

@ -0,0 +1,78 @@
CHART NAME: {{ .Chart.Name }}
CHART VERSION: {{ .Chart.Version }}
APP VERSION: {{ .Chart.AppVersion }}
{{- if and (not .Values.auth.client.enabled) (eq .Values.service.type "LoadBalancer") }}
-------------------------------------------------------------------------------
WARNING
By specifying "serviceType=LoadBalancer" and not specifying "auth.enabled=true"
you have most likely exposed the ZooKeeper service externally without any
authentication mechanism.
For security reasons, we strongly suggest that you switch to "ClusterIP" or
"NodePort". As alternative, you can also specify a valid password on the
"auth.clientPassword" parameter.
-------------------------------------------------------------------------------
{{- end }}
** Please be patient while the chart is being deployed **
{{- if .Values.diagnosticMode.enabled }}
The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with:
command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }}
args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }}
Get the list of pods by executing:
kubectl get pods --namespace {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }}
Access the pod you want to debug by executing
kubectl exec --namespace {{ .Release.Namespace }} -ti <NAME OF THE POD> -- bash
In order to replicate the container startup scripts execute this command:
/opt/bitnami/scripts/zookeeper/entrypoint.sh /opt/bitnami/scripts/zookeeper/run.sh
{{- else }}
ZooKeeper can be accessed via port {{ .Values.service.ports.client }} on the following DNS name from within your cluster:
{{ template "common.names.fullname" . }}.{{ template "zookeeper.namespace" . }}.svc.{{ .Values.clusterDomain }}
To connect to your ZooKeeper server run the following commands:
export POD_NAME=$(kubectl get pods --namespace {{ template "zookeeper.namespace" . }} -l "app.kubernetes.io/name={{ template "common.names.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=zookeeper" -o jsonpath="{.items[0].metadata.name}")
kubectl exec -it $POD_NAME -- zkCli.sh
To connect to your ZooKeeper server from outside the cluster execute the following commands:
{{- if eq .Values.service.type "NodePort" }}
export NODE_IP=$(kubectl get nodes --namespace {{ template "zookeeper.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}")
export NODE_PORT=$(kubectl get --namespace {{ template "zookeeper.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "common.names.fullname" . }})
zkCli.sh $NODE_IP:$NODE_PORT
{{- else if eq .Values.service.type "LoadBalancer" }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
Watch the status with: 'kubectl get svc --namespace {{ template "zookeeper.namespace" . }} -w {{ template "common.names.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ template "zookeeper.namespace" . }} {{ template "common.names.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}")
zkCli.sh $SERVICE_IP:{{ .Values.service.ports.client }}
{{- else if eq .Values.service.type "ClusterIP" }}
kubectl port-forward --namespace {{ template "zookeeper.namespace" . }} svc/{{ template "common.names.fullname" . }} {{ .Values.service.ports.client }}:{{ .Values.containerPorts.client }} &
zkCli.sh 127.0.0.1:{{ .Values.service.ports.client }}
{{- end }}
{{- end }}
{{- include "zookeeper.validateValues" . }}
{{- include "zookeeper.checkRollingTags" . }}
{{- include "common.warnings.resources" (dict "sections" (list "" "tls" "volumePermissions") "context" $) }}
{{- include "common.warnings.modifiedImages" (dict "images" (list .Values.image .Values.volumePermissions.image) "context" $) }}

View File

@ -0,0 +1,352 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Return the proper ZooKeeper image name
*/}}
{{- define "zookeeper.image" -}}
{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }}
{{- end -}}
{{/*
Return the proper image name (for the init container volume-permissions image)
*/}}
{{- define "zookeeper.volumePermissions.image" -}}
{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }}
{{- end -}}
{{/*
Return the proper Docker Image Registry Secret Names
*/}}
{{- define "zookeeper.imagePullSecrets" -}}
{{- include "common.images.pullSecrets" (dict "images" (list .Values.image .Values.volumePermissions.image) "global" .Values.global) -}}
{{- end -}}
{{/*
Check if there are rolling tags in the images
*/}}
{{- define "zookeeper.checkRollingTags" -}}
{{- include "common.warnings.rollingTag" .Values.image }}
{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }}
{{- end -}}
{{/*
Return ZooKeeper Namespace to use
*/}}
{{- define "zookeeper.namespace" -}}
{{- if .Values.namespaceOverride -}}
{{- .Values.namespaceOverride -}}
{{- else -}}
{{- .Release.Namespace -}}
{{- end -}}
{{- end -}}
{{/*
Create the name of the service account to use
*/}}
{{- define "zookeeper.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
{{ default (include "common.names.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
{{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}
{{/*
Return the ZooKeeper client-server authentication credentials secret
*/}}
{{- define "zookeeper.client.secretName" -}}
{{- if .Values.auth.client.existingSecret -}}
{{- printf "%s" (tpl .Values.auth.client.existingSecret $) -}}
{{- else -}}
{{- printf "%s-client-auth" (include "common.names.fullname" .) -}}
{{- end -}}
{{- end -}}
{{/*
Return the ZooKeeper server-server authentication credentials secret
*/}}
{{- define "zookeeper.quorum.secretName" -}}
{{- if .Values.auth.quorum.existingSecret -}}
{{- printf "%s" (tpl .Values.auth.quorum.existingSecret $) -}}
{{- else -}}
{{- printf "%s-quorum-auth" (include "common.names.fullname" .) -}}
{{- end -}}
{{- end -}}
{{/*
Return true if a ZooKeeper client-server authentication credentials secret object should be created
*/}}
{{- define "zookeeper.client.createSecret" -}}
{{- if and .Values.auth.client.enabled (empty .Values.auth.client.existingSecret) -}}
{{- true -}}
{{- end -}}
{{- end -}}
{{/*
Return true if a ZooKeeper server-server authentication credentials secret object should be created
*/}}
{{- define "zookeeper.quorum.createSecret" -}}
{{- if and .Values.auth.quorum.enabled (empty .Values.auth.quorum.existingSecret) -}}
{{- true -}}
{{- end -}}
{{- end -}}
{{/*
Return the ZooKeeper configuration ConfigMap name
*/}}
{{- define "zookeeper.configmapName" -}}
{{- if .Values.existingConfigmap -}}
{{- printf "%s" (tpl .Values.existingConfigmap $) -}}
{{- else -}}
{{- printf "%s" (include "common.names.fullname" .) -}}
{{- end -}}
{{- end -}}
{{/*
Return true if a ConfigMap object should be created for ZooKeeper configuration
*/}}
{{- define "zookeeper.createConfigmap" -}}
{{- if and .Values.configuration (not .Values.existingConfigmap) }}
{{- true -}}
{{- end -}}
{{- end -}}
{{/*
Return true if a TLS secret should be created for ZooKeeper quorum
*/}}
{{- define "zookeeper.quorum.createTlsSecret" -}}
{{- if and .Values.tls.quorum.enabled .Values.tls.quorum.autoGenerated (not .Values.tls.quorum.existingSecret) }}
{{- true -}}
{{- end -}}
{{- end -}}
{{/*
Return the secret containing ZooKeeper quorum TLS certificates
*/}}
{{- define "zookeeper.quorum.tlsSecretName" -}}
{{- $secretName := .Values.tls.quorum.existingSecret -}}
{{- if $secretName -}}
{{- printf "%s" (tpl $secretName $) -}}
{{- else -}}
{{- printf "%s-quorum-crt" (include "common.names.fullname" .) -}}
{{- end -}}
{{- end -}}
{{/*
Return true if a secret containing the Keystore and Truststore password should be created for ZooKeeper quorum
*/}}
{{- define "zookeeper.quorum.createTlsPasswordsSecret" -}}
{{- if and .Values.tls.quorum.enabled (not .Values.tls.quorum.passwordsSecretName) }}
{{- true -}}
{{- end -}}
{{- end -}}
{{/*
Return the name of the secret containing the Keystore and Truststore password
*/}}
{{- define "zookeeper.quorum.tlsPasswordsSecret" -}}
{{- $secretName := .Values.tls.quorum.passwordsSecretName -}}
{{- if $secretName -}}
{{- printf "%s" (tpl $secretName $) -}}
{{- else -}}
{{- printf "%s-quorum-tls-pass" (include "common.names.fullname" .) -}}
{{- end -}}
{{- end -}}
{{/*
Return true if a TLS secret should be created for ZooKeeper client
*/}}
{{- define "zookeeper.client.createTlsSecret" -}}
{{- if and .Values.tls.client.enabled .Values.tls.client.autoGenerated (not .Values.tls.client.existingSecret) }}
{{- true -}}
{{- end -}}
{{- end -}}
{{/*
Return the secret containing ZooKeeper client TLS certificates
*/}}
{{- define "zookeeper.client.tlsSecretName" -}}
{{- $secretName := .Values.tls.client.existingSecret -}}
{{- if $secretName -}}
{{- printf "%s" (tpl $secretName $) -}}
{{- else -}}
{{- printf "%s-client-crt" (include "common.names.fullname" .) -}}
{{- end -}}
{{- end -}}
{{/*
Get the quorum keystore key to be retrieved from tls.quorum.existingSecret.
*/}}
{{- define "zookeeper.quorum.tlsKeystoreKey" -}}
{{- if and .Values.tls.quorum.existingSecret .Values.tls.quorum.existingSecretKeystoreKey -}}
{{- printf "%s" .Values.tls.quorum.existingSecretKeystoreKey -}}
{{- else -}}
{{- printf "zookeeper.keystore.jks" -}}
{{- end -}}
{{- end -}}
{{/*
Get the quorum truststore key to be retrieved from tls.quorum.existingSecret.
*/}}
{{- define "zookeeper.quorum.tlsTruststoreKey" -}}
{{- if and .Values.tls.quorum.existingSecret .Values.tls.quorum.existingSecretTruststoreKey -}}
{{- printf "%s" .Values.tls.quorum.existingSecretTruststoreKey -}}
{{- else -}}
{{- printf "zookeeper.truststore.jks" -}}
{{- end -}}
{{- end -}}
{{/*
Get the client keystore key to be retrieved from tls.client.existingSecret.
*/}}
{{- define "zookeeper.client.tlsKeystoreKey" -}}
{{- if and .Values.tls.client.existingSecret .Values.tls.client.existingSecretKeystoreKey -}}
{{- printf "%s" .Values.tls.client.existingSecretKeystoreKey -}}
{{- else -}}
{{- printf "zookeeper.keystore.jks" -}}
{{- end -}}
{{- end -}}
{{/*
Get the client truststore key to be retrieved from tls.client.existingSecret.
*/}}
{{- define "zookeeper.client.tlsTruststoreKey" -}}
{{- if and .Values.tls.client.existingSecret .Values.tls.client.existingSecretTruststoreKey -}}
{{- printf "%s" .Values.tls.client.existingSecretTruststoreKey -}}
{{- else -}}
{{- printf "zookeeper.truststore.jks" -}}
{{- end -}}
{{- end -}}
{{/*
Return true if a secret containing the Keystore and Truststore password should be created for ZooKeeper client
*/}}
{{- define "zookeeper.client.createTlsPasswordsSecret" -}}
{{- if and .Values.tls.client.enabled (not .Values.tls.client.passwordsSecretName) }}
{{- true -}}
{{- end -}}
{{- end -}}
{{/*
Return the name of the secret containing the Keystore and Truststore password
*/}}
{{- define "zookeeper.client.tlsPasswordsSecret" -}}
{{- $secretName := .Values.tls.client.passwordsSecretName -}}
{{- if $secretName -}}
{{- printf "%s" (tpl $secretName $) -}}
{{- else -}}
{{- printf "%s-client-tls-pass" (include "common.names.fullname" .) -}}
{{- end -}}
{{- end -}}
{{/*
Get the quorum keystore password key to be retrieved from tls.quorum.passwordSecretName.
*/}}
{{- define "zookeeper.quorum.tlsPasswordKeystoreKey" -}}
{{- if and .Values.tls.quorum.passwordsSecretName .Values.tls.quorum.passwordsSecretKeystoreKey -}}
{{- printf "%s" .Values.tls.quorum.passwordsSecretKeystoreKey -}}
{{- else -}}
{{- printf "keystore-password" -}}
{{- end -}}
{{- end -}}
{{/*
Get the quorum truststore password key to be retrieved from tls.quorum.passwordSecretName.
*/}}
{{- define "zookeeper.quorum.tlsPasswordTruststoreKey" -}}
{{- if and .Values.tls.quorum.passwordsSecretName .Values.tls.quorum.passwordsSecretTruststoreKey -}}
{{- printf "%s" .Values.tls.quorum.passwordsSecretTruststoreKey -}}
{{- else -}}
{{- printf "truststore-password" -}}
{{- end -}}
{{- end -}}
{{/*
Get the client keystore password key to be retrieved from tls.client.passwordSecretName.
*/}}
{{- define "zookeeper.client.tlsPasswordKeystoreKey" -}}
{{- if and .Values.tls.client.passwordsSecretName .Values.tls.client.passwordsSecretKeystoreKey -}}
{{- printf "%s" .Values.tls.client.passwordsSecretKeystoreKey -}}
{{- else -}}
{{- printf "keystore-password" -}}
{{- end -}}
{{- end -}}
{{/*
Get the client truststore password key to be retrieved from tls.client.passwordSecretName.
*/}}
{{- define "zookeeper.client.tlsPasswordTruststoreKey" -}}
{{- if and .Values.tls.client.passwordsSecretName .Values.tls.client.passwordsSecretTruststoreKey -}}
{{- printf "%s" .Values.tls.client.passwordsSecretTruststoreKey -}}
{{- else -}}
{{- printf "truststore-password" -}}
{{- end -}}
{{- end -}}
{{/*
Compile all warnings into a single message.
*/}}
{{- define "zookeeper.validateValues" -}}
{{- $messages := list -}}
{{- $messages := append $messages (include "zookeeper.validateValues.client.auth" .) -}}
{{- $messages := append $messages (include "zookeeper.validateValues.quorum.auth" .) -}}
{{- $messages := append $messages (include "zookeeper.validateValues.client.tls" .) -}}
{{- $messages := append $messages (include "zookeeper.validateValues.quorum.tls" .) -}}
{{- $messages := without $messages "" -}}
{{- $message := join "\n" $messages -}}
{{- if $message -}}
{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}}
{{- end -}}
{{- end -}}
{{/*
Validate values of ZooKeeper - Authentication enabled
*/}}
{{- define "zookeeper.validateValues.client.auth" -}}
{{- if and .Values.auth.client.enabled (not .Values.auth.client.existingSecret) (or (not .Values.auth.client.clientUser) (not .Values.auth.client.serverUsers)) }}
zookeeper: auth.client.enabled
In order to enable client-server authentication, you need to provide the list
of users to be created and the user to use for clients authentication.
{{- end -}}
{{- end -}}
{{/*
Validate values of ZooKeeper - Authentication enabled
*/}}
{{- define "zookeeper.validateValues.quorum.auth" -}}
{{- if and .Values.auth.quorum.enabled (not .Values.auth.quorum.existingSecret) (or (not .Values.auth.quorum.learnerUser) (not .Values.auth.quorum.serverUsers)) }}
zookeeper: auth.quorum.enabled
In order to enable server-server authentication, you need to provide the list
of users to be created and the user to use for quorum authentication.
{{- end -}}
{{- end -}}
{{/*
Validate values of ZooKeeper - Client TLS enabled
*/}}
{{- define "zookeeper.validateValues.client.tls" -}}
{{- if and .Values.tls.client.enabled (not .Values.tls.client.autoGenerated) (not .Values.tls.client.existingSecret) }}
zookeeper: tls.client.enabled
In order to enable Client TLS encryption, you also need to provide
an existing secret containing the Keystore and Truststore or
enable auto-generated certificates.
{{- end -}}
{{- end -}}
{{/*
Validate values of ZooKeeper - Quorum TLS enabled
*/}}
{{- define "zookeeper.validateValues.quorum.tls" -}}
{{- if and .Values.tls.quorum.enabled (not .Values.tls.quorum.autoGenerated) (not .Values.tls.quorum.existingSecret) }}
zookeeper: tls.quorum.enabled
In order to enable Quorum TLS, you also need to provide
an existing secret containing the Keystore and Truststore or
enable auto-generated certificates.
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,20 @@
{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{- if (include "zookeeper.createConfigmap" .) }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "common.names.fullname" . }}
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: zookeeper
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
data:
zoo.cfg: |-
{{- include "common.tplvalues.render" ( dict "value" .Values.configuration "context" $ ) | nindent 4 }}
{{- end }}

View File

@ -0,0 +1,9 @@
{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{- range .Values.extraDeploy }}
---
{{ include "common.tplvalues.render" (dict "value" . "context" $) }}
{{- end }}

View File

@ -0,0 +1,27 @@
{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{- if .Values.metrics.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ template "common.names.fullname" . }}-metrics
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: metrics
{{- if or .Values.metrics.service.annotations .Values.commonAnnotations }}
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.annotations .Values.commonAnnotations ) "context" . ) }}
annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.metrics.service.type }}
ports:
- name: tcp-metrics
port: {{ .Values.metrics.service.port }}
targetPort: metrics
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }}
selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: zookeeper
{{- end }}

View File

@ -0,0 +1,86 @@
{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{- if .Values.networkPolicy.enabled }}
kind: NetworkPolicy
apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }}
metadata:
name: {{ include "common.names.fullname" . }}
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
spec:
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }}
podSelector:
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }}
policyTypes:
- Ingress
- Egress
{{- if .Values.networkPolicy.allowExternalEgress }}
egress:
- {}
{{- else }}
egress:
# Allow dns resolution
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
# Allow internal communications between nodes
- ports:
- port: {{ .Values.containerPorts.follower }}
- port: {{ .Values.containerPorts.election }}
to:
- podSelector:
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }}
{{- if .Values.networkPolicy.extraEgress }}
{{- include "common.tplvalues.render" ( dict "value" .Values.rts.networkPolicy.extraEgress "context" $ ) | nindent 4 }}
{{- end }}
{{- end }}
ingress:
# Allow inbound connections to ZooKeeper
- ports:
- port: {{ .Values.containerPorts.client }}
{{- if .Values.metrics.enabled }}
- port: {{ coalesce .Values.metrics.containerPort .Values.containerPorts.metrics }}
{{- end }}
{{- if not .Values.networkPolicy.allowExternal }}
from:
- podSelector:
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }}
- podSelector:
matchLabels:
{{ include "common.names.fullname" . }}-client: "true"
- podSelector:
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 14 }}
{{- if .Values.networkPolicy.ingressNSMatchLabels }}
- namespaceSelector:
matchLabels:
{{- range $key, $value := .Values.networkPolicy.ingressNSMatchLabels }}
{{ $key | quote }}: {{ $value | quote }}
{{- end }}
{{- if .Values.networkPolicy.ingressNSPodMatchLabels }}
podSelector:
matchLabels:
{{- range $key, $value := .Values.networkPolicy.ingressNSPodMatchLabels }}
{{ $key | quote }}: {{ $value | quote }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
# Allow internal communications between nodes
- ports:
- port: {{ .Values.containerPorts.follower }}
- port: {{ .Values.containerPorts.election }}
from:
- podSelector:
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 14 }}
{{- if .Values.networkPolicy.extraIngress }}
{{- include "common.tplvalues.render" ( dict "value" .Values.networkPolicy.extraIngress "context" $ ) | nindent 4 }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,28 @@
{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{- if .Values.pdb.create }}
apiVersion: {{ include "common.capabilities.policy.apiVersion" . }}
kind: PodDisruptionBudget
metadata:
name: {{ template "common.names.fullname" . }}
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: zookeeper
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
spec:
{{- if .Values.pdb.minAvailable }}
minAvailable: {{ .Values.pdb.minAvailable }}
{{- end }}
{{- if or .Values.pdb.maxUnavailable (not .Values.pdb.minAvailable) }}
maxUnavailable: {{ .Values.pdb.maxUnavailable | default 1 }}
{{- end }}
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }}
selector:
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }}
app.kubernetes.io/component: zookeeper
{{- end }}

View File

@ -0,0 +1,25 @@
{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled .Values.metrics.prometheusRule.rules }}
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: {{ include "common.names.fullname" . }}
namespace: {{ default .Release.Namespace .Values.metrics.prometheusRule.namespace | quote }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: metrics
{{- if .Values.metrics.prometheusRule.additionalLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.additionalLabels "context" $ ) | nindent 4 }}
{{- end }}
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
spec:
groups:
- name: {{ include "common.names.fullname" . }}
rules: {{- toYaml .Values.metrics.prometheusRule.rules | nindent 8 }}
{{- end }}

View File

@ -0,0 +1,104 @@
{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-scripts" (include "common.names.fullname" .) }}
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: zookeeper
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
data:
init-certs.sh: |-
#!/bin/bash
{{- if .Values.tls.client.enabled }}
if [[ -f "/certs/client/tls.key" ]] && [[ -f "/certs/client/tls.crt" ]] && [[ -f "/certs/client/ca.crt" ]]; then
if [[ -f "/opt/bitnami/zookeeper/config/certs/client/.initialized" ]]; then
exit 0
fi
openssl pkcs12 -export -in "/certs/client/tls.crt" \
-passout pass:"${ZOO_TLS_CLIENT_KEYSTORE_PASSWORD}" \
-inkey "/certs/client/tls.key" \
-out "/tmp/keystore.p12"
keytool -importkeystore -srckeystore "/tmp/keystore.p12" \
-srcstoretype PKCS12 \
-srcstorepass "${ZOO_TLS_CLIENT_KEYSTORE_PASSWORD}" \
-deststorepass "${ZOO_TLS_CLIENT_KEYSTORE_PASSWORD}" \
-destkeystore "/opt/bitnami/zookeeper/config/certs/client/zookeeper.keystore.jks"
rm "/tmp/keystore.p12"
keytool -import -file "/certs/client/ca.crt" \
-keystore "/opt/bitnami/zookeeper/config/certs/client/zookeeper.truststore.jks" \
-storepass "${ZOO_TLS_CLIENT_TRUSTSTORE_PASSWORD}" \
-noprompt
touch /opt/bitnami/zookeeper/config/certs/client/.initialized
{{- if .Values.tls.client.autoGenerated }}
else
echo "Couldn't find the expected PEM certificates! They are mandatory when Client encryption via TLS is enabled."
exit 1
fi
{{- else }}
elif [[ -f {{ printf "/certs/client/%s" (include "zookeeper.client.tlsTruststoreKey" .) | quote }} ]] && [[ -f {{ printf "/certs/client/%s" (include "zookeeper.client.tlsKeystoreKey" .) | quote }} ]]; then
cp {{ printf "/certs/client/%s" (include "zookeeper.client.tlsTruststoreKey" .) | quote }} "/opt/bitnami/zookeeper/config/certs/client/zookeeper.truststore.jks"
cp {{ printf "/certs/client/%s" (include "zookeeper.client.tlsKeystoreKey" .) | quote }} "/opt/bitnami/zookeeper/config/certs/client/zookeeper.keystore.jks"
else
echo "Couldn't find the expected Java Key Stores (JKS) files! They are mandatory when Client encryption via TLS is enabled."
exit 1
fi
{{- end }}
{{- end }}
{{- if .Values.tls.quorum.enabled }}
if [[ -f "/certs/quorum/tls.key" ]] && [[ -f "/certs/quorum/tls.crt" ]] && [[ -f "/certs/quorum/ca.crt" ]]; then
openssl pkcs12 -export -in "/certs/quorum/tls.crt" \
-passout pass:"${ZOO_TLS_QUORUM_KEYSTORE_PASSWORD}" \
-inkey "/certs/quorum/tls.key" \
-out "/tmp/keystore.p12"
keytool -importkeystore -srckeystore "/tmp/keystore.p12" \
-srcstoretype PKCS12 \
-srcstorepass "${ZOO_TLS_QUORUM_KEYSTORE_PASSWORD}" \
-deststorepass "${ZOO_TLS_QUORUM_KEYSTORE_PASSWORD}" \
-destkeystore "/opt/bitnami/zookeeper/config/certs/quorum/zookeeper.keystore.jks"
rm "/tmp/keystore.p12"
keytool -import -file "/certs/quorum/ca.crt" \
-keystore "/opt/bitnami/zookeeper/config/certs/quorum/zookeeper.truststore.jks" \
-storepass "${ZOO_TLS_QUORUM_TRUSTSTORE_PASSWORD}" \
-noprompt
{{- if .Values.tls.quorum.autoGenerated }}
else
echo "Couldn't find the expected PEM certificates! They are mandatory when encryption Quorum via TLS is enabled."
exit 1
fi
{{- else }}
elif [[ -f {{ printf "/certs/quorum/%s" (include "zookeeper.quorum.tlsTruststoreKey" .) | quote }} ]] && [[ -f {{ printf "/certs/quorum/%s" (include "zookeeper.quorum.tlsKeystoreKey" .) | quote }} ]]; then
cp {{ printf "/certs/quorum/%s" (include "zookeeper.quorum.tlsTruststoreKey" .) | quote }} "/opt/bitnami/zookeeper/config/certs/quorum/zookeeper.truststore.jks"
cp {{ printf "/certs/quorum/%s" (include "zookeeper.quorum.tlsKeystoreKey" .) | quote }} "/opt/bitnami/zookeeper/config/certs/quorum/zookeeper.keystore.jks"
else
echo "Couldn't find the expected Java Key Stores (JKS) files! They are mandatory when Quorum encryption via TLS is enabled."
exit 1
fi
{{- end }}
{{- end }}
setup.sh: |-
#!/bin/bash
# Execute entrypoint as usual after obtaining ZOO_SERVER_ID
# check ZOO_SERVER_ID in persistent volume via myid
# if not present, set based on POD hostname
if [[ -f "/bitnami/zookeeper/data/myid" ]]; then
export ZOO_SERVER_ID="$(cat /bitnami/zookeeper/data/myid)"
else
HOSTNAME="$(hostname -s)"
if [[ $HOSTNAME =~ (.*)-([0-9]+)$ ]]; then
ORD=${BASH_REMATCH[2]}
export ZOO_SERVER_ID="$((ORD + {{ .Values.minServerId }} ))"
else
echo "Failed to get index from hostname $HOSTNAME"
exit 1
fi
fi
exec /entrypoint.sh /run.sh

View File

@ -0,0 +1,70 @@
{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{- if (include "zookeeper.client.createSecret" .) }}
apiVersion: v1
kind: Secret
metadata:
name: {{ printf "%s-client-auth" (include "common.names.fullname" .) }}
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: zookeeper
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
type: Opaque
data:
client-password: {{ include "common.secrets.passwords.manage" (dict "secret" (printf "%s-client-auth" (include "common.names.fullname" .)) "key" "client-password" "providedValues" (list "auth.client.clientPassword") "context" $) }}
server-password: {{ include "common.secrets.passwords.manage" (dict "secret" (printf "%s-client-auth" (include "common.names.fullname" .)) "key" "server-password" "providedValues" (list "auth.client.serverPasswords") "context" $) }}
{{- end }}
{{- if (include "zookeeper.quorum.createSecret" .) }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ printf "%s-quorum-auth" (include "common.names.fullname" .) }}
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: zookeeper
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
type: Opaque
data:
quorum-learner-password: {{ include "common.secrets.passwords.manage" (dict "secret" (printf "%s-quorum-auth" (include "common.names.fullname" .)) "key" "quorum-learner-password" "providedValues" (list "auth.quorum.learnerPassword") "context" $) }}
quorum-server-password: {{ include "common.secrets.passwords.manage" (dict "secret" (printf "%s-quorum-auth" (include "common.names.fullname" .)) "key" "quorum-server-password" "providedValues" (list "auth.quorum.serverPasswords") "context" $) }}
{{- end }}
{{- if (include "zookeeper.client.createTlsPasswordsSecret" .) }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ template "common.names.fullname" . }}-client-tls-pass
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
type: Opaque
data:
keystore-password: {{ default (randAlphaNum 10) .Values.tls.client.keystorePassword | b64enc | quote }}
truststore-password: {{ default (randAlphaNum 10) .Values.tls.client.truststorePassword | b64enc | quote }}
{{- end }}
{{- if (include "zookeeper.quorum.createTlsPasswordsSecret" .) }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ template "common.names.fullname" . }}-quorum-tls-pass
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
type: Opaque
data:
keystore-password: {{ default (randAlphaNum 10) .Values.tls.quorum.keystorePassword | b64enc | quote }}
truststore-password: {{ default (randAlphaNum 10) .Values.tls.quorum.truststorePassword | b64enc | quote }}
{{- end }}

View File

@ -0,0 +1,20 @@
{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "zookeeper.serviceAccountName" . }}
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: zookeeper
role: zookeeper
{{- if or .Values.commonAnnotations .Values.serviceAccount.annotations }}
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }}
annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
{{- end }}
automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
{{- end }}

View File

@ -0,0 +1,51 @@
{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ template "common.names.fullname" . }}
namespace: {{ default .Release.Namespace .Values.metrics.serviceMonitor.namespace | quote }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: metrics
{{- if .Values.metrics.serviceMonitor.additionalLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.additionalLabels "context" $ ) | nindent 4 }}
{{- end }}
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
spec:
{{- if .Values.metrics.serviceMonitor.jobLabel }}
jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }}
{{- end }}
selector:
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }}
{{- if .Values.metrics.serviceMonitor.selector }}
{{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }}
{{- end }}
app.kubernetes.io/component: metrics
endpoints:
- port: tcp-metrics
path: "/metrics"
{{- if .Values.metrics.serviceMonitor.interval }}
interval: {{ .Values.metrics.serviceMonitor.interval }}
{{- end }}
{{- if .Values.metrics.serviceMonitor.scrapeTimeout }}
scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }}
{{- end }}
{{- if .Values.metrics.serviceMonitor.relabelings }}
relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 6 }}
{{- end }}
{{- if .Values.metrics.serviceMonitor.metricRelabelings }}
metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 6 }}
{{- end }}
{{- if .Values.metrics.serviceMonitor.honorLabels }}
honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }}
{{- end }}
namespaceSelector:
matchNames:
- {{ template "zookeeper.namespace" . }}
{{- end }}

View File

@ -0,0 +1,569 @@
{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }}
kind: StatefulSet
metadata:
name: {{ template "common.names.fullname" . }}
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: zookeeper
role: zookeeper
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.replicaCount }}
revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}
podManagementPolicy: {{ .Values.podManagementPolicy }}
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }}
selector:
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }}
app.kubernetes.io/component: zookeeper
serviceName: {{ printf "%s-%s" (include "common.names.fullname" .) (default "headless" .Values.service.headless.servicenameOverride) | trunc 63 | trimSuffix "-" }}
{{- if .Values.updateStrategy }}
updateStrategy: {{- toYaml .Values.updateStrategy | nindent 4 }}
{{- end }}
template:
metadata:
annotations:
{{- if .Values.podAnnotations }}
{{- include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }}
{{- end }}
{{- if (include "zookeeper.createConfigmap" .) }}
checksum/configuration: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
{{- end }}
{{- if or (include "zookeeper.quorum.createSecret" .) (include "zookeeper.client.createSecret" .) (include "zookeeper.client.createTlsPasswordsSecret" .) (include "zookeeper.quorum.createTlsPasswordsSecret" .) }}
checksum/secrets: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }}
{{- end }}
{{- if or (include "zookeeper.client.createTlsSecret" .) (include "zookeeper.quorum.createTlsSecret" .) }}
checksum/tls-secrets: {{ include (print $.Template.BasePath "/tls-secrets.yaml") . | sha256sum }}
{{- end }}
labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }}
app.kubernetes.io/component: zookeeper
spec:
enableServiceLinks: {{ .Values.enableServiceLinks }}
serviceAccountName: {{ template "zookeeper.serviceAccountName" . }}
{{- include "zookeeper.imagePullSecrets" . | nindent 6 }}
automountServiceAccountToken: {{ .Values.automountServiceAccountToken }}
{{- if .Values.hostAliases }}
hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }}
{{- end }}
{{- if .Values.affinity }}
affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }}
{{- else }}
affinity:
podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "component" "zookeeper" "customLabels" $podLabels "context" $) | nindent 10 }}
podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "component" "zookeeper" "customLabels" $podLabels "context" $) | nindent 10 }}
nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }}
{{- end }}
{{- if .Values.nodeSelector }}
nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }}
{{- end }}
{{- if .Values.tolerations }}
tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }}
{{- end }}
{{- if .Values.topologySpreadConstraints }}
topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.topologySpreadConstraints "context" .) | nindent 8 }}
{{- end }}
{{- if .Values.priorityClassName }}
priorityClassName: {{ .Values.priorityClassName }}
{{- end }}
{{- if .Values.schedulerName }}
schedulerName: {{ .Values.schedulerName }}
{{- end }}
{{- if .Values.podSecurityContext.enabled }}
securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 8 }}
{{- end }}
{{- if .Values.dnsPolicy }}
dnsPolicy: {{ .Values.dnsPolicy }}
{{- end }}
{{- if .Values.dnsConfig }}
dnsConfig: {{- include "common.tplvalues.render" (dict "value" .Values.dnsConfig "context" $) | nindent 8 }}
{{- end }}
initContainers:
{{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }}
- name: volume-permissions
image: {{ template "zookeeper.volumePermissions.image" . }}
imagePullPolicy: {{ default "" .Values.volumePermissions.image.pullPolicy | quote }}
command:
- /bin/bash
args:
- -ec
- |
mkdir -p /bitnami/zookeeper
chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} /bitnami/zookeeper
find /bitnami/zookeeper -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }}
{{- if .Values.dataLogDir }}
mkdir -p {{ .Values.dataLogDir }}
chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} {{ .Values.dataLogDir }}
find {{ .Values.dataLogDir }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }}
{{- end }}
{{- if .Values.volumePermissions.containerSecurityContext.enabled }}
securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.volumePermissions.containerSecurityContext "context" $) | nindent 12 }}
{{- end }}
{{- if .Values.volumePermissions.resources }}
resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }}
{{- else if ne .Values.volumePermissions.resourcesPreset "none" }}
resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }}
{{- end }}
volumeMounts:
- name: empty-dir
mountPath: /tmp
subPath: tmp-dir
- name: data
mountPath: /bitnami/zookeeper
{{- if .Values.dataLogDir }}
- name: data-log
mountPath: {{ .Values.dataLogDir }}
{{- end }}
{{- end }}
{{- if or .Values.tls.client.enabled .Values.tls.quorum.enabled }}
- name: init-certs
image: {{ include "zookeeper.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
{{- if .Values.containerSecurityContext.enabled }}
securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }}
{{- end }}
command:
- /scripts/init-certs.sh
env:
- name: MY_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
{{- if or .Values.tls.client.passwordsSecretName (include "zookeeper.client.createTlsPasswordsSecret" .) }}
- name: ZOO_TLS_CLIENT_KEYSTORE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "zookeeper.client.tlsPasswordsSecret" . }}
key: {{ include "zookeeper.client.tlsPasswordKeystoreKey" . }}
- name: ZOO_TLS_CLIENT_TRUSTSTORE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "zookeeper.client.tlsPasswordsSecret" . }}
key: {{ include "zookeeper.client.tlsPasswordTruststoreKey" . }}
{{- end }}
{{- if or .Values.tls.quorum.passwordsSecretName (include "zookeeper.quorum.createTlsPasswordsSecret" .) }}
- name: ZOO_TLS_QUORUM_KEYSTORE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "zookeeper.quorum.tlsPasswordsSecret" . }}
key: {{ include "zookeeper.quorum.tlsPasswordKeystoreKey" . }}
- name: ZOO_TLS_QUORUM_TRUSTSTORE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "zookeeper.quorum.tlsPasswordsSecret" . }}
key: {{ include "zookeeper.quorum.tlsPasswordTruststoreKey" . }}
{{- end }}
{{- if .Values.tls.resources }}
resources: {{- toYaml .Values.tls.resources | nindent 12 }}
{{- else if ne .Values.tls.resourcesPreset "none" }}
resources: {{- include "common.resources.preset" (dict "type" .Values.tls.resourcesPreset) | nindent 12 }}
{{- end }}
volumeMounts:
- name: empty-dir
mountPath: /tmp
subPath: tmp-dir
- name: scripts
mountPath: /scripts/init-certs.sh
subPath: init-certs.sh
{{- if or .Values.tls.client.enabled }}
- name: client-certificates
mountPath: /certs/client
- name: client-shared-certs
mountPath: /opt/bitnami/zookeeper/config/certs/client
{{- end }}
{{- if or .Values.tls.quorum.enabled }}
- name: quorum-certificates
mountPath: /certs/quorum
- name: quorum-shared-certs
mountPath: /opt/bitnami/zookeeper/config/certs/quorum
{{- end }}
{{- end }}
{{- if .Values.initContainers }}
{{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | trim | nindent 8 }}
{{- end }}
containers:
- name: zookeeper
image: {{ template "zookeeper.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
{{- if .Values.containerSecurityContext.enabled }}
securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }}
{{- end }}
{{- if .Values.diagnosticMode.enabled }}
command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }}
{{- else if .Values.command }}
command: {{- include "common.tplvalues.render" (dict "value" .Values.command "context" $) | nindent 12 }}
{{- end }}
{{- if .Values.diagnosticMode.enabled }}
args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }}
{{- else if .Values.args }}
args: {{- include "common.tplvalues.render" (dict "value" .Values.args "context" $) | nindent 12 }}
{{- end }}
{{- if .Values.resources }}
resources: {{- toYaml .Values.resources | nindent 12 }}
{{- else if ne .Values.resourcesPreset "none" }}
resources: {{- include "common.resources.preset" (dict "type" .Values.resourcesPreset) | nindent 12 }}
{{- end }}
env:
- name: BITNAMI_DEBUG
value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }}
- name: ZOO_DATA_LOG_DIR
value: {{ .Values.dataLogDir | quote }}
- name: ZOO_PORT_NUMBER
value: {{ .Values.containerPorts.client | quote }}
- name: ZOO_TICK_TIME
value: {{ .Values.tickTime | quote }}
- name: ZOO_INIT_LIMIT
value: {{ .Values.initLimit | quote }}
- name: ZOO_SYNC_LIMIT
value: {{ .Values.syncLimit | quote }}
- name: ZOO_PRE_ALLOC_SIZE
value: {{ .Values.preAllocSize | quote }}
- name: ZOO_SNAPCOUNT
value: {{ .Values.snapCount | quote }}
- name: ZOO_MAX_CLIENT_CNXNS
value: {{ .Values.maxClientCnxns | quote }}
- name: ZOO_4LW_COMMANDS_WHITELIST
value: {{ .Values.fourlwCommandsWhitelist | quote }}
- name: ZOO_LISTEN_ALLIPS_ENABLED
value: {{ ternary "yes" "no" .Values.listenOnAllIPs | quote }}
- name: ZOO_AUTOPURGE_INTERVAL
value: {{ .Values.autopurge.purgeInterval | quote }}
- name: ZOO_AUTOPURGE_RETAIN_COUNT
value: {{ .Values.autopurge.snapRetainCount | quote }}
- name: ZOO_MAX_SESSION_TIMEOUT
value: {{ .Values.maxSessionTimeout | quote }}
- name: ZOO_SERVERS
{{- $replicaCount := int .Values.replicaCount }}
{{- $minServerId := int .Values.minServerId }}
{{- $followerPort := int .Values.containerPorts.follower }}
{{- $electionPort := int .Values.containerPorts.election }}
{{- $releaseNamespace := include "zookeeper.namespace" . }}
{{- $zookeeperFullname := include "common.names.fullname" . }}
{{- $zookeeperHeadlessServiceName := printf "%s-%s" $zookeeperFullname "headless" | trunc 63 }}
{{- $clusterDomain := .Values.clusterDomain }}
value: {{ range $i, $e := until $replicaCount }}{{ $zookeeperFullname }}-{{ $e }}.{{ $zookeeperHeadlessServiceName }}.{{ $releaseNamespace }}.svc.{{ $clusterDomain }}:{{ $followerPort }}:{{ $electionPort }}::{{ add $e $minServerId }} {{ end }}
- name: ZOO_ENABLE_AUTH
value: {{ ternary "yes" "no" .Values.auth.client.enabled | quote }}
{{- if .Values.auth.client.enabled }}
- name: ZOO_CLIENT_USER
value: {{ .Values.auth.client.clientUser | quote }}
- name: ZOO_CLIENT_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "zookeeper.client.secretName" . }}
key: client-password
- name: ZOO_SERVER_USERS
value: {{ .Values.auth.client.serverUsers | quote }}
- name: ZOO_SERVER_PASSWORDS
valueFrom:
secretKeyRef:
name: {{ include "zookeeper.client.secretName" . }}
key: server-password
{{- end }}
- name: ZOO_ENABLE_QUORUM_AUTH
value: {{ ternary "yes" "no" .Values.auth.quorum.enabled | quote }}
{{- if .Values.auth.quorum.enabled }}
- name: ZOO_QUORUM_LEARNER_USER
value: {{ .Values.auth.quorum.learnerUser | quote }}
- name: ZOO_QUORUM_LEARNER_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "zookeeper.quorum.secretName" . }}
key: quorum-learner-password
- name: ZOO_QUORUM_SERVER_USERS
value: {{ .Values.auth.quorum.serverUsers | quote }}
- name: ZOO_QUORUM_SERVER_PASSWORDS
valueFrom:
secretKeyRef:
name: {{ include "zookeeper.quorum.secretName" . }}
key: quorum-server-password
{{- end }}
- name: ZOO_HEAP_SIZE
value: {{ .Values.heapSize | quote }}
- name: ZOO_LOG_LEVEL
value: {{ .Values.logLevel | quote }}
- name: ALLOW_ANONYMOUS_LOGIN
value: {{ ternary "no" "yes" .Values.auth.client.enabled | quote }}
{{- if .Values.jvmFlags }}
- name: JVMFLAGS
value: {{ .Values.jvmFlags | quote }}
{{- end }}
{{- if .Values.metrics.enabled }}
- name: ZOO_ENABLE_PROMETHEUS_METRICS
value: "yes"
- name: ZOO_PROMETHEUS_METRICS_PORT_NUMBER
value: {{ coalesce .Values.metrics.containerPort .Values.containerPorts.metrics | quote }}
{{- end }}
{{- if .Values.tls.client.enabled }}
- name: ZOO_TLS_PORT_NUMBER
value: {{ .Values.containerPorts.tls | quote }}
- name: ZOO_TLS_CLIENT_ENABLE
value: {{ .Values.tls.client.enabled | quote }}
- name: ZOO_TLS_CLIENT_AUTH
value: {{ .Values.tls.client.auth | quote }}
- name: ZOO_TLS_CLIENT_KEYSTORE_FILE
value: {{ .Values.tls.client.keystorePath | quote }}
- name: ZOO_TLS_CLIENT_TRUSTSTORE_FILE
value: {{ .Values.tls.client.truststorePath | quote }}
{{- if or .Values.tls.client.keystorePassword .Values.tls.client.passwordsSecretName .Values.tls.client.autoGenerated }}
- name: ZOO_TLS_CLIENT_KEYSTORE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "zookeeper.client.tlsPasswordsSecret" . }}
key: {{ include "zookeeper.client.tlsPasswordKeystoreKey" . }}
{{- end }}
{{- if or .Values.tls.client.truststorePassword .Values.tls.client.passwordsSecretName .Values.tls.client.autoGenerated }}
- name: ZOO_TLS_CLIENT_TRUSTSTORE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "zookeeper.client.tlsPasswordsSecret" . }}
key: {{ include "zookeeper.client.tlsPasswordTruststoreKey" . }}
{{- end }}
{{- end }}
{{- if .Values.tls.quorum.enabled }}
- name: ZOO_TLS_QUORUM_ENABLE
value: {{ .Values.tls.quorum.enabled | quote }}
- name: ZOO_TLS_QUORUM_CLIENT_AUTH
value: {{ .Values.tls.quorum.auth | quote }}
- name: ZOO_TLS_QUORUM_KEYSTORE_FILE
value: {{ .Values.tls.quorum.keystorePath | quote }}
- name: ZOO_TLS_QUORUM_TRUSTSTORE_FILE
value: {{ .Values.tls.quorum.truststorePath | quote }}
{{- if or .Values.tls.quorum.keystorePassword .Values.tls.quorum.passwordsSecretName .Values.tls.quorum.autoGenerated }}
- name: ZOO_TLS_QUORUM_KEYSTORE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "zookeeper.quorum.tlsPasswordsSecret" . }}
key: {{ include "zookeeper.quorum.tlsPasswordKeystoreKey" . }}
{{- end }}
{{- if or .Values.tls.quorum.truststorePassword .Values.tls.quorum.passwordsSecretName .Values.tls.quorum.autoGenerated }}
- name: ZOO_TLS_QUORUM_TRUSTSTORE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "zookeeper.quorum.tlsPasswordsSecret" . }}
key: {{ include "zookeeper.quorum.tlsPasswordTruststoreKey" . }}
{{- end }}
{{- end }}
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: ZOO_ADMIN_SERVER_PORT_NUMBER
value: {{ .Values.containerPorts.adminServer | quote }}
{{- if .Values.extraEnvVars }}
{{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }}
{{- end }}
{{- if or .Values.extraEnvVarsCM .Values.extraEnvVarsSecret }}
envFrom:
{{- if .Values.extraEnvVarsCM }}
- configMapRef:
name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsCM "context" $) }}
{{- end }}
{{- if .Values.extraEnvVarsSecret }}
- secretRef:
name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsSecret "context" $) }}
{{- end }}
{{- end }}
ports:
{{- if not .Values.service.disableBaseClientPort }}
- name: client
containerPort: {{ .Values.containerPorts.client }}
{{- end }}
{{- if .Values.tls.client.enabled }}
- name: client-tls
containerPort: {{ .Values.containerPorts.tls }}
{{- end }}
{{- if gt (int .Values.replicaCount) 1 }}
{{- /* These ports are only open when there are more than 1 replica */}}
- name: follower
containerPort: {{ .Values.containerPorts.follower }}
- name: election
containerPort: {{ .Values.containerPorts.election }}
{{- end }}
{{- if .Values.metrics.enabled }}
- name: metrics
containerPort: {{ coalesce .Values.metrics.containerPort .Values.containerPorts.metrics }}
{{- end }}
- name: http-admin
containerPort: {{ .Values.containerPorts.adminServer }}
{{- if not .Values.diagnosticMode.enabled }}
{{- if .Values.customLivenessProbe }}
livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }}
{{- else if .Values.livenessProbe.enabled }}
livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.livenessProbe "enabled" "probeCommandTimeout") "context" $) | nindent 12 }}
exec:
command:
- /bin/bash
- -ec
- ZOO_HC_TIMEOUT={{ .Values.livenessProbe.probeCommandTimeout }} /opt/bitnami/scripts/zookeeper/healthcheck.sh
{{- end }}
{{- if .Values.customReadinessProbe }}
readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }}
{{- else if .Values.readinessProbe.enabled }}
readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readinessProbe "enabled" "probeCommandTimeout") "context" $) | nindent 12 }}
exec:
command:
- /bin/bash
- -ec
- ZOO_HC_TIMEOUT={{ .Values.readinessProbe.probeCommandTimeout }} /opt/bitnami/scripts/zookeeper/healthcheck.sh
{{- end }}
{{- if .Values.customStartupProbe }}
startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customStartupProbe "context" $) | nindent 12 }}
{{- else if .Values.startupProbe.enabled }}
startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.startupProbe "enabled") "context" $) | nindent 12 }}
tcpSocket:
{{- if not .Values.service.disableBaseClientPort }}
port: client
{{- else }}
port: follower
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.lifecycleHooks }}
lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.lifecycleHooks "context" $) | nindent 12 }}
{{- end }}
volumeMounts:
- name: empty-dir
mountPath: /tmp
subPath: tmp-dir
- name: empty-dir
mountPath: /opt/bitnami/zookeeper/conf
subPath: app-conf-dir
- name: empty-dir
mountPath: /opt/bitnami/zookeeper/logs
subPath: app-logs-dir
- name: scripts
mountPath: /scripts/setup.sh
subPath: setup.sh
- name: data
mountPath: /bitnami/zookeeper
{{- if .Values.dataLogDir }}
- name: data-log
mountPath: {{ .Values.dataLogDir }}
{{- end }}
{{- if or .Values.configuration .Values.existingConfigmap }}
- name: config
mountPath: /opt/bitnami/zookeeper/conf/zoo.cfg
subPath: zoo.cfg
{{- end }}
{{- if .Values.tls.client.enabled }}
- name: client-shared-certs
mountPath: /opt/bitnami/zookeeper/config/certs/client
readOnly: true
{{- end }}
{{- if .Values.tls.quorum.enabled }}
- name: quorum-shared-certs
mountPath: /opt/bitnami/zookeeper/config/certs/quorum
readOnly: true
{{- end }}
{{- if .Values.extraVolumeMounts }}
{{- include "common.tplvalues.render" ( dict "value" .Values.extraVolumeMounts "context" $ ) | nindent 12 }}
{{- end }}
{{- if .Values.sidecars }}
{{- include "common.tplvalues.render" ( dict "value" .Values.sidecars "context" $ ) | nindent 8 }}
{{- end }}
volumes:
- name: empty-dir
emptyDir: {}
- name: scripts
configMap:
name: {{ printf "%s-scripts" (include "common.names.fullname" .) }}
defaultMode: 493
{{- if or .Values.configuration .Values.existingConfigmap }}
- name: config
configMap:
name: {{ include "zookeeper.configmapName" . }}
{{- end }}
{{- if and .Values.persistence.enabled .Values.persistence.existingClaim }}
- name: data
persistentVolumeClaim:
claimName: {{ printf "%s" (tpl .Values.persistence.existingClaim .) }}
{{- else if not .Values.persistence.enabled }}
- name: data
emptyDir: {}
{{- end }}
{{- if and .Values.persistence.enabled .Values.persistence.dataLogDir.existingClaim }}
- name: data-log
persistentVolumeClaim:
claimName: {{ printf "%s" (tpl .Values.persistence.dataLogDir.existingClaim .) }}
{{- else if and ( not .Values.persistence.enabled ) .Values.dataLogDir }}
- name: data-log
emptyDir: {}
{{- end }}
{{- if .Values.tls.client.enabled }}
- name: client-certificates
secret:
secretName: {{ include "zookeeper.client.tlsSecretName" . }}
defaultMode: 256
- name: client-shared-certs
emptyDir: {}
{{- end }}
{{- if .Values.tls.quorum.enabled }}
- name: quorum-certificates
secret:
secretName: {{ include "zookeeper.quorum.tlsSecretName" . }}
defaultMode: 256
- name: quorum-shared-certs
emptyDir: {}
{{- end }}
{{- if .Values.extraVolumes }}
{{- include "common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }}
{{- end }}
{{- if and .Values.persistence.enabled (not (and .Values.persistence.existingClaim .Values.persistence.dataLogDir.existingClaim) ) }}
volumeClaimTemplates:
{{- if not .Values.persistence.existingClaim }}
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data
{{- if .Values.persistence.annotations }}
annotations: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.annotations "context" $) | nindent 10 }}
{{- end }}
{{- if .Values.persistence.labels }}
labels: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.labels "context" $) | nindent 10 }}
{{- end }}
spec:
accessModes:
{{- range .Values.persistence.accessModes }}
- {{ . | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.persistence.size | quote }}
{{- include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) | nindent 8 }}
{{- if .Values.persistence.selector }}
selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.selector "context" $) | nindent 10 }}
{{- end }}
{{- end }}
{{- if and (not .Values.persistence.dataLogDir.existingClaim) .Values.dataLogDir }}
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-log
{{- if .Values.persistence.annotations }}
annotations: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.annotations "context" $) | nindent 10 }}
{{- end }}
{{- if .Values.persistence.labels }}
labels: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.labels "context" $) | nindent 10 }}
{{- end }}
spec:
accessModes:
{{- range .Values.persistence.accessModes }}
- {{ . | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.persistence.dataLogDir.size | quote }}
{{- include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) | nindent 8 }}
{{- if .Values.persistence.dataLogDir.selector }}
selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.dataLogDir.selector "context" $) | nindent 10 }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,40 @@
{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
apiVersion: v1
kind: Service
metadata:
name: {{ printf "%s-%s" (include "common.names.fullname" .) (default "headless" .Values.service.headless.servicenameOverride) | trunc 63 | trimSuffix "-" }}
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: zookeeper
{{- if or .Values.commonAnnotations .Values.service.headless.annotations }}
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.headless.annotations .Values.commonAnnotations ) "context" . ) }}
annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
{{- end }}
spec:
type: ClusterIP
clusterIP: None
publishNotReadyAddresses: {{ .Values.service.headless.publishNotReadyAddresses }}
ports:
{{- if not .Values.service.disableBaseClientPort }}
- name: tcp-client
port: {{ .Values.service.ports.client }}
targetPort: client
{{- end }}
{{- if .Values.tls.client.enabled }}
- name: tcp-client-tls
port: {{ .Values.service.ports.tls }}
targetPort: client-tls
{{- end }}
- name: tcp-follower
port: {{ .Values.service.ports.follower }}
targetPort: follower
- name: tcp-election
port: {{ .Values.service.ports.election }}
targetPort: election
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }}
selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: zookeeper

View File

@ -0,0 +1,72 @@
{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
apiVersion: v1
kind: Service
metadata:
name: {{ template "common.names.fullname" . }}
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: zookeeper
{{- if or .Values.commonAnnotations .Values.service.annotations }}
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.annotations .Values.commonAnnotations ) "context" . ) }}
annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.service.type }}
{{- if and .Values.service.clusterIP (eq .Values.service.type "ClusterIP") }}
clusterIP: {{ .Values.service.clusterIP }}
{{- end }}
{{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }}
externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }}
{{- end }}
{{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerSourceRanges)) }}
loadBalancerSourceRanges: {{ .Values.service.loadBalancerSourceRanges }}
{{- end }}
{{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP)) }}
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
{{- end }}
{{- if .Values.service.sessionAffinity }}
sessionAffinity: {{ .Values.service.sessionAffinity }}
{{- end }}
{{- if .Values.service.sessionAffinityConfig }}
sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.service.sessionAffinityConfig "context" $) | nindent 4 }}
{{- end }}
ports:
{{- if not .Values.service.disableBaseClientPort }}
- name: tcp-client
port: {{ .Values.service.ports.client }}
targetPort: client
{{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.client)) }}
nodePort: {{ .Values.service.nodePorts.client }}
{{- else if eq .Values.service.type "ClusterIP" }}
nodePort: null
{{- end }}
{{- end }}
{{- if .Values.tls.client.enabled }}
- name: tcp-client-tls
port: {{ .Values.service.ports.tls }}
targetPort: client-tls
{{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.tls)) }}
nodePort: {{ .Values.service.nodePorts.tls }}
{{- else if eq .Values.service.type "ClusterIP" }}
nodePort: null
{{- end }}
{{- end }}
{{- if gt (int .Values.replicaCount) 1 }}
{{- /* These ports are only open when there are more than 1 replica */}}
- name: tcp-follower
port: {{ .Values.service.ports.follower }}
targetPort: follower
- name: tcp-election
port: {{ .Values.service.ports.election }}
targetPort: election
{{- end }}
{{- if .Values.service.extraPorts }}
{{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }}
{{- end }}
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }}
selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: zookeeper

View File

@ -0,0 +1,56 @@
{{- /*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{- if (include "zookeeper.client.createTlsSecret" .) }}
{{- $secretName := printf "%s-client-crt" (include "common.names.fullname" .) }}
{{- $ca := genCA "zookeeper-client-ca" 365 }}
{{- $releaseNamespace := .Release.Namespace }}
{{- $clusterDomain := .Values.clusterDomain }}
{{- $fullname := include "common.names.fullname" . }}
{{- $serviceName := include "common.names.fullname" . }}
{{- $headlessServiceName := printf "%s-headless" (include "common.names.fullname" .) }}
{{- $altNames := list (printf "*.%s.%s.svc.%s" $headlessServiceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $headlessServiceName $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) "127.0.0.1" "localhost" $fullname }}
{{- $cert := genSignedCert $fullname nil $altNames 365 $ca }}
apiVersion: v1
kind: Secret
metadata:
name: {{ $secretName }}
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
type: kubernetes.io/tls
data:
tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }}
tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }}
ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }}
{{- end }}
{{- if (include "zookeeper.quorum.createTlsSecret" .) }}
{{- $secretName := printf "%s-quorum-crt" (include "common.names.fullname" .) }}
{{- $ca := genCA "zookeeper-quorum-ca" 365 }}
{{- $releaseNamespace := .Release.Namespace }}
{{- $clusterDomain := .Values.clusterDomain }}
{{- $fullname := include "common.names.fullname" . }}
{{- $serviceName := include "common.names.fullname" . }}
{{- $headlessServiceName := printf "%s-headless" (include "common.names.fullname" .) }}
{{- $altNames := list (printf "*.%s.%s.svc.%s" $headlessServiceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $headlessServiceName $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) $fullname }}
{{- $cert := genSignedCert $fullname nil $altNames 365 $ca }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ $secretName }}
namespace: {{ template "zookeeper.namespace" . }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
type: kubernetes.io/tls
data:
tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }}
tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }}
ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }}
{{- end }}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
# Example values file for Apache NiFi with LDAP Authentication
# This file demonstrates LDAP authentication configuration
# Note: Basic auth is automatically disabled when LDAP is enabled
# Basic cluster configuration
global:
busybox:
repository: public.ecr.aws/docker/library/busybox:stable
nifi:
nodeCount: 3
# Authentication configuration
# Basic auth (automatically disabled when LDAP is enabled)
basic:
admin_username: "admin"
admin_password: "your32characterpasswordhere123"
# LDAP Authentication
ldap:
enabled: true
url: "ldaps://dc-1.example.com:636,ldaps://dc-2.example.com:636"
tlsProtocol: "TLSv1.2"
authenticationStrategy: "LDAPS" # ANONYMOUS|SIMPLE|LDAPS|START_TLS
identityStrategy: "USE_USERNAME" # USE_DN|USE_USERNAME
initialAdminIdentity: "CN=Administrator,DC=example,DC=com"
manager:
distinguishedName: "CN=Administrator,DC=example,DC=com"
passwordSecretRef:
name: "ldap-manager-secret"
key: "password"
userSearchBase: "DC=example,DC=com"
userSearchFilter: "sAMAccountName={0}"
# OIDC is disabled
oidc:
enabled: false
# Resource configuration for single node
resources:
requests:
memory: "2Gi"
cpu: "1000m"
limits:
memory: "4Gi"
cpu: "2000m"
# JVM Heap configuration for single node
jvmHeap:
min: 512m
max: 1g
# Storage configuration
volumeClaims:
config:
storageClass: "gp3"
size: "5Gi"
state:
storageClass: "gp3"
size: "10Gi"
logs:
storageClass: "gp3"
size: "2Gi"
flowfile:
storageClass: "gp3"
size: "10Gi"
content:
storageClass: "gp3"
size: "15Gi"
provenance:
storageClass: "gp3"
size: "10Gi"
# Your specific ALB ingress configuration
ingress:
enabled: true
ingressClassName: alb
hostName: example.com # nifi.example.com
siteToSite:
subDomain: s2s # Subdomain for site-to-site traffic (e.g. s2s.example.com)
annotations: { }
# Node selector and tolerations (adjust as needed for your cluster)
nodeSelector: {}
tolerations: []
affinity: {}

View File

@ -0,0 +1,77 @@
# Example values file for Apache NiFi with OIDC Authentication
# This file demonstrates OIDC authentication configuration
# Note: Basic auth is automatically disabled when OIDC is enabled
# Basic cluster configuration
global:
busybox:
repository: public.ecr.aws/docker/library/busybox:stable
nifi:
nodeCount: 3
# Authentication Configuration
# Basic auth (automatically disabled when OIDC is enabled)
basic:
admin_username: "admin"
admin_password: "your32characterpasswordhere123" # Must be at least 12 characters
# LDAP is disabled
ldap:
enabled: false
# OpenID Connect (OIDC) Authentication
oidc:
enabled: true
oidc_url: "https://auth.example.com/.well-known/openid-configuration"
client_id: "nifi-client"
client_secret: "your-client-secret-here"
claim_identifying_user: "preferred_username"
initial_admin_identity: "admin@example.com"
# Resource configuration for single node
resources:
requests:
memory: "2Gi"
cpu: "1000m"
limits:
memory: "4Gi"
cpu: "2000m"
# Storage configuration
volumeClaims:
config:
storageClass: "gp3"
size: "5Gi"
state:
storageClass: "gp3"
size: "10Gi"
logs:
storageClass: "gp3"
size: "2Gi"
flowfile:
storageClass: "gp3"
size: "10Gi"
content:
storageClass: "gp3"
size: "15Gi"
provenance:
storageClass: "gp3"
size: "10Gi"
# Your specific ALB ingress configuration
ingress:
enabled: true
ingressClassName: alb
hostName: example.com # nifi.example.com
siteToSite:
subDomain: s2s # Subdomain for site-to-site traffic (e.g. s2s.example.com)
annotations: { }
# JVM Heap configuration for single node
jvmHeap:
min: 512m
max: 1g
# Node selector and tolerations (adjust as needed for your cluster)
nodeSelector: {}
tolerations: []
affinity: {}

View File

@ -0,0 +1,64 @@
# Example values for NiFi with Basic Authentication (Single User Authentication)
# Basic auth only supports single-node deployment
global:
busybox:
repository: public.ecr.aws/docker/library/busybox:stable
nifi:
nodeCount: 1 # REQUIRED: Basic auth only supports single node
# Basic Authentication Configuration
# This is the default fallback when OIDC and LDAP are disabled
basic:
admin_username: "admin"
admin_password: "your32characterpasswordhere123" # Must be at least 12 characters
# Resource configuration for single node
resources:
requests:
memory: "2Gi"
cpu: "1000m"
limits:
memory: "4Gi"
cpu: "2000m"
# Storage configuration
volumeClaims:
config:
storageClass: "gp3"
size: "5Gi"
state:
storageClass: "gp3"
size: "10Gi"
logs:
storageClass: "gp3"
size: "2Gi"
flowfile:
storageClass: "gp3"
size: "10Gi"
content:
storageClass: "gp3"
size: "15Gi"
provenance:
storageClass: "gp3"
size: "10Gi"
# Your specific ALB ingress configuration
ingress:
enabled: true
ingressClassName: alb
hostName: example.com # nifi.example.com
siteToSite:
subDomain: s2s # Subdomain for site-to-site traffic (e.g. s2s.example.com)
annotations: { }
# JVM Heap configuration for single node
jvmHeap:
min: 512m
max: 1g
# Node selector and tolerations (adjust as needed for your cluster)
nodeSelector: {}
tolerations: []
affinity: {}

View File

@ -0,0 +1,953 @@
{
"__inputs": [
{
"name": "DS_PROMETHEUS",
"label": "Prometheus",
"description": "",
"type": "datasource",
"pluginId": "prometheus",
"pluginName": "Prometheus"
}
],
"__requires": [
{
"type": "panel",
"id": "bargauge",
"name": "Bar Gauge",
"version": ""
},
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "6.4.3"
},
{
"type": "panel",
"id": "graph",
"name": "Graph",
"version": ""
},
{
"type": "datasource",
"id": "prometheus",
"name": "Prometheus",
"version": "1.0.0"
},
{
"type": "panel",
"id": "singlestat",
"name": "Singlestat",
"version": ""
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": 11387,
"graphTooltip": 0,
"id": null,
"iteration": 1576052456962,
"links": [],
"panels": [
{
"cacheTimeout": null,
"colorBackground": false,
"colorValue": false,
"colors": [
"#299c46",
"rgba(237, 129, 40, 0.89)",
"#d44a3a"
],
"datasource": "${DS_PROMETHEUS}",
"format": "none",
"gauge": {
"maxValue": 100,
"minValue": 0,
"show": false,
"thresholdLabels": false,
"thresholdMarkers": true
},
"gridPos": {
"h": 4,
"w": 3,
"x": 0,
"y": 0
},
"id": 2,
"interval": null,
"links": [],
"mappingType": 1,
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
"options": {},
"postfix": "",
"postfixFontSize": "50%",
"prefix": "",
"prefixFontSize": "50%",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"sparkline": {
"fillColor": "rgba(31, 118, 189, 0.18)",
"full": false,
"lineColor": "rgb(31, 120, 193)",
"show": false,
"ymax": null,
"ymin": null
},
"tableColumn": "",
"targets": [
{
"expr": "nifi_cluster_version_info{cluster='$nifi_cluster'}",
"instant": false,
"legendFormat": "{{version}}",
"refId": "A"
}
],
"thresholds": "",
"timeFrom": null,
"timeShift": null,
"title": "NiFI Version",
"type": "singlestat",
"valueFontSize": "80%",
"valueMaps": [
{
"op": "=",
"text": "N/A",
"value": "null"
}
],
"valueName": "name"
},
{
"collapsed": false,
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 4
},
"id": 28,
"panels": [],
"repeat": null,
"title": "General view",
"type": "row"
},
{
"cacheTimeout": null,
"colorBackground": true,
"colorValue": false,
"colors": [
"#d44a3a",
"rgba(237, 129, 40, 0.89)",
"#299c46"
],
"datasource": "${DS_PROMETHEUS}",
"format": "none",
"gauge": {
"maxValue": 100,
"minValue": 0,
"show": false,
"thresholdLabels": false,
"thresholdMarkers": true
},
"gridPos": {
"h": 4,
"w": 8,
"x": 0,
"y": 5
},
"id": 25,
"interval": null,
"links": [],
"mappingType": 1,
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
"options": {},
"postfix": "",
"postfixFontSize": "50%",
"prefix": "",
"prefixFontSize": "50%",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"repeat": "nifi_node",
"repeatDirection": "h",
"sparkline": {
"fillColor": "rgba(31, 118, 189, 0.18)",
"full": false,
"lineColor": "rgb(31, 120, 193)",
"show": false,
"ymax": null,
"ymin": null
},
"tableColumn": "",
"targets": [
{
"expr": "nifi_nodes_status{cluster='$nifi_cluster', exported_instance=~\"$nifi_node\"}",
"instant": true,
"refId": "A"
}
],
"thresholds": "1,0",
"timeFrom": null,
"timeShift": null,
"title": "$nifi_node",
"type": "singlestat",
"valueFontSize": "80%",
"valueMaps": [
{
"op": "=",
"text": "CONNECTED",
"value": "1"
},
{
"op": "=",
"text": "DISCONNECTED",
"value": "0"
}
],
"valueName": "current"
},
{
"collapsed": false,
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 9
},
"id": 6,
"panels": [],
"repeat": null,
"title": "Nodes - Queued Items",
"type": "row"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 8,
"x": 0,
"y": 10
},
"id": 10,
"legend": {
"alignAsTable": true,
"avg": false,
"current": false,
"max": false,
"min": false,
"rightSide": true,
"show": false,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 2,
"points": false,
"renderer": "flot",
"repeat": "nifi_node",
"repeatDirection": "h",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "nifi_node_queuedItems{cluster='$nifi_cluster'}",
"instant": false,
"legendFormat": "",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "$nifi_node",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"transparent": true,
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"collapsed": false,
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 18
},
"id": 14,
"panels": [],
"title": "Nodes - Active Thread Count",
"type": "row"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 7,
"w": 8,
"x": 0,
"y": 19
},
"id": 15,
"legend": {
"alignAsTable": true,
"avg": false,
"current": false,
"max": false,
"min": false,
"rightSide": true,
"show": false,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 2,
"points": false,
"renderer": "flot",
"repeat": "nifi_node",
"repeatDirection": null,
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "nifi_node_activeThreadCount{cluster='$nifi_cluster'}",
"legendFormat": "{{exported_instance}}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "$nifi_node",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"transparent": true,
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"collapsed": false,
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 26
},
"id": 19,
"panels": [],
"title": "Cluster",
"type": "row"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 7,
"w": 11,
"x": 0,
"y": 27
},
"id": 20,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": false,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "nifi_cluster_flowFilesQueued{cluster='$nifi_cluster'}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Flow Files Queued",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"transparent": true,
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 7,
"w": 11,
"x": 11,
"y": 27
},
"id": 21,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": false,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "nifi_cluster_bytesQueued{cluster='$nifi_cluster'}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Bytes Queued",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"transparent": true,
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "deckbytes",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "deckbytes",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"cacheTimeout": null,
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 7,
"w": 22,
"x": 0,
"y": 34
},
"id": 23,
"links": [],
"options": {
"displayMode": "gradient",
"fieldOptions": {
"calcs": [
"mean"
],
"defaults": {
"mappings": [
{
"id": 0,
"op": "=",
"text": "N/A",
"type": 1,
"value": "null"
}
],
"max": 100,
"min": 0,
"nullValueMode": "connected",
"thresholds": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
],
"unit": "none"
},
"override": {},
"values": false
},
"orientation": "horizontal"
},
"pluginVersion": "6.4.3",
"targets": [
{
"expr": "nifi_cluster_stoppedCount{cluster='$nifi_cluster'}",
"legendFormat": "Stopped Count",
"refId": "A"
},
{
"expr": "nifi_cluster_invalidCount{cluster='$nifi_cluster'}",
"legendFormat": "Invalid Count",
"refId": "B"
},
{
"expr": "nifi_cluster_runningCount{cluster='$nifi_cluster'}",
"legendFormat": "Running Count",
"refId": "C"
}
],
"timeFrom": null,
"timeShift": null,
"title": "General proccessor counters ",
"transparent": true,
"type": "bargauge"
},
{
"collapsed": false,
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 41
},
"id": 32,
"panels": [],
"title": "Queued Item",
"type": "row"
},
{
"alert": {
"alertRuleTags": {},
"conditions": [
{
"evaluator": {
"params": [
100000
],
"type": "gt"
},
"operator": {
"type": "and"
},
"query": {
"params": [
"A",
"10s",
"now"
]
},
"reducer": {
"params": [],
"type": "max"
},
"type": "query"
}
],
"executionErrorState": "alerting",
"for": "1m",
"frequency": "1m",
"handler": 1,
"message": "Hi Team \nThe following groups in NiFi has reached a high threshold. Please check",
"name": "Queue item alert",
"noDataState": "ok",
"notifications": [
{
"uid": "FOTPSl-Zz"
},
{
"uid": "6vzky_aZk"
}
]
},
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"decimals": null,
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 10,
"w": 24,
"x": 0,
"y": 42
},
"id": 34,
"legend": {
"alignAsTable": true,
"avg": false,
"current": true,
"hideEmpty": false,
"hideZero": true,
"max": false,
"min": false,
"rightSide": true,
"show": true,
"sort": "current",
"sortDesc": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "nifi_amount_items_queued{cluster='$nifi_cluster'}",
"instant": false,
"legendFormat": "{{processorName}}",
"refId": "A"
}
],
"thresholds": [
{
"colorMode": "critical",
"fill": true,
"line": true,
"op": "gt",
"value": 100000
}
],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Queue item per PG",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"transparent": true,
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"decimals": null,
"format": "short",
"label": "",
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
}
],
"refresh": "5m",
"schemaVersion": 20,
"style": "dark",
"tags": [
"NiFi"
],
"templating": {
"list": [
{
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
"definition": "label_values(nifi_nodes_status,cluster)",
"hide": 0,
"includeAll": true,
"label": null,
"multi": false,
"name": "nifi_cluster",
"options": [],
"query": "label_values(nifi_nodes_status,cluster)",
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"tagValuesQuery": "",
"tags": [],
"tagsQuery": "",
"type": "query",
"useTags": false
},
{
"type": "query",
"name": "nifi_node",
"label": "NiFi Instance",
"datasource": "${DS_PROMETHEUS}",
"query": "label_values(nifi_nodes_status{cluster=~\"$nifi_cluster\"}, exported_instance)",
"refresh": 1,
"multi": true,
"includeAll": true,
"current": {},
"options": []
}
]
},
"time": {
"from": "now-1h",
"to": "now"
},
"timepicker": {
"refresh_intervals": [
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
]
},
"timezone": "",
"title": "NiFi Cluster Health",
"uid": "SaketMittal",
"version": 10,
"description": "General view of Nifi \r\n"
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,288 @@
#!/bin/bash
# 🚀 Apache NiFi Helm Chart Release Script
# This script helps with local development and testing before releases
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Functions
log_info() {
echo -e "${BLUE} $1${NC}"
}
log_success() {
echo -e "${GREEN}$1${NC}"
}
log_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
log_error() {
echo -e "${RED}$1${NC}"
}
# Check prerequisites
check_prerequisites() {
log_info "Checking prerequisites..."
# Check if helm is installed
if ! command -v helm &> /dev/null; then
log_error "Helm is not installed. Please install Helm 3.8+ first."
exit 1
fi
# Check helm version
HELM_VERSION=$(helm version --short | cut -d'+' -f1 | cut -d'v' -f2)
log_info "Helm version: $HELM_VERSION"
# Check if yq is installed
if ! command -v yq &> /dev/null; then
log_warning "yq is not installed. Some features may not work."
fi
# Check if we're in the right directory
if [ ! -f "Chart.yaml" ]; then
log_error "Chart.yaml not found. Please run this script from the chart root directory."
exit 1
fi
log_success "Prerequisites check passed"
}
# Get current chart information
get_chart_info() {
CHART_NAME=$(yq eval '.name' Chart.yaml 2>/dev/null || grep '^name:' Chart.yaml | cut -d' ' -f2)
CHART_VERSION=$(yq eval '.version' Chart.yaml 2>/dev/null || grep '^version:' Chart.yaml | cut -d' ' -f2)
APP_VERSION=$(yq eval '.appVersion' Chart.yaml 2>/dev/null || grep '^appVersion:' Chart.yaml | cut -d' ' -f2 | tr -d '"')
log_info "Chart: $CHART_NAME"
log_info "Chart Version: $CHART_VERSION"
log_info "App Version: $APP_VERSION"
}
# Lint the chart
lint_chart() {
log_info "Linting Helm chart..."
if helm lint .; then
log_success "Chart linting passed"
else
log_error "Chart linting failed"
exit 1
fi
}
# Update dependencies
update_dependencies() {
log_info "Updating Helm dependencies..."
if helm dependency update; then
log_success "Dependencies updated successfully"
else
log_error "Failed to update dependencies"
exit 1
fi
}
# Template validation
validate_templates() {
log_info "Validating Helm templates..."
# Test default values
if helm template test-release . --debug > /dev/null 2>&1; then
log_success "Default template validation passed"
else
log_error "Default template validation failed"
helm template test-release . --debug
exit 1
fi
# Test example values files
if [ -d "examples" ]; then
for values_file in examples/values-*.yaml; do
if [ -f "$values_file" ]; then
log_info "Testing template with $values_file"
if helm template test-release . -f "$values_file" --debug > /dev/null 2>&1; then
log_success "Template validation passed for $values_file"
else
log_error "Template validation failed for $values_file"
helm template test-release . -f "$values_file" --debug
exit 1
fi
fi
done
fi
}
# Package the chart
package_chart() {
log_info "Packaging Helm chart..."
mkdir -p dist
if helm package . -d dist/; then
PACKAGE_FILE="dist/${CHART_NAME}-${CHART_VERSION}.tgz"
log_success "Chart packaged: $PACKAGE_FILE"
# Show package info
log_info "Package size: $(du -h "$PACKAGE_FILE" | cut -f1)"
log_info "Package contents:"
tar -tzf "$PACKAGE_FILE" | head -10
if [ $(tar -tzf "$PACKAGE_FILE" | wc -l) -gt 10 ]; then
echo "... and $(( $(tar -tzf "$PACKAGE_FILE" | wc -l) - 10 )) more files"
fi
else
log_error "Failed to package chart"
exit 1
fi
}
# Generate index
generate_index() {
log_info "Generating Helm repository index..."
if [ -d "dist" ] && [ -n "$(ls -A dist/*.tgz 2>/dev/null)" ]; then
helm repo index dist/ --url "https://sakkiii.github.io/apache-nifi-helm"
log_success "Repository index generated"
else
log_warning "No packages found in dist/ directory"
fi
}
# Test installation (dry-run)
test_install() {
log_info "Testing chart installation (dry-run)..."
if helm install test-release . --dry-run --debug > /dev/null 2>&1; then
log_success "Dry-run installation test passed"
else
log_error "Dry-run installation test failed"
helm install test-release . --dry-run --debug
exit 1
fi
}
# Security scan (if available)
security_scan() {
log_info "Running security scans..."
# Check if kubesec is available
if command -v kubesec &> /dev/null; then
log_info "Running kubesec scan..."
helm template test-release . | kubesec scan -
else
log_warning "kubesec not found, skipping security scan"
fi
# Check if checkov is available
if command -v checkov &> /dev/null; then
log_info "Running checkov scan..."
checkov -d . --framework kubernetes --quiet
else
log_warning "checkov not found, skipping security scan"
fi
}
# Show usage
show_usage() {
echo "🚀 Apache NiFi Helm Chart Release Script"
echo ""
echo "Usage: $0 [COMMAND]"
echo ""
echo "Commands:"
echo " check Check prerequisites and chart info"
echo " lint Lint the Helm chart"
echo " deps Update Helm dependencies"
echo " validate Validate Helm templates"
echo " package Package the Helm chart"
echo " index Generate repository index"
echo " test Test chart installation (dry-run)"
echo " security Run security scans"
echo " all Run all checks and package"
echo " clean Clean build artifacts"
echo ""
echo "Examples:"
echo " $0 all # Run complete validation and packaging"
echo " $0 lint validate # Run linting and validation only"
echo " $0 package # Package the chart"
}
# Clean build artifacts
clean_artifacts() {
log_info "Cleaning build artifacts..."
rm -rf dist/
rm -rf charts/*.tgz
rm -f Chart.lock
log_success "Build artifacts cleaned"
}
# Main execution
main() {
if [ $# -eq 0 ]; then
show_usage
exit 0
fi
check_prerequisites
get_chart_info
for cmd in "$@"; do
case $cmd in
check)
log_info "Chart information already displayed"
;;
lint)
lint_chart
;;
deps)
update_dependencies
;;
validate)
validate_templates
;;
package)
package_chart
;;
index)
generate_index
;;
test)
test_install
;;
security)
security_scan
;;
all)
lint_chart
update_dependencies
validate_templates
test_install
security_scan
package_chart
generate_index
log_success "All checks completed successfully! 🎉"
;;
clean)
clean_artifacts
;;
*)
log_error "Unknown command: $cmd"
show_usage
exit 1
;;
esac
done
}
# Run main function with all arguments
main "$@"

View File

@ -0,0 +1 @@
NiFi deployed

View File

@ -0,0 +1,343 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "nifi.name" -}}
nifi
{{- 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 "nifi.fullname" -}}
{{- $name := include "nifi.name" . }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "nifi.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "nifi.labels" -}}
helm.sh/chart: {{ include "nifi.chart" . }}
{{ include "nifi.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "nifi.selectorLabels" -}}
app.kubernetes.io/name: {{ include "nifi.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "nifi.siteToSiteHostName" -}}
{{ printf "%s.%s" .Values.ingress.siteToSite.subDomain .Values.ingress.hostName }}
{{- end }}
{{- define "nifi.hostNodeList" -}}
{{- $ctx := . }} # Save the context in a variable
{{- range $i := until ($ctx.Values.global.nifi.nodeCount | int) }}
- {{ printf "%s-%d.%s.%s" (include "nifi.fullname" $ctx) $i (include "nifi.fullname" $ctx) $ctx.Release.Namespace }}
{{- end }}
{{- end }}
{{- define "nifi.ingressNodeList" -}}
{{- range $i, $e := until (.Values.global.nifi.nodeCount | int) }}
{{ printf "- %s-%d.%s" (include "nifi.fullname" $) $i (include "nifi.siteToSiteHostName" $) }}
{{- end }}
{{- end }}
{{/*
NiFi Registry FQDN
*/}}
{{- define "nifi.registryUrl" -}}
{{ .Release.Name }}-{{ include "nifi-registry.fullname" . }}.{{ .Release.Namespace }}.svc
{{- end }}
{{/*
Certificate path constants
*/}}
{{- $keystoreFile := "keystore.p12" }}
{{- $truststoreFile := "truststore.p12" }}
{{- define "nifi.certPath" -}}
{{ "/opt/certmanager" }}
{{- end }}
{{- define "nifi.tlsPath" -}}
{{ "/opt/tls" }}
{{- end }}
{{/*
Certificate subject alternative names
*/}}
{{- define "nifi.certificateSubjectAltNames" }}
{{- $fullName := (include "nifi.fullname" . ) }}
{{- $namespace := .Release.Namespace }}
{{- printf "${POD_NAME}.%s.%s,%s-http.%s" $fullName $namespace $fullName $namespace }}
{{- with .Values.tls.subjectAltNames }}
{{- printf ",%s" (join "," .) }}
{{- end }}
{{- end }}
{{/*
Returns whether `.Values.extraPorts` contains one or more entries with either `nodePort` or `loadBalancerPort`
*/}}
{{- define "nifi.hasExternalPorts" -}}
{{- $hasNodePorts := false }}
{{- $hasLoadBalancerPorts := false }}
{{- range $name, $port := .Values.extraPorts }}
{{- if and (hasKey $port "nodePort") (gt (int $port.nodePort) 0) }}
{{- $hasNodePorts = true }}
{{- else if and (hasKey $port "loadBalancerPort") (gt (int $port.loadBalancerPort) 0) }}
{{- $hasLoadBalancerPorts = true }}
{{- end }}
{{- end }}
{{- if (or $hasNodePorts $hasLoadBalancerPorts) }}true{{ end }}
{{- end }}
{{/*
Common NiFi keystore environment variables
*/}}
{{- define "nifi.keystoreEnvironment" -}}
- name: KEYSTORE_PATH
value: {{ include "nifi.tlsPath" . }}/keystore.p12
- name: KEYSTORE_TYPE
value: PKCS12
- name: KEYSTORE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ default "certificate-keystore-password" .Values.global.tls.certificate.keystorePasswordSecretRef.name | quote }}
key: {{ .Values.global.tls.certificate.keystorePasswordSecretRef.key | quote }}
- name: TRUSTSTORE_PATH
value: {{ include "nifi.tlsPath" . }}/truststore.p12
- name: TRUSTSTORE_TYPE
value: PKCS12
- name: TRUSTSTORE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ default "certificate-keystore-password" .Values.global.tls.certificate.keystorePasswordSecretRef.name | quote }}
key: {{ .Values.global.tls.certificate.keystorePasswordSecretRef.key | quote }}
{{- end }}
{{/*
Common NiFi OIDC environment variables
*/}}
{{- define "nifi.oidcEnvironment" -}}
{{- with .Values.global.oidc -}}
- name: AUTH
value: oidc
- name: NIFI_SECURITY_USER_OIDC_DISCOVERY_URL
value: {{ .oidc_url | quote }}
- name: NIFI_SECURITY_USER_OIDC_CLIENT_ID
value: {{ .client_id | quote }}
{{- if .client_secretFrom }}
- name: NIFI_SECURITY_USER_OIDC_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: {{ .client_secretFrom.secretName | quote }}
key: {{ .client_secretFrom.secretKey | quote }}
{{- else if .client_secret }}
- name: NIFI_SECURITY_USER_OIDC_CLIENT_SECRET
value: {{ .client_secret | quote }}
{{- end }}
- name: NIFI_SECURITY_USER_OIDC_CLAIM_IDENTIFYING_USER
value: {{ .claim_identifying_user | quote }}
- name: INITIAL_ADMIN_IDENTITY
value: {{ .initial_admin_identity | quote }}
{{- end }}
{{- end }}
{{/*
Common NiFi LDAP environment variables
*/}}
{{- define "nifi.ldapEnvironment" -}}
{{- with .Values.global.ldap -}}
- name: AUTH
value: ldap
- name: LDAP_URL
value: {{ .url | quote }}
- name: LDAP_TLS_PROTOCOL
value: {{ .tlsProtocol | quote }}
- name: LDAP_AUTHENTICATION_STRATEGY
value: {{ .authenticationStrategy | quote }}
- name: LDAP_IDENTITY_STRATEGY
value: {{ .identityStrategy | quote }}
- name: INITIAL_ADMIN_IDENTITY
value: {{ .initialAdminIdentity | quote }}
- name: LDAP_MANAGER_DN
value: {{ .manager.distinguishedName | quote }}
- name: LDAP_MANAGER_PASSWORD
valueFrom:
secretKeyRef:
{{- toYaml .manager.passwordSecretRef | nindent 6 }}
- name: LDAP_USER_SEARCH_BASE
value: {{ .userSearchBase | quote }}
- name: LDAP_USER_SEARCH_FILTER
value: {{ .userSearchFilter | quote }}
{{- if or (eq .authenticationStrategy "LDAPS") (eq .authenticationStrategy "START_TLS") }}
- name: LDAP_TLS_KEYSTORE
value: {{ include "nifi.tlsPath" $ }}/keystore.p12
- name: LDAP_TLS_KEYSTORE_TYPE
value: PKCS12
- name: LDAP_TLS_KEYSTORE_PASSWORD
valueFrom:
secretKeyRef:
{{- toYaml $.Values.global.tls.certificate.keystorePasswordSecretRef | nindent 6 }}
- name: LDAP_TLS_TRUSTSTORE
value: {{ include "nifi.tlsPath" $ }}/truststore.p12
- name: LDAP_TLS_TRUSTSTORE_TYPE
value: PKCS12
- name: LDAP_TLS_TRUSTSTORE_PASSWORD
valueFrom:
secretKeyRef:
{{- toYaml $.Values.global.tls.certificate.keystorePasswordSecretRef | nindent 6 }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Common NiFi Basic Authentication environment variables
Uses official NiFi Single User Authentication environment variables
Automatically disabled if OIDC or LDAP is enabled
*/}}
{{- define "nifi.basicAuthEnvironment" -}}
{{- /* Only enable basic auth if both OIDC and LDAP are disabled */ -}}
{{- if and (not .Values.global.oidc.enabled) (not .Values.global.ldap.enabled) -}}
{{- with .Values.global.basic -}}
- name: AUTH
value: single-user
- name: SINGLE_USER_CREDENTIALS_USERNAME
value: {{ .admin_username | quote }}
- name: SINGLE_USER_CREDENTIALS_PASSWORD
value: {{ .admin_password | quote }}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Determine if NiFi version is 2.0 or higher
*/}}
{{- define "nifi.isVersion2Plus" -}}
{{- $appVersion := .Chart.AppVersion | toString -}}
{{- $version := $appVersion | replace "v" "" | replace "-SNAPSHOT" "" -}}
{{- $majorVersion := $version | splitList "." | first | int -}}
{{- if ge $majorVersion 2 -}}
true
{{- else -}}
false
{{- end -}}
{{- end }}
{{/*
Determine the state management strategy to use
Returns: "kubernetes" or "zookeeper"
*/}}
{{- define "nifi.stateManagementStrategy" -}}
{{- $strategy := .Values.stateManagement.strategy | default "auto" -}}
{{- if eq $strategy "auto" -}}
{{- if eq (include "nifi.isVersion2Plus" .) "true" -}}
kubernetes
{{- else -}}
zookeeper
{{- end -}}
{{- else -}}
{{ $strategy }}
{{- end -}}
{{- end }}
{{/*
Check if ZooKeeper should be enabled
*/}}
{{- define "nifi.useZooKeeper" -}}
{{- if eq (include "nifi.stateManagementStrategy" .) "zookeeper" -}}
true
{{- else -}}
false
{{- end -}}
{{- end }}
{{/*
Check if Kubernetes state management should be used
*/}}
{{- define "nifi.useKubernetesStateManagement" -}}
{{- if eq (include "nifi.stateManagementStrategy" .) "kubernetes" -}}
true
{{- else -}}
false
{{- end -}}
{{- end }}
{{/*
Get the namespace for Kubernetes state management resources
Always uses the release namespace for security and simplicity
*/}}
{{- define "nifi.stateManagementNamespace" -}}
{{ .Release.Namespace }}
{{- end }}
{{/*
Common cluster environment variables (used by both state management strategies)
*/}}
{{- define "nifi.clusterEnvironment" -}}
- name: NIFI_CLUSTER_NODE_PROTOCOL_MAX_THREADS
value: {{ .Values.cluster.nodeProtocol.maxThreads | quote }}
{{- end }}
{{/*
Kubernetes state management environment variables
*/}}
{{- define "nifi.kubernetesStateEnvironment" -}}
- name: NIFI_CLUSTER_LEADER_ELECTION_IMPLEMENTATION
value: KubernetesLeaderElectionManager
- name: NIFI_CLUSTER_LEADER_ELECTION_KUBERNETES_LEASE_PREFIX
value: {{ .Values.stateManagement.kubernetes.leasePrefix | quote }}
- name: NIFI_CLUSTER_LEADER_ELECTION_KUBERNETES_LEASE_NAMESPACE
value: {{ include "nifi.stateManagementNamespace" . | quote }}
- name: NIFI_STATE_MANAGEMENT_PROVIDER_CLUSTER
value: kubernetes-provider
- name: NIFI_STATE_MANAGEMENT_KUBERNETES_CONFIG_MAP_NAME_PREFIX
value: {{ .Values.stateManagement.kubernetes.statePrefix | quote }}
- name: NIFI_STATE_MANAGEMENT_KUBERNETES_CONFIG_MAP_NAMESPACE
value: {{ include "nifi.stateManagementNamespace" . | quote }}
{{- end }}
{{/*
ZooKeeper state management environment variables
*/}}
{{- define "nifi.zookeeperStateEnvironment" -}}
{{- if .Values.zookeeper.enabled }}
- name: NIFI_ZK_CONNECT_STRING
value: "{{ .Release.Name }}-zookeeper:{{ .Values.zookeeper.external.port | default 2181 }}"
{{- else }}
- name: NIFI_ZK_CONNECT_STRING
value: "{{ .Values.zookeeper.external.url }}"
{{- end }}
- name: NIFI_ZK_ROOT_NODE
value: {{ .Values.zookeeper.rootNode | default "/nifi" | quote }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "nifi.serviceAccountName" -}}
{{- if .Values.global.serviceAccount.name }}
{{- .Values.global.serviceAccount.name }}
{{- else }}
{{- include "nifi.fullname" . }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,44 @@
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: {{ include "nifi.fullname" . }}
labels:
{{- include "nifi.labels" . | nindent 4 }}
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: {{ include "nifi.fullname" . }}
labels:
{{- include "nifi.labels" . | nindent 4 }}
spec:
secretName: {{ include "nifi.fullname" . }}-tls
commonName: {{ include "nifi.fullname" . }}.{{ .Release.Namespace }}
dnsNames:
- {{ .Values.ingress.hostName }}
- {{ include "nifi.siteToSiteHostName" . }}
- {{ include "nifi.fullname" . }}-http.{{ .Release.Namespace }}
{{- include "nifi.hostNodeList" . | nindent 4 }}
{{- include "nifi.ingressNodeList" . | nindent 4 }}
usages:
- server auth
- client auth
{{- with .Values.global.tls.certificate }}
duration: {{ .duration }}
renewBefore: {{ .renewBefore }}
keystores:
pkcs12:
create: true
passwordSecretRef:
{{- if .keystorePasswordSecretRef.name }}
{{- toYaml .keystorePasswordSecretRef | nindent 8 }}
{{- else }}
name: {{ printf "%s-keystore-password" (include "nifi.fullname" $) | quote }}
key: {{ default "password" .keystorePasswordSecretRef.key | quote }}
{{- end }}
{{- end }}
issuerRef:
name: {{ include "nifi.fullname" . }}
kind: Issuer

View File

@ -0,0 +1,326 @@
{{- $serviceHostName := printf "%s-http.%s" (include "nifi.fullname" . ) .Release.Namespace }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "nifi.fullname" . }}
labels:
{{- include "nifi.labels" . | nindent 4 }}
data:
custom-startup.sh: |
#!/bin/bash -e
prop_add () {
target_file="${3:-${nifi_props_file}}"
echo "adding property to target file ${target_file}"
echo "$1=$2" >> "${target_file}"
}
prop_remove () {
target_file="${3:-${nifi_props_file}}"
echo "removing property from target file ${target_file}"
sed -i -e "s|^$1=.*$||" "${target_file}"
}
authorizers_file='conf/authorizers.xml'
bootstrap_file='conf/bootstrap.conf'
nifi_properties_file='conf/nifi.properties'
logback_file='conf/logback.xml'
scripts_dir='/opt/nifi/scripts'
[ -f "${scripts_dir}/common.sh" ] && . "${scripts_dir}/common.sh"
{{- /* Set host connection properties so the node is reachable, with TLS hostname verification */}}
host_name="${HOSTNAME}.{{ include "nifi.fullname" . }}.{{ .Release.Namespace }}"
pod_index=$(echo ${HOSTNAME} | sed -E 's/^.*([0-9]+)$/\1/g')
prop_replace 'nifi.web.https.host' "${host_name}"
export NIFI_WEB_HTTPS_HOST="${host_name}"
export NIFI_WEB_PROXY_HOST=" \
${host_name}, \
{{ .Values.ingress.hostName }}, \
{{ include "nifi.siteToSiteHostName" . }}, \
{{ include "nifi.siteToSiteHostName" . }}:443, \
{{ printf "%s-${pod_index}.%s" (include "nifi.fullname" .) (include "nifi.siteToSiteHostName" .) }}, \
{{ printf "%s-${pod_index}.%s" (include "nifi.fullname" .) (include "nifi.siteToSiteHostName" .) }}:443, \
{{ $serviceHostName }}, \
{{ $serviceHostName }}:{{ .Values.ports.https }}"
{{- /* S2S cluster-local connections */}}
export NIFI_REMOTE_INPUT_HOST="${HOSTNAME}"
prop_add 'nifi.remote.route.raw.cluster.when' '${s2s.source.hostname:equals('\''{{ $serviceHostName }}'\'')}'
prop_add 'nifi.remote.route.raw.cluster.hostname' '${s2s.target.hostname}'
prop_add 'nifi.remote.route.raw.cluster.port' {{ .Values.ports.remoteinput | squote }}
prop_add 'nifi.remote.route.raw.cluster.secure' 'true'
{{- /* S2S connections via Ingress */}}
prop_add 'nifi.remote.route.http.ingress.when' '${X-ProxyHost:contains('\''{{ include "nifi.siteToSiteHostName" . }}'\'')}'
prop_add 'nifi.remote.route.http.ingress.hostname' '${s2s.target.hostname}.{{ include "nifi.siteToSiteHostName" . }}'
prop_add 'nifi.remote.route.http.ingress.port' '443'
prop_add 'nifi.remote.route.http.ingress.secure' 'true'
{{- /* Replace properties not exposed by environment variables */}}
{{- if eq (include "nifi.useZooKeeper" .) "true" }}
prop_replace 'nifi.zookeeper.client.secure' 'false'
{{- else }}
prop_replace 'nifi.state.management.provider.cluster' 'kubernetes-provider'
xmlstarlet ed --inplace --update "/stateManagement/cluster-provider[id='kubernetes-provider']/property[@name='ConfigMap Name Prefix']" --value '{{ .Values.stateManagement.kubernetes.statePrefix }}' "conf/state-management.xml"
xmlstarlet ed --inplace --update "/stateManagement/cluster-provider[id='kubernetes-provider']/property[@name='ConfigMap Namespace']" --value '{{ include "nifi.stateManagementNamespace" . }}' "conf/state-management.xml"
{{- end }}
{{- /* Grant nodes cluster permissions */}}
list_identities () {
node_identities=""
for (( i = 0; i < {{ .Values.global.nifi.nodeCount }}; i++ )); do
node_dn="CN={{ include "nifi.fullname" . }}-${i}.{{ include "nifi.fullname" . }}.{{ .Release.Namespace }}"
node_identities="${node_identities}<property name=\"$1 Node-${i}\">${node_dn}</property>\n"
done
ingress_dn="CN={{ include "nifi.fullname" . }}.{{ .Release.Namespace }}"
node_identities="${node_identities}<property name=\"$1 Node-Ingress\">${ingress_dn}</property>\n"
sed -i -E "s|(<property name=\"$1 1\">.*</property>)|\1\n${node_identities}|g" "${authorizers_file}"
}
list_identities 'Node Identity'
list_identities 'Initial User Identity'
{{- /* Set file and directory paths to persistent locations */}}
{{- with .Values.persistence }}
conf_dir='./persistent_conf'
prop_replace 'nifi.flow.configuration.file' "${conf_dir}/{{ .config.files.flowJson }}"
prop_replace 'nifi.flow.configuration.archive.dir' "${conf_dir}/archive"
sed -i -E "s|(<property name=\"Authorizations File\">).*(</property>)|\1${conf_dir}/{{ .config.files.authorizations }}\2|g" "${authorizers_file}"
sed -i -E "s|(<property name=\"Users File\">).*(</property>)|\1${conf_dir}/{{ .config.files.users }}\2|g" "${authorizers_file}"
{{- end }}
{{- /* Define flowfile repository */}}
{{- with .Values.persistence.repo.flowfile }}
prop_replace 'nifi.flowfile.repository.directory' {{ printf "./%s" .mountDir | squote }}
{{- end }}
{{- /* Define content repositories */}}
prop_remove 'nifi.content.repository.directory.default'
{{- range .Values.persistence.repo.content }}
prop_add 'nifi.content.repository.directory.{{ .name }}' {{ printf "./%s" .mountDir | squote }}
{{- end }}
{{- /* Define provenance repositories */}}
prop_remove 'nifi.provenance.repository.directory.default'
{{- range .Values.persistence.repo.provenance }}
prop_add 'nifi.provenance.repository.directory.{{ .name }}' {{ printf "./%s" .mountDir | squote }}
{{- end }}
{{- /* Define custom nar library path */}}
prop_add 'nifi.nar.library.directory.custom' {{ .Values.customLibPath | squote }}
{{- /* Generate a TLS cert for this node from the CSI-provided certificates and private key */}}
{{- if .Values.global.tls.certificate }}
cert_dir='/opt/certmanager'
tls_dir='/opt/tls'
rm -f $tls_dir/*
openssl pkcs12 -export \
-in $cert_dir/tls.crt \
-inkey $cert_dir/tls.key \
-CAfile $cert_dir/ca.crt \
-passout "pass:${KEYSTORE_PASSWORD}" \
-out $tls_dir/keystore.p12
keytool -import -noprompt -trustcacerts \
-file $cert_dir/ca.crt \
-storepass "${TRUSTSTORE_PASSWORD}" \
-destkeystore $tls_dir/truststore.p12 \
-deststoretype pkcs12
{{- end }}
{{- /* Task termination period */}}
prop_replace 'graceful.shutdown.seconds' {{ .Values.shutdown.gracefulShutdownSeconds }} "${bootstrap_file}"
{{- /* Set UI autorefresh interval */}}
prop_replace 'nifi.ui.autorefresh.interval' {{ .Values.ui.refreshInterval | squote }}
{{- with .Values.ui.timeZone }}
echo 'java.arg.8=-Duser.timezone={{ . }}' >> "${bootstrap_file}"
{{- end }}
{{- with .Values.ui.maxThreads }}
prop_replace 'nifi.web.jetty.threads' {{ . | squote }}
{{- end }}
{{- /* Set user logging levels */}}
{{- range $logger, $level := .Values.logging.levels }}
xmlstarlet ed --inplace --update "//logger[@name='{{ $logger }}']/@level" --value '{{ $level }}' "${logback_file}"
{{- end }}
{{- /* Set user logging max size capping */}}
{{- range $appender, $size := .Values.logging.totalSizeCap }}
xmlstarlet ed -L -s '//appender[@name="{{ $appender }}"]/rollingPolicy' -t elem -n 'totalSizeCap' -v '{{ $size }}' "${logback_file}"
{{- end }}
{{- range $key, $value := .Values.extraConfig.nifiProperties }}
prop_replace {{ $key | squote }} {{ $value | quote }}
{{- end }}
{{- if .Values.debugStartup }}
sleep 1000000
{{- end }}
{{- with .Values.umask }}
umask {{ . }}
{{- end }}
exec $scripts_dir/start.sh
pre-stop.sh: |
#!/bin/bash
# NiFi toolkit CLI path
NIFI_CLI="/opt/nifi/nifi-toolkit-current/bin/cli.sh"
# NiFi Cluster variables (use a proper hostname substitution here)
NIFI_URL="https://{{ $serviceHostName }}:8443"
# Log file path (update to your desired destination)
LOG_FILE="/opt/nifi/nifi-current/logs/k8s-pre-stop.log"
# Redirect all output (stdout and stderr) to the log file
exec > >(tee -a "$LOG_FILE") 2>&1
# Function to get the status of the node
get_node_status() {
NODE_ID="$1"
NODE_STATUS=$($NIFI_CLI nifi get-node --nifiNodeId "$NODE_ID" -u "$NIFI_URL" -ot json | jq -r '.node.status')
echo "$NODE_STATUS"
}
# Retry function for critical steps (like disconnecting or offloading nodes)
retry_command() {
local retries=5
local wait_time=5
local cmd="$@"
for ((i=1; i<=retries; i++)); do
eval "$cmd"
if [ $? -eq 0 ]; then
return 0
fi
echo "$(date): Command failed. Retrying in $wait_time seconds... (Attempt $i/$retries)"
sleep $wait_time
done
echo "$(date): Command failed after $retries attempts. Exiting."
exit 1
}
# Get the hostname
HOSTNAME=$(hostname)
echo "$(date): Retrieving node information for the hostname: $HOSTNAME..."
# Retrieve the list of nodes
NODE_INFO=$($NIFI_CLI nifi get-nodes -u "$NIFI_URL")
# Check if NODE_INFO is empty (failed retrieval)
if [ -z "$NODE_INFO" ]; then
echo "$(date): Failed to retrieve node information. Exiting."
exit 1
fi
# Extract the node ID based on the hostname
NODE_ID=$(echo "$NODE_INFO" | grep "$HOSTNAME" | awk '{print $2}')
# Check if the NODE_ID is empty
if [ -z "$NODE_ID" ]; then
echo "$(date): Node ID for $HOSTNAME not found. Exiting."
exit 1
fi
echo "$(date): Node ID for $HOSTNAME is $NODE_ID"
# Get the current node status
CURRENT_STATUS=$(get_node_status "$NODE_ID")
echo "$(date): Current node status: $CURRENT_STATUS"
# Disconnect the current node if it is not already disconnected
if [ "$CURRENT_STATUS" != "DISCONNECTED" ]; then
echo "$(date): Disconnecting node $NODE_ID..."
retry_command "$NIFI_CLI nifi disconnect-node --nifiNodeId $NODE_ID"
echo "$(date): Node $NODE_ID disconnected."
else
echo "$(date): Node $NODE_ID is already disconnected."
fi
# Offload the current node if not already offloaded
if [ "$CURRENT_STATUS" != "OFFLOADED" ]; then
echo "$(date): Offloading node $NODE_ID..."
retry_command "$NIFI_CLI nifi offload-node --nifiNodeId $NODE_ID --connectionTimeout 60000 --readTimeout 60000 -u $NIFI_URL"
echo "$(date): Node $NODE_ID offloading..."
else
echo "$(date): Node $NODE_ID is already offloaded."
fi
# Wait for the node to be fully offloaded with a retry limit
MAX_ATTEMPTS=12 # Limit the retries to 12 (with 5-second interval = 1 minute total)
attempt=1
while [ $attempt -le $MAX_ATTEMPTS ]; do
CURRENT_STATUS=$(get_node_status "$NODE_ID")
if [ "$CURRENT_STATUS" == "OFFLOADED" ]; then
echo "$(date): Node $NODE_ID successfully offloaded."
break
else
echo "$(date): Current node status: $CURRENT_STATUS. Retrying in 5 seconds... (Attempt $attempt/$MAX_ATTEMPTS)"
attempt=$((attempt+1))
sleep 5
fi
done
# If the node hasn't offloaded after the max attempts, exit with an error
CURRENT_STATUS=$(get_node_status "$NODE_ID")
if [ "$CURRENT_STATUS" != "OFFLOADED" ]; then
echo "$(date): Node $NODE_ID failed to offload after $MAX_ATTEMPTS attempts. Exiting."
exit 1
fi
# Remove the node
echo "$(date): Removing node $NODE_ID..."
retry_command "$NIFI_CLI nifi delete-node --nifiNodeId $NODE_ID -u $NIFI_URL"
echo "$(date): Node $NODE_ID offloaded and removed successfully."
{{- with .Values.filebeat }}
{{- if .enabled }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "nifi.fullname" $ }}-filebeat
labels:
{{- include "nifi.labels" $ | nindent 4 }}
data:
filebeat.yml: |
tags:
{{- toYaml .tags | nindent 6 }}
filebeat.inputs:
- type: filestream
id: nifi-app
fields:
log_id: app
paths: ["/nifi/logs/nifi-app*.log"]
- type: filestream
id: nifi-request
fields:
log_id: request
paths: ["/nifi/logs/nifi-request*.log"]
- type: filestream
id: nifi-user
fields:
log_id: user
paths: ["/nifi/logs/nifi-user*.log"]
{{- if or .labels .processors }}
processors:
{{- if .labels }}
- add_labels:
labels:
{{- toYaml .labels | nindent 12 }}
{{- end }}
{{- toYaml .processors | nindent 6 }}
{{- end }}
{{ printf "output.%s:" .output.type }}
{{- toYaml .output.parameters | nindent 6 }}
queue.mem:
flush.timeout: {{ .queue.flushTimeout }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,76 @@
{{- if .Values.nifiMonitor.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "nifi.fullname" . }}-monitor
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ include "nifi.name" . }}-monitor
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
replicas: {{ .Values.nifiMonitor.replicas }}
selector:
matchLabels:
app: {{ include "nifi.name" . }}-monitor
template:
metadata:
labels:
app: {{ include "nifi.name" . }}-monitor
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "5000"
prometheus.io/path: "/metrics"
spec:
containers:
- name: nifi-monitor
image: {{ .Values.nifiMonitor.image.repository }}:{{ .Values.nifiMonitor.image.tag | default "latest" }}
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5000
env:
- name: BASE_URL
value: https://{{ include "nifi.fullname" . }}-http.{{ .Release.Namespace }}:{{ .Values.ports.https }}
- name: CERT_FILE
value: "/opt/nifiMonitor/tls.crt"
- name: KEY_FILE
value: "/opt/nifiMonitor/tls.key"
volumeMounts:
- name: certs
mountPath: /opt/nifiMonitor
readOnly: true
resources:
{{- toYaml .Values.nifiMonitor.resources | nindent 12 }}
tolerations:
{{- toYaml .Values.nifiMonitor.tolerations | nindent 8 }}
affinity:
{{- toYaml .Values.nifiMonitor.affinity | nindent 8 }}
nodeSelector:
{{- toYaml .Values.nifiMonitor.nodeSelector | nindent 8 }}
volumes:
- name: certs
secret:
secretName: {{ include "nifi.fullname" . }}-tls # The secret created by cert-manager
optional: false # Secret must be present
restartPolicy: Always
{{- end }}
---
{{- if .Values.nifiMonitor.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "nifi.fullname" . }}-monitor-service
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ include "nifi.name" . }}-monitor
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
ports:
- port: 5000
targetPort: 5000
protocol: TCP
name: metrics
selector:
app: {{ include "nifi.name" . }}-monitor
type: ClusterIP
{{- end }}

View File

@ -0,0 +1,41 @@
{{- if .Values.ingress.enabled }}
{{- $serviceName := (printf "%s-http" (include "nifi.fullname" . )) }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "nifi.fullname" . }}
labels:
{{- include "nifi.labels" . | nindent 4 }}
annotations:
# nginx.ingress.kubernetes.io/backend-protocol: HTTPS
# nginx.ingress.kubernetes.io/affinity: cookie
# nginx.ingress.kubernetes.io/affinity-mode: persistent
{{- with .Values.ingress.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.ingressClassName }}
ingressClassName: {{ .Values.ingress.ingressClassName | quote }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
- host: {{ .Values.ingress.hostName }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ $serviceName }}
port:
name: https
{{- end }}

View File

@ -0,0 +1,17 @@
{{- if .Values.pdb.enabled }}
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ include "nifi.fullname" . }}-pdb
labels:
app: {{ include "nifi.name" . }}
chart: {{ include "nifi.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
maxUnavailable: {{ .Values.pdb.maxUnavailable | default 1 }}
selector:
matchLabels:
app.kubernetes.io/name: nifi
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

View File

@ -0,0 +1,75 @@
{{- if .Values.nifiMonitor.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "nifi.fullname" . }}-monitor
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ include "nifi.name" . }}-monitor
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
replicas: {{ .Values.nifiMonitor.replicas }}
selector:
matchLabels:
app: {{ include "nifi.name" . }}-monitor
template:
metadata:
labels:
app: {{ include "nifi.name" . }}-monitor
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "5000"
prometheus.io/path: "/metrics"
spec:
containers:
- name: nifi-monitor
image: "sakkiii/nifi_exporter:latest"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5000
env:
- name: BASE_URL
value: {{ include "nifi.fullname" . }}.{{ .Release.Namespace }}
- name: CERT_FILE
value: "/opt/nifiMonitor/tls.crt"
- name: KEY_FILE
value: "/opt/nifiMonitor/tls.key"
volumeMounts:
- name: certs
mountPath: /opt/nifiMonitor
readOnly: true
resources:
{{- toYaml .Values.nifiMonitor.resources | nindent 12 }}
tolerations:
{{- toYaml .Values.nifiMonitor.tolerations | nindent 8 }}
affinity:
{{- toYaml .Values.nifiMonitor.affinity | nindent 8 }}
nodeSelector:
{{- toYaml .Values.nifiMonitor.nodeSelector | nindent 8 }}
volumes:
- name: certs
secret:
secretName: {{ include "nifi.fullname" . }}-tls # The secret created by cert-manager
optional: false # Secret must be present
restartPolicy: Always
{{- end }}
---
{{- if .Values.nifiMonitor.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "nifi.fullname" . }}-monitor-service
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ include "nifi.name" . }}-monitor
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
ports:
- port: 5000
targetPort: 5000
protocol: TCP
name: metrics
selector:
app: {{ include "nifi.name" . }}-monitor
type: ClusterIP
{{- end }}

View File

@ -0,0 +1,46 @@
{{- if eq (include "nifi.useKubernetesStateManagement" .) "true" }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "nifi.fullname" . }}-state-management
namespace: {{ .Release.Namespace }}
labels:
{{- include "nifi.labels" . | nindent 4 }}
component: state-management
rules:
# Permissions for Kubernetes state management (ConfigMaps)
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "create", "update", "patch", "delete"]
# Permissions for leader election (Leases)
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["get", "list", "create", "update", "patch", "delete"]
# Permissions to read pods (for cluster membership)
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
# Permissions for events (optional, for better observability)
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "nifi.fullname" . }}-state-management
namespace: {{ .Release.Namespace }}
labels:
{{- include "nifi.labels" . | nindent 4 }}
component: state-management
subjects:
- kind: ServiceAccount
name: {{ include "nifi.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
roleRef:
kind: Role
name: {{ include "nifi.fullname" . }}-state-management
apiGroup: rbac.authorization.k8s.io
{{- end }}

View File

@ -0,0 +1,40 @@
{{- /*
Create secrets if they don't exist
*/ -}}
{{- /* Sensitive Properties Key Secret */ -}}
{{- $sensitiveKeySecretName := default "encryption-sensitive-key" .Values.global.encryption.sensitivePropertiesKey.secretRef.name -}}
{{- $existingSensitiveKey := (lookup "v1" "Secret" .Release.Namespace $sensitiveKeySecretName) -}}
{{- if not $existingSensitiveKey }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ $sensitiveKeySecretName }}
labels:
{{- include "nifi.labels" . | nindent 4 }}
annotations:
"helm.sh/resource-policy": "keep"
type: Opaque
data:
{{ .Values.global.encryption.sensitivePropertiesKey.secretRef.key }}: {{ randAlphaNum 32 | b64enc | quote }}
{{- end }}
{{- /* Keystore Password Secret */ -}}
{{- $keystorePasswordSecretName := default "certificate-keystore-password" .Values.global.tls.certificate.keystorePasswordSecretRef.name -}}
{{- $existingKeystorePassword := (lookup "v1" "Secret" .Release.Namespace $keystorePasswordSecretName) -}}
{{- if not $existingKeystorePassword }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ $keystorePasswordSecretName }}
labels:
{{- include "nifi.labels" . | nindent 4 }}
annotations:
"helm.sh/resource-policy": "keep"
type: Opaque
data:
{{ .Values.global.tls.certificate.keystorePasswordSecretRef.key }}: {{ randAlphaNum 32 | b64enc | quote }}
{{- end }}

View File

@ -0,0 +1,86 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "nifi.fullname" . }}-http
labels:
{{- include "nifi.labels" . | nindent 4 }}
spec:
type: ClusterIP
ports:
- port: {{ .Values.ports.https }}
targetPort: https
protocol: TCP
name: https
- port: {{ .Values.ports.remoteinput }}
targetPort: remoteinput
protocol: TCP
name: remoteinput
{{- /* Only include extra ports that don't have a nodePort specified. For those that do, include them in a separate Service */}}
{{- range $name, $port := .Values.extraPorts }}
{{- if not (and $port.nodePort $port.loadBalancerPort) }}
- name: {{ $name }}
port: {{ $port.containerPort }}
targetPort: {{ $port.containerPort }}
protocol: {{ $port.protocol | default "TCP" }}
{{- end }}
{{- end }}
selector:
{{- include "nifi.selectorLabels" . | nindent 4 }}
{{- if eq (include "nifi.hasExternalPorts" . ) "true" }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "nifi.fullname" . }}-external
labels:
{{- include "nifi.labels" . | nindent 4 }}
{{- with .Values.service.external.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.service.external.type }}
externalTrafficPolicy: {{ .Values.service.external.externalTrafficPolicy }}
ports:
{{- range $name, $port := .Values.extraPorts }}
{{- if or $port.nodePort $port.loadBalancerPort }}
- name: {{ $name }}
targetPort: {{ $port.containerPort }}
protocol: {{ $port.protocol | default "TCP" }}
{{- if $port.nodePort }}
nodePort: {{ $port.nodePort }}
{{- end }}
{{- if $port.loadBalancerPort }}
port: {{ $port.loadBalancerPort}}
{{- else }}
port: {{ $port.containerPort }}
{{- end }}
{{- end }}
{{- end }}
selector:
{{- include "nifi.selectorLabels" . | nindent 4 }}
{{- end }}
{{- range $i, $e := until (int .Values.global.nifi.nodeCount) }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "nifi.fullname" $ }}-{{ $i }}
labels:
{{- include "nifi.labels" $ | nindent 4 }}
spec:
type: ClusterIP
clusterIP: None
ports:
- port: {{ $.Values.ports.https }}
targetPort: https
protocol: TCP
name: https
- port: {{ $.Values.ports.metrics }}
targetPort: metrics
protocol: TCP
name: metrics
selector:
statefulset.kubernetes.io/pod-name: {{ include "nifi.fullname" $ }}-{{ $i }}
{{- include "nifi.selectorLabels" $ | nindent 4 }}
{{- end }}

View File

@ -0,0 +1,12 @@
{{- if not .Values.global.serviceAccount.name -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "nifi.fullname" . }}
labels:
{{- include "nifi.labels" . | nindent 4 }}
{{- with .Values.global.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,19 @@
{{- if .Values.metrics.serviceMonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "nifi.fullname" . }}
labels:
{{- include "nifi.labels" . | nindent 4 }}
spec:
endpoints:
- interval: {{ .Values.metrics.serviceMonitor.interval }}
port: metrics
path: /metrics
namespaceSelector:
matchNames:
- {{ .Release.Namespace }}
selector:
matchLabels:
{{- include "nifi.selectorLabels" . | nindent 6 }}
{{- end }}

View File

@ -0,0 +1,388 @@
{{- $nifiHome := "/opt/nifi/nifi-current" }}
{{- /* Validate that basic auth is only used with single node */ -}}
{{- if and (not .Values.global.oidc.enabled) (not .Values.global.ldap.enabled) (gt (.Values.global.nifi.nodeCount | int) 1) }}
{{- fail "Basic authentication (Single User Authentication) only supports single-node deployment. Please set global.nifi.nodeCount to 1, or enable OIDC/LDAP authentication for clustering." }}
{{- end }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "nifi.fullname" . }}
labels:
{{- include "nifi.labels" . | nindent 4 }}
spec:
podManagementPolicy: Parallel
replicas: {{ .Values.global.nifi.nodeCount }}
selector:
matchLabels:
{{- include "nifi.selectorLabels" . | nindent 6 }}
serviceName: {{ include "nifi.fullname" . }}
template:
metadata:
labels:
{{- include "nifi.selectorLabels" . | nindent 8 }}
spec:
terminationGracePeriodSeconds: {{ .Values.shutdown.podTerminationGracePeriodSeconds }}
{{- if or .Values.persistence.takeOwnershipOnStartup .Values.extraTakeOwnershipPaths }}
initContainers:
{{- if eq (include "nifi.useZooKeeper" .) "true" }}
- name: wait-for-zookeeper
image: {{ .Values.global.busybox.repository }}
command:
- sh
- -c
- |
{{- if .Values.zookeeper.enabled }}
echo "Connecting to embedded ZooKeeper {{ .Release.Name }}-zookeeper"
until nc -vzw 1 {{ .Release.Name }}-zookeeper {{ .Values.zookeeper.external.port | default 2181 }} ; do
echo "Waiting for zookeeper to start"
sleep 3
done
{{- else }}
echo "Connecting to external ZooKeeper {{ .Values.zookeeper.external.url }}"
{{- if .Values.zookeeper.external.url }}
{{- range $url := splitList "," .Values.zookeeper.external.url }}
{{- $hostPort := splitList ":" $url }}
{{- if gt (len $hostPort) 1 }}
until nc -vzw 1 {{ index $hostPort 0 }} {{ index $hostPort 1 }} ; do
echo "Waiting for zookeeper {{ $url }} to start"
sleep 3
done
{{- else }}
until nc -vzw 1 {{ index $hostPort 0 }} 2181 ; do
echo "Waiting for zookeeper {{ $url }}:2181 to start"
sleep 3
done
{{- end }}
{{- end }}
{{- else }}
echo "No external ZooKeeper URL configured"
{{- end }}
{{- end }}
resources:
requests:
cpu: 20m
memory: 10Mi
limits:
cpu: 20m
memory: 10Mi
{{- else }}
- name: check-kubernetes-permissions
image: {{ .Values.global.busybox.repository }}
command:
- sh
- -c
- |
echo "Using Kubernetes state management for NiFi {{ .Chart.AppVersion }}"
echo "Checking Kubernetes API permissions..."
echo "Namespace: {{ include "nifi.stateManagementNamespace" . }}"
echo "Lease prefix: {{ .Values.stateManagement.kubernetes.leasePrefix }}"
echo "State prefix: {{ .Values.stateManagement.kubernetes.statePrefix }}"
echo "✅ Kubernetes state management configured"
resources:
requests:
cpu: 20m
memory: 10Mi
limits:
cpu: 20m
memory: 10Mi
{{- end }}
securityContext:
allowPrivilegeEscalation: false
privileged: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
- name: take-ownership
image: {{ .Values.global.busybox.repository }}
command:
- sh
- -c
- |
{{- if .Values.persistence.takeOwnershipOnStartup }}
chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/persistent_conf
chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/state
chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/logs
chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/flowfile_repo
chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/content_repo
chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/provenance_repo
{{- end }}
{{- range .Values.extraTakeOwnershipPaths }}
chown {{ $.Values.securityContext.runAsUser | int64 }}:{{ $.Values.securityContext.runAsGroup | int64 }} {{ . | quote }}
{{- end }}
securityContext:
runAsUser: 0
runAsNonRoot: false
volumeMounts:
- name: config
mountPath: {{ $nifiHome }}/persistent_conf
- name: state
mountPath: {{ $nifiHome }}/state
- name: logs
mountPath: {{ $nifiHome }}/logs
{{- if .Values.persistence.takeOwnershipOnStartup }}
- name: flowfile
mountPath: {{ $nifiHome }}/flowfile_repo
- name: content
mountPath: {{ $nifiHome }}/content_repo
- name: provenance
mountPath: {{ $nifiHome }}/provenance_repo
{{- end }}
{{- with .Values.extraVolumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: [ "../scripts/k8s/custom-startup.sh" ]
lifecycle:
preStop:
exec:
command: [ "../scripts/k8s/pre-stop.sh" ]
env:
- name: NIFI_SENSITIVE_PROPS_KEY
valueFrom:
secretKeyRef:
name: {{ default "encryption-sensitive-key" .Values.global.encryption.sensitivePropertiesKey.secretRef.name | quote }}
key: {{ default "sensitivekey" .Values.global.encryption.sensitivePropertiesKey.secretRef.key | quote }}
- name: NIFI_JVM_HEAP_INIT
value: {{ .Values.jvmHeap.min | quote }}
- name: NIFI_JVM_HEAP_MAX
value: {{ .Values.jvmHeap.max | quote }}
- name: NIFI_WEB_HTTPS_PORT
value: {{ .Values.ports.https | quote }}
- name: NIFI_REMOTE_INPUT_SOCKET_PORT
value: {{ .Values.ports.remoteinput | quote }}
- name: NIFI_CLUSTER_NODE_PROTOCOL_PORT
value: {{ .Values.ports.cluster | quote }}
- name: NIFI_CLUSTER_IS_NODE
value: "true"
- name: NIFI_ELECTION_MAX_CANDIDATES
value: {{ .Values.global.nifi.nodeCount | quote }}
{{- /* Common cluster environment variables (required for both state management strategies) */}}
{{- include "nifi.clusterEnvironment" . | nindent 12 }}
{{- if eq (include "nifi.useZooKeeper" .) "true" }}
{{- include "nifi.zookeeperStateEnvironment" . | nindent 12 }}
{{- else }}
{{- include "nifi.kubernetesStateEnvironment" . | nindent 12 }}
{{- end }}
{{- include "nifi.keystoreEnvironment" . | nindent 12 }}
{{- /* Authentication environment variables with priority: OIDC > LDAP > Basic Auth */}}
{{- if .Values.global.oidc.enabled }}
{{- /* OIDC has highest priority */}}
{{- include "nifi.oidcEnvironment" . | nindent 12 }}
{{- else if .Values.global.ldap.enabled }}
{{- /* LDAP is second priority (only if OIDC is disabled) */}}
{{- include "nifi.ldapEnvironment" . | nindent 12 }}
{{- else }}
{{- /* Basic auth is the default fallback (when both OIDC and LDAP are disabled) */}}
{{- include "nifi.basicAuthEnvironment" . | nindent 12 }}
{{- end }}
{{- with .Values.extraEnv }}
{{ toYaml . | nindent 12 }}
{{- end }}
ports:
{{- range $name, $number := .Values.ports }}
- name: {{ $name }}
containerPort: {{ $number }}
protocol: TCP
{{- end }}
{{- if .Values.extraPorts }}
{{- range $name, $port := .Values.extraPorts }}
- name: {{ $name }}
containerPort: {{ $port.containerPort }}
protocol: {{ $port.protocol | default "TCP" }}
{{- end }}
{{- end }}
volumeMounts:
- mountPath: {{ include "nifi.certPath" . }}
name: certs
readOnly: true
- mountPath: {{ include "nifi.tlsPath" . }}
name: tls
- mountPath: /opt/nifi/scripts/k8s
name: config-script
readOnly: true
- name: config
mountPath: {{ $nifiHome }}/persistent_conf
- name: state
mountPath: {{ $nifiHome }}/state
- name: logs
mountPath: {{ $nifiHome }}/logs
- name: flowfile
mountPath: {{ $nifiHome }}/flowfile_repo
- name: content
mountPath: {{ $nifiHome }}/content_repo
- name: provenance
mountPath: {{ $nifiHome }}/provenance_repo
{{- with .Values.extraVolumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- if not .Values.debugStartup }}
startupProbe:
tcpSocket:
port: https
{{- toYaml .Values.probeTimings.startup | nindent 12 }}
readinessProbe:
exec:
command:
- sh
- -c
- curl -k -s https://${HOSTNAME}.{{ include "nifi.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.ports.https }}/nifi
{{- toYaml .Values.probeTimings.readiness | nindent 12 }}
livenessProbe:
exec:
command:
- sh
- -c
- curl -k -s https://${HOSTNAME}.{{ include "nifi.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.ports.https }}/nifi
{{- toYaml .Values.probeTimings.liveness | nindent 12 }}
{{- end }}
{{- if .Values.filebeat.enabled }}
- name: filebeat
image: {{ .Values.filebeat.image.repository }}:{{ .Values.filebeat.image.tag | default "latest" }}
args:
- -e
- -E
- http.enabled=true
volumeMounts:
- mountPath: /usr/share/filebeat/filebeat.yml
subPath: filebeat.yml
name: filebeat-config
readOnly: true
- mountPath: /nifi/logs
{{- with .Values.persistence.logs.volumeMount }}
name: {{ .name | default "logs" }}
{{- if .subPath }}
subPath: {{ .subPath }}
{{- end }}
{{- end }}
{{- with .Values.filebeat.volumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.filebeat.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
startupProbe:
exec:
command:
- sh
- -c
- |
#!/usr/bin/env bash -e
filebeat test input
{{- toYaml .Values.probeTimings.startup | nindent 12 }}
readinessProbe:
exec:
command:
- sh
- -c
- |
#!/usr/bin/env bash -e
filebeat test output
{{- toYaml .Values.probeTimings.readiness | nindent 12 }}
livenessProbe:
exec:
command:
- sh
- -c
- |
#!/usr/bin/env bash -e
curl --fail 127.0.0.1:5066
{{- toYaml .Values.probeTimings.liveness | nindent 12 }}
{{- end }}
volumes:
- name: certs
secret:
secretName: {{ include "nifi.fullname" . }}-tls # The secret created by cert-manager
optional: false # Secret must be present
- name: tls
emptyDir: { }
- name: config-script
configMap:
name: {{ include "nifi.fullname" . }}
defaultMode: 0554
{{- with .Values.persistence.logs.volumeMount }}
{{- /* Use an emptyDir volume if no persistence is configured */}}
{{- if not .name }}
- name: logs
emptyDir: { }
{{- end }}
{{- end }}
{{- with .Values.extraVolumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.filebeat }}
{{- if .enabled }}
- name: filebeat-config
configMap:
name: {{ include "nifi.fullname" $ }}-filebeat
{{- end }}
{{- end }}
{{- with .Values.global.serviceAccount }}
serviceAccountName: {{ .name | default (include "nifi.fullname" $) }}
{{- end }}
securityContext:
{{- toYaml .Values.securityContext | nindent 8 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
affinity:
{{- if .Values.affinity }}
{{- toYaml . | nindent 8 }}
{{- else }}
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchLabels:
{{- include "nifi.selectorLabels" . | nindent 20 }}
topologyKey: kubernetes.io/hostname
weight: 100
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.volumeClaims }}
volumeClaimTemplates:
{{- range $name, $volumeClaim := . }}
- metadata:
name: {{ $name }}
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: {{ $volumeClaim.size }}
storageClassName: {{ $volumeClaim.storageClass }}
{{- end }}
{{- end }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "nifi.fullname" . }}
labels:
{{- include "nifi.labels" . | nindent 4 }}
spec:
type: ClusterIP
clusterIP: None
publishNotReadyAddresses: true
ports:
{{- range $name, $number := .Values.ports }}
- name: {{ $name }}
port: {{ $number }}
protocol: TCP
{{- end }}
selector:
{{- include "nifi.selectorLabels" . | nindent 4 }}

389
charts/nifi/values.yaml Normal file
View File

@ -0,0 +1,389 @@
# Default values for nifi.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
global:
busybox:
repository: public.ecr.aws/docker/library/busybox:stable
nifi:
nodeCount: 1 # Default to 1 node since basic auth (default) doesn't support clustering
serviceAccount:
# Name of the existing service account to use. If not defined, one is created.
name: ""
# Annotations to add to the service account
annotations: { }
tls:
certificate:
duration: 8760h # 365 days
renewBefore: 168h # 7 days
keystorePasswordSecretRef:
# Use default auto-generated secret, or specify existing secret name
name: "certificate-keystore-password"
key: password
encryption:
sensitivePropertiesKey:
# Use default auto-generated secret, or specify existing secret name
secretRef:
name: "encryption-sensitive-key"
key: "sensitivekey"
# Authentication is automatically determined by priority:
# 1. OIDC (if enabled) - highest priority
# 2. LDAP (if OIDC disabled and LDAP enabled) - second priority
# 3. Basic Auth (if both OIDC and LDAP disabled) - default fallback
# Single User Authentication (default fallback)
# Uses NiFi's built-in Single User Authentication
# Note: Basic auth is automatically disabled when OIDC or LDAP is enabled
# IMPORTANT: Basic auth only supports single-node deployment (nodeCount: 1)
basic:
admin_username: "admin"
admin_password: "your32characterpasswordhere123" # Must be at least 12 characters
# LDAP Authentication
ldap:
enabled: false
url: "" # ldaps://dc-1.example.com:636,ldaps://dc-2.example.com:636
tlsProtocol: TLSv1.2
authenticationStrategy: LDAPS # ANONYMOUS|SIMPLE|LDAPS|START_TLS
identityStrategy: USE_USERNAME # USE_DN|USE_USERNAME
initialAdminIdentity: "" # CN=Administrator,DC=example,DC=com
manager:
distinguishedName: "" # CN=Administrator,DC=example,DC=com
passwordSecretRef:
name: ""
key: ""
userSearchBase: "" # DC=example,DC=com
userSearchFilter: sAMAccountName={0}
# OpenID Connect (OIDC) Authentication
oidc:
enabled: false
oidc_url: ""
client_id: ""
client_secret: ""
client_secretFrom: ""
claim_identifying_user: "preferred_username"
initial_admin_identity: ""
image:
repository: apache/nifi
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
# Set to `true` to pause at startup before loading the application
debugStartup: false
# Number of seconds to wait for tasks to complete on shutdown, before forcefully terminating them
shutdown:
gracefulShutdownSeconds: 20 # Consider whether there are any long-running processors defined in the flow
podTerminationGracePeriodSeconds: 30 # Should be longer than `gracefulShutdownSeconds`
ui:
refreshInterval: 10 sec
timeZone: "Asia/Calcutta" # IANA timezone identifier. Time is displayed using this timezone in the UI.
maxThreads: "" # Maximum number of Jetty threads to use for UI and HTTP site-to-site connections
# Cluster Communication Configuration
cluster:
# Maximum number of threads for inter-node communication
# Used for both ZooKeeper and Kubernetes state management strategies
nodeProtocol:
maxThreads: 100
tls:
# Additional subject alternative names included in the certificate issued to cluster nodes
subjectAltNames: [ ]
# - nifi.internal
encryption:
# Used to encrypt all repositories
repository:
enabled: false
keyId: 1
secretRef:
name: ""
key: repository.p12 # File extension must be either .p12 or .bcfks
logging:
# Override log verbosity settings in conf/logback.xml
levels:
# org.apache.nifi.web.security: ERROR
org.apache.nifi.processors: WARN
org.apache.nifi.processors.standard.LogAttribute: WARN
org.apache.nifi.processors.standard.LogMessage: WARN
totalSizeCap:
APP_FILE: 5GB
USER_FILE: 2GB
persistence:
takeOwnershipOnStartup: true
config:
files:
authorizations: authorizations.xml
users: users.xml
flowJson: flow.json.gz
volumeMount:
name: config # Name of the volume mount to use
state:
volumeMount:
name: state
logs:
volumeMount:
# Specify a custom mount to persist log data in a separate volume (recommended)
name: ""
subPath: ""
repo:
# By default, repositories are mapped to a single PVC.
# If multiple PVCs are desired (for instance, having separate content and provenance repos), override the relevant section.
flowfile:
mountDir: flowfile_repo # Relative directory within the container (i.e. /opt/nifi/nifi-current/flowfile_repository)
volumeName: flowfile # Name of the volume to mount
content:
- name: default
mountDir: content_repo
volumeName: content
provenance:
- name: default
mountDir: provenance_repo
volumeName: provenance
ports:
https: 8443
cluster: 11443
remoteinput: 10443
loadbalance: 6342
metrics: 9092
service:
external:
annotations: { }
type: LoadBalancer # NodePort | LoadBalancer
externalTrafficPolicy: Cluster # Cluster | Local
## ==========================================
## STATE MANAGEMENT CONFIGURATION
## ==========================================
## NiFi supports two state management approaches:
## 1. ZooKeeper (NiFi < 2.0 and backward compatibility)
## 2. Kubernetes Native (NiFi 2.0+, recommended)
## State Management Strategy (auto-detected based on NiFi version)
## - For NiFi 2.0+: Kubernetes state management is used by default
## - For NiFi < 2.0: ZooKeeper is used by default
## - Manual override available via stateManagement.strategy
stateManagement:
# Strategy: "auto" | "zookeeper" | "kubernetes"
# - auto: Automatically choose based on NiFi version (recommended)
# - zookeeper: Force ZooKeeper for all versions
# - kubernetes: Force Kubernetes for all versions (requires NiFi 2.0+)
strategy: "auto"
# Kubernetes State Management (NiFi 2.0+)
kubernetes:
# Prefix for Kubernetes lease resources (for leader election)
leasePrefix: "nifi-lease"
# Prefix for Kubernetes ConfigMap resources (for cluster state)
statePrefix: "nifi-state"
# Note: Always uses release namespace for security and simplicity
## ZooKeeper Configuration (for backward compatibility and NiFi < 2.0)
zookeeper:
## Enable ZooKeeper deployment
## Automatically disabled when Kubernetes state management is used
enabled: true
## External ZooKeeper Configuration
## If enabled=false, provide external ZooKeeper connection details
external:
# External ZooKeeper connection string (comma-separated)
url: "" # e.g., "zk1.example.com:2181,zk2.example.com:2181"
port: 2181
rootNode: "/nifi"
## Embedded ZooKeeper Configuration (when enabled=true)
## ref: https://github.com/bitnami/charts/blob/master/bitnami/zookeeper/values.yaml
replicaCount: 3
rootNode: "/nifi"
metrics:
enabled: true
## Set container resources according to one common
## preset allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge.
## This is ignored if resources is set
resourcesPreset: small
metrics:
# Expose metrics for each node via Ingress
ingress:
enabled: false
https: false
basePath: /metrics # Metrics are available externally via Ingress for each pod at: /metrics/<pod name>
requireClientCertificate: false
# Create a ServiceMonitor to enable Prometheus to scrape metrics from each pod
serviceMonitor:
enabled: false
interval: 10s
nifiMonitor:
## Monitor NiFi cluster health using NiFi API calls, scrape these call response using prometheus or VM cluster
enabled: false
image:
repository: ghcr.io/sakkiii/nifi_exporter
tag: latest
replicas: 1
resources:
limits:
memory: "128Mi"
cpu: "20m"
requests:
memory: "64Mi"
cpu: "2m"
tolerations: []
affinity: {}
nodeSelector: {}
# Optionally deploy a filebeat sidecar to ship NiFi logs to a receiver
filebeat:
enabled: false
image:
repository: docker.elastic.co/beats/filebeat
tag: ""
resources:
requests:
cpu: 100m
memory: 128Mi
securityContext: { }
volumeMounts: [ ]
# - mountPath: /opt/secrets
# name: secret
tags:
- nifi
labels: { }
# instance: production
processors: [ ]
# - drop_event:
# when:
# regexp:
# message: "drop_event.*"
queue:
flushTimeout: 5s
output:
type: "" # kafka
parameters: { }
# hosts: ["kafka-1:9092"]
# topic: nifi
# Additional ports and Ingress rules to configure for each node
extraPorts: { }
# datafeed:
# containerPort: 9443
# protocol: TCP
# nodePort: 30443 # Set if NodePort is required
# loadBalancerPort: 9443
# ingress: # Omit if ingress is not required
# path: /datafeed
# pathType: Exact
# Extra nar library directory
customLibPath: ""
# Extra config properties to set at runtime
extraConfig:
nifiProperties: { }
# nifi.cluster.node.connection.timeout: 5 secs
extraEnv: [ ]
# - name: MY_VAR
# value: "some value"
extraVolumes: [ ]
# - name: my-volume
# nfs:
# server: fs.example.com
# path: /my-volume
extraVolumeMounts: [ ]
# - mountPath: /data/vol-1
# name: my-volume
# Additional directories to take ownership of (chown) during startup. Useful where `extraVolumeMounts` are provided.
# Chown is applied to the specified directory only (shallow), not recursively.
extraTakeOwnershipPaths: [ ]
# - /data/vol-1
ingress:
enabled: true
ingressClassName: alb
hostName: example.com # nifi.example.com
siteToSite:
subDomain: s2s # Subdomain for site-to-site traffic (e.g. s2s.example.com)
annotations: { }
jvmHeap:
min: 512m
max: 1g
resources:
requests:
cpu: 500m
memory: 2Gi
securityContext:
runAsUser: 1000
runAsGroup: 1000
runAsNonRoot: true
# Set a custom umask for the `nifi` user
umask: "" # "0002"
volumeClaims:
config:
storageClass: "gp3"
size: "5Gi"
state:
storageClass: "gp3"
size: "10Gi"
logs:
storageClass: "gp3"
size: "2Gi"
flowfile:
storageClass: "gp3"
size: "10Gi"
content:
storageClass: "gp3"
size: "15Gi"
provenance:
storageClass: "gp3"
size: "10Gi"
probeTimings:
startup:
initialDelaySeconds: 15
timeoutSeconds: 1
periodSeconds: 5
failureThreshold: 10
readiness:
initialDelaySeconds: 5
timeoutSeconds: 1
periodSeconds: 10
failureThreshold: 3
liveness:
initialDelaySeconds: 30
timeoutSeconds: 3
periodSeconds: 10
failureThreshold: 3
nodeSelector: { }
tolerations: [ ]
affinity: { }
topologySpreadConstraints: []
pdb:
enabled: true # Set to false if you want to disable PDB
maxUnavailable: 1 # Maximum unavailable pods during disruptions

View File

@ -0,0 +1,42 @@
replicaCount: 1
image:
repository: apache/nifi
tag: latest
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 8080
targetPort: 8080
ingress:
enabled: true
className: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt
traefik.ingress.kubernetes.io/router.entrypoints: web
hosts:
- host: nifi.dvirlabs.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: nifi-cert
hosts:
- nifi.dvirlabs.com
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
nodeSelector:
workload: general
tolerations: []
affinity: {}