diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..13fa5d41
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,19 @@
+# EditorConfig is awesome: https://editorconfig.org
+
+# top-most EditorConfig file
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+max_line_length = 150
+tab_width = 2
+
+[*.md]
+max_line_length = 0
+
+[values.schema.json]
+indent_size = 4
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index a3123570..0880ff69 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -56,6 +56,7 @@ body:
- universal
- clusterpirate
- common
+ - etcd
- ghost
- keycloak
- mariadb
@@ -68,6 +69,7 @@ body:
- redis
- timescaledb
- valkey
+ - wordpress
- zookeeper
validations:
required: true
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index d9447e43..41db4486 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -45,6 +45,7 @@ body:
- universal
- clusterpirate
- common
+ - etcd
- ghost
- keycloak
- mariadb
@@ -57,4 +58,5 @@ body:
- redis
- timescaledb
- valkey
+ - wordpress
- zookeeper
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 1821d8e9..ce3d8b29 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -4,6 +4,9 @@
- Describe the scope of your change - i.e. what the change does.
- Describe any known limitations with your change.
- Please run any tests or examples that can exercise your modified code.
+ - Labels are automatically applied when they are inside the square brackets of your PR title on opening. Examples:
+ - [redis]: adds `redis` label
+ - [redis, valkey] Adds `redis` and `valkey` labels
Thank you for contributing! We will try to test and integrate the change as soon as we can.
-->
@@ -23,6 +26,7 @@
### Applicable issues
+
- fixes #
### Additional information
@@ -33,6 +37,6 @@
-- [ ] Chart version bumped in `Chart.yaml` according to [semver](http://semver.org/). This is *not necessary* when the changes only affect README.md files.
+- [ ] Chart version bumped in `Chart.yaml` according to [semver](http://semver.org/). This is _not necessary_ when the changes only affect README.md files.
- [ ] Variables are documented in the values.yaml and added to the `README.md`
- [ ] Title of the pull request follows this pattern [] Descriptive title
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..7bdbf3ef
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,22 @@
+version: 2
+updates:
+ # Maintain dependencies for GitHub Actions
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+ labels:
+ - "dependencies"
+ - "github-actions"
+ commit-message:
+ prefix: "chore(deps)"
+ include: "scope"
+ open-pull-requests-limit: 10
+ assignees:
+ - "CloudPirates-io/maintainers"
+ # Group all GitHub Actions updates into a single PR
+ groups:
+ github-actions:
+ patterns:
+ - "*"
diff --git a/.github/workflows/auto-label.yaml b/.github/workflows/auto-label.yaml
index 9530d41f..75b2a9ef 100644
--- a/.github/workflows/auto-label.yaml
+++ b/.github/workflows/auto-label.yaml
@@ -2,23 +2,45 @@ name: Auto-label issues
on:
issues:
types: [opened]
+ pull_request:
+ types: [opened]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.issue.number }}
+ cancel-in-progress: true
jobs:
label:
+ if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false }}
runs-on: ubuntu-latest
+ timeout-minutes: 5
permissions:
issues: write
+ pull-requests: write
steps:
- name: Apply labels
- uses: actions/github-script@v7
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with:
script: |
- const labels = (context.payload.issue.body.split(/### Affected Helm charts/)[1] || "")
+ let content = "";
+ if (context.payload.pull_request) {
+ const parsedTitle = context.payload.pull_request.title.match(/^\[([a-z_-]+(?:, [a-z_-]+)*)\].+$/);
+ content = parsedTitle ? parsedTitle[1] : "";
+ } else {
+ content = context.payload.issue.body.split(/### Affected Helm charts/)[1] || "";
+ }
+ const { data } = await github.rest.issues.listLabelsForRepo({
+ ...context.repo,
+ per_page: 100,
+ });
+ const existingLabels = new Set(data.map((label) => label.name));
+ const labels = content
.trim()
.split(",")
.map((s) => s.trim())
- .filter((s) => s && s !== "_No response_");
+ .filter((s) => s && existingLabels.has(s));
if (labels.length) {
+ console.log(`Adding ${labels.length} labels: ${labels.join(', ')}`)
await github.rest.issues.addLabels({
...context.repo,
issue_number: context.issue.number,
diff --git a/.github/workflows/check-signed-commits.yaml b/.github/workflows/check-signed-commits.yaml
new file mode 100644
index 00000000..950523ec
--- /dev/null
+++ b/.github/workflows/check-signed-commits.yaml
@@ -0,0 +1,75 @@
+name: Check signed commits in PR
+on: pull_request_target
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
+ cancel-in-progress: true
+
+jobs:
+ check-signed-commits:
+ name: Check signed commits in PR
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ permissions:
+ contents: read
+ pull-requests: write
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ ref: ${{ github.event.pull_request.head.sha }}
+ fetch-depth: 0
+
+ - name: Check for bot commits
+ id: check-bots
+ run: |
+ # Get all commits in the PR
+ git fetch origin ${{ github.event.pull_request.base.ref }}
+ COMMITS=$(git log origin/${{ github.event.pull_request.base.ref }}..HEAD --format="%an")
+
+ echo "Commits in PR:"
+ echo "$COMMITS"
+
+ # Check if any commits are NOT from bots
+ # grep -v returns 0 (true) if it finds lines NOT matching the pattern
+ # grep -v returns 1 (false) if all lines match the pattern (all are bots)
+ if echo "$COMMITS" | grep -qv '\[bot\]'; then
+ echo "Found human commits"
+ echo "has_human_commits=true" >> $GITHUB_OUTPUT
+ else
+ echo "All commits are from bots"
+ echo "has_human_commits=false" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Check signed commits in PR
+ if: steps.check-bots.outputs.has_human_commits == 'true'
+ continue-on-error: true
+ uses: 1Password/check-signed-commits-action@ed2885f3ed2577a4f5d3c3fe895432a557d23d52 # v1.2.0
+ with:
+ comment: |
+ ## โ ๏ธ Unsigned Commits Detected
+
+ This pull request contains unsigned commits.
+
+ ### What does this mean?
+
+ Signed commits help ensure the authenticity and traceability of contributions. They allow us to verify that commits actually came from the stated author, even if GitHub accounts are deleted or modified in the future.
+
+ ### Current Policy (Grace Period)
+
+ **This is currently a warning only.** We are in a transition period to give all contributors time to set up commit signing.
+
+ After this grace period, **all commits will be required to be signed** before PRs can be merged.
+
+ ### How to sign your commits
+
+ Please see our [Contributing Guide](../blob/main/CONTRIBUTING.md#setting-up-your-development-environment) for detailed instructions on setting up commit signing.
+
+ ### Resources
+
+ - [Contributing Guide: Development Setup](../blob/main/CONTRIBUTING.md#setting-up-your-development-environment)
+ - [GitHub Docs: About Commit Signature Verification](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification)
+
+ ---
+
+ _This check will become mandatory in the future. Please start signing your commits now to avoid issues later._
diff --git a/.github/workflows/generate-schema.yaml b/.github/workflows/generate-schema.yaml
new file mode 100644
index 00000000..f4bb4afb
--- /dev/null
+++ b/.github/workflows/generate-schema.yaml
@@ -0,0 +1,317 @@
+name: "Generate values.schema.json"
+
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - 'charts/**/values.yaml'
+ pull_request:
+ paths:
+ - 'charts/**/values.yaml'
+ workflow_dispatch:
+ inputs:
+ charts:
+ description: 'Specific charts to generate schema for (comma-separated, e.g., "nginx,redis"). Leave empty for all charts.'
+ required: false
+ type: string
+ force_regenerate:
+ description: 'Force regeneration even if values.yaml has not changed'
+ required: false
+ type: boolean
+ default: false
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ generate-schema:
+ runs-on: ubuntu-latest
+ timeout-minutes: 15
+ # Skip if the commit was made by github-actions bot to prevent infinite loops
+ if: github.actor != 'github-actions[bot]'
+ permissions:
+ contents: write
+ pull-requests: write
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ fetch-depth: 0
+ token: ${{ secrets.CHANGELOG_PAT }}
+
+ - name: Set up Python
+ uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
+ with:
+ python-version: '3.11'
+
+ - name: Set up Helm
+ uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4.3.1
+ with:
+ version: 'latest'
+
+ - name: Install helm-schema plugin
+ run: |
+ set -e
+ # Check if plugin is already installed
+ if helm plugin list | grep -q "schema"; then
+ echo "Plugin already installed"
+ helm plugin list | grep "schema"
+ else
+ echo "Installing helm-values-schema-json plugin..."
+ helm plugin install https://github.com/losisin/helm-values-schema-json.git --version v1.9.2
+ fi
+
+ # Verify plugin installation
+ echo "Verifying plugin installation..."
+ helm plugin list
+ if ! helm plugin list | grep -q "schema"; then
+ echo "ERROR: Plugin installation failed"
+ exit 1
+ fi
+
+ echo "Plugin installed successfully"
+
+ - name: Determine charts to process
+ id: determine-charts
+ run: |
+ set -e
+
+ # Function to get all charts except 'common'
+ get_all_charts() {
+ find charts -mindepth 1 -maxdepth 1 -type d ! -name 'common' -exec basename {} \; | sort
+ }
+
+ # For workflow_dispatch with specific charts
+ if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ -n "${{ github.event.inputs.charts }}" ]; then
+ echo "Manual trigger with specific charts: ${{ github.event.inputs.charts }}"
+ CHARTS="${{ github.event.inputs.charts }}"
+ echo "charts=$CHARTS" >> $GITHUB_OUTPUT
+ echo "mode=manual-specific" >> $GITHUB_OUTPUT
+
+ # For workflow_dispatch with force regenerate all
+ elif [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ github.event.inputs.force_regenerate }}" = "true" ]; then
+ echo "Manual trigger: force regenerate all charts"
+ CHARTS=$(get_all_charts | tr '\n' ',' | sed 's/,$//')
+ echo "charts=$CHARTS" >> $GITHUB_OUTPUT
+ echo "mode=manual-all" >> $GITHUB_OUTPUT
+
+ # For push/PR events - detect changed charts
+ else
+ echo "Detecting changed charts from git diff"
+
+ if [ "${{ github.event_name }}" = "pull_request" ]; then
+ BASE_REF="${{ github.event.pull_request.base.sha }}"
+ else
+ BASE_REF="${{ github.event.before }}"
+ fi
+
+ # Get changed values.yaml files
+ CHANGED_FILES=$(git diff --name-only "$BASE_REF" HEAD -- 'charts/**/values.yaml' || echo "")
+
+ if [ -z "$CHANGED_FILES" ]; then
+ echo "No values.yaml files changed"
+ echo "charts=" >> $GITHUB_OUTPUT
+ echo "mode=none" >> $GITHUB_OUTPUT
+ else
+ echo "Changed values.yaml files:"
+ echo "$CHANGED_FILES"
+
+ # Extract chart names from changed files
+ CHARTS=$(echo "$CHANGED_FILES" | grep -o 'charts/[^/]*' | cut -d/ -f2 | sort -u | grep -v '^common$' | tr '\n' ',' | sed 's/,$//')
+
+ if [ -z "$CHARTS" ]; then
+ echo "Only common chart changed, skipping schema generation"
+ echo "charts=" >> $GITHUB_OUTPUT
+ echo "mode=none" >> $GITHUB_OUTPUT
+ else
+ echo "Charts to process: $CHARTS"
+ echo "charts=$CHARTS" >> $GITHUB_OUTPUT
+ echo "mode=auto" >> $GITHUB_OUTPUT
+ fi
+ fi
+ fi
+
+ - name: Generate schema for charts
+ if: steps.determine-charts.outputs.charts != ''
+ run: |
+ set -e
+
+ CHARTS="${{ steps.determine-charts.outputs.charts }}"
+ IFS=',' read -ra CHART_ARRAY <<< "$CHARTS"
+
+ echo "Generating schemas for: ${CHART_ARRAY[*]}"
+
+ SUCCESS_COUNT=0
+ FAIL_COUNT=0
+ FAILED_CHARTS=""
+
+ for chart in "${CHART_ARRAY[@]}"; do
+ chart=$(echo "$chart" | xargs) # trim whitespace
+
+ if [ -z "$chart" ]; then
+ continue
+ fi
+
+ echo "Processing chart: $chart"
+ CHART_DIR="charts/$chart"
+
+ if [ ! -d "$CHART_DIR" ]; then
+ echo "Warning: Chart directory not found: $CHART_DIR"
+ FAIL_COUNT=$((FAIL_COUNT + 1))
+ FAILED_CHARTS="$FAILED_CHARTS $chart"
+ continue
+ fi
+
+ if [ ! -f "$CHART_DIR/values.yaml" ]; then
+ echo "Warning: values.yaml not found in $CHART_DIR"
+ FAIL_COUNT=$((FAIL_COUNT + 1))
+ FAILED_CHARTS="$FAILED_CHARTS $chart"
+ continue
+ fi
+
+ echo "Generating schema for $chart..."
+ if helm schema -input "$CHART_DIR/values.yaml" -output "$CHART_DIR/values.schema.json" -draft 7; then
+ echo "Successfully generated schema for $chart"
+ SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
+ else
+ echo "Failed to generate schema for $chart"
+ FAIL_COUNT=$((FAIL_COUNT + 1))
+ FAILED_CHARTS="$FAILED_CHARTS $chart"
+ fi
+ done
+
+ echo ""
+ echo "Summary:"
+ echo " Success: $SUCCESS_COUNT"
+ echo " Failed: $FAIL_COUNT"
+
+ if [ $FAIL_COUNT -gt 0 ]; then
+ echo " Failed charts:$FAILED_CHARTS"
+ fi
+
+ echo "success_count=$SUCCESS_COUNT" >> $GITHUB_ENV
+ echo "fail_count=$FAIL_COUNT" >> $GITHUB_ENV
+
+ - name: Check for schema changes
+ if: steps.determine-charts.outputs.charts != ''
+ id: check-changes
+ run: |
+ if git status --porcelain | grep -q 'values.schema.json'; then
+ echo "has_changes=true" >> $GITHUB_OUTPUT
+ echo "Schema files have been updated"
+ git status --porcelain | grep 'values.schema.json'
+ else
+ echo "has_changes=false" >> $GITHUB_OUTPUT
+ echo "No schema changes detected"
+ fi
+
+ - name: Debug commit conditions
+ if: steps.determine-charts.outputs.charts != ''
+ run: |
+ echo "Debug information for commit step:"
+ echo " github.event_name: ${{ github.event_name }}"
+ echo " github.ref: ${{ github.ref }}"
+ echo " has_changes: ${{ steps.check-changes.outputs.has_changes }}"
+ echo " Should commit to main: ${{ (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/heads/main' && steps.check-changes.outputs.has_changes == 'true' }}"
+
+ - name: Create PR for schema updates (push to main)
+ if: |
+ (github.event_name == 'push' || github.event_name == 'workflow_dispatch') &&
+ github.ref == 'refs/heads/main' &&
+ steps.check-changes.outputs.has_changes == 'true'
+ env:
+ GH_TOKEN: ${{ secrets.CHANGELOG_PAT }}
+ run: |
+ git config user.name 'github-actions[bot]'
+ git config user.email 'github-actions[bot]@users.noreply.github.com'
+
+ # Create a new branch for the schema updates
+ BRANCH_NAME="auto/schema-update-$(date +%s)"
+ git checkout -b "$BRANCH_NAME"
+
+ git add charts/*/values.schema.json
+
+ git commit -m "chore: auto-generate values.schema.json for updated charts" \
+ -m "Automatically generated JSON schemas for Helm values files." \
+ -m "" \
+ -m "Signed-off-by: github-actions[bot] "
+
+ # Push the branch
+ git push origin "$BRANCH_NAME"
+
+ # Create a pull request
+ gh pr create \
+ --title "chore: auto-generate values.schema.json" \
+ --body "This PR contains automatically generated JSON schemas for Helm values files.
+
+ ## Changes
+ - Auto-generated \`values.schema.json\` files for charts with updated \`values.yaml\`
+
+ ## Notes
+ - This PR was automatically created by the schema generation workflow
+ - Please review and merge if the changes look correct
+ - The workflow will not run again on this bot's commits to prevent loops
+
+ ---
+ ๐ค Generated by [generate-schema workflow](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" \
+ --base main \
+ --head "$BRANCH_NAME"
+
+ - name: Commit schema updates to PR branch
+ if: |
+ github.event_name == 'pull_request' &&
+ steps.check-changes.outputs.has_changes == 'true'
+ run: |
+ git config user.name 'github-actions[bot]'
+ git config user.email 'github-actions[bot]@users.noreply.github.com'
+
+ git add charts/*/values.schema.json
+
+ git commit -m "chore: auto-generate values.schema.json" \
+ -m "Signed-off-by: github-actions[bot] " || echo "No changes to commit"
+
+ # Push to PR branch
+ git push origin HEAD:${{ github.head_ref }}
+
+ - name: Commit schema updates to current branch (workflow_dispatch on non-main)
+ if: |
+ github.event_name == 'workflow_dispatch' &&
+ github.ref != 'refs/heads/main' &&
+ steps.check-changes.outputs.has_changes == 'true'
+ run: |
+ git config user.name 'github-actions[bot]'
+ git config user.email 'github-actions[bot]@users.noreply.github.com'
+
+ git add charts/*/values.schema.json
+
+ git commit -m "chore: auto-generate values.schema.json" \
+ -m "Signed-off-by: github-actions[bot] "
+
+ # Push to current branch
+ git push origin HEAD:${{ github.ref }}
+
+ - name: Generate job summary
+ if: steps.determine-charts.outputs.charts != ''
+ run: |
+ echo "## ๐ Schema Generation Summary" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+
+ if [ "${{ steps.determine-charts.outputs.mode }}" = "none" ]; then
+ echo "No charts required schema generation." >> $GITHUB_STEP_SUMMARY
+ else
+ echo "**Mode:** ${{ steps.determine-charts.outputs.mode }}" >> $GITHUB_STEP_SUMMARY
+ echo "**Charts processed:** ${{ steps.determine-charts.outputs.charts }}" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "**Results:**" >> $GITHUB_STEP_SUMMARY
+ echo "- โ
Success: ${success_count}" >> $GITHUB_STEP_SUMMARY
+ echo "- โ Failed: ${fail_count}" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+
+ if [ "${{ steps.check-changes.outputs.has_changes }}" = "true" ]; then
+ echo "**Status:** Schema files updated and committed" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "**Status:** No schema changes detected" >> $GITHUB_STEP_SUMMARY
+ fi
+ fi
\ No newline at end of file
diff --git a/.github/workflows/post-merge.yaml b/.github/workflows/post-merge.yaml
new file mode 100644
index 00000000..8c528ae8
--- /dev/null
+++ b/.github/workflows/post-merge.yaml
@@ -0,0 +1,272 @@
+name: "Post-Merge Changelog Update"
+
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - 'charts/**'
+ workflow_dispatch: # Manual trigger
+ inputs:
+ update_all_charts:
+ description: 'Update all charts (not just changed ones)'
+ required: false
+ type: boolean
+ default: false
+ clean_start:
+ description: 'Delete existing CHANGELOG.md files and start fresh'
+ required: false
+ type: boolean
+ default: false
+ custom_message:
+ description: 'Custom changelog message (optional)'
+ required: false
+ type: string
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}
+ cancel-in-progress: false
+
+jobs:
+ update-changelog:
+ runs-on: ubuntu-latest
+ timeout-minutes: 15
+ permissions:
+ contents: write
+ steps:
+ - name: Checkout main branch
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ fetch-depth: 0
+ token: ${{ secrets.CHANGELOG_PAT || secrets.GITHUB_TOKEN }}
+
+ - name: Configure Git
+ run: |
+ git config user.name 'github-actions[bot]'
+ git config user.email 'github-actions[bot]@users.noreply.github.com'
+
+ - name: Fetch all tags
+ run: |
+ git fetch --tags --force
+ echo "Available tags:"
+ git tag -l | head -20
+
+ - name: Install yq
+ run: |
+ sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
+ sudo chmod +x /usr/local/bin/yq
+
+ - name: Determine charts to update
+ id: charts-to-update
+ run: |
+ # For manual trigger with update_all_charts enabled
+ if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ github.event.inputs.update_all_charts }}" = "true" ]; then
+ echo "Manual trigger: updating all charts"
+ all_charts=$(find charts -mindepth 1 -maxdepth 1 -type d | sed 's|^charts/||' | tr '\n' ' ')
+ echo "All charts: $all_charts"
+ echo "changed=true" >> $GITHUB_OUTPUT
+ echo "changedCharts=$all_charts" >> $GITHUB_OUTPUT
+ echo "update_mode=all" >> $GITHUB_OUTPUT
+ # For manual trigger without update_all_charts (default behavior - changed charts only)
+ elif [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
+ echo "Manual trigger: finding changed charts from last commit"
+ # Use the same logic as push event to find changed charts
+ BEFORE_SHA=$(git rev-parse HEAD~1)
+ changed_files=$(git diff --name-only "${BEFORE_SHA}" HEAD -- 'charts/**')
+
+ if [[ -n "$changed_files" ]]; then
+ changed_charts=$(echo "$changed_files" | grep '^charts/' | cut -d/ -f1-2 | sort -u | tr '\n' ' ')
+ if [[ -n "$changed_charts" ]]; then
+ echo "Changed charts: $changed_charts"
+ echo "changed=true" >> $GITHUB_OUTPUT
+ echo "changedCharts=${changed_charts}" >> $GITHUB_OUTPUT
+ echo "update_mode=changed" >> $GITHUB_OUTPUT
+ else
+ echo "No chart changes detected in last commit"
+ echo "changed=false" >> $GITHUB_OUTPUT
+ fi
+ else
+ echo "No chart changes detected in last commit"
+ echo "changed=false" >> $GITHUB_OUTPUT
+ fi
+ # For push event (original behavior)
+ else
+ echo "Push event: finding changed charts from merge commit"
+ BEFORE_SHA="${{ github.event.before }}"
+ changed_files=$(git diff --name-only "${BEFORE_SHA}" HEAD -- 'charts/**')
+
+ if [[ -n "$changed_files" ]]; then
+ changed_charts=$(echo "$changed_files" | grep '^charts/' | cut -d/ -f1-2 | sort -u | tr '\n' ' ')
+ if [[ -n "$changed_charts" ]]; then
+ echo "Changed charts: $changed_charts"
+ echo "changed=true" >> $GITHUB_OUTPUT
+ echo "changedCharts=${changed_charts}" >> $GITHUB_OUTPUT
+ echo "update_mode=changed" >> $GITHUB_OUTPUT
+ else
+ echo "No chart changes detected"
+ echo "changed=false" >> $GITHUB_OUTPUT
+ fi
+ else
+ echo "No chart changes detected"
+ echo "changed=false" >> $GITHUB_OUTPUT
+ fi
+ fi
+
+ - name: Clean start - Delete existing CHANGELOG.md files
+ if: github.event_name == 'workflow_dispatch' && github.event.inputs.clean_start == 'true' && steps.charts-to-update.outputs.changed == 'true'
+ run: |
+ echo "Clean start enabled - deleting existing CHANGELOG.md files"
+ CHANGED_CHARTS="${{ steps.charts-to-update.outputs.changedCharts }}"
+
+ for chart_directory in $CHANGED_CHARTS; do
+ CHART_NAME=${chart_directory#charts/}
+ CHANGELOG_FILE="charts/${CHART_NAME}/CHANGELOG.md"
+
+ if [ -f "$CHANGELOG_FILE" ]; then
+ echo "Deleting $CHANGELOG_FILE"
+ rm "$CHANGELOG_FILE"
+
+ # Check if directory is empty except for ignored files
+ if [ -z "$(ls -A "charts/${CHART_NAME}" | grep -vE '^(Chart\.yaml|values\.yaml|\.helmignore|templates|crds|\.gitkeep)$')" ]; then
+ echo "Directory charts/${CHART_NAME} would be empty after deletion, but keeping it"
+ fi
+ else
+ echo "No CHANGELOG.md found at $CHANGELOG_FILE"
+ fi
+ done
+
+ # Commit the deletions if any files were removed
+ if git status --porcelain | grep -q 'CHANGELOG.md'; then
+ echo "CHANGELOG.md files deleted successfully"
+ git add charts/*/CHANGELOG.md
+ git commit -m "chore: remove existing CHANGELOG.md files for clean start" \
+ -m "Signed-off-by: github-actions[bot] "
+ echo "clean_start_completed=true" >> $GITHUB_ENV
+ else
+ echo "No CHANGELOG.md files to delete"
+ echo "clean_start_completed=false" >> $GITHUB_ENV
+ fi
+
+ - name: Get PR information for push events
+ id: pr-info-push
+ if: github.event_name == 'push' && steps.charts-to-update.outputs.changed == 'true'
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const commit = context.payload.head_commit;
+ const commitSha = commit.id;
+
+ // Find the PR that was merged
+ const { data: prs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ commit_sha: commitSha
+ });
+
+ const mergedPR = prs.find(pr => pr.merged_at);
+
+ if (mergedPR) {
+ core.setOutput('pr_number', mergedPR.number);
+ core.setOutput('pr_title', mergedPR.title);
+ core.setOutput('pr_url', mergedPR.html_url);
+ console.log(`Found merged PR #${mergedPR.number}: ${mergedPR.title}`);
+ } else {
+ console.log('No merged PR found for this commit');
+ core.setOutput('pr_number', '');
+ core.setOutput('pr_title', commit.message.split('\n')[0]);
+ core.setOutput('pr_url', '');
+ }
+
+ - name: Set manual trigger info
+ id: manual-info
+ if: github.event_name == 'workflow_dispatch' && steps.charts-to-update.outputs.changed == 'true'
+ run: |
+ if [ -n "${{ github.event.inputs.custom_message }}" ]; then
+ PR_TITLE="${{ github.event.inputs.custom_message }}"
+ else
+ if [ "${{ github.event.inputs.clean_start }}" = "true" ]; then
+ PR_TITLE="Manual changelog update with clean start"
+ else
+ PR_TITLE="Manual changelog update triggered via workflow_dispatch"
+ fi
+ fi
+
+ echo "pr_number=manual" >> $GITHUB_OUTPUT
+ echo "pr_title=${PR_TITLE}" >> $GITHUB_OUTPUT
+ echo "pr_url=https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_OUTPUT
+
+ - name: Generate changelog
+ id: generate-changelog
+ if: steps.charts-to-update.outputs.changed == 'true'
+ env:
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+ GITHUB_REPOSITORY: "${{ github.repository }}"
+ GITHUB_REPOSITORY_URL: "${{ github.server_url }}/${{ github.repository }}"
+ PR_NUMBER: ${{ github.event_name == 'push' && steps.pr-info-push.outputs.pr_number || steps.manual-info.outputs.pr_number }}
+ PR_TITLE: ${{ github.event_name == 'push' && steps.pr-info-push.outputs.pr_title || steps.manual-info.outputs.pr_title }}
+ PR_URL: ${{ github.event_name == 'push' && steps.pr-info-push.outputs.pr_url || steps.manual-info.outputs.pr_url }}
+ UPDATE_MODE: ${{ steps.charts-to-update.outputs.update_mode }}
+ CLEAN_START: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.clean_start || 'false' }}
+ run: |
+ set -e
+
+ CHANGED_CHARTS="${{ steps.charts-to-update.outputs.changedCharts }}"
+
+ echo "Update mode: $UPDATE_MODE"
+ echo "Clean start: $CLEAN_START"
+ echo "Processing charts: $CHANGED_CHARTS"
+
+ # Process each chart individually
+ for chart_directory in $CHANGED_CHARTS; do
+ CHART_NAME=${chart_directory#charts/}
+ echo "Processing chart: $CHART_NAME"
+
+ # Run the changelog script for this specific chart
+ ./generate-changelog.sh \
+ --chart "$CHART_NAME" \
+ --pr-title "${PR_TITLE}" \
+ --pr-number "${PR_NUMBER}" \
+ --pr-url "${PR_URL}"
+ done
+
+ # Check if there are changes
+ if git status --porcelain | grep -q 'CHANGELOG.md'; then
+ echo "has_changes=true" >> $GITHUB_OUTPUT
+ echo "Changelog changes detected"
+ git status --porcelain
+ else
+ echo "No CHANGELOG changes"
+ echo "has_changes=false" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Update appVersion in Chart.yaml files
+ if: steps.generate-changelog.outputs.has_changes == 'true' && env.clean_start_completed != 'true'
+ run: ./update-appversion.sh --all
+
+ - name: Commit and push changelog and chart updates
+ if: steps.generate-changelog.outputs.has_changes == 'true' && env.clean_start_completed != 'true'
+ run: |
+ git add charts/*/CHANGELOG.md
+ git add charts/*/Chart.yaml
+
+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
+ COMMIT_MSG="chore: update CHANGELOG.md via manual trigger"
+ if [ "${{ github.event.inputs.update_all_charts }}" = "true" ]; then
+ COMMIT_MSG="chore: update CHANGELOG.md for all charts via manual trigger"
+ fi
+ if [ "${{ github.event.inputs.clean_start }}" = "true" ]; then
+ COMMIT_MSG="chore: regenerate CHANGELOG.md with clean start"
+ fi
+ else
+ COMMIT_MSG="chore: update CHANGELOG.md for merged changes"
+ fi
+
+ git commit -m "$COMMIT_MSG" \
+ -m "Signed-off-by: github-actions[bot] "
+
+ # Pull latest changes and rebase our commit on top
+ git pull --rebase origin main
+
+ # Push the changes
+ git push origin main
diff --git a/.github/workflows/pull-request.yaml b/.github/workflows/pull-request.yaml
index 09052118..34993e03 100644
--- a/.github/workflows/pull-request.yaml
+++ b/.github/workflows/pull-request.yaml
@@ -8,32 +8,48 @@ on:
branches:
- main
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
+ cancel-in-progress: true
+
jobs:
lint-test:
runs-on: ubuntu-latest
+ timeout-minutes: 30
+ permissions:
+ contents: read
outputs:
changed: ${{ steps.list-changed.outputs.changed }}
changedCharts: ${{ steps.list-changed.outputs.changedCharts }}
steps:
- name: Setup Helm
- uses: Azure/setup-helm@v4.3.1
+ uses: Azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4.3.1
- name: Checkout pull request branch
- uses: actions/checkout@v5.0.0
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
ref: ${{ github.head_ref }}
repository: ${{github.event.pull_request.head.repo.full_name}}
fetch-depth: 0
+ - name: Fetch upstream main branch
+ run: |
+ # Fetch the base repository's target branch and update origin/main to point to it
+ git remote set-url origin https://github.com/CloudPirates-io/helm-charts.git
+ git fetch origin ${{ github.event.repository.default_branch }}
+ # Re-add the fork as a remote and checkout the PR branch
+ git remote add fork https://github.com/${{ github.event.pull_request.head.repo.full_name }}.git || true
+ git fetch fork ${{ github.head_ref }}
+
# Python is required because `ct lint` runs Yamale (https://github.com/23andMe/Yamale) and
# yamllint (https://github.com/adrienverge/yamllint) which require Python
- name: Set up Python
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1
+ uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with:
- python-version: 3.x
+ python-version: 3.11
- name: Set up chart-testing-action
- uses: helm/chart-testing-action@v2.7.0
+ uses: helm/chart-testing-action@0d28d3144d3a25ea2cc349d6e59901c4ff469b3b # v2.7.0
- name: Get changed charts
id: list-changed
@@ -50,97 +66,97 @@ jobs:
echo "No chart changes detected"
fi
+ - name: Cache Helm plugins
+ if: steps.list-changed.outputs.changed == 'true'
+ uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
+ with:
+ path: ~/.local/share/helm/plugins
+ key: ${{ runner.os }}-helm-plugins-${{ hashFiles('**/plugin.yaml') }}
+ restore-keys: |
+ ${{ runner.os }}-helm-plugins-
+
- name: Installing plugin helm-unittest
if: steps.list-changed.outputs.changed == 'true'
- run: helm plugin install https://github.com/helm-unittest/helm-unittest >/dev/null
+ run: |
+ if ! helm plugin list | grep -q unittest; then
+ helm plugin install https://github.com/helm-unittest/helm-unittest
+ else
+ echo "helm-unittest plugin already installed"
+ fi
- name: Run chart testing (lint & unittest)
if: steps.list-changed.outputs.changed == 'true'
- run: ct lint --target-branch ${{ github.event.repository.default_branch }} --validate-maintainers=false --additional-commands "helm unittest {{ .Path }}"
+ run: |
+ ct lint --target-branch ${{ github.event.repository.default_branch }} --validate-maintainers=false --additional-commands 'helm unittest {{ .Path }}'
- update-changelog:
+ integration-test:
runs-on: ubuntu-latest
- needs: [lint-test]
- name: Automatically update CHANGELOG
+ timeout-minutes: 30
permissions:
- contents: write
+ contents: read
+ needs: [lint-test]
if: needs.lint-test.outputs.changed == 'true'
steps:
- name: Checkout pull request branch
- uses: actions/checkout@v5.0.0
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
ref: ${{ github.head_ref }}
repository: ${{github.event.pull_request.head.repo.full_name}}
fetch-depth: 0
- - name: Configure Git
- run: |
- git config user.name 'github-actions[bot]'
- git config user.email 'github-actions[bot]@users.noreply.github.com'
+ - name: Setup Helm
+ uses: Azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4.3.1
- - name: Fetch tags
- run: |
- git fetch --tags
+ - name: Setup kubectl
+ uses: azure/setup-kubectl@776406bce94f63e41d621b960d78ee25c8b76ede # v4.0.1
- - name: Install conventional-changelog-cli
- run: npm install -g conventional-changelog-cli
+ - name: Login to Docker Hub to avoid rate limits
+ uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
+ with:
+ username: ${{ secrets.REGISTRY_USER }}
+ password: ${{ secrets.REGISTRY_PASSWORD }}
- - name: Generate changelog
- id: generate-changelog
+ - name: Create kind cluster
+ uses: helm/kind-action@92086f6be054225fa813e0a4b13787fc9088faab # v1.13.0
+ with:
+ cluster_name: helm-chart-test
+ wait: 300s
+
+ - name: Cache Helm plugins
+ uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
+ with:
+ path: ~/.local/share/helm/plugins
+ key: ${{ runner.os }}-helm-plugins-${{ hashFiles('**/plugin.yaml') }}
+ restore-keys: |
+ ${{ runner.os }}-helm-plugins-
+
+ - name: Installing plugin helm-unittest
+ run: |
+ if ! helm plugin list | grep -q unittest; then
+ helm plugin install https://github.com/helm-unittest/helm-unittest
+ else
+ echo "helm-unittest plugin already installed"
+ fi
+
+ - name: Run integration tests
env:
- PULL_REQUEST_NUMBER: "${{ github.event.pull_request.number }}"
- PULL_REQUEST_URL: "${{ github.server_url }}/${{ github.repository }}/pull/${{ github.event.number }}"
- GITHUB_TOKEN: "${{ github.token }}"
CHANGED_CHARTS: ${{ needs.lint-test.outputs.changedCharts }}
run: |
- PR_TITLE="$(gh api "/repos/${GITHUB_REPOSITORY}/pulls/${PULL_REQUEST_NUMBER}" | jq -r '.title')"
+ # Make script executable
+ chmod +x ./test-charts.sh
+
+ # Test each changed chart
for chart_directory in ${CHANGED_CHARTS}; do
CHART_NAME=${chart_directory#charts/}
- echo "Updating CHANGELOG for chart $CHART_NAME"
-
- # Extract version from Chart.yaml
- CHART_VERSION=$(yq eval '.version' "${GITHUB_WORKSPACE}/charts/${CHART_NAME}/Chart.yaml")
- CHANGELOG_FILE="${GITHUB_WORKSPACE}/charts/${CHART_NAME}/CHANGELOG.md"
- CHANGELOG_TMP_FILE="${GITHUB_WORKSPACE}/charts/${CHART_NAME}/CHANGELOG.md.tmp"
-
- touch "$CHANGELOG_FILE"
-
- # Generate new CHANGELOG.md
- npx conventional-changelog-cli -i "$CHANGELOG_FILE" -s -t "${CHART_NAME}-" -r 0 --commit-path "charts/${CHART_NAME}"
-
- # Remove unreleased section (includes all intermediate commits in the branch) and create future entry based on PR title
- # The unreleased section looks like this "## (YYYY-MM-DD)" whereas a released section looks like this "## 0.0.1 (YYYY-MM-DD)"
- # So we only need to find a released section to start printing in the awk script below
- awk '/^##[^(]*[0-9]/ {flag=1} flag {print}' "$CHANGELOG_FILE" > "$CHANGELOG_TMP_FILE"
-
- # Remove chart name prefixes from commit messages
- sed -i -E "s/\* \[${CHART_NAME}\] /\* /gi" "$CHANGELOG_TMP_FILE"
- sed -i -E "s/\* \[$(echo ${CHART_NAME} | tr '[:lower:]' '[:upper:]')\] /\* /g" "$CHANGELOG_TMP_FILE"
-
- # Remove extra newlines so the changelog file passes the markdown linter
- sed -i -E -e '/^$/d' "$CHANGELOG_TMP_FILE" && sed -i -E -e 's/(##.*)/\n\1\n/g' "$CHANGELOG_TMP_FILE"
-
- # Include h1 heading and add entry for the current version. There is no tag for the current version (this will be created once merged), so we need to manually add it.
- # We know the final squashed commit title, which will be the PR title. We cannot add a link to the commit in the main branch because it has not been
- # merged yet (this will be corrected once a new version regenerates the changelog). Instead, we add the PR url which contains the exact same information.
- echo -e -n "# Changelog\n\n## $CHART_VERSION ($(date +'%Y-%m-%d'))\n\n* ${PR_TITLE} ([#${PULL_REQUEST_NUMBER}](${PULL_REQUEST_URL}))\n" > "$CHANGELOG_FILE"
-
- cat "$CHANGELOG_TMP_FILE" >> "$CHANGELOG_FILE"
- rm "$CHANGELOG_TMP_FILE"
-
- # Commit all changes, if any
- if git status -s | grep "charts/${CHART_NAME}/CHANGELOG.md"; then
- git add "charts/${CHART_NAME}/CHANGELOG.md"
- git commit -m "Update CHANGELOG.md" --signoff
+ echo "Testing chart: $CHART_NAME"
+
+ # Check if integration test is disabled for this chart
+ if [ -f "${chart_directory}/.disable-unittest" ]; then
+ echo "โฉ Skipping integration test for $CHART_NAME (.disable-unittest found)"
+ continue
fi
- done
- - name: Push all changes
- run: |
- cd $GITHUB_WORKSPACE/charts
- # Push all the new commits, if any
- if [[ $(git cherry -v) ]]; then
- git push
- else
- echo "No changed CHANGELOGS, skip push"
- fi
+ # Run test script without cluster creation (kind-action already created it)
+ # and without cleanup (let GitHub Actions handle it)
+ ./test-charts.sh "$CHART_NAME" --no-cleanup
+ done
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index b6d834c0..b4f130a9 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -4,6 +4,17 @@ on:
push:
branches:
- main
+ workflow_dispatch:
+ inputs:
+ dry_run:
+ description: 'Dry run (skip actual release)'
+ required: false
+ type: boolean
+ default: false
+
+concurrency:
+ group: release
+ cancel-in-progress: true
jobs:
release:
@@ -11,9 +22,10 @@ jobs:
contents: write
packages: write
runs-on: ubuntu-latest
+ timeout-minutes: 30
steps:
- name: Checkout
- uses: actions/checkout@v5.0.0
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
@@ -23,14 +35,14 @@ jobs:
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Login to Registry
- uses: docker/login-action@v3
+ uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ${{ vars.REGISTRY }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Login to GHCR
- uses: docker/login-action@v3
+ uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
@@ -38,18 +50,18 @@ jobs:
- name: Run chart-releaser
id: chart-releaser
- uses: helm/chart-releaser-action@v1.7.0
+ uses: helm/chart-releaser-action@cae68fefc6b5f367a0275617c9f83181ba54714f # v1.7.0
with:
skip_existing: true
env:
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- name: Install cosign
- uses: sigstore/cosign-installer@v3.9.2
+ uses: sigstore/cosign-installer@v3.10.0
if: ${{ steps.chart-releaser.outputs.changed_charts }}
- id: github-repo-owner-name
- uses: ASzc/change-string-case-action@v6
+ uses: ASzc/change-string-case-action@d0603cd0a7dd490be678164909f65c7737470a7f # v6
with:
string: ${{ github.repository_owner }}
@@ -61,13 +73,38 @@ jobs:
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
run: |
- CHANGED_CHARTS="${{ steps.chart-releaser.outputs.changed_charts }}"
+ set -euo pipefail
- # Login to primary registry
- helm registry login --username $REGISTRY_USER --password ${{ secrets.REGISTRY_PASSWORD }} https://${{ vars.REGISTRY }}
+ CHANGED_CHARTS="${{ steps.chart-releaser.outputs.changed_charts }}"
- # Login to GHCR
- helm registry login --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }} https://ghcr.io
+ # Retry function for network operations
+ retry() {
+ local max_attempts=3
+ local attempt=1
+ local delay=5
+
+ while [ $attempt -le $max_attempts ]; do
+ if "$@"; then
+ return 0
+ else
+ echo "Attempt $attempt failed. Retrying in ${delay}s..."
+ sleep $delay
+ delay=$((delay * 2))
+ attempt=$((attempt + 1))
+ fi
+ done
+
+ echo "ERROR: All $max_attempts attempts failed"
+ return 1
+ }
+
+ # Login to primary registry with retry
+ echo "Logging into primary registry..."
+ retry helm registry login --username $REGISTRY_USER --password ${{ secrets.REGISTRY_PASSWORD }} https://${{ vars.REGISTRY }}
+
+ # Login to GHCR with retry
+ echo "Logging into GHCR..."
+ retry helm registry login --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }} https://ghcr.io
RELEASED_CHARTS=""
for chart_directory in ${CHANGED_CHARTS//,/ }; do
@@ -79,33 +116,63 @@ jobs:
CHART_VERSION=$(yq eval '.version' "Chart.yaml")
APP_VERSION=$(yq eval '.appVersion' "Chart.yaml")
- # Push to primary registry (Docker Hub)
+ # Push to primary registry (Docker Hub) with retry
echo "Pushing Helm chart $CHART_NAME-$CHART_VERSION.tgz to oci://${{ vars.REGISTRY }}/${{ vars.REPOSITORY }}"
- if helm push ${{ github.workspace }}/.cr-release-packages/${CHART_NAME}-${CHART_VERSION}.tgz oci://${{ vars.REGISTRY }}/${{ vars.REPOSITORY }} 2>&1 | tee ${CHART_NAME}-output.log; then
+ if retry helm push ${{ github.workspace }}/.cr-release-packages/${CHART_NAME}-${CHART_VERSION}.tgz oci://${{ vars.REGISTRY }}/${{ vars.REPOSITORY }} 2>&1 | tee ${CHART_NAME}-output.log; then
# Extract digest and sign chart
- DIGEST=$(cat ${CHART_NAME}-output.log | awk -F '[, ]+' '/Digest/{print $NF}')
- cosign sign -y --key env://COSIGN_KEY ${{ vars.REGISTRY }}/${{ vars.REPOSITORY }}/${CHART_NAME}:${CHART_VERSION}@$DIGEST
+ # More robust parsing: looks for "Digest: sha256:..." pattern
+ DIGEST=$(grep -oP 'Digest:\s*\K(sha256:[a-f0-9]+)' ${CHART_NAME}-output.log || echo "")
+
+ if [ -z "$DIGEST" ]; then
+ echo "ERROR: Failed to extract digest from helm push output"
+ echo "Output was:"
+ cat ${CHART_NAME}-output.log
+ exit 1
+ fi
+
+ echo "Extracted digest: $DIGEST"
+ echo "Signing chart at ${{ vars.REGISTRY }}/${{ vars.REPOSITORY }}/${CHART_NAME}:${CHART_VERSION}@$DIGEST"
+
+ if ! cosign sign -y --upload=true --key env://COSIGN_KEY ${{ vars.REGISTRY }}/${{ vars.REPOSITORY }}/${CHART_NAME}:${CHART_VERSION}@$DIGEST; then
+ echo "ERROR: Failed to sign chart"
+ exit 1
+ fi
RELEASED_CHARTS="$RELEASED_CHARTS ${CHART_NAME}"
echo "Successfully released $CHART_NAME-$CHART_VERSION to primary registry"
else
- echo "Failed to push $CHART_NAME-$CHART_VERSION to primary registry"
+ echo "ERROR: Failed to push $CHART_NAME-$CHART_VERSION to primary registry"
cat ${CHART_NAME}-output.log
exit 1
fi
- # Push to GHCR
+ # Push to GHCR with retry
echo "Pushing Helm chart $CHART_NAME-$CHART_VERSION.tgz to oci://ghcr.io/${{ steps.github-repo-owner-name.outputs.lowercase }}/helm-charts"
- if helm push ${{ github.workspace }}/.cr-release-packages/${CHART_NAME}-${CHART_VERSION}.tgz oci://ghcr.io/${{ steps.github-repo-owner-name.outputs.lowercase }}/helm-charts 2>&1 | tee ${CHART_NAME}-ghcr-output.log; then
+ if retry helm push ${{ github.workspace }}/.cr-release-packages/${CHART_NAME}-${CHART_VERSION}.tgz oci://ghcr.io/${{ steps.github-repo-owner-name.outputs.lowercase }}/helm-charts 2>&1 | tee ${CHART_NAME}-ghcr-output.log; then
# Extract digest and sign GHCR chart
- GHCR_DIGEST=$(cat ${CHART_NAME}-ghcr-output.log | awk -F '[, ]+' '/Digest/{print $NF}')
- cosign sign -y --key env://COSIGN_KEY ghcr.io/${{ steps.github-repo-owner-name.outputs.lowercase }}/helm-charts/${CHART_NAME}:${CHART_VERSION}@$GHCR_DIGEST
+ # More robust parsing: looks for "Digest: sha256:..." pattern
+ GHCR_DIGEST=$(grep -oP 'Digest:\s*\K(sha256:[a-f0-9]+)' ${CHART_NAME}-ghcr-output.log || echo "")
+
+ if [ -z "$GHCR_DIGEST" ]; then
+ echo "ERROR: Failed to extract digest from helm push output"
+ echo "Output was:"
+ cat ${CHART_NAME}-ghcr-output.log
+ exit 1
+ fi
+
+ echo "Extracted digest: $GHCR_DIGEST"
+ echo "Signing chart at ghcr.io/${{ steps.github-repo-owner-name.outputs.lowercase }}/helm-charts/${CHART_NAME}:${CHART_VERSION}@$GHCR_DIGEST"
+
+ if ! cosign sign -y --upload=true --key env://COSIGN_KEY ghcr.io/${{ steps.github-repo-owner-name.outputs.lowercase }}/helm-charts/${CHART_NAME}:${CHART_VERSION}@$GHCR_DIGEST; then
+ echo "ERROR: Failed to sign chart"
+ exit 1
+ fi
echo "Successfully released $CHART_NAME-$CHART_VERSION to GHCR"
else
- echo "Failed to push $CHART_NAME-$CHART_VERSION to GHCR"
+ echo "ERROR: Failed to push $CHART_NAME-$CHART_VERSION to GHCR"
cat ${CHART_NAME}-ghcr-output.log
exit 1
fi
@@ -113,3 +180,16 @@ jobs:
cd ${{ github.workspace }}
done
echo "released_charts=$RELEASED_CHARTS" >> "$GITHUB_OUTPUT"
+
+ # Generate job summary
+ echo "## ๐ฆ Helm Charts Released" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "Successfully released the following charts:" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ for chart in $RELEASED_CHARTS; do
+ echo "- โ
**$chart**" >> $GITHUB_STEP_SUMMARY
+ done
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "### ๐ Registries" >> $GITHUB_STEP_SUMMARY
+ echo "- Primary: \`${{ vars.REGISTRY }}/${{ vars.REPOSITORY }}\`" >> $GITHUB_STEP_SUMMARY
+ echo "- GHCR: \`ghcr.io/${{ steps.github-repo-owner-name.outputs.lowercase }}/helm-charts\`" >> $GITHUB_STEP_SUMMARY
diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml
new file mode 100644
index 00000000..386aac17
--- /dev/null
+++ b/.github/workflows/stale.yaml
@@ -0,0 +1,70 @@
+name: "Close stale issues and PRs"
+
+on:
+ schedule:
+ # Run daily at 00:00 UTC
+ - cron: "0 0 * * *"
+ workflow_dispatch:
+
+permissions:
+ issues: write
+ pull-requests: write
+
+jobs:
+ stale:
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ steps:
+ - name: Close stale issues and PRs
+ uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0
+ with:
+ # Issue settings
+ stale-issue-message: |
+ This issue has been automatically marked as stale because it has not had any activity for 14 days.
+
+ It will be closed in 7 days if no further activity occurs.
+
+ If this issue is still relevant, please comment to keep it open.
+
+ Thank you for your contributions!
+ close-issue-message: |
+ This issue has been automatically closed due to inactivity.
+
+ If you believe this issue is still relevant, please reopen it or create a new issue with updated information.
+
+ Thank you for your understanding!
+ days-before-issue-stale: 14
+ days-before-issue-close: 7
+ stale-issue-label: "stale"
+ exempt-issue-labels: "pinned,security,bug,enhancement,no-stale"
+
+ # PR settings
+ stale-pr-message: |
+ This pull request has been automatically marked as stale because it has not had any activity for 14 days.
+
+ It will be closed in 7 days if no further activity occurs.
+
+ If this PR is still relevant, please:
+ - Rebase against the latest main branch
+ - Resolve any conflicts
+ - Address any review comments
+ - Comment on this PR to keep it open
+
+ Thank you for your contributions!
+ close-pr-message: |
+ This pull request has been automatically closed due to inactivity.
+
+ If you would like to continue with these changes, please:
+ 1. Rebase your branch against the latest main
+ 2. Open a new pull request
+
+ Thank you for your understanding!
+ days-before-pr-stale: 14
+ days-before-pr-close: 7
+ stale-pr-label: "stale"
+ exempt-pr-labels: "pinned,security,work-in-progress,wip,no-stale"
+
+ # General settings
+ operations-per-run: 100
+ remove-stale-when-updated: true
+ ascending: true
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
deleted file mode 100644
index 993d1fce..00000000
--- a/.gitlab-ci.yml
+++ /dev/null
@@ -1,218 +0,0 @@
-stages:
- - test
- - release
- - sign
-
-variables:
- CHART_REPO_PREFIX: cloudpirates
- REGISTRY: $DOCKER_REGISTRY
- REGISTRY_USER: $DOCKER_USER
- REGISTRY_PASSWORD: $DOCKER_PASSWORD
-
-test-charts:
- stage: test
- image: alpine/helm:latest
- before_script:
- - apk add --no-cache git
- - helm plugin install https://github.com/helm-unittest/helm-unittest
- script:
- - |
- echo "Discovering helm charts with tests..."
-
- FAILED_CHARTS=""
- PASSED_CHARTS=""
- TESTED_CHARTS=""
-
- # Find all chart directories with Chart.yaml and tests directory
- for chart_dir in charts/*/; do
- if [[ -f "${chart_dir}Chart.yaml" ]]; then
- chart_name=$(basename "$chart_dir")
-
- # Check if chart has a tests directory
- if [[ -d "${chart_dir}tests" ]]; then
- echo "================================"
- echo "Testing chart: $chart_name"
- echo "Chart path: $chart_dir"
- echo "Tests directory found: ${chart_dir}tests"
- echo "================================"
-
- TESTED_CHARTS="$TESTED_CHARTS $chart_name"
-
- # Update dependencies if Chart.yaml contains dependencies
- cd "$chart_dir"
- if grep -q "dependencies:" Chart.yaml; then
- echo "Updating dependencies for $chart_name"
- helm dependency update
- fi
- cd - > /dev/null
-
- if helm unittest "$chart_dir" --strict; then
- echo "$chart_name PASSED"
- PASSED_CHARTS="$PASSED_CHARTS $chart_name"
- else
- echo "$chart_name FAILED"
- FAILED_CHARTS="$FAILED_CHARTS $chart_name"
- fi
- echo ""
- else
- echo "Skipping $chart_name (no tests directory found)"
- fi
- fi
- done
-
- echo "================================"
- echo "TEST SUMMARY"
- echo "================================"
- echo "Charts with tests:$TESTED_CHARTS"
- echo "Passed charts:$PASSED_CHARTS"
-
- if [[ -z "$TESTED_CHARTS" ]]; then
- echo "No charts with tests found"
- exit 0
- elif [[ -n "$FAILED_CHARTS" ]]; then
- echo "Failed charts:$FAILED_CHARTS"
- echo "Some tests failed!"
- exit 1
- else
- echo "All charts with tests passed!"
- fi
- rules:
- - if: $CI_PIPELINE_SOURCE == "merge_request_event"
- changes:
- - charts/**/*
- - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
- changes:
- - charts/**/*
-
-release-charts:
- stage: release
- image: alpine/helm:latest
- before_script:
- - apk add --no-cache git yq
- - helm registry login --username ${REGISTRY_USER} --password ${REGISTRY_PASSWORD} ${REGISTRY}
- needs:
- - test-charts
- script:
- - |
- echo "Detecting changed charts..."
-
- # Get list of changed files in the last commit
- CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD || git ls-files charts/)
- echo "Changed files: $CHANGED_FILES"
-
- # Find unique chart directories that have changes
- CHANGED_CHARTS=""
- for file in $CHANGED_FILES; do
- if [[ "$file" == charts/* ]]; then
- CHART_DIR=$(echo "$file" | cut -d'/' -f1-2)
- if [[ -f "$CHART_DIR/Chart.yaml" ]]; then
- CHANGED_CHARTS="$CHANGED_CHARTS $CHART_DIR"
- fi
- fi
- done
-
- # Remove duplicates
- CHANGED_CHARTS=$(echo "$CHANGED_CHARTS" | tr ' ' '\n' | sort -u | tr '\n' ' ')
-
- echo "Changed charts: $CHANGED_CHARTS"
-
- # Process each changed chart
- RELEASED_CHARTS=""
- for chart_path in $CHANGED_CHARTS; do
- if [[ -n "$chart_path" && -f "$chart_path/Chart.yaml" ]]; then
- chart_name=$(basename "$chart_path")
-
- echo "Processing chart: $chart_name at $chart_path"
- cd "$chart_path"
-
- # Extract version and appVersion from Chart.yaml
- CHART_VERSION=$(yq eval '.version' Chart.yaml)
- APP_VERSION=$(yq eval '.appVersion' Chart.yaml)
-
- echo "Chart: $chart_name, Version: $CHART_VERSION, App Version: $APP_VERSION"
-
- # Update dependencies if Chart.yaml contains dependencies
- if grep -q "dependencies:" Chart.yaml; then
- echo "Updating dependencies for $chart_name"
- helm dependency update
- fi
-
- # Package the chart
- echo "Packaging Helm chart $chart_name version $CHART_VERSION"
- helm package . --version=$CHART_VERSION --app-version=$APP_VERSION
-
- # Push the chart to dynamic repository
- CHART_REPO="${CHART_REPO_PREFIX}"
- echo "Pushing Helm chart $chart_name-$CHART_VERSION.tgz to oci://$REGISTRY/$CHART_REPO"
-
- if helm push ${chart_name}-${CHART_VERSION}.tgz oci://${REGISTRY}/${CHART_REPO} 2>&1 | tee $CI_PROJECT_DIR/${chart_name}-output.log; then
- # Extract digest for signing
- DIGEST=$(cat $CI_PROJECT_DIR/${chart_name}-output.log | awk -F '[, ]+' '/Digest/{print $NF}')
- echo "${chart_name}_VERSION=$CHART_VERSION" >> $CI_PROJECT_DIR/digest.env
- echo "${chart_name}_DIGEST=$DIGEST" >> $CI_PROJECT_DIR/digest.env
-
- RELEASED_CHARTS="$RELEASED_CHARTS $chart_name"
- echo "Successfully released $chart_name:$CHART_VERSION"
- else
- echo "Failed to push $chart_name:$CHART_VERSION"
- cat $CI_PROJECT_DIR/${chart_name}-output.log
- exit 1
- fi
-
- cd - > /dev/null
- fi
- done
-
- echo "RELEASED_CHARTS=$RELEASED_CHARTS" >> $CI_PROJECT_DIR/digest.env
-
- if [[ -z "$RELEASED_CHARTS" ]]; then
- echo "No charts were released"
- else
- echo "Released charts: $RELEASED_CHARTS"
- fi
- artifacts:
- expire_in: 24h
- reports:
- dotenv: digest.env
- rules:
- - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
- changes:
- - charts/**/Chart.yaml
-
-sign-charts:
- stage: sign
- image: harbor.cloudpirates.io/public/cosign:v2.4.2@sha256:4731b7f62d0a98236769dbb6f97543a66e25e46d5a35d46111248e7c0d628230
- variables:
- GIT_STRATEGY: none
- before_script:
- - mkdir -p ~/.docker
- - echo "{\"auths\":{\"$REGISTRY\":{\"username\":\"$REGISTRY_USER\",\"password\":\"$REGISTRY_PASSWORD\"}}}" > ~/.docker/config.json
- script:
- - |
- if [[ -z "$RELEASED_CHARTS" ]]; then
- echo "No charts were released, nothing to sign"
- exit 0
- fi
-
- echo "Signing charts: $RELEASED_CHARTS"
- for chart_name in $RELEASED_CHARTS; do
- VERSION_VAR="${chart_name}_VERSION"
- DIGEST_VAR="${chart_name}_DIGEST"
-
- CHART_VERSION=$(eval echo \$$VERSION_VAR)
- DIGEST=$(eval echo \$$DIGEST_VAR)
-
- if [[ -n "$DIGEST" && -n "$CHART_VERSION" ]]; then
- CHART_REPO="${CHART_REPO_PREFIX}"
- echo "Signing chart: $chart_name:$CHART_VERSION with digest: $DIGEST"
- cosign sign --key env://COSIGN_KEY --tlog-upload=false ${REGISTRY}/${CHART_REPO}/${chart_name}:${CHART_VERSION}@$DIGEST
- else
- echo "Missing version or digest for chart: $chart_name (version: $CHART_VERSION, digest: $DIGEST)"
- fi
- done
- needs:
- - release-charts
- rules:
- - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
- changes:
- - charts/**/Chart.yaml
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index df6176ef..db883d62 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -6,11 +6,23 @@ Hi there! We are thrilled that you'd like to contribute to this project. It's pe
- [Code of Conduct](#code-of-conduct)
- [How Can I Contribute?](#how-can-i-contribute)
+ - [Reporting Bugs](#reporting-bugs)
+ - [Suggesting Enhancements](#suggesting-enhancements)
+ - [Types of Contributions We're Looking For](#types-of-contributions-were-looking-for)
- [Development Setup](#development-setup)
+ - [Prerequisites](#prerequisites)
+ - [Setting Up Your Development Environment](#setting-up-your-development-environment)
- [Contributing Guidelines](#contributing-guidelines)
-- [Chart Development Standards](#chart-development-standards)
+ - [Chart Development Standards](#chart-development-standards)
+ - [Chart Structure](#chart-structure)
+ - [Documentation Requirements](#documentation-requirements)
+ - [Versioning](#versioning)
- [Testing](#testing)
+ - [Running Tests](#running-tests)
+ - [Test Requirements](#test-requirements)
+ - [Manual Testing](#manual-testing)
- [Pull Request Process](#pull-request-process)
+ - [Pull Request Checklist](#pull-request-checklist)
## Code of Conduct
@@ -22,21 +34,21 @@ This project and everyone participating in it is governed by our [Code of Conduc
Before creating bug reports, please check the existing issues as you might find out that you don't need to create one. When you are creating a bug report, please include as many details as possible:
-- **Use a clear and descriptive title**
-- **Describe the exact steps to reproduce the problem**
-- **Provide specific examples to demonstrate the steps**
-- **Describe the behavior you observed and what behavior you expected**
-- **Include details about your configuration and environment**
+- Use a **clear and descriptive title**
+- Describe the **exact steps to reproduce** the problem
+- Provide **specific examples** to demonstrate the steps
+- Describe the **behavior you observed** and what **behavior you expected**
+- Include details about **your configuration and environment**
### Suggesting Enhancements
Enhancement suggestions are tracked as GitHub issues. When creating an enhancement suggestion, please include:
-- **Use a clear and descriptive title**
-- **Provide a step-by-step description of the suggested enhancement**
-- **Provide specific examples to demonstrate the steps**
-- **Describe the current behavior and explain which behavior you expected to see**
-- **Explain why this enhancement would be useful**
+- Use a **clear and descriptive title**
+- Provide a **step-by-step description** of the suggested enhancement
+- Provide **specific examples** to demonstrate the steps
+- Describe the **current behavior** and explain which **behavior you expected** to see
+- Explain **why this enhancement would be useful**
### Types of Contributions We're Looking For
@@ -52,21 +64,39 @@ Enhancement suggestions are tracked as GitHub issues. When creating an enhanceme
- Kubernetes 1.24+
- Helm 3.2.0+
- [helm-unittest](https://github.com/helm-unittest/helm-unittest) plugin
+- Commits verified by signature
### Setting Up Your Development Environment
1. Fork the repository on GitHub
2. Clone your fork locally:
+
```bash
git clone https://github.com/your-username/helm-charts.git
cd helm-charts
```
3. Install the helm-unittest plugin:
+
```bash
helm plugin install https://github.com/helm-unittest/helm-unittest
```
+4. Make sure to sign your commits
+
+ ```bash
+ git config gpg.format ssh
+ git config user.signingkey
+ git config commit.gpgsign true
+ git config tag.gpgsign true
+ ```
+
+ Replace `` with the path to your public ssh key file, e.g. `~/.ssh/id_ed25519.pub`, wich you use to push to GitHub.
+ Alternatively, a signing ssh key can be used instead.
+ If you want to sign commits in every repository, not just this one, add the `--global` parameter.
+
+ > More information: [GitHub docs](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification)
+
## Contributing Guidelines
### Chart Development Standards
@@ -74,18 +104,21 @@ Enhancement suggestions are tracked as GitHub issues. When creating an enhanceme
All charts in this repository must follow these standards:
#### Security First
+
- Implement read-only root filesystems where possible
- Drop unnecessary Linux capabilities
- Configure security contexts properly
- Never hardcode credentials
#### Production Ready
+
- Include comprehensive health checks (liveness, readiness, startup probes)
- Support resource requests and limits
- Provide persistent storage configurations
- Include health check endpoints
#### Highly Configurable
+
- Provide extensive `values.yaml` with detailed documentation
- Support existing secrets and ConfigMaps
- Offer flexible ingress configurations
@@ -144,7 +177,7 @@ All charts must include comprehensive tests. Run tests using:
```bash
# Test all charts
-./test-all-charts.sh
+./test-charts.sh
# Test individual chart
helm dependency update charts/your-chart
@@ -154,6 +187,7 @@ helm unittest charts/your-chart
### Test Requirements
Your tests should cover:
+
- Template rendering with default values
- Template rendering with custom values
- Required value validation
@@ -181,6 +215,7 @@ kubectl get all -n test
## Pull Request Process
1. **Branch**: Create a feature branch from `main`
+
```bash
git checkout -b feature/your-chart-improvement
```
@@ -188,14 +223,16 @@ kubectl get all -n test
2. **Development**: Make your changes following the guidelines above
3. **Testing**: Run all tests and ensure they pass
+
```bash
- ./test-all-charts.sh
+ ./test-charts.sh
helm lint ./charts/your-chart
```
4. **Documentation**: Update documentation as needed
5. **Commit**: Use clear, descriptive commit messages
+
```bash
git commit -m "[chart-name] Add support for custom annotations"
```
diff --git a/README.md b/README.md
index 5d7b817c..3987662f 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,12 @@
+
+
+
+
+
+
# CloudPirates Open Source Helm Charts
@@ -11,23 +17,25 @@ This repository provides secure, well-documented, and configurable Helm charts f
## Available Charts
-| Chart | Description |
-| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
-| [ClusterPirate](charts/clusterpirate/) | Client agent for the CloudPirates Managed Observability Platform to connect your Kubernetes cluster to our infrastructure |
-| [Common](charts/common/) | A library chart for common templates and helper functions |
-| [Ghost](charts/ghost/) | A simple, powerful publishing platform that allows you to share your stories with the world. |
-| [Keycloak](charts/keycloak/) | Open Source Identity and Access Management solution |
-| [MariaDB](charts/mariadb/) | High-performance, open-source relational database server that is a drop-in replacement for MySQL |
-| [Memcached](charts/memcached/) | High-performance, distributed memory object caching system |
-| [MinIO](charts/minio/) | High-Performance Object Storage compatible with Amazon S3 APIs |
-| [MongoDB](charts/mongodb/) | MongoDB a flexible NoSQL database for scalable, real-time data management |
-| [Nginx](charts/nginx/) | High-performance HTTP server and reverse proxy |
-| [PostgreSQL](charts/postgres/) | The World's Most Advanced Open Source Relational Database |
-| [RabbitMQ](charts/rabbitmq/) | A messaging broker that implements the Advanced Message Queuing Protocol (AMQP) |
-| [Redis](charts/redis/) | In-memory data structure store, used as a database, cache, and message broker |
-| [TimescaleDB](charts/timescaledb/) | TimescaleDB is a PostgreSQL extension for high-performance real-time analytics on time-series and event data |
-| [Valkey](charts/valkey/) | High-performance in-memory data structure store, fork of Redis |
-| [Zookeeper](charts/zookeeper/) | Centralized service for maintaining configuration information, naming, providing distributed synchronization, and group services |
+| Chart | Description | Version |
+| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| [ClusterPirate](charts/clusterpirate/) | Client agent for the CloudPirates Managed Observability Platform to connect your Kubernetes cluster to our infrastructure |  |
+| [Common](charts/common/) | A library chart for common templates and helper functions |  |
+| [Etcd](charts/etcd/) | A distributed reliable key-value store |  |
+| [Ghost](charts/ghost/) | A simple, powerful publishing platform that allows you to share your stories with the world. |  |
+| [Keycloak](charts/keycloak/) | Open Source Identity and Access Management solution |  |
+| [MariaDB](charts/mariadb/) | High-performance, open-source relational database server that is a drop-in replacement for MySQL |  |
+| [Memcached](charts/memcached/) | High-performance, distributed memory object caching system |  |
+| [MinIO](charts/minio/) | High-Performance Object Storage compatible with Amazon S3 APIs |  |
+| [MongoDB](charts/mongodb/) | MongoDB a flexible NoSQL database for scalable, real-time data management |  |
+| [Nginx](charts/nginx/) | High-performance HTTP server and reverse proxy |  |
+| [PostgreSQL](charts/postgres/) | The World's Most Advanced Open Source Relational Database |  |
+| [RabbitMQ](charts/rabbitmq/) | A messaging broker that implements the Advanced Message Queuing Protocol (AMQP) |  |
+| [Redis](charts/redis/) | In-memory data structure store, used as a database, cache, and message broker |  |
+| [RustFS](charts/rustfs/) | High-performance distributed object storage with S3-compatible API (MinIO alternative) [ALPHA] |  |
+| [TimescaleDB](charts/timescaledb/) | TimescaleDB is a PostgreSQL extension for high-performance real-time analytics on time-series and event data |  |
+| [Valkey](charts/valkey/) | High-performance in-memory data structure store, fork of Redis |  |
+| [Zookeeper](charts/zookeeper/) | Centralized service for maintaining configuration information, naming, providing distributed synchronization, and group services |  |
## Quick Start
@@ -54,7 +62,7 @@ helm install my-release ./charts/
All charts in this repository provide:
-### ๐ **Security First**
+### **Security First**
- **Cryptographically Signed**: All charts are signed with [Cosign](COSIGN.md) for supply chain security
- Non-root containers by default
@@ -63,7 +71,7 @@ All charts in this repository provide:
- Security contexts configured
- No hardcoded credentials
-### ๐ **Production Ready**
+### **Production Ready**
- Comprehensive health checks (liveness, readiness, startup probes)
- Resource requests and limits support
@@ -71,7 +79,7 @@ All charts in this repository provide:
- Rolling update strategies
- Health check endpoints
-### ๐๏ธ **Highly Configurable**
+### **Highly Configurable**
- Extensive values.yaml with detailed documentation
- Support for existing secrets and ConfigMaps
@@ -91,9 +99,16 @@ Each chart provides extensive configuration options through `values.yaml`. Key c
Refer to individual chart READMEs for detailed configuration options.
-## Contributing
+## Get Involved
+
+Want to contribute? Awesome! The most basic way to show your support is to star the project, or to raise issues.
+
+If you want to open a PR, read our [contributing guidelines](CONTRIBUTING.md) for information about setting up your environment and instructions on the signature verification that we require.
+
+Chat with us and the community on our [Discord server](https://discord.gg/XUn9Kt5dsy)!\
+Everyone is welcome, wether you have a question, need help with a chart, want to contribute, know what's coming next or just have a talk with us.
-Want to contribute? Awesome! The most basic way to show your support is to star the project, or to raise issues. If you want to open a pull request, please read the [contributing guidelines](CONTRIBUTING.md).
+[](https://discord.gg/XUn9Kt5dsy)
**This project is built and maintained by our growing community of contributors!**
diff --git a/TESTING.md b/TESTING.md
index c596ad8c..acc9da31 100644
--- a/TESTING.md
+++ b/TESTING.md
@@ -17,7 +17,7 @@ helm plugin install https://github.com/helm-unittest/helm-unittest
Use the provided test runner script to run tests for all charts:
```bash
-./test-all-charts.sh
+./test-charts.sh
```
This script will:
diff --git a/charts/clusterpirate/.disable-unittest b/charts/clusterpirate/.disable-unittest
new file mode 100644
index 00000000..aa617f45
--- /dev/null
+++ b/charts/clusterpirate/.disable-unittest
@@ -0,0 +1,2 @@
+# This file disables helm unittest for this chart
+# The clusterpirate service depends on external services that are not reachable during testing
diff --git a/charts/clusterpirate/CHANGELOG.md b/charts/clusterpirate/CHANGELOG.md
index c067e73c..07dbac59 100644
--- a/charts/clusterpirate/CHANGELOG.md
+++ b/charts/clusterpirate/CHANGELOG.md
@@ -1,25 +1,95 @@
# Changelog
-## 1.0.7 (2025-08-27)
-
-* Add logo and fix OCI reference for installation ([1e8bb7a](https://github.com/CloudPirates-io/helm-charts/commit/1e8bb7a))
-* add new helm chart ([65b66d8](https://github.com/CloudPirates-io/helm-charts/commit/65b66d8))
-* Fix README.md ([bc2bdea](https://github.com/CloudPirates-io/helm-charts/commit/bc2bdea))
-* Release version 1.0.1 ([2b46314](https://github.com/CloudPirates-io/helm-charts/commit/2b46314))
-* Trigger Release ([414545d](https://github.com/CloudPirates-io/helm-charts/commit/414545d))
-* Update default values ([ac5e69b](https://github.com/CloudPirates-io/helm-charts/commit/ac5e69b))
-* Update README and Chart.yaml descriptions ([5afa09c](https://github.com/CloudPirates-io/helm-charts/commit/5afa09c))
-* Update valkey dependency ([d430fe5](https://github.com/CloudPirates-io/helm-charts/commit/d430fe5))
-* Add ArtifactHub Badges to all Charts ([08b855b](https://github.com/CloudPirates-io/helm-charts/commit/08b855b))
-* Add ArtifactHub repo config ([15180a8](https://github.com/CloudPirates-io/helm-charts/commit/15180a8))
-* Add cosign signature READMEs ([5f82e7f](https://github.com/CloudPirates-io/helm-charts/commit/5f82e7f))
-* Add extensive chart testing ([a46efac](https://github.com/CloudPirates-io/helm-charts/commit/a46efac))
-* Add generated values.schema.json files from values.yaml ([aa79ac3](https://github.com/CloudPirates-io/helm-charts/commit/aa79ac3))
-* Add release pipeline ([ebd7277](https://github.com/CloudPirates-io/helm-charts/commit/ebd7277))
-* Fix image tag/digest handling ([a5c982b](https://github.com/CloudPirates-io/helm-charts/commit/a5c982b))
-* Fix imagePullSecrets format and pull always ([ce0d301](https://github.com/CloudPirates-io/helm-charts/commit/ce0d301))
-* Format README files ([04aacab](https://github.com/CloudPirates-io/helm-charts/commit/04aacab))
-* Release new chart versions / update sources ([dbb0e45](https://github.com/CloudPirates-io/helm-charts/commit/dbb0e45))
-* Remove leading $ from code blocks ([836b2e3](https://github.com/CloudPirates-io/helm-charts/commit/836b2e3))
-* Test Release of ClusterPirate ([b217adc](https://github.com/CloudPirates-io/helm-charts/commit/b217adc))
-* Update valkey Docker tag to v0.1.5 ([d3fd18d](https://github.com/CloudPirates-io/helm-charts/commit/d3fd18d))
+
+## 1.2.9 (2025-11-04)
+
+* chore: update CHANGELOG.md for merged changes ([5cc4e82](https://github.com/CloudPirates-io/helm-charts/commit/5cc4e82))
+* chore: update CHANGELOG.md for merged changes ([8138b4a](https://github.com/CloudPirates-io/helm-charts/commit/8138b4a))
+
+## 1.2.8 (2025-11-03)
+
+
+## 1.2.7 (2025-10-31)
+
+* chore: update CHANGELOG.md for merged changes ([5686ce7](https://github.com/CloudPirates-io/helm-charts/commit/5686ce7))
+* chore: update CHANGELOG.md for merged changes ([20c99bd](https://github.com/CloudPirates-io/helm-charts/commit/20c99bd))
+* chore: update CHANGELOG.md for merged changes ([08e6bc1](https://github.com/CloudPirates-io/helm-charts/commit/08e6bc1))
+* chore: update CHANGELOG.md for merged changes ([5f5500a](https://github.com/CloudPirates-io/helm-charts/commit/5f5500a))
+
+## 1.2.6 (2025-10-29)
+
+* chore: update CHANGELOG.md for merged changes ([82bee53](https://github.com/CloudPirates-io/helm-charts/commit/82bee53))
+* chore: update CHANGELOG.md for merged changes ([0a732be](https://github.com/CloudPirates-io/helm-charts/commit/0a732be))
+* chore: update CHANGELOG.md for merged changes ([4abe8c4](https://github.com/CloudPirates-io/helm-charts/commit/4abe8c4))
+
+## 1.2.5 (2025-10-26)
+
+* chore: update CHANGELOG.md for merged changes ([f9c3ff0](https://github.com/CloudPirates-io/helm-charts/commit/f9c3ff0))
+* chore: update CHANGELOG.md for merged changes ([db2d800](https://github.com/CloudPirates-io/helm-charts/commit/db2d800))
+
+## 1.2.4 (2025-10-23)
+
+* chore: update CHANGELOG.md for merged changes ([1053460](https://github.com/CloudPirates-io/helm-charts/commit/1053460))
+* chore: update CHANGELOG.md for merged changes ([6230965](https://github.com/CloudPirates-io/helm-charts/commit/6230965))
+
+## 1.2.3 (2025-10-22)
+
+* chore: update CHANGELOG.md for merged changes ([051ad83](https://github.com/CloudPirates-io/helm-charts/commit/051ad83))
+* chore: update CHANGELOG.md for merged changes ([1a50307](https://github.com/CloudPirates-io/helm-charts/commit/1a50307))
+
+## 1.2.2 (2025-10-22)
+
+* chore: update CHANGELOG.md for merged changes ([5d1f01a](https://github.com/CloudPirates-io/helm-charts/commit/5d1f01a))
+* chore: update CHANGELOG.md for merged changes ([fc47c5d](https://github.com/CloudPirates-io/helm-charts/commit/fc47c5d))
+* chore: update CHANGELOG.md for merged changes ([1a4f87b](https://github.com/CloudPirates-io/helm-charts/commit/1a4f87b))
+* chore: update CHANGELOG.md for merged changes ([da866ca](https://github.com/CloudPirates-io/helm-charts/commit/da866ca))
+* chore: update CHANGELOG.md for merged changes ([5187c4d](https://github.com/CloudPirates-io/helm-charts/commit/5187c4d))
+* chore: update CHANGELOG.md for merged changes ([bb0b090](https://github.com/CloudPirates-io/helm-charts/commit/bb0b090))
+
+## 1.2.1 (2025-10-17)
+
+* chore: update CHANGELOG.md for merged changes ([b54c4f1](https://github.com/CloudPirates-io/helm-charts/commit/b54c4f1))
+* chore: update CHANGELOG.md for merged changes ([5a2ed20](https://github.com/CloudPirates-io/helm-charts/commit/5a2ed20))
+* chore: update CHANGELOG.md for merged changes ([bf2e3b2](https://github.com/CloudPirates-io/helm-charts/commit/bf2e3b2))
+* chore: update CHANGELOG.md for merged changes ([2f87d0e](https://github.com/CloudPirates-io/helm-charts/commit/2f87d0e))
+
+## 1.2.0 (2025-10-14)
+
+* chore: update CHANGELOG.md for merged changes ([84cf67b](https://github.com/CloudPirates-io/helm-charts/commit/84cf67b))
+* chore: update CHANGELOG.md for all charts via manual trigger ([6974964](https://github.com/CloudPirates-io/helm-charts/commit/6974964))
+* chore: update CHANGELOG.md for merged changes ([63b7bfa](https://github.com/CloudPirates-io/helm-charts/commit/63b7bfa))
+* chore: update CHANGELOG.md for merged changes ([da69e0e](https://github.com/CloudPirates-io/helm-charts/commit/da69e0e))
+* chore: update CHANGELOG.md for merged changes ([5da1b15](https://github.com/CloudPirates-io/helm-charts/commit/5da1b15))
+
+## 1.1.4 (2025-10-13)
+
+* chore: update CHANGELOG.md for merged changes ([9bfae89](https://github.com/CloudPirates-io/helm-charts/commit/9bfae89))
+* chore: update CHANGELOG.md for merged changes ([dc7faee](https://github.com/CloudPirates-io/helm-charts/commit/dc7faee))
+
+## 1.1.3 (2025-10-13)
+
+* Fix clusterpirate (#372) ([e659f51](https://github.com/CloudPirates-io/helm-charts/commit/e659f51))
+
+## 1.1.2 (2025-10-13)
+
+* Fix formatting (#371) ([cf4670a](https://github.com/CloudPirates-io/helm-charts/commit/cf4670a))
+* Bugfix/lint workflow (#365) ([adeac21](https://github.com/CloudPirates-io/helm-charts/commit/adeac21))
+
+## 1.1.1 (2025-10-13)
+
+* Bugfix/lint workflow (#363) ([ce5c550](https://github.com/CloudPirates-io/helm-charts/commit/ce5c550))
+* Bugfix/lint workflow (#362) ([bbf7bd5](https://github.com/CloudPirates-io/helm-charts/commit/bbf7bd5))
+
+## 1.1.0 (2025-10-13)
+
+* Bump dependencies (#357) ([c2909cd](https://github.com/CloudPirates-io/helm-charts/commit/c2909cd))
+
+## 1.0.7 (2025-08-27)
+
+* Fix linting for values.yaml ([504ac61](https://github.com/CloudPirates-io/helm-charts/commit/504ac61))
+* Fix values.yaml / Chart.yaml linting issues ([043c7e0](https://github.com/CloudPirates-io/helm-charts/commit/043c7e0))
+* Add initial Changelogs to all Charts ([68f10ca](https://github.com/CloudPirates-io/helm-charts/commit/68f10ca))
+
+## 1.0.6 (2025-08-26)
+
+* Initial tagged release
diff --git a/charts/clusterpirate/Chart.lock b/charts/clusterpirate/Chart.lock
index 48503674..67c2ff24 100644
--- a/charts/clusterpirate/Chart.lock
+++ b/charts/clusterpirate/Chart.lock
@@ -1,9 +1,9 @@
dependencies:
- name: common
repository: oci://registry-1.docker.io/cloudpirates
- version: 1.0.0
+ version: 2.0.0
- name: valkey
repository: oci://registry-1.docker.io/cloudpirates
- version: 0.1.5
-digest: sha256:20b766f851e5333f32bae40eb761424ec9e43e02141127defd9037e3c112cb2c
-generated: "2025-08-14T11:33:42.043028181Z"
+ version: 0.9.2
+digest: sha256:f2091174754807696e0633286f5498061b7816d8084e3161bcbb19d05b455ef6
+generated: "2025-11-04T10:17:14.827792567Z"
diff --git a/charts/clusterpirate/Chart.yaml b/charts/clusterpirate/Chart.yaml
index f1dc0010..f6ef6a4f 100644
--- a/charts/clusterpirate/Chart.yaml
+++ b/charts/clusterpirate/Chart.yaml
@@ -2,29 +2,42 @@ apiVersion: v2
name: clusterpirate
description: Client agent for the CloudPirates Managed Observability Platform to connect your Kubernetes cluster to our infrastructure
type: application
-version: 1.0.7
+version: 1.2.9
appVersion: "1.0.1"
-
keywords:
- kubernetes
- clusterpirate
- cloudpirates
- observability
- agent
-
home: https://www.cloudpirates.io
-
+sources:
+ - https://github.com/CloudPirates-io/helm-charts/tree/main/charts/clusterpirate
maintainers:
- name: CloudPirates GmbH & Co. KG
+ email: hello@cloudpirates.io
url: https://www.cloudpirates.io
-
dependencies:
- name: common
- version: "1.x.x"
+ version: "2.x.x"
repository: oci://registry-1.docker.io/cloudpirates
- name: valkey
- version: "0.1.5"
+ version: "0.9.2"
repository: oci://registry-1.docker.io/cloudpirates
condition: valkey.enabled
-
icon: https://a.storyblok.com/f/143071/512x512/88dc07809a/cluster-pirate-logo.svg
+annotations:
+ license: Apache-2.0
+ artifacthub.io/category: monitoring-logging
+ artifacthub.io/containsSecurityUpdates: "false"
+ artifacthub.io/signKey: |
+ fingerprint: 6917f1a88c122cbb1de5aa55457752135bdcf95a
+ url: https://raw.githubusercontent.com/CloudPirates-io/helm-charts/refs/heads/main/cosign.pub
+ artifacthub.io/links: |
+ - name: Helm Chart
+ url: https://github.com/CloudPirates-io/helm-charts/tree/main/charts/clusterpirate
+ - name: Maintainer CloudPirates
+ url: https://www.cloudpirates.io
+ artifacthub.io/changes: |2
+ - kind: changed
+ description: "Chart updated"
diff --git a/charts/clusterpirate/ci/default-values.yaml b/charts/clusterpirate/ci/default-values.yaml
new file mode 100644
index 00000000..10f03ce7
--- /dev/null
+++ b/charts/clusterpirate/ci/default-values.yaml
@@ -0,0 +1,17 @@
+# CI test values for clusterpirate chart
+# This file provides minimal required configuration for chart testing
+
+auth:
+ # Provide a test access token for CI testing
+ accessToken: "test-token-for-ci-only"
+
+# Disable Valkey dependency for faster CI testing
+valkey:
+ enabled: false
+
+# Configure cache to not require Valkey
+clusterPirate:
+ metrics:
+ cache:
+ host: "localhost"
+ password: ""
diff --git a/charts/clusterpirate/templates/_helpers.tpl b/charts/clusterpirate/templates/_helpers.tpl
index ec338207..7dae35ae 100644
--- a/charts/clusterpirate/templates/_helpers.tpl
+++ b/charts/clusterpirate/templates/_helpers.tpl
@@ -2,7 +2,7 @@
Expand the name of the chart.
*/}}
{{- define "clusterpirate.name" -}}
-{{- include "common.name" . -}}
+{{- include "cloudpirates.name" . -}}
{{- end }}
{{/*
@@ -11,35 +11,35 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
If release name contains chart name it will be used as a full name.
*/}}
{{- define "clusterpirate.fullname" -}}
-{{- include "common.fullname" . -}}
+{{- include "cloudpirates.fullname" . -}}
{{- end }}
{{/*
Common labels
*/}}
{{- define "clusterpirate.labels" -}}
-{{- include "common.labels" . }}
+{{- include "cloudpirates.labels" . }}
{{- end }}
{{/*
Common annotations
*/}}
{{- define "clusterpirate.annotations" -}}
-{{- include "common.annotations" . }}
+{{- include "cloudpirates.annotations" . }}
{{- end }}
{{/*
Return the proper Docker Image Registry Secret Names
*/}}
{{- define "clusterpirate.imagePullSecrets" -}}
-{{ include "common.images.renderPullSecrets" (dict "images" (list .Values.image) "context" .) }}
+{{ include "cloudpirates.images.renderPullSecrets" (dict "images" (list .Values.image) "context" .) }}
{{- end -}}
{{/*
Selector labels
*/}}
{{- define "clusterpirate.selectorLabels" -}}
-{{- include "common.selectorLabels" . -}}
+{{- include "cloudpirates.selectorLabels" . -}}
{{- end }}
{{/*
@@ -62,5 +62,5 @@ release: {{ .Release.Name }}
Return the proper ClusterPirate image name
*/}}
{{- define "clusterpirate.image" -}}
-{{- include "common.image" (dict "image" .Values.image "global" .Values.global) -}}
+{{- include "cloudpirates.image" (dict "image" .Values.image "global" .Values.global) -}}
{{- end }}
\ No newline at end of file
diff --git a/charts/clusterpirate/templates/deployment.yaml b/charts/clusterpirate/templates/deployment.yaml
index b0f140a7..b093d278 100644
--- a/charts/clusterpirate/templates/deployment.yaml
+++ b/charts/clusterpirate/templates/deployment.yaml
@@ -29,7 +29,7 @@ spec:
containers:
- name: {{ include "clusterpirate.fullname" . }}
image: {{ include "clusterpirate.image" . }}
- imagePullPolicy: {{ include "common.imagePullPolicy" (dict "image" .Values.image) }}
+ imagePullPolicy: {{ include "cloudpirates.imagePullPolicy" (dict "image" .Values.image) }}
resources:
{{ toYaml .Values.deployment.resources | indent 10 }}
{{- if .Values.deployment.probes.livenessProbe.enabled }}
@@ -98,6 +98,7 @@ spec:
configMapKeyRef:
name: {{ include "clusterpirate.fullname" . }}
key: valkeyTtl
+ {{- if or .Values.valkey.enabled .Values.clusterPirate.metrics.cache.password }}
- name: VALKEY_PASSWORD
valueFrom:
secretKeyRef:
@@ -107,13 +108,17 @@ spec:
key: password
{{- else if .Values.valkey.auth.existingSecret }}
# Use existing secret specified for Valkey
- name: {{ .Values.valkey.auth.existingSecret }}
+ name: {{ include "cloudpirates.tplvalues.render" (dict "value" .Values.valkey.auth.existingSecret "context" .) }}
key: {{ .Values.valkey.auth.existingSecretPasswordKey | default "password" }}
{{- else if .Values.clusterPirate.metrics.cache.password }}
# Use password from ClusterPirate cache config (external Valkey)
name: {{ include "clusterpirate.fullname" . }}
key: valkeyPassword
{{- end }}
+ {{- else }}
+ - name: VALKEY_PASSWORD
+ value: ""
+ {{- end }}
- name: MONITORING_RESOURCE_EVENTS_ENABLED
valueFrom:
configMapKeyRef:
@@ -133,7 +138,7 @@ spec:
valueFrom:
secretKeyRef:
{{- if .Values.auth.existingSecret }}
- name: {{ .Values.auth.existingSecret }}
+ name: {{ include "cloudpirates.tplvalues.render" (dict "value" .Values.auth.existingSecret "context" .) }}
key: {{ .Values.auth.existingSecretAccessTokenKey | default "accessToken" }}
{{- else }}
name: {{ include "clusterpirate.fullname" . }}
diff --git a/charts/clusterpirate/values.schema.json b/charts/clusterpirate/values.schema.json
index 536e64ec..1ee14e11 100644
--- a/charts/clusterpirate/values.schema.json
+++ b/charts/clusterpirate/values.schema.json
@@ -1,458 +1,253 @@
{
- "$schema": "https://json-schema.org/draft-07/schema#",
- "type": "object",
- "title": "ClusterPirate Helm Chart Values Schema",
- "description": "Schema for ClusterPirate Helm chart values",
- "properties": {
- "commonLabels": {
- "type": "object",
- "title": "Common Labels",
- "description": "Common labels applied to all resources",
- "additionalProperties": {
- "type": "string"
- }
- },
- "commonAnnotations": {
- "type": "object",
- "title": "Common Annotations",
- "description": "Common annotations applied to all resources",
- "additionalProperties": {
- "type": "string"
- }
- },
- "imagePullSecrets": {
- "type": "array",
- "title": "Image Pull Secrets",
- "description": "Registry secret names as an array of objects",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string",
- "title": "Secret Name",
- "description": "Name of the image pull secret"
- }
- },
- "required": ["name"]
- }
- },
- "image": {
- "type": "object",
- "title": "ClusterPirate Image Configuration",
- "description": "Container image settings for ClusterPirate",
- "properties": {
- "registry": {
- "type": "string",
- "title": "Image Registry",
- "description": "ClusterPirate image registry"
- },
- "repository": {
- "type": "string",
- "title": "Image Repository",
- "description": "ClusterPirate image repository"
- },
- "tag": {
- "type": "string",
- "title": "Image Tag",
- "description": "ClusterPirate image tag with digest"
- },
- "imagePullPolicy": {
- "type": "string",
- "title": "Image Pull Policy",
- "description": "ClusterPirate image pull policy",
- "enum": [
- "Always",
- "Never",
- "IfNotPresent"
- ]
- }
- }
- },
- "deployment": {
- "type": "object",
- "title": "Deployment Configuration",
- "description": "Configuration for the ClusterPirate deployment",
- "properties": {
- "resources": {
- "type": "object",
- "title": "Pod Resource Configuration",
- "description": "Pod resource limits and requests",
- "properties": {
- "limits": {
- "type": "object",
- "title": "Resource Limits",
- "description": "Resource limits for the container",
- "properties": {
- "cpu": {
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "number"
- }
- ],
- "title": "CPU Limit",
- "description": "CPU resource limit"
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "type": "object",
+ "properties": {
+ "auth": {
+ "type": "object",
+ "properties": {
+ "accessToken": {
+ "type": "string"
},
- "memory": {
- "type": "string",
- "title": "Memory Limit",
- "description": "Memory resource limit"
- }
- }
- },
- "requests": {
- "type": "object",
- "title": "Resource Requests",
- "description": "Resource requests for the container",
- "properties": {
- "cpu": {
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "number"
- }
- ],
- "title": "CPU Request",
- "description": "CPU resource request"
+ "existingSecret": {
+ "type": "string"
},
- "memory": {
- "type": "string",
- "title": "Memory Request",
- "description": "Memory resource request"
+ "existingSecretAccessTokenKey": {
+ "type": "string"
}
- }
}
- }
},
- "extraEnvVars": {
- "type": "array",
- "title": "Extra Environment Variables",
- "description": "Additional environment variables",
- "items": {
+ "cloudpiratesApi": {
"type": "object",
"properties": {
- "name": {
- "type": "string",
- "title": "Variable Name",
- "description": "Environment variable name"
- },
- "value": {
- "type": "string",
- "title": "Variable Value",
- "description": "Environment variable value"
- },
- "valueFrom": {
- "type": "object",
- "title": "Value From",
- "description": "Source for the environment variable value"
- }
- },
- "required": [
- "name"
- ]
- }
+ "registerEndpoint": {
+ "type": "string"
+ }
+ }
},
- "probes": {
- "type": "object",
- "title": "Health Probe Configuration",
- "description": "Health probe settings",
- "properties": {
- "livenessProbe": {
- "type": "object",
- "title": "Liveness Probe",
- "description": "Liveness probe configuration",
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable Liveness Probe",
- "description": "Enable liveness probe"
- },
- "initialDelaySeconds": {
- "type": "integer",
- "title": "Initial Delay Seconds",
- "description": "Initial delay seconds for liveness probe",
- "minimum": 0
- },
- "periodSeconds": {
- "type": "integer",
- "title": "Period Seconds",
- "description": "Period seconds for liveness probe",
- "minimum": 1
+ "clusterPirate": {
+ "type": "object",
+ "properties": {
+ "healthPort": {
+ "type": "integer"
},
- "timeoutSeconds": {
- "type": "integer",
- "title": "Timeout Seconds",
- "description": "Timeout seconds for liveness probe",
- "minimum": 1
+ "logLevel": {
+ "type": "string"
},
- "failureThreshold": {
- "type": "integer",
- "title": "Failure Threshold",
- "description": "Failure threshold for liveness probe",
- "minimum": 1
+ "metrics": {
+ "type": "object",
+ "properties": {
+ "cache": {
+ "type": "object",
+ "properties": {
+ "host": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "port": {
+ "type": "integer"
+ },
+ "ttl": {
+ "type": "integer"
+ }
+ }
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "updateIntervalSeconds": {
+ "type": "integer"
+ }
+ }
},
- "successThreshold": {
- "type": "integer",
- "title": "Success Threshold",
- "description": "Success threshold for liveness probe",
- "minimum": 1
+ "monitoring": {
+ "type": "object",
+ "properties": {
+ "resourceEventsEnabled": {
+ "type": "boolean"
+ },
+ "systemEventsEnabled": {
+ "type": "boolean"
+ }
+ }
}
- }
- },
- "readinessProbe": {
- "type": "object",
- "title": "Readiness Probe",
- "description": "Readiness probe configuration",
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable Readiness Probe",
- "description": "Enable readiness probe"
- },
- "initialDelaySeconds": {
- "type": "integer",
- "title": "Initial Delay Seconds",
- "description": "Initial delay seconds for readiness probe",
- "minimum": 0
- },
- "periodSeconds": {
- "type": "integer",
- "title": "Period Seconds",
- "description": "Period seconds for readiness probe",
- "minimum": 1
- },
- "timeoutSeconds": {
- "type": "integer",
- "title": "Timeout Seconds",
- "description": "Timeout seconds for readiness probe",
- "minimum": 1
+ }
+ },
+ "commonAnnotations": {
+ "type": "object"
+ },
+ "commonLabels": {
+ "type": "object"
+ },
+ "deployment": {
+ "type": "object",
+ "properties": {
+ "extraEnvVars": {
+ "type": "array"
},
- "failureThreshold": {
- "type": "integer",
- "title": "Failure Threshold",
- "description": "Failure threshold for readiness probe",
- "minimum": 1
+ "probes": {
+ "type": "object",
+ "properties": {
+ "livenessProbe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ }
+ }
+ },
+ "readinessProbe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ }
+ }
+ }
+ }
},
- "successThreshold": {
- "type": "integer",
- "title": "Success Threshold",
- "description": "Success threshold for readiness probe",
- "minimum": 1
+ "resources": {
+ "type": "object",
+ "properties": {
+ "limits": {
+ "type": "object",
+ "properties": {
+ "memory": {
+ "type": "string"
+ }
+ }
+ },
+ "requests": {
+ "type": "object",
+ "properties": {
+ "cpu": {
+ "type": "string"
+ },
+ "memory": {
+ "type": "string"
+ }
+ }
+ }
+ }
}
- }
}
- }
- }
- }
- },
- "clusterPirate": {
- "type": "object",
- "title": "ClusterPirate Application Configuration",
- "description": "ClusterPirate specific configuration",
- "properties": {
- "logLevel": {
- "type": "string",
- "title": "Log Level",
- "description": "Application logging level",
- "enum": [
- "debug",
- "info",
- "warn",
- "error",
- "fatal"
- ]
},
- "healthPort": {
- "type": "integer",
- "title": "Health Port",
- "description": "Health check server port",
- "minimum": 1,
- "maximum": 65535
+ "fullnameOverride": {
+ "type": "string"
},
- "metrics": {
- "type": "object",
- "title": "Metrics Configuration",
- "description": "Metrics collection configuration",
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable Metrics",
- "description": "Enable/disable metrics collection"
- },
- "updateIntervalSeconds": {
- "type": "integer",
- "title": "Update Interval",
- "description": "Interval in seconds for metrics updates",
- "minimum": 1
- },
- "cache": {
- "type": "object",
- "title": "Cache Configuration",
- "description": "Metrics caching configuration using Valkey",
- "properties": {
- "host": {
- "type": "string",
- "title": "Valkey Host",
- "description": "Valkey server hostname or IP address"
- },
- "port": {
- "type": "integer",
- "title": "Valkey Port",
- "description": "Valkey server port",
- "minimum": 1,
- "maximum": 65535
- },
- "password": {
- "type": "string",
- "title": "Valkey Password",
- "description": "Valkey authentication password"
+ "global": {
+ "type": "object",
+ "properties": {
+ "imagePullSecrets": {
+ "type": "array"
},
- "ttl": {
- "type": "integer",
- "title": "Cache TTL",
- "description": "Time-to-live for cached metrics in seconds",
- "minimum": 1
+ "imageRegistry": {
+ "type": "string"
}
- }
}
- }
},
- "monitoring": {
- "type": "object",
- "title": "Monitoring Configuration",
- "description": "Kubernetes resource monitoring configuration",
- "properties": {
- "resourceEventsEnabled": {
- "type": "boolean",
- "title": "Enable Resource Events",
- "description": "Enable monitoring of Kubernetes resources"
- },
- "systemEventsEnabled": {
- "type": "boolean",
- "title": "Enable System Events",
- "description": "Enable monitoring of Kubernetes system events"
+ "image": {
+ "type": "object",
+ "properties": {
+ "imagePullPolicy": {
+ "type": "string"
+ },
+ "registry": {
+ "type": "string"
+ },
+ "repository": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ }
}
- }
- }
- }
- },
- "cloudpiratesApi": {
- "type": "object",
- "title": "CloudPirates API Configuration",
- "description": "CloudPirates API settings",
- "properties": {
- "registerEndpoint": {
- "type": "string",
- "title": "Register Endpoint",
- "description": "API endpoint for cluster registration",
- "format": "uri"
- }
- }
- },
- "auth": {
- "type": "object",
- "title": "Authentication Configuration",
- "description": "Authentication settings",
- "properties": {
- "accessToken": {
- "type": "string",
- "title": "Access Token",
- "description": "Inline access token"
- },
- "existingSecret": {
- "type": "string",
- "title": "Existing Secret",
- "description": "Name of existing secret containing the access token"
},
- "existingSecretAccessTokenKey": {
- "type": "string",
- "title": "Existing Secret Access Token Key",
- "description": "Key within the existing secret that contains the access token"
- }
- }
- },
- "rbac": {
- "type": "object",
- "title": "RBAC Configuration",
- "description": "RBAC settings",
- "properties": {
- "create": {
- "type": "boolean",
- "title": "Create RBAC",
- "description": "Whether to create RBAC resources"
- }
- }
- },
- "serviceAccount": {
- "type": "object",
- "title": "Service Account Configuration",
- "description": "Service account settings",
- "properties": {
- "create": {
- "type": "boolean",
- "title": "Create Service Account",
- "description": "Whether to create a service account"
+ "nameOverride": {
+ "type": "string"
},
- "name": {
- "type": "string",
- "title": "Service Account Name",
- "description": "Name of the service account to create or use"
- }
- }
- },
- "valkey": {
- "type": "object",
- "title": "Valkey Configuration",
- "description": "Valkey dependency configuration",
- "additionalProperties": true,
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable Valkey",
- "description": "Enable/disable Valkey installation as a dependency"
+ "rbac": {
+ "type": "object",
+ "properties": {
+ "create": {
+ "type": "boolean"
+ }
+ }
},
- "persistence": {
- "type": "object",
- "title": "Valkey persistence settings",
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable persistence"
+ "serviceAccount": {
+ "type": "object",
+ "properties": {
+ "create": {
+ "type": "boolean"
+ },
+ "name": {
+ "type": "string"
+ }
}
- }
},
- "auth": {
- "type": "object",
- "title": "Valkey Authentication",
- "description": "Valkey authentication configuration",
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable Auth",
- "description": "Enable/disable password authentication for Valkey"
- },
- "password": {
- "type": "string",
- "title": "Password",
- "description": "Valkey password"
- },
- "existingSecret": {
- "type": "string",
- "title": "Existing Secret",
- "description": "Name of existing secret containing the Valkey password"
- },
- "existingSecretPasswordKey": {
- "type": "string",
- "title": "Existing Secret Password Key",
- "description": "Key within the existing secret that contains the password"
+ "valkey": {
+ "type": "object",
+ "properties": {
+ "auth": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "existingSecret": {
+ "type": "string"
+ },
+ "existingSecretPasswordKey": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ }
+ }
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "persistence": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ }
+ }
+ }
}
- }
}
- }
}
- }
-}
\ No newline at end of file
+}
diff --git a/charts/common/CHANGELOG.md b/charts/common/CHANGELOG.md
index 53edbc01..90cf3fd5 100644
--- a/charts/common/CHANGELOG.md
+++ b/charts/common/CHANGELOG.md
@@ -1,5 +1,24 @@
# Changelog
-## 1.1.1 (2025-10-09)
-* [mongodb] feat: add metrics exporter ([#243](https://github.com/CloudPirates-io/helm-charts/pull/243))
+## 2.0.0 (2025-10-14)
+
+* rename templates from common.* to cloudpirates.* to prevent collisions (#377) ([07c6560](https://github.com/CloudPirates-io/helm-charts/commit/07c6560))
+* chore: update CHANGELOG.md for merged changes ([84cf67b](https://github.com/CloudPirates-io/helm-charts/commit/84cf67b))
+* chore: update CHANGELOG.md for all charts via manual trigger ([6974964](https://github.com/CloudPirates-io/helm-charts/commit/6974964))
+
+## 1.1.2 (2025-10-10)
+
+* feat: add "common.namespace", defaults to .Release.Namespaceโฆ (#323) ([951745c](https://github.com/CloudPirates-io/helm-charts/commit/951745c))
+
+## 1.1.1 (2025-09-26)
+
+* apply intend where the helper is used (#168) ([efafd32](https://github.com/CloudPirates-io/helm-charts/commit/efafd32))
+
+## 1.1.0 (2025-09-26)
+
+* Fix/set securitycontext based on targetplatform to comply with openshift clusters (#166) ([f1bb75e](https://github.com/CloudPirates-io/helm-charts/commit/f1bb75e))
+
+## 1.0.0 (2025-08-26)
+
+* Initial tagged release
diff --git a/charts/common/Chart.yaml b/charts/common/Chart.yaml
index 7993fc38..214e4c76 100644
--- a/charts/common/Chart.yaml
+++ b/charts/common/Chart.yaml
@@ -2,14 +2,14 @@ apiVersion: v2
name: common
description: A library chart for common templates and helper functions
type: library
-version: 1.1.1
-appVersion: "1.0.0"
-
+version: 2.0.0
+appVersion: "2.0.0"
home: https://www.cloudpirates.io
-
sources:
- - https://github.com/CloudPirates-io/helm-charts/tree/main/charts/mariadb
-
+ - https://github.com/CloudPirates-io/helm-charts/tree/main/charts/common
maintainers:
- name: CloudPirates GmbH & Co. KG
+ email: hello@cloudpirates.io
url: https://www.cloudpirates.io
+annotations:
+ license: Apache-2.0
\ No newline at end of file
diff --git a/charts/common/templates/_helpers.tpl b/charts/common/templates/_helpers.tpl
index 4a37405a..005b0778 100644
--- a/charts/common/templates/_helpers.tpl
+++ b/charts/common/templates/_helpers.tpl
@@ -1,7 +1,7 @@
{{/*
Expand the name of the chart.
*/}}
-{{- define "common.name" -}}
+{{- define "cloudpirates.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
@@ -10,7 +10,7 @@ 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.fullname" -}}
+{{- define "cloudpirates.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
@@ -23,19 +23,28 @@ If release name contains chart name it will be used as a full name.
{{- end }}
{{- end }}
+{{/*
+Return the namespace to use for resources.
+Defaults to .Release.Namespace but can be overridden via .Values.namespaceOverride.
+Useful for multi-namespace deployments in combined charts.
+*/}}
+{{- define "cloudpirates.namespace" -}}
+{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
{{/*
Create chart name and version as used by the chart label.
*/}}
-{{- define "common.chart" -}}
+{{- define "cloudpirates.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
-{{- define "common.labels" -}}
-helm.sh/chart: {{ include "common.chart" . }}
-{{ include "common.selectorLabels" . }}
+{{- define "cloudpirates.labels" -}}
+helm.sh/chart: {{ include "cloudpirates.chart" . }}
+{{ include "cloudpirates.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
@@ -48,15 +57,15 @@ app.kubernetes.io/managed-by: {{ .Release.Service }}
{{/*
Selector labels
*/}}
-{{- define "common.selectorLabels" -}}
-app.kubernetes.io/name: {{ include "common.name" . }}
+{{- define "cloudpirates.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "cloudpirates.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Common annotations
*/}}
-{{- define "common.annotations" -}}
+{{- define "cloudpirates.annotations" -}}
{{- with .Values.commonAnnotations }}
{{ toYaml . }}
{{- end }}
@@ -65,7 +74,7 @@ Common annotations
{{/*
Return the proper image name with registry and tag (tag includes digest if present)
*/}}
-{{- define "common.image" -}}
+{{- define "cloudpirates.image" -}}
{{- $registryName := .image.registry -}}
{{- $repositoryName := .image.repository -}}
{{- $tag := .image.tag | toString -}}
@@ -84,14 +93,14 @@ Return the proper image name with registry and tag (tag includes digest if prese
{{/*
Return the proper image pull policy
*/}}
-{{- define "common.imagePullPolicy" -}}
+{{- define "cloudpirates.imagePullPolicy" -}}
{{- .image.imagePullPolicy | default .image.pullPolicy | default "Always" -}}
{{- end }}
{{/*
Return the proper Docker Image Registry Secret Names
*/}}
-{{- define "common.imagePullSecrets" -}}
+{{- define "cloudpirates.imagePullSecrets" -}}
{{- $pullSecrets := list }}
{{- if .global }}
@@ -127,7 +136,7 @@ imagePullSecrets:
{{/*
Validate required fields
*/}}
-{{- define "common.validateRequired" -}}
+{{- define "cloudpirates.validateRequired" -}}
{{- $context := index . 0 -}}
{{- $field := index . 1 -}}
{{- $message := index . 2 -}}
@@ -139,7 +148,7 @@ Validate required fields
{{/*
Return a soft nodeAffinity definition
*/}}
-{{- define "common.affinities.nodes.soft" -}}
+{{- define "cloudpirates.affinities.nodes.soft" -}}
{{- $key := index . 0 -}}
{{- $values := index . 1 -}}
preferredDuringSchedulingIgnoredDuringExecution:
@@ -157,7 +166,7 @@ preferredDuringSchedulingIgnoredDuringExecution:
{{/*
Return a hard nodeAffinity definition
*/}}
-{{- define "common.affinities.nodes.hard" -}}
+{{- define "cloudpirates.affinities.nodes.hard" -}}
{{- $key := index . 0 -}}
{{- $values := index . 1 -}}
requiredDuringSchedulingIgnoredDuringExecution:
@@ -174,13 +183,13 @@ requiredDuringSchedulingIgnoredDuringExecution:
{{/*
Return a soft podAffinity/podAntiAffinity definition
*/}}
-{{- define "common.affinities.pods.soft" -}}
+{{- define "cloudpirates.affinities.pods.soft" -}}
{{- $component := index . 0 -}}
{{- $context := index . 1 -}}
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
- matchLabels: {{- (include "common.selectorLabels" $context) | nindent 10 }}
+ matchLabels: {{- (include "cloudpirates.selectorLabels" $context) | nindent 10 }}
{{- if $component }}
app.kubernetes.io/component: {{ $component }}
{{- end }}
@@ -191,12 +200,12 @@ preferredDuringSchedulingIgnoredDuringExecution:
{{/*
Return a hard podAffinity/podAntiAffinity definition
*/}}
-{{- define "common.affinities.pods.hard" -}}
+{{- define "cloudpirates.affinities.pods.hard" -}}
{{- $component := index . 0 -}}
{{- $context := index . 1 -}}
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
- matchLabels: {{- (include "common.selectorLabels" $context) | nindent 8 }}
+ matchLabels: {{- (include "cloudpirates.selectorLabels" $context) | nindent 8 }}
{{- if $component }}
app.kubernetes.io/component: {{ $component }}
{{- end }}
@@ -206,7 +215,7 @@ requiredDuringSchedulingIgnoredDuringExecution:
{{/*
Render a value that contains template perhaps
*/}}
-{{- define "common.tplvalues.render" -}}
+{{- define "cloudpirates.tplvalues.render" -}}
{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }}
{{- if contains "{{" (toString $value) }}
{{- tpl $value .context }}
@@ -217,26 +226,26 @@ Render a value that contains template perhaps
{{/*
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" $) }}
+{{ include "cloudpirates.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }}
*/}}
-{{- define "common.images.renderPullSecrets" -}}
+{{- define "cloudpirates.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)) -}}
+ {{- $pullSecrets = append $pullSecrets (include "cloudpirates.tplvalues.render" (dict "value" .name "context" $context)) -}}
{{- else -}}
- {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}}
+ {{- $pullSecrets = append $pullSecrets (include "cloudpirates.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)) -}}
+ {{- $pullSecrets = append $pullSecrets (include "cloudpirates.tplvalues.render" (dict "value" .name "context" $context)) -}}
{{- else -}}
- {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}}
+ {{- $pullSecrets = append $pullSecrets (include "cloudpirates.tplvalues.render" (dict "value" . "context" $context)) -}}
{{- end -}}
{{- end -}}
{{- end -}}
@@ -251,9 +260,9 @@ imagePullSecrets:
{{/*
Detect if the target platform is OpenShift (via .Values.targetPlatform or API group).
-Usage: {{ include "common.isOpenshift" . }}
+Usage: {{ include "cloudpirates.isOpenshift" . }}
*/}}
-{{- define "common.isOpenshift" -}}
+{{- define "cloudpirates.isOpenshift" -}}
{{- if or (eq (lower (default "" .Values.targetPlatform)) "openshift") (.Capabilities.APIVersions.Has "route.openshift.io/v1") -}}
true
{{- else -}}
@@ -263,10 +272,10 @@ false
{{/*
Render podSecurityContext, omitting runAsUser, runAsGroup, fsGroup, and seLinuxOptions if OpenShift is detected.
-Usage: {{ include "common.renderPodSecurityContext" . }}
+Usage: {{ include "cloudpirates.renderPodSecurityContext" . }}
*/}}
-{{- define "common.renderPodSecurityContext" -}}
-{{- $isOpenshift := include "common.isOpenshift" . | trim }}
+{{- define "cloudpirates.renderPodSecurityContext" -}}
+{{- $isOpenshift := include "cloudpirates.isOpenshift" . | trim }}
{{- if eq $isOpenshift "true" }}
{{- omit .Values.podSecurityContext "runAsUser" "runAsGroup" "fsGroup" "seLinuxOptions" | toYaml }}
{{- else }}
@@ -276,10 +285,10 @@ Usage: {{ include "common.renderPodSecurityContext" . }}
{{/*
Render containerSecurityContext, omitting runAsUser, runAsGroup, and seLinuxOptions if OpenShift is detected.
-Usage: {{ include "common.renderContainerSecurityContext" . }}
+Usage: {{ include "cloudpirates.renderContainerSecurityContext" . }}
*/}}
-{{- define "common.renderContainerSecurityContext" -}}
-{{- $isOpenshift := include "common.isOpenshift" . | trim }}
+{{- define "cloudpirates.renderContainerSecurityContext" -}}
+{{- $isOpenshift := include "cloudpirates.isOpenshift" . | trim }}
{{- if eq $isOpenshift "true" }}
{{- omit .Values.containerSecurityContext "runAsUser" "runAsGroup" "seLinuxOptions" | toYaml }}
{{- else }}
diff --git a/charts/etcd/CHANGELOG.md b/charts/etcd/CHANGELOG.md
new file mode 100644
index 00000000..24884370
--- /dev/null
+++ b/charts/etcd/CHANGELOG.md
@@ -0,0 +1,58 @@
+# Changelog
+
+
+## 0.3.1 (2025-10-28)
+
+* [etcd, rabbitmq, redis, zookeeper] add signature verification documentation to readme (#476) ([91c7310](https://github.com/CloudPirates-io/helm-charts/commit/91c7310))
+* chore: update CHANGELOG.md for merged changes ([8260788](https://github.com/CloudPirates-io/helm-charts/commit/8260788))
+* chore: update CHANGELOG.md for merged changes ([402f7bd](https://github.com/CloudPirates-io/helm-charts/commit/402f7bd))
+
+## 0.3.0 (2025-10-28)
+
+* chore: update CHANGELOG.md for merged changes ([f9c3ff0](https://github.com/CloudPirates-io/helm-charts/commit/f9c3ff0))
+* chore: update CHANGELOG.md for merged changes ([db2d800](https://github.com/CloudPirates-io/helm-charts/commit/db2d800))
+
+## 0.2.3 (2025-10-23)
+
+* chore: update CHANGELOG.md for merged changes ([051ad83](https://github.com/CloudPirates-io/helm-charts/commit/051ad83))
+* chore: update CHANGELOG.md for merged changes ([1a50307](https://github.com/CloudPirates-io/helm-charts/commit/1a50307))
+
+## 0.2.2 (2025-10-22)
+
+* chore: update CHANGELOG.md for merged changes ([c80ea42](https://github.com/CloudPirates-io/helm-charts/commit/c80ea42))
+* chore: update CHANGELOG.md for merged changes ([8ccb4bb](https://github.com/CloudPirates-io/helm-charts/commit/8ccb4bb))
+* chore: update CHANGELOG.md for merged changes ([5d1f01a](https://github.com/CloudPirates-io/helm-charts/commit/5d1f01a))
+* chore: update CHANGELOG.md for merged changes ([fc47c5d](https://github.com/CloudPirates-io/helm-charts/commit/fc47c5d))
+* chore: update CHANGELOG.md for merged changes ([1a4f87b](https://github.com/CloudPirates-io/helm-charts/commit/1a4f87b))
+* chore: update CHANGELOG.md for merged changes ([da866ca](https://github.com/CloudPirates-io/helm-charts/commit/da866ca))
+* chore: update CHANGELOG.md for merged changes ([b54c4f1](https://github.com/CloudPirates-io/helm-charts/commit/b54c4f1))
+* chore: update CHANGELOG.md for merged changes ([5a2ed20](https://github.com/CloudPirates-io/helm-charts/commit/5a2ed20))
+* chore: update CHANGELOG.md for merged changes ([3361964](https://github.com/CloudPirates-io/helm-charts/commit/3361964))
+* chore: update CHANGELOG.md for merged changes ([7f61172](https://github.com/CloudPirates-io/helm-charts/commit/7f61172))
+* chore: update CHANGELOG.md for merged changes ([c9ff4ec](https://github.com/CloudPirates-io/helm-charts/commit/c9ff4ec))
+* chore: update CHANGELOG.md for merged changes ([86f1d25](https://github.com/CloudPirates-io/helm-charts/commit/86f1d25))
+
+## 0.2.0 (2025-10-14)
+
+* Update chart.yaml dependencies for indepentent charts (#382) ([87acfb1](https://github.com/CloudPirates-io/helm-charts/commit/87acfb1))
+* chore: update CHANGELOG.md for merged changes ([84cf67b](https://github.com/CloudPirates-io/helm-charts/commit/84cf67b))
+* chore: update CHANGELOG.md for all charts via manual trigger ([6974964](https://github.com/CloudPirates-io/helm-charts/commit/6974964))
+* chore: update CHANGELOG.md for merged changes ([63b7bfa](https://github.com/CloudPirates-io/helm-charts/commit/63b7bfa))
+* chore: update CHANGELOG.md for merged changes ([da69e0e](https://github.com/CloudPirates-io/helm-charts/commit/da69e0e))
+* chore: update CHANGELOG.md for merged changes ([5da1b15](https://github.com/CloudPirates-io/helm-charts/commit/5da1b15))
+
+## 0.1.3 (2025-10-13)
+
+
+## 0.1.2 (2025-10-13)
+
+* update helm-chart icon (#360) ([6544ddf](https://github.com/CloudPirates-io/helm-charts/commit/6544ddf))
+
+## 0.1.1 (2025-10-10)
+
+* artifact hub repository id (#333) ([36ca7c7](https://github.com/CloudPirates-io/helm-charts/commit/36ca7c7))
+* [etcd]: Invalid repo used (#331) ([92617cf](https://github.com/CloudPirates-io/helm-charts/commit/92617cf))
+
+## 0.1.0 (2025-10-10)
+
+* Initial tagged release
diff --git a/charts/etcd/Chart.lock b/charts/etcd/Chart.lock
new file mode 100644
index 00000000..5658cae6
--- /dev/null
+++ b/charts/etcd/Chart.lock
@@ -0,0 +1,6 @@
+dependencies:
+- name: common
+ repository: oci://registry-1.docker.io/cloudpirates
+ version: 2.0.0
+digest: sha256:ae9378e0dcfd09a35b7f994007db99c2d6fe02ef7634f424d5233237c209a1c7
+generated: "2025-10-14T11:14:03.850244+02:00"
diff --git a/charts/etcd/Chart.yaml b/charts/etcd/Chart.yaml
new file mode 100644
index 00000000..ba6e8cf2
--- /dev/null
+++ b/charts/etcd/Chart.yaml
@@ -0,0 +1,47 @@
+apiVersion: v2
+name: etcd
+description: etcd is a distributed reliable key-value store for the most critical data of a distributed system
+type: application
+version: 0.3.1
+appVersion: "3.6.5"
+keywords:
+ - etcd
+ - distributed
+ - key-value
+ - consensus
+ - raft
+home: https://etcd.io/
+sources:
+ - https://github.com/CloudPirates-io/helm-charts/tree/main/charts/mariadb
+ - https://github.com/etcd-io/etcd
+maintainers:
+ - name: CloudPirates GmbH & Co. KG
+ email: hello@cloudpirates.io
+ url: https://www.cloudpirates.io
+dependencies:
+ - name: common
+ version: "2.x.x"
+ repository: oci://registry-1.docker.io/cloudpirates
+icon: https://a.storyblok.com/f/143071/513x513/36b7a72378/etcd-logo.svg
+annotations:
+ license: Apache-2.0
+ artifacthub.io/category: database
+ artifacthub.io/containsSecurityUpdates: "false"
+ artifacthub.io/signKey: |
+ fingerprint: 6917f1a88c122cbb1de5aa55457752135bdcf95a
+ url: https://raw.githubusercontent.com/CloudPirates-io/helm-charts/refs/heads/main/cosign.pub
+ artifacthub.io/links: |
+ - name: etcd
+ url: https://etcd.io/
+ - name: Helm Chart
+ url: https://github.com/CloudPirates-io/helm-charts/tree/main/charts/mariadb
+ - name: Application
+ url: https://github.com/etcd-io/etcd
+ - name: Maintainer CloudPirates
+ url: https://www.cloudpirates.io
+ artifacthub.io/changes: |2
+ - kind: changed
+ description: "[etcd, rabbitmq, redis, zookeeper] add signature verification documentation to readme (#476)"
+ links:
+ - name: "Commit 91c7310"
+ url: "https://github.com/CloudPirates-io/helm-charts/commit/91c7310"
diff --git a/charts/etcd/LICENSE b/charts/etcd/LICENSE
new file mode 100644
index 00000000..261eeb9e
--- /dev/null
+++ b/charts/etcd/LICENSE
@@ -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.
diff --git a/charts/etcd/README.md b/charts/etcd/README.md
new file mode 100644
index 00000000..ec71a223
--- /dev/null
+++ b/charts/etcd/README.md
@@ -0,0 +1,284 @@
+
+
+
+
+# etcd Helm Chart
+
+etcd is a distributed reliable key-value store for the most critical data of a distributed system, with a focus on being simple, secure, fast, and reliable.
+
+## Quick Start
+
+### Prerequisites
+
+- Kubernetes 1.24+
+- Helm 3.2.0+
+- PV provisioner support in the underlying infrastructure (if persistence is enabled)
+
+### Installation
+
+To install the chart with the release name `my-etcd`:
+
+```bash
+helm install my-etcd oci://registry-1.docker.io/cloudpirates/etcd
+```
+
+To install with custom values:
+
+```bash
+helm install my-etcd oci://registry-1.docker.io/cloudpirates/etcd -f my-values.yaml
+```
+
+Or install directly from the local chart:
+
+```bash
+helm install my-etcd ./charts/etcd
+```
+
+### Getting Started
+
+1. Check the status of your etcd cluster:
+
+```bash
+kubectl exec -it my-etcd-0 -- etcdctl \
+ --endpoints=my-etcd:2379 \
+ endpoint health
+```
+
+2. Connect to etcd from inside the cluster:
+
+```bash
+kubectl run etcd-client --rm --tty -i --restart='Never' \
+ --image gcr.io/etcd-development/etcd:v3.6.0-alpha.0 -- bash
+
+# Inside the pod:
+etcdctl --endpoints=my-etcd:2379 endpoint status --write-out=table
+```
+
+## Security & Signature Verification
+
+This Helm chart is cryptographically signed with Cosign to ensure authenticity and prevent tampering.
+
+**Public Key:**
+
+```
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7BgqFgKdPtHdXz6OfYBklYwJgGWQ
+mZzYz8qJ9r6QhF3NxK8rD2oG7Bk6nHJz7qWXhQoU2JvJdI3Zx9HGpLfKvw==
+-----END PUBLIC KEY-----
+```
+
+To verify the helm chart before installation, copy the public key to the file `cosign.pub` and run cosign:
+
+```bash
+cosign verify --key cosign.pub registry-1.docker.io/cloudpirates/etcd:
+```
+
+## Configuration
+
+### Image Configuration
+
+| Parameter | Description | Default |
+| ------------------------- | ------------------------------------- | ----------------------- |
+| `image.registry` | etcd image registry | `gcr.io` |
+| `image.repository` | etcd image repository | `etcd-development/etcd` |
+| `image.tag` | etcd image tag | `v3.6.0-alpha.0` |
+| `image.pullPolicy` | Image pull policy | `IfNotPresent` |
+| `global.imageRegistry` | Global Docker image registry override | `""` |
+| `global.imagePullSecrets` | Global Docker registry secret names | `[]` |
+
+### Common Parameters
+
+| Parameter | Description | Default |
+| ------------------- | ----------------------------------------------- | ------- |
+| `nameOverride` | String to partially override etcd.fullname | `""` |
+| `fullnameOverride` | String to fully override etcd.fullname | `""` |
+| `commonLabels` | Labels to add to all deployed objects | `{}` |
+| `commonAnnotations` | Annotations to add to all deployed objects | `{}` |
+| `replicaCount` | Number of etcd replicas to deploy (must be odd) | `3` |
+| `podLabels` | Additional labels for etcd pods | `{}` |
+| `podAnnotations` | Additional annotations for etcd pods | `{}` |
+
+### Service Configuration
+
+| Parameter | Description | Default |
+| --------------------- | ----------------------- | ----------- |
+| `service.type` | Kubernetes service type | `ClusterIP` |
+| `service.annotations` | Service annotations | `{}` |
+| `service.clientPort` | etcd client port | `2379` |
+| `service.peerPort` | etcd peer port | `2380` |
+| `service.metricsPort` | etcd metrics port | `2381` |
+
+### Authentication and Security
+
+| Parameter | Description | Default |
+| -------------------------- | ------------------------------------------------------ | ------- |
+| `auth.enabled` | Enable client-to-server TLS authentication | `false` |
+| `auth.existingSecret` | Name of existing secret containing client certificates | `""` |
+| `auth.peer.enabled` | Enable peer-to-peer TLS authentication | `false` |
+| `auth.peer.existingSecret` | Name of existing secret containing peer certificates | `""` |
+
+### etcd Configuration
+
+| Parameter | Description | Default |
+| -------------------------------- | -------------------------------------------------- | -------------- |
+| `config.initialClusterState` | Initial cluster state (new or existing) | `new` |
+| `config.autoCompactionMode` | Auto compaction mode (periodic or revision) | `periodic` |
+| `config.autoCompactionRetention` | Auto compaction retention | `1` |
+| `config.snapshotCount` | Number of transactions to trigger a snapshot | `10000` |
+| `config.quotaBackendBytes` | Backend storage quota in bytes (2GB) | `2147483648` |
+| `config.maxRequestBytes` | Maximum client request size in bytes | `1572864` |
+| `config.logLevel` | Log level (debug, info, warn, error, panic, fatal) | `info` |
+| `config.initialClusterToken` | Initial cluster token | `etcd-cluster` |
+| `config.heartbeatInterval` | Heartbeat interval in milliseconds | `100` |
+| `config.electionTimeout` | Election timeout in milliseconds | `1000` |
+| `config.maxSnapshots` | Maximum number of snapshot files to retain | `5` |
+| `config.maxWals` | Maximum number of WAL files to retain | `5` |
+| `config.listenPeerIp` | IP address to bind for peer traffic | `0.0.0.0` |
+| `config.listenClientIp` | IP address to bind for client traffic | `0.0.0.0` |
+
+### Persistence
+
+| Parameter | Description | Default |
+| -------------------------- | ------------------------------ | ----------------- |
+| `persistence.enabled` | Enable persistence using PVC | `true` |
+| `persistence.storageClass` | Storage class of backing PVC | `""` |
+| `persistence.annotations` | Annotations for the PVC | `{}` |
+| `persistence.size` | Size of data volume | `8Gi` |
+| `persistence.accessModes` | Persistent Volume Access Modes | `[ReadWriteOnce]` |
+| `persistence.mountPath` | Mount path for data volume | `/var/run/etcd` |
+
+### Resources
+
+| Parameter | Description | Default |
+| ----------- | ----------------------------------- | ------- |
+| `resources` | CPU/Memory resource requests/limits | `{}` |
+
+### StatefulSet Configuration
+
+| Parameter | Description | Default |
+| --------------------- | --------------------------- | --------------- |
+| `updateStrategy.type` | StatefulSet update strategy | `RollingUpdate` |
+
+### Metrics Configuration
+
+| Parameter | Description | Default |
+| ------------------------------------------ | --------------------------------------------- | ------- |
+| `metrics.enabled` | Enable Prometheus metrics | `true` |
+| `metrics.serviceMonitor.enabled` | Create ServiceMonitor for Prometheus Operator | `false` |
+| `metrics.serviceMonitor.namespace` | Namespace for ServiceMonitor | `""` |
+| `metrics.serviceMonitor.interval` | Scrape interval | `30s` |
+| `metrics.serviceMonitor.scrapeTimeout` | Scrape timeout | `""` |
+| `metrics.serviceMonitor.relabelings` | Relabel configurations | `[]` |
+| `metrics.serviceMonitor.metricRelabelings` | Metric relabel configurations | `[]` |
+| `metrics.serviceMonitor.labels` | Additional labels for ServiceMonitor | `{}` |
+| `metrics.serviceMonitor.honorLabels` | Honor labels from metrics | `false` |
+
+### High Availability
+
+| Parameter | Description | Default |
+| ------------------------------------ | ---------------------------------- | ------- |
+| `podDisruptionBudget.enabled` | Enable PodDisruptionBudget | `false` |
+| `podDisruptionBudget.minAvailable` | Minimum number of available pods | `""` |
+| `podDisruptionBudget.maxUnavailable` | Maximum number of unavailable pods | `1` |
+
+### Service Account
+
+| Parameter | Description | Default |
+| --------------------------------------------- | ------------------------------- | ------- |
+| `serviceAccount.create` | Create service account | `true` |
+| `serviceAccount.name` | Service account name | `""` |
+| `serviceAccount.annotations` | Service account annotations | `{}` |
+| `serviceAccount.automountServiceAccountToken` | Automount service account token | `false` |
+
+### Network Policy
+
+| Parameter | Description | Default |
+| ----------------------------- | ------------------------ | ------- |
+| `networkPolicy.enabled` | Enable NetworkPolicy | `false` |
+| `networkPolicy.allowExternal` | Allow external traffic | `true` |
+| `networkPolicy.extraIngress` | Additional ingress rules | `[]` |
+| `networkPolicy.extraEgress` | Additional egress rules | `[]` |
+
+### Security Context
+
+| Parameter | Description | Default |
+| --------------------------------------------------- | ---------------------------------- | ------- |
+| `containerSecurityContext.runAsUser` | User ID to run the container | `1000` |
+| `containerSecurityContext.runAsGroup` | Group ID to run the container | `1000` |
+| `containerSecurityContext.runAsNonRoot` | Run as non-root user | `true` |
+| `containerSecurityContext.allowPrivilegeEscalation` | Allow privilege escalation | `false` |
+| `containerSecurityContext.readOnlyRootFilesystem` | Mount root filesystem as read-only | `true` |
+| `containerSecurityContext.capabilities.drop` | Linux capabilities to drop | `[ALL]` |
+| `podSecurityContext.fsGroup` | Group ID for the volumes | `1000` |
+
+### Probes
+
+| Parameter | Description | Default |
+| ------------------------------------ | ------------------------------------- | ------- |
+| `startupProbe.enabled` | Enable startup probe | `true` |
+| `startupProbe.initialDelaySeconds` | Initial delay for startup probe | `0` |
+| `startupProbe.periodSeconds` | Period for startup probe | `10` |
+| `startupProbe.timeoutSeconds` | Timeout for startup probe | `5` |
+| `startupProbe.failureThreshold` | Failure threshold for startup probe | `30` |
+| `livenessProbe.enabled` | Enable liveness probe | `true` |
+| `livenessProbe.initialDelaySeconds` | Initial delay for liveness probe | `10` |
+| `livenessProbe.periodSeconds` | Period for liveness probe | `10` |
+| `livenessProbe.timeoutSeconds` | Timeout for liveness probe | `5` |
+| `livenessProbe.failureThreshold` | Failure threshold for liveness probe | `3` |
+| `readinessProbe.enabled` | Enable readiness probe | `true` |
+| `readinessProbe.initialDelaySeconds` | Initial delay for readiness probe | `5` |
+| `readinessProbe.periodSeconds` | Period for readiness probe | `10` |
+| `readinessProbe.timeoutSeconds` | Timeout for readiness probe | `5` |
+| `readinessProbe.failureThreshold` | Failure threshold for readiness probe | `3` |
+
+### Scheduling
+
+| Parameter | Description | Default |
+| --------------------------- | ------------------------------------ | ------- |
+| `nodeSelector` | Node labels for pod assignment | `{}` |
+| `tolerations` | Tolerations for pod assignment | `[]` |
+| `affinity` | Affinity rules for pod assignment | `{}` |
+| `topologySpreadConstraints` | Topology Spread Constraints | `[]` |
+| `priorityClassName` | Priority class name for pod eviction | `""` |
+
+### Extra Configuration
+
+| Parameter | Description | Default |
+| ------------------- | ------------------------------------------------- | ------- |
+| `extraArgs` | Additional etcd command line arguments | `[]` |
+| `extraEnvVars` | Additional environment variables | `[]` |
+| `extraVolumes` | Additional volumes to add to the pod | `[]` |
+| `extraVolumeMounts` | Additional volume mounts for etcd container | `[]` |
+| `extraObjects` | Array of extra objects to deploy with the release | `[]` |
+
+## Upgrading
+
+To upgrade your release:
+
+```bash
+helm upgrade my-etcd oci://registry-1.docker.io/cloudpirates/etcd
+```
+
+## Uninstalling
+
+To uninstall/delete the `my-etcd` deployment:
+
+```bash
+helm delete my-etcd
+```
+
+## License
+
+Copyright ยฉ 2024 CloudPirates GmbH & Co. KG
+
+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.
diff --git a/charts/etcd/artifacthub-repo.yml b/charts/etcd/artifacthub-repo.yml
new file mode 100644
index 00000000..3b8407ed
--- /dev/null
+++ b/charts/etcd/artifacthub-repo.yml
@@ -0,0 +1 @@
+repositoryID: 229cfa80-872a-4900-ad74-d9d1252e8214
\ No newline at end of file
diff --git a/charts/etcd/templates/_helpers.tpl b/charts/etcd/templates/_helpers.tpl
new file mode 100644
index 00000000..cf373e9f
--- /dev/null
+++ b/charts/etcd/templates/_helpers.tpl
@@ -0,0 +1,93 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "etcd.name" -}}
+{{- include "cloudpirates.name" . -}}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+*/}}
+{{- define "etcd.fullname" -}}
+{{- include "cloudpirates.fullname" . -}}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "etcd.chart" -}}
+{{- include "cloudpirates.chart" . -}}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "etcd.labels" -}}
+{{- include "cloudpirates.labels" . }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "etcd.selectorLabels" -}}
+{{- include "cloudpirates.selectorLabels" . -}}
+{{- end }}
+
+{{/*
+Common annotations
+*/}}
+{{- define "etcd.annotations" -}}
+{{- include "cloudpirates.annotations" . -}}
+{{- end }}
+
+{{/*
+Return the proper etcd image name
+*/}}
+{{- define "etcd.image" -}}
+{{- include "cloudpirates.image" (dict "image" .Values.image "global" .Values.global) -}}
+{{- end }}
+
+{{/*
+Return the proper Docker Image Registry Secret Names
+*/}}
+{{- define "etcd.imagePullSecrets" -}}
+{{ include "cloudpirates.images.renderPullSecrets" (dict "images" (list .Values.image) "context" .) }}
+{{- end -}}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "etcd.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "etcd.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
+
+{{/*
+Validate etcd values
+*/}}
+{{- define "etcd.validateValues" -}}
+{{- $replicaCount := int .Values.replicaCount }}
+{{- if and (gt $replicaCount 1) (eq (mod $replicaCount 2) 0) }}
+{{- fail (printf "etcd: Invalid replica count. etcd requires an odd number of replicas for quorum (e.g., 1, 3, 5, 7). Current value: %d" $replicaCount) }}
+{{- end }}
+{{- end }}
+
+{{/*
+Generate etcd initial cluster string
+*/}}
+{{- define "etcd.initialCluster" -}}
+{{- $namespace := .Release.Namespace }}
+{{- $name := include "etcd.fullname" . -}}
+{{- $peerPort := .Values.service.peerPort -}}
+{{- $replicaCount := int .Values.replicaCount }}
+{{- $protocol := "http" }}
+{{- if .Values.auth.peer.enabled }}
+{{- $protocol = "https" }}
+{{- end }}
+{{- range $i := until $replicaCount }}
+{{- if $i }},{{ end -}}{{ $name }}-{{ $i }}={{ $protocol }}://{{ $name }}-{{ $i }}.{{ $name }}-headless.{{ $namespace }}.svc.cluster.local:{{ $peerPort }}
+{{- end }}
+{{- end }}
diff --git a/charts/etcd/templates/extraobjects.yaml b/charts/etcd/templates/extraobjects.yaml
new file mode 100644
index 00000000..d12e6cc6
--- /dev/null
+++ b/charts/etcd/templates/extraobjects.yaml
@@ -0,0 +1,4 @@
+{{- range .Values.extraObjects }}
+---
+{{- include "cloudpirates.tplvalues.render" (dict "value" . "context" $) }}
+{{- end }}
diff --git a/charts/etcd/templates/networkpolicy.yaml b/charts/etcd/templates/networkpolicy.yaml
new file mode 100644
index 00000000..01809f68
--- /dev/null
+++ b/charts/etcd/templates/networkpolicy.yaml
@@ -0,0 +1,72 @@
+{{- if .Values.networkPolicy.enabled }}
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+metadata:
+ name: {{ include "etcd.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "etcd.labels" . | nindent 4 }}
+ {{- with (include "etcd.annotations" .) }}
+ annotations:
+{{- . | indent 4 }}
+ {{- end }}
+spec:
+ podSelector:
+ matchLabels:
+ {{- include "etcd.selectorLabels" . | nindent 6 }}
+ policyTypes:
+ - Ingress
+ - Egress
+ ingress:
+ # Allow client connections
+ - ports:
+ - port: {{ .Values.service.clientPort }}
+ protocol: TCP
+ {{- if not .Values.networkPolicy.allowExternal }}
+ from:
+ - podSelector:
+ matchLabels: {}
+ {{- end }}
+ # Allow peer connections
+ - ports:
+ - port: {{ .Values.service.peerPort }}
+ protocol: TCP
+ from:
+ - podSelector:
+ matchLabels:
+ {{- include "etcd.selectorLabels" . | nindent 14 }}
+ {{- if .Values.metrics.enabled }}
+ # Allow metrics scraping
+ - ports:
+ - port: {{ .Values.service.metricsPort }}
+ protocol: TCP
+ {{- if not .Values.networkPolicy.allowExternal }}
+ from:
+ - namespaceSelector: {}
+ podSelector:
+ matchLabels:
+ app.kubernetes.io/name: prometheus
+ {{- end }}
+ {{- end }}
+ {{- with .Values.networkPolicy.extraIngress }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ egress:
+ # Allow DNS resolution
+ - ports:
+ - port: 53
+ protocol: UDP
+ - port: 53
+ protocol: TCP
+ # Allow etcd peer communication
+ - ports:
+ - port: {{ .Values.service.peerPort }}
+ protocol: TCP
+ to:
+ - podSelector:
+ matchLabels:
+ {{- include "etcd.selectorLabels" . | nindent 14 }}
+ {{- with .Values.networkPolicy.extraEgress }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/charts/etcd/templates/poddisruptionbudget.yaml b/charts/etcd/templates/poddisruptionbudget.yaml
new file mode 100644
index 00000000..fd8b6f80
--- /dev/null
+++ b/charts/etcd/templates/poddisruptionbudget.yaml
@@ -0,0 +1,23 @@
+{{- if .Values.podDisruptionBudget.enabled }}
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+ name: {{ include "etcd.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "etcd.labels" . | nindent 4 }}
+ {{- with (include "etcd.annotations" .) }}
+ annotations:
+{{- . | indent 4 }}
+ {{- end }}
+spec:
+ {{- if .Values.podDisruptionBudget.minAvailable }}
+ minAvailable: {{ .Values.podDisruptionBudget.minAvailable | quote }}
+ {{- end }}
+ {{- if .Values.podDisruptionBudget.maxUnavailable }}
+ maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "etcd.selectorLabels" . | nindent 6 }}
+{{- end }}
diff --git a/charts/etcd/templates/service.yaml b/charts/etcd/templates/service.yaml
new file mode 100644
index 00000000..bcb2ace0
--- /dev/null
+++ b/charts/etcd/templates/service.yaml
@@ -0,0 +1,52 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "etcd.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "etcd.labels" . | nindent 4 }}
+ {{- if or (include "etcd.annotations" .) .Values.service.annotations }}
+ annotations:
+{{- (include "etcd.annotations" .) | indent 4 }}
+{{- if .Values.service.annotations }}
+{{ toYaml .Values.service.annotations | indent 4 }}
+{{- end }}
+ {{- end }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.clientPort | default 2379 }}
+ targetPort: client
+ protocol: TCP
+ name: client
+ {{- if .Values.metrics.enabled }}
+ - port: {{ .Values.service.metricsPort | default 2381 }}
+ targetPort: metrics
+ protocol: TCP
+ name: metrics
+ {{- end }}
+ selector:
+ {{- include "etcd.selectorLabels" . | nindent 4 }}
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "etcd.fullname" . }}-headless
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "etcd.labels" . | nindent 4 }}
+spec:
+ type: ClusterIP
+ clusterIP: None
+ publishNotReadyAddresses: true
+ ports:
+ - port: {{ .Values.service.clientPort | default 2379 }}
+ targetPort: client
+ protocol: TCP
+ name: client
+ - port: {{ .Values.service.peerPort | default 2380 }}
+ targetPort: peer
+ protocol: TCP
+ name: peer
+ selector:
+ {{- include "etcd.selectorLabels" . | nindent 4 }}
diff --git a/charts/etcd/templates/serviceaccount.yaml b/charts/etcd/templates/serviceaccount.yaml
new file mode 100644
index 00000000..12c30577
--- /dev/null
+++ b/charts/etcd/templates/serviceaccount.yaml
@@ -0,0 +1,17 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "etcd.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "etcd.labels" . | nindent 4 }}
+ {{- if or (include "etcd.annotations" .) .Values.serviceAccount.annotations }}
+ annotations:
+{{- (include "etcd.annotations" .) | indent 4 }}
+{{- if .Values.serviceAccount.annotations }}
+{{- toYaml .Values.serviceAccount.annotations | nindent 4 }}
+{{- end }}
+ {{- end }}
+automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
+{{- end }}
diff --git a/charts/etcd/templates/servicemonitor.yaml b/charts/etcd/templates/servicemonitor.yaml
new file mode 100644
index 00000000..6a45ab30
--- /dev/null
+++ b/charts/etcd/templates/servicemonitor.yaml
@@ -0,0 +1,42 @@
+{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+ name: {{ include "etcd.fullname" . }}
+ namespace: {{ default .Release.Namespace .Values.metrics.serviceMonitor.namespace }}
+ labels:
+ {{- include "etcd.labels" . | nindent 4 }}
+ {{- with .Values.metrics.serviceMonitor.labels }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with (include "etcd.annotations" .) }}
+ annotations:
+{{- . | indent 4 }}
+ {{- end }}
+spec:
+ selector:
+ matchLabels:
+ {{- include "etcd.selectorLabels" . | nindent 6 }}
+ endpoints:
+ - port: metrics
+ {{- if .Values.metrics.serviceMonitor.interval }}
+ interval: {{ .Values.metrics.serviceMonitor.interval }}
+ {{- end }}
+ {{- if .Values.metrics.serviceMonitor.scrapeTimeout }}
+ scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }}
+ {{- end }}
+ {{- with .Values.metrics.serviceMonitor.relabelings }}
+ relabelings:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.metrics.serviceMonitor.metricRelabelings }}
+ metricRelabelings:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- if .Values.metrics.serviceMonitor.honorLabels }}
+ honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }}
+ {{- end }}
+ namespaceSelector:
+ matchNames:
+ - {{ .Release.Namespace }}
+{{- end }}
diff --git a/charts/etcd/templates/statefulset.yaml b/charts/etcd/templates/statefulset.yaml
new file mode 100644
index 00000000..67d97881
--- /dev/null
+++ b/charts/etcd/templates/statefulset.yaml
@@ -0,0 +1,241 @@
+{{- include "etcd.validateValues" . }}
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: {{ include "etcd.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "etcd.labels" . | nindent 4 }}
+ {{- with (include "etcd.annotations" .) }}
+ annotations:
+ {{- . | nindent 4 }}
+ {{- end }}
+spec:
+ serviceName: {{ include "etcd.fullname" . }}-headless
+ replicas: {{ .Values.replicaCount }}
+ podManagementPolicy: Parallel
+ {{- if .Values.updateStrategy }}
+ updateStrategy: {{- toYaml .Values.updateStrategy | nindent 4 }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "etcd.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ labels:
+ {{- include "etcd.selectorLabels" . | nindent 8 }}
+ {{- with .Values.podLabels }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- if or (include "etcd.annotations" .) .Values.podAnnotations }}
+ annotations:
+ {{- with (include "etcd.annotations" .) }}
+ {{- . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- end }}
+ spec:
+{{- with (include "etcd.imagePullSecrets" .) }}
+{{ . | nindent 6 }}
+{{- end }}
+ serviceAccountName: {{ include "etcd.serviceAccountName" . }}
+ securityContext: {{ include "cloudpirates.renderPodSecurityContext" . | nindent 8 }}
+ containers:
+ - name: {{ .Chart.Name }}
+ securityContext: {{ include "cloudpirates.renderContainerSecurityContext" . | nindent 12 }}
+ image: {{ include "etcd.image" . | quote }}
+ imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" | quote }}
+ command:
+ - /usr/local/bin/etcd
+ args:
+ - --name=$(POD_NAME)
+ - --listen-peer-urls={{ if .Values.auth.peer.enabled }}https{{ else }}http{{ end }}://{{ .Values.config.listenPeerIp }}:{{ .Values.service.peerPort }}
+ - --listen-client-urls={{ if .Values.auth.enabled }}https{{ else }}http{{ end }}://{{ .Values.config.listenClientIp }}:{{ .Values.service.clientPort }}
+ - --advertise-client-urls={{ if .Values.auth.enabled }}https{{ else }}http{{ end }}://$(POD_NAME).{{ include "etcd.fullname" . }}-headless.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.clientPort }}
+ - --initial-advertise-peer-urls={{ if .Values.auth.peer.enabled }}https{{ else }}http{{ end }}://$(POD_NAME).{{ include "etcd.fullname" . }}-headless.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.peerPort }}
+ - --initial-cluster={{ include "etcd.initialCluster" . }}
+ - --initial-cluster-token={{ .Values.config.initialClusterToken }}
+ - --initial-cluster-state={{ .Values.config.initialClusterState }}
+ - --data-dir={{ .Values.persistence.mountPath }}/default.etcd
+ - --auto-compaction-mode={{ .Values.config.autoCompactionMode }}
+ - --auto-compaction-retention={{ .Values.config.autoCompactionRetention }}
+ - --snapshot-count={{ .Values.config.snapshotCount | int64 }}
+ - --quota-backend-bytes={{ .Values.config.quotaBackendBytes | int64 }}
+ - --max-request-bytes={{ .Values.config.maxRequestBytes | int64 }}
+ - --heartbeat-interval={{ .Values.config.heartbeatInterval }}
+ - --election-timeout={{ .Values.config.electionTimeout }}
+ - --max-snapshots={{ .Values.config.maxSnapshots }}
+ - --max-wals={{ .Values.config.maxWals }}
+ - --log-level={{ .Values.config.logLevel }}
+ {{- if .Values.auth.enabled }}
+ - --client-cert-auth
+ - --trusted-ca-file=/etc/etcd/certs/client/ca.crt
+ - --cert-file=/etc/etcd/certs/client/tls.crt
+ - --key-file=/etc/etcd/certs/client/tls.key
+ {{- end }}
+ {{- if .Values.auth.peer.enabled }}
+ - --peer-client-cert-auth
+ - --peer-trusted-ca-file=/etc/etcd/certs/peer/ca.crt
+ - --peer-cert-file=/etc/etcd/certs/peer/tls.crt
+ - --peer-key-file=/etc/etcd/certs/peer/tls.key
+ {{- end }}
+ {{- if .Values.metrics.enabled }}
+ - --listen-metrics-urls=http://{{ .Values.config.listenClientIp }}:{{ .Values.service.metricsPort }}
+ {{- end }}
+ {{- range .Values.extraArgs }}
+ - {{ . }}
+ {{- end }}
+ ports:
+ - name: client
+ containerPort: {{ .Values.service.clientPort | default 2379 }}
+ protocol: TCP
+ - name: peer
+ containerPort: {{ .Values.service.peerPort | default 2380 }}
+ protocol: TCP
+ {{- if .Values.metrics.enabled }}
+ - name: metrics
+ containerPort: {{ .Values.service.metricsPort | default 2381 }}
+ protocol: TCP
+ {{- end }}
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ {{- with .Values.extraEnvVars }}
+{{- toYaml . | nindent 12 }}
+ {{- end }}
+ {{- if .Values.startupProbe.enabled }}
+ startupProbe:
+ httpGet:
+ path: /health
+ port: client
+ {{- if .Values.auth.enabled }}
+ scheme: HTTPS
+ {{- else }}
+ scheme: HTTP
+ {{- end }}
+ initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.startupProbe.periodSeconds }}
+ timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }}
+ failureThreshold: {{ .Values.startupProbe.failureThreshold }}
+ successThreshold: {{ .Values.startupProbe.successThreshold }}
+ {{- end }}
+ {{- if .Values.livenessProbe.enabled }}
+ livenessProbe:
+ httpGet:
+ path: /health
+ port: client
+ {{- if .Values.auth.enabled }}
+ scheme: HTTPS
+ {{- else }}
+ scheme: HTTP
+ {{- end }}
+ initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
+ timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
+ failureThreshold: {{ .Values.livenessProbe.failureThreshold }}
+ successThreshold: {{ .Values.livenessProbe.successThreshold }}
+ {{- end }}
+ {{- if .Values.readinessProbe.enabled }}
+ readinessProbe:
+ httpGet:
+ path: /health?serializable=true
+ port: client
+ {{- if .Values.auth.enabled }}
+ scheme: HTTPS
+ {{- else }}
+ scheme: HTTP
+ {{- end }}
+ initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
+ timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
+ failureThreshold: {{ .Values.readinessProbe.failureThreshold }}
+ successThreshold: {{ .Values.readinessProbe.successThreshold }}
+ {{- end }}
+ resources: {{- toYaml .Values.resources | nindent 12 }}
+ volumeMounts:
+ - name: data
+ mountPath: {{ .Values.persistence.mountPath }}
+ {{- if .Values.containerSecurityContext.readOnlyRootFilesystem }}
+ - name: tmp
+ mountPath: /tmp
+ {{- end }}
+ {{- if .Values.auth.enabled }}
+ - name: client-certs
+ mountPath: /etc/etcd/certs/client
+ readOnly: true
+ {{- end }}
+ {{- if .Values.auth.peer.enabled }}
+ - name: peer-certs
+ mountPath: /etc/etcd/certs/peer
+ readOnly: true
+ {{- end }}
+ {{- if .Values.extraVolumeMounts }}
+ {{- toYaml .Values.extraVolumeMounts | nindent 12 }}
+ {{- end }}
+ volumes:
+ {{- if not .Values.persistence.enabled }}
+ - name: data
+ emptyDir: {}
+ {{- end }}
+ {{- if .Values.containerSecurityContext.readOnlyRootFilesystem }}
+ - name: tmp
+ emptyDir: {}
+ {{- end }}
+ {{- if .Values.auth.enabled }}
+ - name: client-certs
+ secret:
+ secretName: {{ include "cloudpirates.tplvalues.render" (dict "value" .Values.auth.existingSecret "context" .) }}
+ defaultMode: 0400
+ {{- end }}
+ {{- if .Values.auth.peer.enabled }}
+ - name: peer-certs
+ secret:
+ secretName: {{ include "cloudpirates.tplvalues.render" (dict "value" .Values.auth.peer.existingSecret "context" .) }}
+ defaultMode: 0400
+ {{- end }}
+ {{- if .Values.extraVolumes }}
+ {{- toYaml .Values.extraVolumes | nindent 8 }}
+ {{- end }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.priorityClassName }}
+ priorityClassName: {{ . }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.topologySpreadConstraints }}
+ topologySpreadConstraints:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- if .Values.persistence.enabled }}
+ volumeClaimTemplates:
+ - metadata:
+ name: data
+ {{- with .Values.persistence.annotations }}
+ annotations:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ spec:
+ accessModes:
+ {{- with .Values.persistence.accessModes }}
+ {{- toYaml . | nindent 10 }}
+ {{- end}}
+ {{- if .Values.persistence.storageClass }}
+ storageClassName: {{ .Values.persistence.storageClass | quote }}
+ {{- end }}
+ resources:
+ requests:
+ storage: {{ .Values.persistence.size | quote }}
+ {{- end }}
diff --git a/charts/etcd/tests/common-parameters_test.yaml b/charts/etcd/tests/common-parameters_test.yaml
new file mode 100644
index 00000000..ea73fca5
--- /dev/null
+++ b/charts/etcd/tests/common-parameters_test.yaml
@@ -0,0 +1,210 @@
+suite: test etcd common parameters
+templates:
+ - statefulset.yaml
+set:
+ image:
+ tag: v3.6.0-alpha.0
+tests:
+ - it: should use default values when nothing is overridden
+ asserts:
+ - equal:
+ path: metadata.name
+ value: RELEASE-NAME-etcd
+ - equal:
+ path: metadata.labels["app.kubernetes.io/name"]
+ value: etcd
+ - equal:
+ path: metadata.labels["app.kubernetes.io/instance"]
+ value: RELEASE-NAME
+ - equal:
+ path: spec.template.spec.containers[0].image
+ value: quay.io/coreos/etcd:v3.6.0-alpha.0
+ - equal:
+ path: spec.template.spec.containers[0].imagePullPolicy
+ value: IfNotPresent
+
+ - it: should respect global.imageRegistry override
+ set:
+ global:
+ imageRegistry: "my-registry.com"
+ asserts:
+ - equal:
+ path: spec.template.spec.containers[0].image
+ value: my-registry.com/coreos/etcd:v3.6.0-alpha.0
+
+ - it: should respect global.imagePullSecrets
+ set:
+ global:
+ imagePullSecrets:
+ - name: my-secret-1
+ - name: my-secret-2
+ asserts:
+ - equal:
+ path: spec.template.spec.imagePullSecrets[0].name
+ value: my-secret-1
+ - equal:
+ path: spec.template.spec.imagePullSecrets[1].name
+ value: my-secret-2
+
+ - it: should respect nameOverride
+ set:
+ nameOverride: "custom-name"
+ asserts:
+ - equal:
+ path: metadata.name
+ value: RELEASE-NAME-custom-name
+ - equal:
+ path: metadata.labels["app.kubernetes.io/name"]
+ value: custom-name
+
+ - it: should respect fullnameOverride
+ set:
+ fullnameOverride: "completely-custom-name"
+ asserts:
+ - equal:
+ path: metadata.name
+ value: completely-custom-name
+
+ - it: should add commonLabels to all resources
+ set:
+ commonLabels:
+ environment: "test"
+ team: "platform"
+ asserts:
+ - equal:
+ path: metadata.labels.environment
+ value: test
+ - equal:
+ path: metadata.labels.team
+ value: platform
+
+ - it: should add commonAnnotations to all resources
+ set:
+ commonAnnotations:
+ deployment.kubernetes.io/revision: "1"
+ prometheus.io/scrape: "true"
+ asserts:
+ - equal:
+ path: metadata.annotations["deployment.kubernetes.io/revision"]
+ value: "1"
+ - equal:
+ path: metadata.annotations["prometheus.io/scrape"]
+ value: "true"
+
+ - it: should respect image.registry override
+ set:
+ image:
+ registry: "custom-registry.io"
+ asserts:
+ - equal:
+ path: spec.template.spec.containers[0].image
+ value: custom-registry.io/coreos/etcd:v3.6.0-alpha.0
+
+ - it: should respect image.repository override
+ set:
+ image:
+ repository: "custom/etcd"
+ asserts:
+ - equal:
+ path: spec.template.spec.containers[0].image
+ value: quay.io/custom/etcd:v3.6.0-alpha.0
+
+ - it: should respect image.tag override
+ set:
+ image:
+ tag: "v3.5.0"
+ asserts:
+ - equal:
+ path: spec.template.spec.containers[0].image
+ value: quay.io/coreos/etcd:v3.5.0
+
+ - it: should respect image.pullPolicy override
+ set:
+ image:
+ pullPolicy: "Always"
+ asserts:
+ - equal:
+ path: spec.template.spec.containers[0].imagePullPolicy
+ value: Always
+
+ - it: should prioritize global.imageRegistry over image.registry
+ set:
+ global:
+ imageRegistry: "global-registry.com"
+ image:
+ registry: "image-registry.com"
+ asserts:
+ - equal:
+ path: spec.template.spec.containers[0].image
+ value: global-registry.com/coreos/etcd:v3.6.0-alpha.0
+
+ - it: should add podLabels to pod template
+ set:
+ podLabels:
+ custom: "label"
+ foo: "bar"
+ asserts:
+ - equal:
+ path: spec.template.metadata.labels.custom
+ value: label
+ - equal:
+ path: spec.template.metadata.labels.foo
+ value: bar
+
+ - it: should add podAnnotations to pod template
+ set:
+ podAnnotations:
+ custom: "annotation"
+ foo: "bar"
+ asserts:
+ - equal:
+ path: spec.template.metadata.annotations.custom
+ value: annotation
+ - equal:
+ path: spec.template.metadata.annotations.foo
+ value: bar
+
+ - it: should combine all overrides correctly
+ set:
+ global:
+ imageRegistry: "global-reg.io"
+ imagePullSecrets:
+ - name: global-secret
+ nameOverride: "custom-etcd"
+ commonLabels:
+ env: "prod"
+ commonAnnotations:
+ version: "v1.0.0"
+ podLabels:
+ pod-label: "value"
+ podAnnotations:
+ pod-annotation: "value"
+ image:
+ repository: "custom/etcd"
+ tag: "v3.5.0"
+ pullPolicy: "Never"
+ asserts:
+ - equal:
+ path: metadata.name
+ value: RELEASE-NAME-custom-etcd
+ - equal:
+ path: metadata.labels.env
+ value: prod
+ - equal:
+ path: metadata.annotations.version
+ value: v1.0.0
+ - equal:
+ path: spec.template.metadata.labels.pod-label
+ value: value
+ - equal:
+ path: spec.template.metadata.annotations.pod-annotation
+ value: value
+ - equal:
+ path: spec.template.spec.containers[0].image
+ value: global-reg.io/custom/etcd:v3.5.0
+ - equal:
+ path: spec.template.spec.containers[0].imagePullPolicy
+ value: Never
+ - equal:
+ path: spec.template.spec.imagePullSecrets[0].name
+ value: global-secret
diff --git a/charts/etcd/tests/etcd-functionality_test.yaml b/charts/etcd/tests/etcd-functionality_test.yaml
new file mode 100644
index 00000000..6a3b749f
--- /dev/null
+++ b/charts/etcd/tests/etcd-functionality_test.yaml
@@ -0,0 +1,258 @@
+suite: test etcd functionality
+templates:
+ - statefulset.yaml
+ - service.yaml
+ - poddisruptionbudget.yaml
+ - servicemonitor.yaml
+ - networkpolicy.yaml
+set:
+ image:
+ tag: v3.6.0-alpha.0
+tests:
+ # Replica count validation
+ - it: should fail with even replica count
+ template: statefulset.yaml
+ set:
+ replicaCount: 2
+ asserts:
+ - failedTemplate: {}
+
+ - it: should succeed with odd replica count
+ template: statefulset.yaml
+ set:
+ replicaCount: 5
+ asserts:
+ - equal:
+ path: spec.replicas
+ value: 5
+
+ # etcd configuration
+ - it: should configure initial cluster state
+ template: statefulset.yaml
+ set:
+ config:
+ initialClusterState: "existing"
+ asserts:
+ - contains:
+ path: spec.template.spec.containers[0].args
+ content: "--initial-cluster-state=existing"
+
+ - it: should configure heartbeat and election timeout
+ template: statefulset.yaml
+ set:
+ config:
+ heartbeatInterval: 200
+ electionTimeout: 2000
+ asserts:
+ - contains:
+ path: spec.template.spec.containers[0].args
+ content: "--heartbeat-interval=200"
+ - contains:
+ path: spec.template.spec.containers[0].args
+ content: "--election-timeout=2000"
+
+ - it: should configure listen IPs
+ template: statefulset.yaml
+ set:
+ config:
+ listenPeerIp: "127.0.0.1"
+ listenClientIp: "127.0.0.1"
+ asserts:
+ - contains:
+ path: spec.template.spec.containers[0].args
+ content: "--listen-peer-urls=http://127.0.0.1:2380"
+ - contains:
+ path: spec.template.spec.containers[0].args
+ content: "--listen-client-urls=http://127.0.0.1:2379"
+
+ - it: should add extraArgs
+ template: statefulset.yaml
+ set:
+ extraArgs:
+ - "--max-txn-ops=128"
+ - "--grpc-keepalive-min-time=5s"
+ asserts:
+ - contains:
+ path: spec.template.spec.containers[0].args
+ content: "--max-txn-ops=128"
+ - contains:
+ path: spec.template.spec.containers[0].args
+ content: "--grpc-keepalive-min-time=5s"
+
+ # TLS configuration
+ - it: should enable client TLS
+ template: statefulset.yaml
+ set:
+ auth:
+ enabled: true
+ existingSecret: "etcd-client-certs"
+ asserts:
+ - contains:
+ path: spec.template.spec.containers[0].args
+ content: "--client-cert-auth"
+ - contains:
+ path: spec.template.spec.containers[0].args
+ content: "--listen-client-urls=https://0.0.0.0:2379"
+
+ - it: should enable peer TLS
+ template: statefulset.yaml
+ set:
+ auth:
+ peer:
+ enabled: true
+ existingSecret: "etcd-peer-certs"
+ asserts:
+ - contains:
+ path: spec.template.spec.containers[0].args
+ content: "--peer-client-cert-auth"
+ - contains:
+ path: spec.template.spec.containers[0].args
+ content: "--listen-peer-urls=https://0.0.0.0:2380"
+
+ # Metrics configuration
+ - it: should expose metrics port when enabled
+ template: statefulset.yaml
+ set:
+ metrics:
+ enabled: true
+ asserts:
+ - contains:
+ path: spec.template.spec.containers[0].args
+ content: "--listen-metrics-urls=http://0.0.0.0:2381"
+ - contains:
+ path: spec.template.spec.containers[0].ports
+ content:
+ name: metrics
+ containerPort: 2381
+ protocol: TCP
+
+ - it: should not expose metrics port when disabled
+ template: statefulset.yaml
+ set:
+ metrics:
+ enabled: false
+ asserts:
+ - notContains:
+ path: spec.template.spec.containers[0].args
+ content: "--listen-metrics-urls=http://0.0.0.0:2381"
+
+ - it: should create ServiceMonitor when enabled
+ template: servicemonitor.yaml
+ set:
+ metrics:
+ enabled: true
+ serviceMonitor:
+ enabled: true
+ asserts:
+ - hasDocuments:
+ count: 1
+ - isKind:
+ of: ServiceMonitor
+
+ - it: should not create ServiceMonitor when disabled
+ template: servicemonitor.yaml
+ set:
+ metrics:
+ enabled: true
+ serviceMonitor:
+ enabled: false
+ asserts:
+ - hasDocuments:
+ count: 0
+
+ # Service configuration
+ - it: should add service annotations
+ template: service.yaml
+ set:
+ service:
+ annotations:
+ key1: "value1"
+ key2: "value2"
+ asserts:
+ - equal:
+ path: metadata.annotations.key1
+ value: value1
+ documentIndex: 0
+ - equal:
+ path: metadata.annotations.key2
+ value: value2
+ documentIndex: 0
+
+ - it: should expose metrics port in service
+ template: service.yaml
+ set:
+ metrics:
+ enabled: true
+ asserts:
+ - contains:
+ path: spec.ports
+ content:
+ name: metrics
+ port: 2381
+ targetPort: metrics
+ protocol: TCP
+ documentIndex: 0
+
+ # PodDisruptionBudget
+ - it: should create PDB when enabled
+ template: poddisruptionbudget.yaml
+ set:
+ podDisruptionBudget:
+ enabled: true
+ asserts:
+ - hasDocuments:
+ count: 1
+ - isKind:
+ of: PodDisruptionBudget
+
+ - it: should not create PDB when disabled
+ template: poddisruptionbudget.yaml
+ set:
+ podDisruptionBudget:
+ enabled: false
+ asserts:
+ - hasDocuments:
+ count: 0
+
+ - it: should set minAvailable in PDB
+ template: poddisruptionbudget.yaml
+ set:
+ podDisruptionBudget:
+ enabled: true
+ minAvailable: "2"
+ asserts:
+ - equal:
+ path: spec.minAvailable
+ value: "2"
+
+ # NetworkPolicy
+ - it: should create NetworkPolicy when enabled
+ template: networkpolicy.yaml
+ set:
+ networkPolicy:
+ enabled: true
+ asserts:
+ - hasDocuments:
+ count: 1
+ - isKind:
+ of: NetworkPolicy
+
+ - it: should not create NetworkPolicy when disabled
+ template: networkpolicy.yaml
+ set:
+ networkPolicy:
+ enabled: false
+ asserts:
+ - hasDocuments:
+ count: 0
+
+ # UpdateStrategy
+ - it: should configure update strategy
+ template: statefulset.yaml
+ set:
+ updateStrategy:
+ type: "OnDelete"
+ asserts:
+ - equal:
+ path: spec.updateStrategy.type
+ value: OnDelete
diff --git a/charts/etcd/tests/service-account_test.yaml b/charts/etcd/tests/service-account_test.yaml
new file mode 100644
index 00000000..22388d09
--- /dev/null
+++ b/charts/etcd/tests/service-account_test.yaml
@@ -0,0 +1,58 @@
+suite: test etcd service account parameters
+templates:
+ - serviceaccount.yaml
+set:
+ serviceAccount:
+ create: true
+tests:
+ - it: should use default labels for the manifest
+ asserts:
+ - equal:
+ path: metadata.name
+ value: RELEASE-NAME-etcd
+ - equal:
+ path: metadata.labels["app.kubernetes.io/name"]
+ value: etcd
+ - equal:
+ path: metadata.labels["app.kubernetes.io/instance"]
+ value: RELEASE-NAME
+
+ - it: should respect serviceAccount.name override
+ set:
+ serviceAccount:
+ name: "my-service-account"
+ asserts:
+ - equal:
+ path: metadata.name
+ value: my-service-account
+
+ - it: should respect serviceAccount.annotations override
+ set:
+ serviceAccount:
+ annotations:
+ key1: "value1"
+ key2: "value2"
+ asserts:
+ - equal:
+ path: metadata.annotations.key1
+ value: value1
+ - equal:
+ path: metadata.annotations.key2
+ value: value2
+
+ - it: should respect serviceAccount.automountServiceAccountToken
+ set:
+ serviceAccount:
+ automountServiceAccountToken: true
+ asserts:
+ - equal:
+ path: automountServiceAccountToken
+ value: true
+
+ - it: should not render when create is false
+ set:
+ serviceAccount:
+ create: false
+ asserts:
+ - hasDocuments:
+ count: 0
diff --git a/charts/etcd/values.schema.json b/charts/etcd/values.schema.json
new file mode 100644
index 00000000..b130b16f
--- /dev/null
+++ b/charts/etcd/values.schema.json
@@ -0,0 +1,404 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "type": "object",
+ "properties": {
+ "affinity": {
+ "type": "object"
+ },
+ "auth": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "existingSecret": {
+ "type": "string"
+ },
+ "peer": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "existingSecret": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "commonAnnotations": {
+ "type": "object"
+ },
+ "commonLabels": {
+ "type": "object"
+ },
+ "config": {
+ "type": "object",
+ "properties": {
+ "autoCompactionMode": {
+ "type": "string"
+ },
+ "autoCompactionRetention": {
+ "type": "string"
+ },
+ "electionTimeout": {
+ "type": "integer"
+ },
+ "heartbeatInterval": {
+ "type": "integer"
+ },
+ "initialClusterState": {
+ "type": "string"
+ },
+ "initialClusterToken": {
+ "type": "string"
+ },
+ "listenClientIp": {
+ "type": "string"
+ },
+ "listenPeerIp": {
+ "type": "string"
+ },
+ "logLevel": {
+ "type": "string"
+ },
+ "maxRequestBytes": {
+ "type": "integer"
+ },
+ "maxSnapshots": {
+ "type": "integer"
+ },
+ "maxWals": {
+ "type": "integer"
+ },
+ "quotaBackendBytes": {
+ "type": "integer"
+ },
+ "snapshotCount": {
+ "type": "integer"
+ }
+ }
+ },
+ "containerSecurityContext": {
+ "type": "object",
+ "properties": {
+ "allowPrivilegeEscalation": {
+ "type": "boolean"
+ },
+ "capabilities": {
+ "type": "object",
+ "properties": {
+ "drop": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "readOnlyRootFilesystem": {
+ "type": "boolean"
+ },
+ "runAsGroup": {
+ "type": "integer"
+ },
+ "runAsNonRoot": {
+ "type": "boolean"
+ },
+ "runAsUser": {
+ "type": "integer"
+ }
+ }
+ },
+ "extraArgs": {
+ "type": "array"
+ },
+ "extraEnvVars": {
+ "type": "array"
+ },
+ "extraObjects": {
+ "type": "array"
+ },
+ "extraVolumeMounts": {
+ "type": "array"
+ },
+ "extraVolumes": {
+ "type": "array"
+ },
+ "fullnameOverride": {
+ "type": "string"
+ },
+ "global": {
+ "type": "object",
+ "properties": {
+ "imagePullSecrets": {
+ "type": "array"
+ },
+ "imageRegistry": {
+ "type": "string"
+ }
+ }
+ },
+ "image": {
+ "type": "object",
+ "properties": {
+ "pullPolicy": {
+ "type": "string"
+ },
+ "registry": {
+ "type": "string"
+ },
+ "repository": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ }
+ }
+ },
+ "livenessProbe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ }
+ }
+ },
+ "metrics": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "serviceMonitor": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "honorLabels": {
+ "type": "boolean"
+ },
+ "interval": {
+ "type": "string"
+ },
+ "labels": {
+ "type": "object"
+ },
+ "metricRelabelings": {
+ "type": "array"
+ },
+ "namespace": {
+ "type": "string"
+ },
+ "relabelings": {
+ "type": "array"
+ },
+ "scrapeTimeout": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "nameOverride": {
+ "type": "string"
+ },
+ "networkPolicy": {
+ "type": "object",
+ "properties": {
+ "allowExternal": {
+ "type": "boolean"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "extraEgress": {
+ "type": "array"
+ },
+ "extraIngress": {
+ "type": "array"
+ }
+ }
+ },
+ "nodeSelector": {
+ "type": "object"
+ },
+ "persistence": {
+ "type": "object",
+ "properties": {
+ "accessModes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "annotations": {
+ "type": "object"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "mountPath": {
+ "type": "string"
+ },
+ "size": {
+ "type": "string"
+ },
+ "storageClass": {
+ "type": "string"
+ }
+ }
+ },
+ "podAnnotations": {
+ "type": "object"
+ },
+ "podDisruptionBudget": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "maxUnavailable": {
+ "type": "integer"
+ },
+ "minAvailable": {
+ "type": "string"
+ }
+ }
+ },
+ "podLabels": {
+ "type": "object"
+ },
+ "podSecurityContext": {
+ "type": "object",
+ "properties": {
+ "fsGroup": {
+ "type": "integer"
+ }
+ }
+ },
+ "priorityClassName": {
+ "type": "string"
+ },
+ "readinessProbe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ }
+ }
+ },
+ "replicaCount": {
+ "type": "integer"
+ },
+ "resources": {
+ "type": "object"
+ },
+ "service": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object"
+ },
+ "clientPort": {
+ "type": "integer"
+ },
+ "metricsPort": {
+ "type": "integer"
+ },
+ "peerPort": {
+ "type": "integer"
+ },
+ "type": {
+ "type": "string"
+ }
+ }
+ },
+ "serviceAccount": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object"
+ },
+ "automountServiceAccountToken": {
+ "type": "boolean"
+ },
+ "create": {
+ "type": "boolean"
+ },
+ "name": {
+ "type": "string"
+ }
+ }
+ },
+ "startupProbe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ }
+ }
+ },
+ "tolerations": {
+ "type": "array"
+ },
+ "topologySpreadConstraints": {
+ "type": "array"
+ },
+ "updateStrategy": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ }
+ }
+ }
+ }
+}
diff --git a/charts/etcd/values.yaml b/charts/etcd/values.yaml
new file mode 100644
index 00000000..6d888ae7
--- /dev/null
+++ b/charts/etcd/values.yaml
@@ -0,0 +1,276 @@
+## @section Global parameters
+global:
+ ## @param global.imageRegistry Global Docker Image registry
+ imageRegistry: ""
+ ## @param global.imagePullSecrets Global Docker registry secret names as an array
+ imagePullSecrets: []
+
+## @section Common parameters
+## @param nameOverride String to partially override etcd.fullname
+nameOverride: ""
+## @param fullnameOverride String to fully override etcd.fullname
+fullnameOverride: ""
+## @param commonLabels Labels to add to all deployed objects
+commonLabels: {}
+## @param commonAnnotations Annotations to add to all deployed objects
+commonAnnotations: {}
+
+## @section etcd image parameters
+image:
+ ## @param image.registry etcd image registry
+ registry: quay.io
+ ## @param image.repository etcd image repository
+ repository: coreos/etcd
+ ## @param image.tag etcd image tag
+ tag: "v3.6.5@sha256:3397341272b9e0a6f44d7e3fc7c321c6efe6cbe82ce866b9b01d0c704bfc5bf3"
+ ## @param image.pullPolicy etcd image pull policy
+ pullPolicy: IfNotPresent
+
+## @param replicaCount Number of etcd replicas to deploy (must be odd number for quorum)
+replicaCount: 3
+
+## @param podLabels Additional labels for etcd pods
+podLabels: {}
+
+## @param podAnnotations Additional annotations for etcd pods
+podAnnotations: {}
+
+## @section Service configuration
+service:
+ ## @param service.type Kubernetes service type
+ type: ClusterIP
+ ## @param service.annotations Service annotations
+ annotations: {}
+ ## @param service.clientPort etcd client service port
+ clientPort: 2379
+ ## @param service.peerPort etcd peer service port
+ peerPort: 2380
+ ## @param service.metricsPort etcd metrics service port
+ metricsPort: 2381
+
+auth:
+ ## @param auth.enabled Enable client-to-server authentication
+ enabled: false
+ ## @param auth.existingSecret Name of existing secret containing client certificates
+ existingSecret: ""
+ peer:
+ ## @param auth.peer.enabled Enable peer-to-peer authentication
+ enabled: false
+ ## @param auth.peer.existingSecret Name of existing secret containing peer certificates
+ existingSecret: ""
+
+## @section etcd configuration
+config:
+ ## @param config.initialClusterState Initial cluster state (new or existing)
+ initialClusterState: new
+ ## @param config.autoCompactionMode Auto compaction mode (periodic or revision)
+ autoCompactionMode: periodic
+ ## @param config.autoCompactionRetention Auto compaction retention (1 hour for periodic mode)
+ autoCompactionRetention: "1"
+ ## @param config.snapshotCount Number of committed transactions to trigger a snapshot
+ snapshotCount: 10000
+ ## @param config.quotaBackendBytes Backend storage quota in bytes (default 2GB)
+ quotaBackendBytes: 2147483648
+ ## @param config.maxRequestBytes Maximum client request size in bytes
+ maxRequestBytes: 1572864
+ ## @param config.logLevel Log level (debug, info, warn, error, panic, fatal)
+ logLevel: info
+ ## @param config.initialClusterToken Initial cluster token for the etcd cluster
+ initialClusterToken: etcd-cluster
+ ## @param config.heartbeatInterval Time (in milliseconds) of a heartbeat interval
+ heartbeatInterval: 100
+ ## @param config.electionTimeout Time (in milliseconds) for an election to timeout
+ electionTimeout: 1000
+ ## @param config.maxSnapshots Maximum number of snapshot files to retain
+ maxSnapshots: 5
+ ## @param config.maxWals Maximum number of wal files to retain
+ maxWals: 5
+ ## @param config.listenPeerIp IP address to listen on for peer traffic (default 0.0.0.0)
+ listenPeerIp: 0.0.0.0
+ ## @param config.listenClientIp IP address to listen on for client traffic (default 0.0.0.0)
+ listenClientIp: 0.0.0.0
+
+## @section Persistence
+persistence:
+ ## @param persistence.enabled Enable persistence using Persistent Volume Claims
+ enabled: true
+ ## @param persistence.storageClass Persistent Volume storage class
+ storageClass: ""
+ ## @param persistence.annotations Persistent Volume Claim annotations
+ annotations: {}
+ ## @param persistence.size Persistent Volume size
+ size: 8Gi
+ ## @param persistence.accessModes Persistent Volume access modes
+ accessModes:
+ - ReadWriteOnce
+ ## @param persistence.mountPath The path where to mount the data volume
+ mountPath: /var/run/etcd
+
+## @param resources Resource limits and requests for etcd pod
+resources: {}
+ # limits:
+ # memory: 512Mi
+ # requests:
+ # cpu: 250m
+ # memory: 256Mi
+
+## @section StatefulSet configuration
+## @param updateStrategy.type StatefulSet update strategy type
+updateStrategy:
+ type: RollingUpdate
+
+## @section Metrics configuration
+metrics:
+ ## @param metrics.enabled Enable Prometheus metrics
+ enabled: true
+ serviceMonitor:
+ ## @param metrics.serviceMonitor.enabled Create ServiceMonitor resource for scraping metrics using PrometheusOperator
+ enabled: false
+ ## @param metrics.serviceMonitor.namespace Namespace which Prometheus is running in
+ namespace: ""
+ ## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped
+ interval: 30s
+ ## @param metrics.serviceMonitor.scrapeTimeout Specify the timeout after which the scrape is ended
+ scrapeTimeout: ""
+ ## @param metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping
+ relabelings: []
+ ## @param metrics.serviceMonitor.metricRelabelings MetricRelabelConfigs to apply to samples before ingestion
+ metricRelabelings: []
+ ## @param metrics.serviceMonitor.labels Additional labels that can be used so ServiceMonitor will be discovered by Prometheus
+ labels: {}
+ ## @param metrics.serviceMonitor.honorLabels honorLabels chooses the metric's labels on collisions with target labels
+ honorLabels: false
+
+## @section High Availability
+podDisruptionBudget:
+ ## @param podDisruptionBudget.enabled Enable Pod Disruption Budget
+ enabled: false
+ ## @param podDisruptionBudget.minAvailable Minimum number of available pods
+ minAvailable: ""
+ ## @param podDisruptionBudget.maxUnavailable Maximum number of unavailable pods
+ maxUnavailable: 1
+
+## @section Service Account
+serviceAccount:
+ ## @param serviceAccount.create Enable creation of ServiceAccount for etcd pod
+ create: true
+ ## @param serviceAccount.name Name of the created serviceAccount
+ name: ""
+ ## @param serviceAccount.annotations Annotations for service account
+ annotations: {}
+ ## @param serviceAccount.automountServiceAccountToken Auto-mount the service account token in the pod
+ automountServiceAccountToken: false
+
+## @section Network Policy
+networkPolicy:
+ ## @param networkPolicy.enabled Enable NetworkPolicy
+ enabled: false
+ ## @param networkPolicy.allowExternal Allow external traffic
+ allowExternal: true
+ ## @param networkPolicy.extraIngress Additional ingress rules
+ extraIngress: []
+ ## @param networkPolicy.extraEgress Additional egress rules
+ extraEgress: []
+
+## @param extraArgs Additional etcd command line arguments as array
+extraArgs: []
+# - --max-txn-ops=128
+# - --grpc-keepalive-min-time=5s
+
+## @param nodeSelector Node selector for pod assignment
+nodeSelector: {}
+
+## @param priorityClassName for pod eviction
+priorityClassName: ""
+
+## @param tolerations Tolerations for pod assignment
+tolerations: []
+
+## @param affinity Affinity rules for pod assignment
+affinity: {}
+
+## @param topologySpreadConstraints Topology Spread Constraints for pod assignment
+topologySpreadConstraints: []
+
+containerSecurityContext:
+ ## @param containerSecurityContext.runAsUser User ID to run the container
+ runAsUser: 1000
+ ## @param containerSecurityContext.runAsGroup Group ID to run the container
+ runAsGroup: 1000
+ ## @param containerSecurityContext.runAsNonRoot Run as non-root user
+ runAsNonRoot: true
+ ## @param containerSecurityContext.allowPrivilegeEscalation Set etcd container's privilege escalation
+ allowPrivilegeEscalation: false
+ ## @param containerSecurityContext.readOnlyRootFilesystem Mount container root filesystem as read-only
+ readOnlyRootFilesystem: true
+ ## @param containerSecurityContext.capabilities.drop Linux capabilities to drop
+ capabilities:
+ drop:
+ - ALL
+
+## @param podSecurityContext Security context for the pod
+podSecurityContext:
+ ## @param podSecurityContext.fsGroup Set etcd pod's Security Context fsGroup
+ fsGroup: 1000
+
+## @section Liveness and readiness probes
+livenessProbe:
+ ## @param livenessProbe.enabled Enable livenessProbe on etcd containers
+ enabled: true
+ ## @param livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe
+ initialDelaySeconds: 10
+ ## @param livenessProbe.periodSeconds Period seconds for livenessProbe
+ periodSeconds: 10
+ ## @param livenessProbe.timeoutSeconds Timeout seconds for livenessProbe
+ timeoutSeconds: 5
+ ## @param livenessProbe.failureThreshold Failure threshold for livenessProbe
+ failureThreshold: 3
+ ## @param livenessProbe.successThreshold Success threshold for livenessProbe
+ successThreshold: 1
+
+readinessProbe:
+ ## @param readinessProbe.enabled Enable readinessProbe on etcd containers
+ enabled: true
+ ## @param readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe
+ initialDelaySeconds: 5
+ ## @param readinessProbe.periodSeconds Period seconds for readinessProbe
+ periodSeconds: 10
+ ## @param readinessProbe.timeoutSeconds Timeout seconds for readinessProbe
+ timeoutSeconds: 5
+ ## @param readinessProbe.failureThreshold Failure threshold for readinessProbe
+ failureThreshold: 3
+ ## @param readinessProbe.successThreshold Success threshold for readinessProbe
+ successThreshold: 1
+
+startupProbe:
+ ## @param startupProbe.enabled Enable startupProbe on etcd containers
+ enabled: true
+ ## @param startupProbe.initialDelaySeconds Initial delay seconds for startupProbe
+ initialDelaySeconds: 0
+ ## @param startupProbe.periodSeconds Period seconds for startupProbe
+ periodSeconds: 10
+ ## @param startupProbe.timeoutSeconds Timeout seconds for startupProbe
+ timeoutSeconds: 5
+ ## @param startupProbe.failureThreshold Failure threshold for startupProbe
+ failureThreshold: 30
+ ## @param startupProbe.successThreshold Success threshold for startupProbe
+ successThreshold: 1
+
+## @param extraEnvVars Additional environment variables to set
+extraEnvVars: []
+ # - name: CUSTOM_VAR
+ # value: "custom-value"
+ # - name: SECRET_VAR
+ # valueFrom:
+ # secretKeyRef:
+ # name: my-secret
+ # key: secret-key
+
+## @param extraVolumes Additional volumes to add to the pod
+extraVolumes: []
+
+## @param extraVolumeMounts Additional volume mounts to add to the etcd container
+extraVolumeMounts: []
+
+## @param extraObjects Array of extra objects to deploy with the release
+extraObjects: []
diff --git a/charts/ghost/CHANGELOG.md b/charts/ghost/CHANGELOG.md
index f9d6b2b0..a94f139a 100644
--- a/charts/ghost/CHANGELOG.md
+++ b/charts/ghost/CHANGELOG.md
@@ -1,5 +1,108 @@
# Changelog
+
+## 0.4.3 (2025-11-04)
+
+* Update charts/ghost/values.yaml ghost (#542) ([6d66d19](https://github.com/CloudPirates-io/helm-charts/commit/6d66d19))
+* chore: update CHANGELOG.md for merged changes ([58cb775](https://github.com/CloudPirates-io/helm-charts/commit/58cb775))
+* chore: update CHANGELOG.md for merged changes ([6daf183](https://github.com/CloudPirates-io/helm-charts/commit/6daf183))
+
+## 0.4.2 (2025-11-04)
+
+* Update charts/ghost/values.yaml ghost to v6.6.0 (minor) (#539) ([fda6611](https://github.com/CloudPirates-io/helm-charts/commit/fda6611))
+* chore: update CHANGELOG.md for merged changes ([232d617](https://github.com/CloudPirates-io/helm-charts/commit/232d617))
+* chore: update CHANGELOG.md for merged changes ([630b637](https://github.com/CloudPirates-io/helm-charts/commit/630b637))
+
+## 0.4.1 (2025-10-30)
+
+* Update charts/ghost/values.yaml ghost (#502) ([5767f7f](https://github.com/CloudPirates-io/helm-charts/commit/5767f7f))
+* chore: update CHANGELOG.md for merged changes ([8260788](https://github.com/CloudPirates-io/helm-charts/commit/8260788))
+* chore: update CHANGELOG.md for merged changes ([402f7bd](https://github.com/CloudPirates-io/helm-charts/commit/402f7bd))
+
+## 0.4.0 (2025-10-28)
+
+* chore: update CHANGELOG.md for merged changes ([a968aa7](https://github.com/CloudPirates-io/helm-charts/commit/a968aa7))
+* chore: update CHANGELOG.md for merged changes ([74ee453](https://github.com/CloudPirates-io/helm-charts/commit/74ee453))
+
+## 0.3.6 (2025-10-25)
+
+* Update charts/ghost/values.yaml ghost to v6.5.3 (patch) (#456) ([3bf647a](https://github.com/CloudPirates-io/helm-charts/commit/3bf647a))
+* chore: update CHANGELOG.md for merged changes ([4cee2f2](https://github.com/CloudPirates-io/helm-charts/commit/4cee2f2))
+* chore: update CHANGELOG.md for merged changes ([2cec192](https://github.com/CloudPirates-io/helm-charts/commit/2cec192))
+* Update charts/ghost/values.yaml ghost (#452) ([4406c00](https://github.com/CloudPirates-io/helm-charts/commit/4406c00))
+* chore: update CHANGELOG.md for merged changes ([f9c3ff0](https://github.com/CloudPirates-io/helm-charts/commit/f9c3ff0))
+* chore: update CHANGELOG.md for merged changes ([db2d800](https://github.com/CloudPirates-io/helm-charts/commit/db2d800))
+
+## 0.3.5 (2025-10-23)
+
+* chore: update CHANGELOG.md for merged changes ([844a243](https://github.com/CloudPirates-io/helm-charts/commit/844a243))
+* chore: update CHANGELOG.md for merged changes ([ad40303](https://github.com/CloudPirates-io/helm-charts/commit/ad40303))
+
+## 0.3.4 (2025-10-23)
+
+* Update charts/ghost/values.yaml ghost to v6.5.0 (minor) (#450) ([10e9958](https://github.com/CloudPirates-io/helm-charts/commit/10e9958))
+* chore: update CHANGELOG.md for merged changes ([787c4fb](https://github.com/CloudPirates-io/helm-charts/commit/787c4fb))
+* chore: update CHANGELOG.md for merged changes ([997f383](https://github.com/CloudPirates-io/helm-charts/commit/997f383))
+
+## 0.3.3 (2025-10-23)
+
+* Update charts/ghost/values.yaml ghost (#447) ([881ef3b](https://github.com/CloudPirates-io/helm-charts/commit/881ef3b))
+* chore: update CHANGELOG.md for merged changes ([6af7d8e](https://github.com/CloudPirates-io/helm-charts/commit/6af7d8e))
+* chore: update CHANGELOG.md for merged changes ([0ba351a](https://github.com/CloudPirates-io/helm-charts/commit/0ba351a))
+
+## 0.3.2 (2025-10-22)
+
+* Update charts/ghost/values.yaml ghost (#433) ([6463206](https://github.com/CloudPirates-io/helm-charts/commit/6463206))
+* chore: update CHANGELOG.md for merged changes ([5b3746e](https://github.com/CloudPirates-io/helm-charts/commit/5b3746e))
+* chore: update CHANGELOG.md for merged changes ([523c7da](https://github.com/CloudPirates-io/helm-charts/commit/523c7da))
+
+## 0.3.1 (2025-10-19)
+
+* Update charts/ghost/values.yaml ghost to v6.4.0 (minor) (#414) ([05b099b](https://github.com/CloudPirates-io/helm-charts/commit/05b099b))
+* chore: update CHANGELOG.md for merged changes ([1a4f87b](https://github.com/CloudPirates-io/helm-charts/commit/1a4f87b))
+* chore: update CHANGELOG.md for merged changes ([da866ca](https://github.com/CloudPirates-io/helm-charts/commit/da866ca))
+* chore: update CHANGELOG.md for merged changes ([b54c4f1](https://github.com/CloudPirates-io/helm-charts/commit/b54c4f1))
+* chore: update CHANGELOG.md for merged changes ([5a2ed20](https://github.com/CloudPirates-io/helm-charts/commit/5a2ed20))
+* chore: update CHANGELOG.md for merged changes ([4b02e57](https://github.com/CloudPirates-io/helm-charts/commit/4b02e57))
+* chore: update CHANGELOG.md for merged changes ([bf2e3b2](https://github.com/CloudPirates-io/helm-charts/commit/bf2e3b2))
+* chore: update CHANGELOG.md for merged changes ([2f87d0e](https://github.com/CloudPirates-io/helm-charts/commit/2f87d0e))
+
+## 0.3.0 (2025-10-14)
+
+* chore: update CHANGELOG.md for merged changes ([84cf67b](https://github.com/CloudPirates-io/helm-charts/commit/84cf67b))
+* chore: update CHANGELOG.md for all charts via manual trigger ([6974964](https://github.com/CloudPirates-io/helm-charts/commit/6974964))
+* Update charts/ghost/values.yaml ghost to v6.3.1 (patch) (#349) ([7111469](https://github.com/CloudPirates-io/helm-charts/commit/7111469))
+
+## 0.2.6 (2025-10-10)
+
+* Update charts/ghost/values.yaml ghost to v6.3.0 (minor) (#327) ([e74a03d](https://github.com/CloudPirates-io/helm-charts/commit/e74a03d))
+* add tests for openshift (#226) ([c80c98a](https://github.com/CloudPirates-io/helm-charts/commit/c80c98a))
+
## 0.2.5 (2025-10-09)
-* [mongodb] feat: add metrics exporter ([#243](https://github.com/CloudPirates-io/helm-charts/pull/243))
+* Update charts/ghost/values.yaml ghost to v6.2.0 (minor) (#268) ([c8d3f80](https://github.com/CloudPirates-io/helm-charts/commit/c8d3f80))
+
+## 0.2.4 (2025-10-09)
+
+* Update charts/ghost/values.yaml ghost to v6.0.10 (patch) (#259) ([c9b9b8b](https://github.com/CloudPirates-io/helm-charts/commit/c9b9b8b))
+
+## 0.2.3 (2025-10-06)
+
+
+## 0.2.2 (2025-10-01)
+
+* use png as icon (#200) ([359e88f](https://github.com/CloudPirates-io/helm-charts/commit/359e88f))
+
+## 0.2.1 (2025-10-01)
+
+* switch helm-chart icon to a new svg (#199) ([44e4d0d](https://github.com/CloudPirates-io/helm-charts/commit/44e4d0d))
+
+## 0.2.0 (2025-10-01)
+
+* make ghost run on openshift (#195) ([93762d4](https://github.com/CloudPirates-io/helm-charts/commit/93762d4))
+* Update CHANGELOG.md ([dc9fbd8](https://github.com/CloudPirates-io/helm-charts/commit/dc9fbd8))
+* Update CHANGELOG.md ([1bee7fe](https://github.com/CloudPirates-io/helm-charts/commit/1bee7fe))
+
+## 0.1.0 (2025-09-23)
+
+* Initial tagged release
diff --git a/charts/ghost/Chart.lock b/charts/ghost/Chart.lock
index 23227805..ec87894e 100644
--- a/charts/ghost/Chart.lock
+++ b/charts/ghost/Chart.lock
@@ -1,9 +1,9 @@
dependencies:
- name: common
repository: oci://registry-1.docker.io/cloudpirates
- version: 1.1.1
+ version: 2.0.0
- name: mariadb
repository: oci://registry-1.docker.io/cloudpirates
- version: 0.3.0
-digest: sha256:4e89daee4a04df25da46810f73b277003ebff8ca938c308ed55214e9a8893183
-generated: "2025-09-30T22:09:51.820397+02:00"
+ version: 0.4.0
+digest: sha256:732fadaa4290d7bcd69b8c7b2b05a75552ac82f188fd0c7b42bf3718bd68c7a1
+generated: "2025-10-14T12:59:56.216526+02:00"
diff --git a/charts/ghost/Chart.yaml b/charts/ghost/Chart.yaml
index 48b23658..a948b87e 100644
--- a/charts/ghost/Chart.yaml
+++ b/charts/ghost/Chart.yaml
@@ -2,27 +2,50 @@ apiVersion: v2
name: ghost
description: A simple, powerful publishing platform that allows you to share your stories with the world.
type: application
-version: 0.2.5
-appVersion: "6.0.9"
+version: 0.4.3
+appVersion: "6.6.0"
keywords:
- ghost
- blogging
- content management
-home: https://www.cloudpirates.io
+home: https://ghost.org
sources:
- https://github.com/CloudPirates-io/helm-charts/tree/main/charts/ghost
+ - https://github.com/TryGhost/Ghost
maintainers:
- name: CloudPirates GmbH & Co. KG
+ email: hello@cloudpirates.io
url: https://www.cloudpirates.io
- name: Gianni Carafa
email: gianni.carafa@srf.ch
url: https://www.srf.ch
dependencies:
- name: common
- version: "1.x.x"
+ version: "2.x.x"
repository: oci://registry-1.docker.io/cloudpirates
- name: mariadb
- version: "0.3.x"
+ version: "0.4.x"
repository: oci://registry-1.docker.io/cloudpirates
condition: mariadb.enabled
icon: https://a.storyblok.com/f/143071/512x512/3a5c1cb0c5/ghost-logo.png
+annotations:
+ license: Apache-2.0
+ artifacthub.io/containsSecurityUpdates: "false"
+ artifacthub.io/signKey: |
+ fingerprint: 6917f1a88c122cbb1de5aa55457752135bdcf95a
+ url: https://raw.githubusercontent.com/CloudPirates-io/helm-charts/refs/heads/main/cosign.pub
+ artifacthub.io/links: |
+ - name: Ghost
+ url: https://ghost.org
+ - name: Helm Chart
+ url: https://github.com/CloudPirates-io/helm-charts/tree/main/charts/ghost
+ - name: Application
+ url: https://github.com/TryGhost/Ghost
+ - name: Maintainer CloudPirates
+ url: https://www.cloudpirates.io
+ artifacthub.io/changes: |2
+ - kind: changed
+ description: "Update charts/ghost/values.yaml ghost (#542)"
+ links:
+ - name: "Commit 6d66d19"
+ url: "https://github.com/CloudPirates-io/helm-charts/commit/6d66d19"
diff --git a/charts/ghost/README.md b/charts/ghost/README.md
index 407ef7b4..dcaa06cc 100644
--- a/charts/ghost/README.md
+++ b/charts/ghost/README.md
@@ -88,111 +88,111 @@ The following tables list the configurable parameters of the Ghost chart organiz
### Global & Common Parameters
-| Parameter | Description | Default |
-|--------------------------|-----------------------------------------------|-----------------|
-| `global.imageRegistry` | Global Docker image registry | `""` |
-| `global.imagePullSecrets`| Global Docker registry secret names as array | `[]` |
-| `nameOverride` | String to partially override ghost.fullname | `""` |
-| `fullnameOverride` | String to fully override ghost.fullname | `""` |
-| `commonLabels` | Labels to add to all deployed objects | `{}` |
-| `commonAnnotations` | Annotations to add to all deployed objects | `{}` |
+| Parameter | Description | Default |
+| ------------------------- | -------------------------------------------- | ------- |
+| `global.imageRegistry` | Global Docker image registry | `""` |
+| `global.imagePullSecrets` | Global Docker registry secret names as array | `[]` |
+| `nameOverride` | String to partially override ghost.fullname | `""` |
+| `fullnameOverride` | String to fully override ghost.fullname | `""` |
+| `commonLabels` | Labels to add to all deployed objects | `{}` |
+| `commonAnnotations` | Annotations to add to all deployed objects | `{}` |
### Image Parameters
-| Parameter | Description | Default |
-|--------------------------|-----------------------------------------------|-----------------|
-| `image.registry` | Ghost image registry | `docker.io` |
-| `image.repository` | Ghost image repository | `ghost` |
-| `image.tag` | Ghost image tag | `6.0.9` |
-| `image.pullPolicy` | Ghost image pull policy | `Always` |
-| `replicaCount` | Number of Ghost replicas to deploy | `1` |
+| Parameter | Description | Default |
+| ------------------ | ---------------------------------- | ----------- |
+| `image.registry` | Ghost image registry | `docker.io` |
+| `image.repository` | Ghost image repository | `ghost` |
+| `image.tag` | Ghost image tag | `6.0.9` |
+| `image.pullPolicy` | Ghost image pull policy | `Always` |
+| `replicaCount` | Number of Ghost replicas to deploy | `1` |
### Network Parameters
-| Parameter | Description | Default |
-|--------------------------|-----------------------------------------------|-----------------|
-| `containerPorts` | List of container ports | `[{name: http, containerPort: 2368}]` |
-| `service.type` | Kubernetes service type | `ClusterIP` |
-| `service.ports` | List of service ports | `[{port: 80, targetPort: http}]` |
-| `ingress.enabled` | Enable ingress record generation | `true` |
-| `ingress.className` | IngressClass for the ingress record | `""` |
-| `ingress.annotations` | Additional ingress annotations | `{}` |
-| `ingress.hosts` | List of ingress hosts | `[{host: ghost.localhost, paths:[{path: /, pathType: Prefix}]}, {host: admin.ghost.localhost, paths:[{path: /ghost, pathType: Prefix}]}]` |
-| `ingress.tls` | TLS configuration for ingress | `[]` |
+| Parameter | Description | Default |
+| --------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
+| `containerPorts` | List of container ports | `[{name: http, containerPort: 2368}]` |
+| `service.type` | Kubernetes service type | `ClusterIP` |
+| `service.ports` | List of service ports | `[{port: 80, targetPort: http}]` |
+| `ingress.enabled` | Enable ingress record generation | `true` |
+| `ingress.className` | IngressClass for the ingress record | `""` |
+| `ingress.annotations` | Additional ingress annotations | `{}` |
+| `ingress.hosts` | List of ingress hosts | `[{host: ghost.localhost, paths:[{path: /, pathType: Prefix}]}, {host: admin.ghost.localhost, paths:[{path: /ghost, pathType: Prefix}]}]` |
+| `ingress.tls` | TLS configuration for ingress | `[]` |
### Persistence Parameters
-| Parameter | Description | Default |
-|-----------------------------|--------------------------------------------|-----------------|
-| `persistence.enabled` | Enable persistence using PVC | `true` |
-| `persistence.annotations` | Annotations for PVC | `{}` |
-| `persistence.existingClaim` | Use an existing PVC | `""` |
-| `persistence.storageClass` | Storage class of backing PVC | `""` |
-| `persistence.accessModes` | PVC access modes | `[ReadWriteOnce]` |
-| `persistence.size` | Size of persistent volume claim | `8Gi` |
+| Parameter | Description | Default |
+| --------------------------- | ------------------------------- | ----------------- |
+| `persistence.enabled` | Enable persistence using PVC | `true` |
+| `persistence.annotations` | Annotations for PVC | `{}` |
+| `persistence.existingClaim` | Use an existing PVC | `""` |
+| `persistence.storageClass` | Storage class of backing PVC | `""` |
+| `persistence.accessModes` | PVC access modes | `[ReadWriteOnce]` |
+| `persistence.size` | Size of persistent volume claim | `8Gi` |
### Database Parameters
-| Parameter | Description | Default |
-|------------------------------|-------------------------------------------|-----------------|
-| `mariadb.enabled` | Deploy MariaDB as dependency | `true` |
-| `mariadb.auth.database` | MariaDB database name | `ghost` |
-| `mariadb.auth.username` | MariaDB username | `ghost` |
-| `mariadb.auth.password` | MariaDB password | `changeme` |
-| `mariadb.auth.existingSecret`| Existing secret with MariaDB credentials | `""` |
-| `mariadb.auth.allowEmptyRootPassword` | Allow empty root password | `false` |
+| Parameter | Description | Default |
+| ------------------------------------- | ---------------------------------------- | ---------- |
+| `mariadb.enabled` | Deploy MariaDB as dependency | `true` |
+| `mariadb.auth.database` | MariaDB database name | `ghost` |
+| `mariadb.auth.username` | MariaDB username | `ghost` |
+| `mariadb.auth.password` | MariaDB password | `changeme` |
+| `mariadb.auth.existingSecret` | Existing secret with MariaDB credentials | `""` |
+| `mariadb.auth.allowEmptyRootPassword` | Allow empty root password | `false` |
### Pod Parameters
-| Parameter | Description | Default |
-|------------------------------|-------------------------------------------|-----------------|
-| `resources` | Resource limits and requests for pod | `{}` |
-| `nodeSelector` | Node selector for pod assignment | `{}` |
-| `tolerations` | Tolerations for pod assignment | `[]` |
-| `affinity` | Affinity for pod assignment | `{}` |
-| `podSecurityContext.fsGroup` | Set pod's Security Context fsGroup | `1000` |
-| `containerSecurityContext.runAsUser` | Set container's Security Context runAsUser | `1000` |
-| `containerSecurityContext.runAsNonRoot` | Run as non-root user | `true` |
-| `containerSecurityContext.allowPrivilegeEscalation` | Allow privilege escalation | `false` |
+| Parameter | Description | Default |
+| --------------------------------------------------- | ------------------------------------------ | ------- |
+| `resources` | Resource limits and requests for pod | `{}` |
+| `nodeSelector` | Node selector for pod assignment | `{}` |
+| `tolerations` | Tolerations for pod assignment | `[]` |
+| `affinity` | Affinity for pod assignment | `{}` |
+| `podSecurityContext.fsGroup` | Set pod's Security Context fsGroup | `1000` |
+| `containerSecurityContext.runAsUser` | Set container's Security Context runAsUser | `1000` |
+| `containerSecurityContext.runAsNonRoot` | Run as non-root user | `true` |
+| `containerSecurityContext.allowPrivilegeEscalation` | Allow privilege escalation | `false` |
### Health Check Parameters
-| Parameter | Description | Default |
-|--------------------------------------|-------------------------------------|-----------------|
-| `livenessProbe.enabled` | Enable liveness probe | `true` |
-| `livenessProbe.type` | Probe type (tcpSocket or httpGet) | `tcpSocket` |
-| `livenessProbe.initialDelaySeconds` | Initial delay seconds | `30` |
-| `livenessProbe.periodSeconds` | Period seconds | `10` |
-| `readinessProbe.enabled` | Enable readiness probe | `true` |
-| `readinessProbe.type` | Probe type (tcpSocket or httpGet) | `tcpSocket` |
-| `readinessProbe.initialDelaySeconds` | Initial delay seconds | `5` |
-| `readinessProbe.periodSeconds` | Period seconds | `12` |
+| Parameter | Description | Default |
+| ------------------------------------ | --------------------------------- | ----------- |
+| `livenessProbe.enabled` | Enable liveness probe | `true` |
+| `livenessProbe.type` | Probe type (tcpSocket or httpGet) | `tcpSocket` |
+| `livenessProbe.initialDelaySeconds` | Initial delay seconds | `30` |
+| `livenessProbe.periodSeconds` | Period seconds | `10` |
+| `readinessProbe.enabled` | Enable readiness probe | `true` |
+| `readinessProbe.type` | Probe type (tcpSocket or httpGet) | `tcpSocket` |
+| `readinessProbe.initialDelaySeconds` | Initial delay seconds | `5` |
+| `readinessProbe.periodSeconds` | Period seconds | `12` |
### Init Container Parameters
-| Parameter | Description | Default |
-|----------------------------------------|-------------------------------------|-----------------|
-| `initContainers.waitForMariadb.image` | MariaDB init container image | `mariadb:12.0.2`|
+| Parameter | Description | Default |
+| ------------------------------------- | ---------------------------- | ---------------- |
+| `initContainers.waitForMariadb.image` | MariaDB init container image | `mariadb:12.0.2` |
### Autoscaling Parameters
-| Parameter | Description | Default |
-|-----------------------------------------|----------------------------------|-----------------|
-| `autoscaling.enabled` | Enable autoscaling | `false` |
-| `autoscaling.minReplicas` | Minimum number of replicas | `""` |
-| `autoscaling.maxReplicas` | Maximum number of replicas | `""` |
-| `autoscaling.targetCPUUtilizationPercentage` | Target CPU utilization | `""` |
-| `autoscaling.targetMemoryUtilizationPercentage` | Target memory utilization| `""` |
+| Parameter | Description | Default |
+| ----------------------------------------------- | -------------------------- | ------- |
+| `autoscaling.enabled` | Enable autoscaling | `false` |
+| `autoscaling.minReplicas` | Minimum number of replicas | `""` |
+| `autoscaling.maxReplicas` | Maximum number of replicas | `""` |
+| `autoscaling.targetCPUUtilizationPercentage` | Target CPU utilization | `""` |
+| `autoscaling.targetMemoryUtilizationPercentage` | Target memory utilization | `""` |
### Additional Configuration
-| Parameter | Description | Default |
-|---------------------|---------------------------------------------------|-----------------|
-| `extraEnv` | Additional environment variables | `[]` |
-| `extraVolumes` | Additional volumes | `[]` |
-| `extraVolumeMounts` | Additional volume mounts | `[]` |
-| `extraObjects` | Extra Kubernetes objects to deploy | `[]` |
-| `config` | Ghost configuration (database, mail, etc.) | See values.yaml |
+| Parameter | Description | Default |
+| ------------------- | ------------------------------------------ | --------------- |
+| `extraEnvVars` | Additional environment variables | `[]` |
+| `extraVolumes` | Additional volumes | `[]` |
+| `extraVolumeMounts` | Additional volume mounts | `[]` |
+| `extraObjects` | Extra Kubernetes objects to deploy | `[]` |
+| `config` | Ghost configuration (database, mail, etc.) | See values.yaml |
## Example: Custom Ghost Configuration
diff --git a/charts/ghost/ci/test-values.yaml b/charts/ghost/ci/test-values.yaml
new file mode 100644
index 00000000..25fa0f33
--- /dev/null
+++ b/charts/ghost/ci/test-values.yaml
@@ -0,0 +1,72 @@
+# CI test values for ghost chart
+# Optimized for faster testing in kind clusters and GitHub Actions
+
+image:
+ # Use IfNotPresent to avoid repeated pulls
+ pullPolicy: IfNotPresent
+ # Use simple tag without digest for better caching
+ tag: "6.4.0"
+
+# Disable ingress for CI tests
+ingress:
+ enabled: false
+
+# Lenient probes for slow CI environments
+readinessProbe:
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ timeoutSeconds: 5
+ failureThreshold: 30
+
+livenessProbe:
+ initialDelaySeconds: 30
+ periodSeconds: 30
+ timeoutSeconds: 5
+ failureThreshold: 10
+
+# Minimal resources for kind cluster
+resources:
+ limits:
+ memory: 512Mi
+ requests:
+ cpu: 100m
+ memory: 256Mi
+
+# Disable persistence for faster CI tests
+persistence:
+ enabled: false
+
+# MariaDB configuration for CI
+mariadb:
+ enabled: true
+
+ auth:
+ database: ghost
+ username: ghost
+ password: ghost-test-password
+ rootPassword: root-test-password
+
+ image:
+ pullPolicy: IfNotPresent
+
+ primary:
+ persistence:
+ enabled: false
+
+ resources:
+ limits:
+ memory: 256Mi
+ requests:
+ cpu: 50m
+ memory: 128Mi
+
+# Override database connection to use the correct service name
+config:
+ database:
+ client: "mysql"
+ connection:
+ host: "test-ghost-mariadb"
+ port: 3306
+ user: "ghost"
+ password: "ghost-test-password"
+ database: "ghost"
diff --git a/charts/ghost/templates/_helpers.tpl b/charts/ghost/templates/_helpers.tpl
index e14445ce..116cccda 100644
--- a/charts/ghost/templates/_helpers.tpl
+++ b/charts/ghost/templates/_helpers.tpl
@@ -2,56 +2,56 @@
Expand the name of the chart.
*/}}
{{- define "ghost.name" -}}
-{{- include "common.name" . -}}
+{{- include "cloudpirates.name" . -}}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "ghost.fullname" -}}
-{{- include "common.fullname" . -}}
+{{- include "cloudpirates.fullname" . -}}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "ghost.chart" -}}
-{{- include "common.chart" . -}}
+{{- include "cloudpirates.chart" . -}}
{{- end }}
{{/*
Common labels
*/}}
{{- define "ghost.labels" -}}
-{{- include "common.labels" . }}
+{{- include "cloudpirates.labels" . }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "ghost.selectorLabels" -}}
-{{- include "common.selectorLabels" . -}}
+{{- include "cloudpirates.selectorLabels" . -}}
{{- end }}
{{/*
Common annotations
*/}}
{{- define "ghost.annotations" -}}
-{{- include "common.annotations" . -}}
+{{- include "cloudpirates.annotations" . -}}
{{- end }}
{{/*
Return the proper Ghost image name
*/}}
{{- define "ghost.image" -}}
-{{- include "common.image" (dict "image" .Values.image "global" .Values.global) -}}
+{{- include "cloudpirates.image" (dict "image" .Values.image "global" .Values.global) -}}
{{- end }}
{{/*
Return the proper Docker Image Registry Secret Names
*/}}
{{- define "ghost.imagePullSecrets" -}}
-{{ include "common.images.renderPullSecrets" (dict "images" (list .Values.image) "context" .) }}
+{{ include "cloudpirates.images.renderPullSecrets" (dict "images" (list .Values.image) "context" .) }}
{{- end -}}
{{/*
diff --git a/charts/ghost/templates/configmap.yaml b/charts/ghost/templates/configmap.yaml
index 00e465ed..8479a508 100644
--- a/charts/ghost/templates/configmap.yaml
+++ b/charts/ghost/templates/configmap.yaml
@@ -5,6 +5,10 @@ metadata:
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "ghost.labels" . | nindent 4 }}
+ {{- with (include "ghost.annotations" .) }}
+ annotations:
+ {{- . | nindent 4 }}
+ {{- end }}
data:
config.production.json: |-
{
diff --git a/charts/ghost/templates/deployment.yaml b/charts/ghost/templates/deployment.yaml
index efd0eff5..f1bd4e93 100644
--- a/charts/ghost/templates/deployment.yaml
+++ b/charts/ghost/templates/deployment.yaml
@@ -32,7 +32,7 @@ spec:
{{ . | nindent 6 }}
{{- end }}
serviceAccountName: {{ include "ghost.serviceAccountName" . }}
- securityContext: {{ include "common.renderPodSecurityContext" . | nindent 8 }}
+ securityContext: {{ include "cloudpirates.renderPodSecurityContext" . | nindent 8 }}
{{- if .Values.mariadb.enabled }}
initContainers:
- name: wait-for-mariadb
@@ -43,10 +43,10 @@ spec:
- >
retries=0;
max_retries=15;
- until [ $retries -ge $max_retries ] || mariadb-admin ping -h {{ include "ghost.name" . }}-mariadb
- -P {{ .Values.mariadb.service.port }}
- -u{{ .Values.mariadb.auth.username }}
- -p{{ .Values.mariadb.auth.password }}
+ until [ $retries -ge $max_retries ] || mariadb-admin ping -h {{ include "ghost.fullname" . }}-mariadb
+ -P {{ .Values.mariadb.service.port }}
+ -u{{ .Values.mariadb.auth.username }}
+ -p{{ .Values.mariadb.auth.password }}
--silent; do
retries=$((retries+1));
echo "Waiting for MariaDB to become ready... (Attempt: $retries/$max_retries)";
@@ -56,13 +56,13 @@ spec:
fi;
sleep 2;
done;
- securityContext: {{ include "common.renderContainerSecurityContext" . | nindent 12 }}
+ securityContext: {{ include "cloudpirates.renderContainerSecurityContext" . | nindent 12 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
- securityContext: {{ include "common.renderContainerSecurityContext" . | nindent 12 }}
+ securityContext: {{ include "cloudpirates.renderContainerSecurityContext" . | nindent 12 }}
image: {{ include "ghost.image" . | quote }}
- imagePullPolicy: {{ include "common.imagePullPolicy" (dict "image" .Values.image) }}
+ imagePullPolicy: {{ include "cloudpirates.imagePullPolicy" (dict "image" .Values.image) }}
#command: ["tail", "-f", "/dev/null"]
ports:
{{- range .Values.containerPorts }}
@@ -70,11 +70,10 @@ spec:
containerPort: {{ .containerPort }}
protocol: {{ .protocol | default "TCP" }}
{{- end }}
- {{- if .Values.extraEnv }}
+ {{- if .Values.extraEnvVars }}
env:
- {{- range .Values.extraEnv }}
- - name: {{ .name }}
- value: {{ .value | quote }}
+ {{- with .Values.extraEnvVars }}
+{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
{{- if .Values.livenessProbe.enabled }}
diff --git a/charts/ghost/templates/extraobjects.yaml b/charts/ghost/templates/extraobjects.yaml
index fd7643e4..7f5ede80 100644
--- a/charts/ghost/templates/extraobjects.yaml
+++ b/charts/ghost/templates/extraobjects.yaml
@@ -1,4 +1,4 @@
{{- range .Values.extraObjects }}
---
-{{- include "common.tplvalues.render" (dict "value" . "context" $) }}
+{{- include "cloudpirates.tplvalues.render" (dict "value" . "context" $) }}
{{- end }}
\ No newline at end of file
diff --git a/charts/ghost/templates/service.yaml b/charts/ghost/templates/service.yaml
index d29f9d6d..a7536786 100644
--- a/charts/ghost/templates/service.yaml
+++ b/charts/ghost/templates/service.yaml
@@ -5,6 +5,10 @@ metadata:
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "ghost.labels" . | nindent 4 }}
+ {{- with (include "ghost.annotations" .) }}
+ annotations:
+ {{- . | nindent 4 }}
+ {{- end }}
spec:
type: {{ .Values.service.type }}
ports:
diff --git a/charts/ghost/values.schema.json b/charts/ghost/values.schema.json
index 6895104f..d44bec84 100644
--- a/charts/ghost/values.schema.json
+++ b/charts/ghost/values.schema.json
@@ -1,388 +1,674 @@
{
- "$schema": "https://json-schema.org/draft-07/schema#",
- "type": "object",
- "title": "Ghost Helm Chart Values Schema",
- "description": "Schema for Ghost Helm chart values",
- "properties": {
- "global": {
- "type": "object",
- "properties": {
- "imageRegistry": { "type": "string" },
- "imagePullSecrets": {
- "type": "array",
- "items": {
- "type": ["string", "object"],
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "type": "object",
+ "properties": {
+ "affinity": {
+ "type": "object"
+ },
+ "autoscaling": {
+ "type": "object",
"properties": {
- "name": { "type": "string" }
- },
- "required": ["name"]
- }
- }
- }
- },
- "nameOverride": { "type": "string" },
- "fullnameOverride": { "type": "string" },
- "commonLabels": { "type": "object", "additionalProperties": { "type": "string" } },
- "commonAnnotations": { "type": "object", "additionalProperties": { "type": "string" } },
- "image": {
- "type": "object",
- "properties": {
- "registry": { "type": "string" },
- "repository": { "type": "string" },
- "tag": { "type": "string" },
- "pullPolicy": { "type": "string", "enum": ["Always", "IfNotPresent", "Never"] }
- }
- },
- "replicaCount": { "type": "integer", "minimum": 1 },
- "containerPort": { "type": "integer", "minimum": 1, "maximum": 65535 },
- "containerPorts": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": { "type": "string" },
- "containerPort": { "type": "integer", "minimum": 1, "maximum": 65535 },
- "protocol": { "type": "string", "enum": ["TCP", "UDP"], "default": "TCP" }
+ "enabled": {
+ "type": "boolean"
+ },
+ "maxReplicas": {
+ "type": "string"
+ },
+ "minReplicas": {
+ "type": "string"
+ },
+ "targetCPUUtilizationPercentage": {
+ "type": "string"
+ },
+ "targetMemoryUtilizationPercentage": {
+ "type": "string"
+ }
+ }
+ },
+ "commonAnnotations": {
+ "type": "object"
},
- "required": ["name", "containerPort"]
- }
- },
- "service": {
- "type": "object",
- "properties": {
- "type": { "type": "string", "enum": ["ClusterIP", "NodePort", "LoadBalancer"] },
- "port": { "type": "integer", "minimum": 1, "maximum": 65535 },
- "ports": {
- "type": "array",
- "items": {
+ "commonLabels": {
+ "type": "object"
+ },
+ "config": {
"type": "object",
"properties": {
- "port": { "type": "integer", "minimum": 1, "maximum": 65535 },
- "targetPort": { "type": "string" },
- "protocol": { "type": "string", "enum": ["TCP", "UDP"], "default": "TCP" },
- "name": { "type": "string" }
- },
- "required": ["port", "targetPort", "name"]
- }
- }
- }
- },
- "ingress": {
- "type": "object",
- "properties": {
- "enabled": { "type": "boolean" },
- "className": { "type": "string" },
- "annotations": { "type": "object", "additionalProperties": { "type": "string" } },
- "hosts": {
- "type": "array",
- "items": {
+ "adapters": {
+ "type": "object",
+ "properties": {
+ "cache": {
+ "type": "object",
+ "properties": {
+ "imageSizes": {
+ "type": "object",
+ "properties": {
+ "adapter": {
+ "type": "string"
+ },
+ "keyPrefix": {
+ "type": "string"
+ },
+ "ttl": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "caching": {
+ "type": "object",
+ "properties": {
+ "contentAPI": {
+ "type": "object",
+ "properties": {
+ "maxAge": {
+ "type": "integer"
+ }
+ }
+ },
+ "cors": {
+ "type": "object",
+ "properties": {
+ "maxAge": {
+ "type": "integer"
+ }
+ }
+ },
+ "customRedirects": {
+ "type": "object",
+ "properties": {
+ "maxAge": {
+ "type": "integer"
+ }
+ }
+ },
+ "frontend": {
+ "type": "object",
+ "properties": {
+ "maxAge": {
+ "type": "integer"
+ }
+ }
+ },
+ "publicAssets": {
+ "type": "object",
+ "properties": {
+ "maxAge": {
+ "type": "integer"
+ }
+ }
+ },
+ "robotstxt": {
+ "type": "object",
+ "properties": {
+ "maxAge": {
+ "type": "integer"
+ }
+ }
+ },
+ "sitemap": {
+ "type": "object",
+ "properties": {
+ "maxAge": {
+ "type": "integer"
+ }
+ }
+ },
+ "sitemapXSL": {
+ "type": "object",
+ "properties": {
+ "maxAge": {
+ "type": "integer"
+ }
+ }
+ },
+ "threeHundredOne": {
+ "type": "object",
+ "properties": {
+ "maxAge": {
+ "type": "integer"
+ }
+ }
+ },
+ "wellKnown": {
+ "type": "object",
+ "properties": {
+ "maxAge": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ },
+ "comments": {
+ "type": "object",
+ "properties": {
+ "styles": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ }
+ }
+ },
+ "compress": {
+ "type": "boolean"
+ },
+ "database": {
+ "type": "object",
+ "properties": {
+ "client": {
+ "type": "string"
+ },
+ "externalConnection": {
+ "type": "object",
+ "properties": {
+ "database": {
+ "type": "string"
+ },
+ "host": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "port": {
+ "type": "integer"
+ },
+ "user": {
+ "type": "string"
+ }
+ }
+ },
+ "pool": {
+ "type": "object",
+ "properties": {
+ "max": {
+ "type": "integer"
+ },
+ "min": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ },
+ "imageOptimization": {
+ "type": "object",
+ "properties": {
+ "resize": {
+ "type": "boolean"
+ }
+ }
+ },
+ "logging": {
+ "type": "object",
+ "properties": {
+ "level": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "rotation": {
+ "type": "object",
+ "properties": {
+ "count": {
+ "type": "integer"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "period": {
+ "type": "string"
+ }
+ }
+ },
+ "transports": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "useLocalTime": {
+ "type": "boolean"
+ }
+ }
+ },
+ "mail": {
+ "type": "object",
+ "properties": {
+ "from": {
+ "type": "string"
+ },
+ "options": {
+ "type": "object",
+ "properties": {
+ "auth": {
+ "type": "object",
+ "properties": {
+ "pass": {
+ "type": "string"
+ },
+ "user": {
+ "type": "string"
+ }
+ }
+ },
+ "host": {
+ "type": "string"
+ },
+ "port": {
+ "type": "integer"
+ },
+ "secure": {
+ "type": "boolean"
+ },
+ "service": {
+ "type": "string"
+ }
+ }
+ },
+ "transport": {
+ "type": "string"
+ }
+ }
+ },
+ "paths": {
+ "type": "object",
+ "properties": {
+ "contentPath": {
+ "type": "string"
+ }
+ }
+ },
+ "portal": {
+ "type": "object",
+ "properties": {
+ "url": {
+ "type": "string"
+ }
+ }
+ },
+ "privacy": {
+ "type": "object",
+ "properties": {
+ "useGravatar": {
+ "type": "boolean"
+ },
+ "useRpcPing": {
+ "type": "boolean"
+ },
+ "useStructuredData": {
+ "type": "boolean"
+ },
+ "useUpdateCheck": {
+ "type": "boolean"
+ }
+ }
+ },
+ "referrerPolicy": {
+ "type": "string"
+ },
+ "security": {
+ "type": "object",
+ "properties": {
+ "staffDeviceVerification": {
+ "type": "boolean"
+ }
+ }
+ },
+ "server": {
+ "type": "object",
+ "properties": {
+ "host": {
+ "type": "string"
+ },
+ "port": {
+ "type": "integer"
+ }
+ }
+ },
+ "sodoSearch": {
+ "type": "object",
+ "properties": {
+ "styles": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ }
+ }
+ },
+ "storage": {
+ "type": "object",
+ "properties": {
+ "active": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "containerPorts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "containerPort": {
+ "type": "integer"
+ },
+ "name": {
+ "type": "string"
+ },
+ "protocol": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "containerSecurityContext": {
"type": "object",
"properties": {
- "host": { "type": "string" },
- "paths": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "path": { "type": "string" },
- "pathType": { "type": "string" }
- },
- "required": ["path", "pathType"]
+ "allowPrivilegeEscalation": {
+ "type": "boolean"
+ },
+ "runAsNonRoot": {
+ "type": "boolean"
+ },
+ "runAsUser": {
+ "type": "integer"
}
- }
- },
- "required": ["host", "paths"]
- }
+ }
+ },
+ "extraEnvVars": {
+ "type": "array"
},
- "tls": {
- "type": "array",
- "items": {
+ "extraObjects": {
+ "type": "array"
+ },
+ "extraVolumeMounts": {
+ "type": "array"
+ },
+ "extraVolumes": {
+ "type": "array"
+ },
+ "fullnameOverride": {
+ "type": "string"
+ },
+ "global": {
"type": "object",
"properties": {
- "hosts": { "type": "array", "items": { "type": "string" } },
- "secretName": { "type": "string" }
+ "imagePullSecrets": {
+ "type": "array"
+ },
+ "imageRegistry": {
+ "type": "string"
+ }
}
- }
- }
- }
- },
- "serviceAccount": {
- "type": "object",
- "properties": {
- "create": { "type": "boolean" },
- "annotations": { "type": "object", "additionalProperties": { "type": "string" } },
- "name": { "type": "string" },
- "automountServiceAccountToken": { "type": "boolean" }
- }
- },
- "autoscaling": {
- "type": "object",
- "properties": {
- "enabled": { "type": "boolean" },
- "minReplicas": { "type": ["integer", "string"] },
- "maxReplicas": { "type": ["integer", "string"] },
- "targetCPUUtilizationPercentage": { "type": ["integer", "string"] },
- "targetMemoryUtilizationPercentage": { "type": ["integer", "string"] }
- }
- },
- "resources": { "type": "object" },
- "nodeSelector": { "type": "object", "additionalProperties": { "type": "string" } },
- "tolerations": { "type": "array", "items": { "type": "object" } },
- "affinity": { "type": "object" },
- "containerSecurityContext": {
- "type": "object",
- "properties": {
- "runAsUser": { "type": "integer" },
- "runAsNonRoot": { "type": "boolean" },
- "allowPrivilegeEscalation": { "type": "boolean" }
- }
- },
- "podSecurityContext": {
- "type": "object",
- "properties": {
- "fsGroup": { "type": "integer" }
- }
- },
- "livenessProbe": {
- "type": "object",
- "properties": {
- "enabled": { "type": "boolean" },
- "type": { "type": "string", "enum": ["tcpSocket", "httpGet"], "default": "tcpSocket" },
- "path": { "type": "string", "default": "/" },
- "initialDelaySeconds": { "type": "integer" },
- "periodSeconds": { "type": "integer" },
- "timeoutSeconds": { "type": "integer" },
- "failureThreshold": { "type": "integer" },
- "successThreshold": { "type": "integer" }
- }
- },
- "readinessProbe": {
- "type": "object",
- "properties": {
- "enabled": { "type": "boolean" },
- "type": { "type": "string", "enum": ["tcpSocket", "httpGet"], "default": "tcpSocket" },
- "path": { "type": "string", "default": "/" },
- "initialDelaySeconds": { "type": "integer" },
- "periodSeconds": { "type": "integer" },
- "timeoutSeconds": { "type": "integer" },
- "failureThreshold": { "type": "integer" },
- "successThreshold": { "type": "integer" }
- }
- },
- "extraEnv": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": { "type": "string" },
- "value": { "type": "string" }
},
- "required": ["name", "value"]
- }
- },
- "extraVolumes": { "type": "array", "items": { "type": "object" } },
- "extraVolumeMounts": { "type": "array", "items": { "type": "object" } },
- "extraObjects": { "type": "array", "items": { "type": "object" } },
- "persistence": {
- "type": "object",
- "properties": {
- "enabled": { "type": "boolean" },
- "annotations": { "type": "object", "additionalProperties": { "type": "string" } },
- "existingClaim": { "type": "string" },
- "storageClass": { "type": "string" },
- "accessModes": { "type": "array", "items": { "type": "string" } },
- "size": { "type": "string" }
- }
- },
- "initContainers": {
- "type": "object",
- "properties": {
- "waitForMariadb": {
- "type": "object",
- "properties": {
- "image": { "type": "string" }
- }
- }
- }
- },
- "config": {
- "type": "object",
- "properties": {
- "database": {
- "type": "object",
- "properties": {
- "client": { "type": "string" },
- "externalConnection": {
- "type": "object",
- "properties": {
- "host": { "type": "string" },
- "port": { "type": "integer" },
- "user": { "type": "string" },
- "password": { "type": "string" },
- "database": { "type": "string" }
- }
- },
- "pool": {
- "type": "object",
- "properties": {
- "min": { "type": "integer" },
- "max": { "type": "integer" }
- }
+ "image": {
+ "type": "object",
+ "properties": {
+ "pullPolicy": {
+ "type": "string"
+ },
+ "registry": {
+ "type": "string"
+ },
+ "repository": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ }
}
- }
},
- "mail": {
- "type": "object",
- "properties": {
- "transport": { "type": "string" },
- "options": {
- "type": "object",
- "properties": {
- "service": { "type": "string" },
- "host": { "type": "string" },
- "port": { "type": "integer" },
- "secure": { "type": "boolean" },
- "auth": {
- "type": "object",
- "properties": {
- "user": { "type": "string" },
- "pass": { "type": "string" }
- }
+ "ingress": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object"
+ },
+ "className": {
+ "type": "string"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "hosts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "host": {
+ "type": "string"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "pathType": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tls": {
+ "type": "array"
}
- }
- },
- "from": { "type": "string" }
- }
+ }
},
- "server": {
- "type": "object",
- "properties": {
- "host": { "type": "string" },
- "port": { "type": "integer" }
- }
+ "initContainers": {
+ "type": "object",
+ "properties": {
+ "waitForMariadb": {
+ "type": "object",
+ "properties": {
+ "image": {
+ "type": "string"
+ }
+ }
+ }
+ }
},
- "privacy": {
- "type": "object",
- "properties": {
- "useUpdateCheck": { "type": "boolean" },
- "useGravatar": { "type": "boolean" },
- "useRpcPing": { "type": "boolean" },
- "useStructuredData": { "type": "boolean" }
- }
+ "livenessProbe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "path": {
+ "type": "string"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ },
+ "type": {
+ "type": "string"
+ }
+ }
},
- "security": {
- "type": "object",
- "properties": {
- "staffDeviceVerification": { "type": "boolean" }
- }
+ "mariadb": {
+ "type": "object",
+ "properties": {
+ "auth": {
+ "type": "object",
+ "properties": {
+ "allowEmptyRootPassword": {
+ "type": "boolean"
+ },
+ "database": {
+ "type": "string"
+ },
+ "existingSecret": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "username": {
+ "type": "string"
+ }
+ }
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "service": {
+ "type": "object",
+ "properties": {
+ "port": {
+ "type": "integer"
+ }
+ }
+ }
+ }
},
- "paths": {
- "type": "object",
- "properties": {
- "contentPath": { "type": "string" }
- }
+ "nameOverride": {
+ "type": "string"
},
- "referrerPolicy": { "type": "string" },
- "logging": {
- "type": "object",
- "properties": {
- "path": { "type": "string" },
- "useLocalTime": { "type": "boolean" },
- "level": { "type": "string" },
- "rotation": {
- "type": "object",
- "properties": {
- "enabled": { "type": "boolean" },
- "count": { "type": "integer" },
- "period": { "type": "string" }
- }
- },
- "transports": { "type": "array", "items": { "type": "string" } }
- }
+ "nodeSelector": {
+ "type": "object"
},
- "caching": {
- "type": "object",
- "additionalProperties": {
- "type": ["object", "integer"],
+ "persistence": {
+ "type": "object",
"properties": {
- "maxAge": { "type": "integer" }
+ "accessModes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "annotations": {
+ "type": "object"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "existingClaim": {
+ "type": "string"
+ },
+ "size": {
+ "type": "string"
+ },
+ "storageClass": {
+ "type": "string"
+ }
}
- }
- },
- "compress": { "type": "boolean" },
- "imageOptimization": {
- "type": "object",
- "properties": {
- "resize": { "type": "boolean" }
- }
},
- "storage": {
- "type": "object",
- "properties": {
- "active": { "type": "string" }
- }
- },
- "adapters": {
- "type": "object",
- "properties": {
- "cache": {
- "type": "object",
- "properties": {
- "imageSizes": {
- "type": "object",
- "properties": {
- "adapter": { "type": "string" },
- "ttl": { "type": "integer" },
- "keyPrefix": { "type": "string" }
- }
+ "podSecurityContext": {
+ "type": "object",
+ "properties": {
+ "fsGroup": {
+ "type": "integer"
}
- }
}
- }
},
- "portal": {
- "type": "object",
- "properties": {
- "url": { "type": "string" }
- }
+ "readinessProbe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "path": {
+ "type": "string"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ },
+ "type": {
+ "type": "string"
+ }
+ }
},
- "sodoSearch": {
- "type": "object",
- "properties": {
- "url": { "type": "string" },
- "styles": { "type": "string" }
- }
+ "replicaCount": {
+ "type": "integer"
},
- "comments": {
- "type": "object",
- "properties": {
- "url": { "type": "string" },
- "styles": { "type": "string" }
- }
- }
- }
- },
- "mariadb": {
- "type": "object",
- "properties": {
- "enabled": { "type": "boolean" },
- "auth": {
- "type": "object",
- "properties": {
- "database": { "type": "string" },
- "username": { "type": "string" },
- "password": { "type": "string" },
- "existingSecret": { "type": "string" },
- "allowEmptyRootPassword": { "type": "boolean" }
- }
+ "resources": {
+ "type": "object"
},
"service": {
- "type": "object",
- "properties": {
- "port": { "type": "integer" }
- }
+ "type": "object",
+ "properties": {
+ "ports": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "port": {
+ "type": "integer"
+ },
+ "protocol": {
+ "type": "string"
+ },
+ "targetPort": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "type": {
+ "type": "string"
+ }
+ }
+ },
+ "serviceAccount": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object"
+ },
+ "automountServiceAccountToken": {
+ "type": "boolean"
+ },
+ "create": {
+ "type": "boolean"
+ },
+ "name": {
+ "type": "string"
+ }
+ }
+ },
+ "tolerations": {
+ "type": "array"
}
- }
}
- }
-}
\ No newline at end of file
+}
diff --git a/charts/ghost/values.yaml b/charts/ghost/values.yaml
index 2decfdf5..6e13933e 100644
--- a/charts/ghost/values.yaml
+++ b/charts/ghost/values.yaml
@@ -22,7 +22,7 @@ image:
## @param image.repository Nginx image repository
repository: ghost
## @param image.tag Nginx image tag
- tag: "6.2.0@sha256:ffc213a6f2db7210b69396dc4330b4a9c5e27c8b044ae453854d53bd3937a6ec"
+ tag: "6.6.0@sha256:d49be5129610c38e9c785478344943d910c141866bb91cbe17b6d451370f03e1"
## @param image.pullPolicy Nginx image pull policy
pullPolicy: Always
@@ -175,10 +175,15 @@ readinessProbe:
## @param readinessProbe.successThreshold Number of successes to mark probe as successful
successThreshold: 1
-## @param extraEnv Additional environment variables to set
-extraEnv: []
-# - name: EXTRA_VAR
-# value: "extra_value"
+## @param extraEnvVars Additional environment variables to set
+extraEnvVars: []
+ # - name: CUSTOM_VAR
+ # value: "custom-value"
+ # - name: SECRET_VAR
+ # valueFrom:
+ # secretKeyRef:
+ # name: my-secret
+ # key: secret-key
## @param extraVolumes Additional volumes to add to the pod
extraVolumes: []
diff --git a/charts/keycloak/CHANGELOG.md b/charts/keycloak/CHANGELOG.md
index e3571349..79acbb02 100644
--- a/charts/keycloak/CHANGELOG.md
+++ b/charts/keycloak/CHANGELOG.md
@@ -1,5 +1,195 @@
# Changelog
+
+## 0.8.2 (2025-11-05)
+
+* [keycloak]: Fix mariadb configuration (#544) ([6cec40c](https://github.com/CloudPirates-io/helm-charts/commit/6cec40c))
+* chore: update CHANGELOG.md for merged changes ([72853a9](https://github.com/CloudPirates-io/helm-charts/commit/72853a9))
+* chore: update CHANGELOG.md for merged changes ([cd5cd19](https://github.com/CloudPirates-io/helm-charts/commit/cd5cd19))
+
+## 0.8.1 (2025-11-02)
+
+* [keycloak]: Fix https settings in keycloak when disabling http (#530) ([b0c34f6](https://github.com/CloudPirates-io/helm-charts/commit/b0c34f6))
+* chore: update CHANGELOG.md for merged changes ([3062545](https://github.com/CloudPirates-io/helm-charts/commit/3062545))
+* chore: update CHANGELOG.md for merged changes ([19b8107](https://github.com/CloudPirates-io/helm-charts/commit/19b8107))
+
+## 0.8.0 (2025-10-30)
+
+* Provide empty mounts for themes and providers (#504) ([4d2f107](https://github.com/CloudPirates-io/helm-charts/commit/4d2f107))
+* chore: update CHANGELOG.md for merged changes ([385f22b](https://github.com/CloudPirates-io/helm-charts/commit/385f22b))
+* chore: update CHANGELOG.md for merged changes ([488fba4](https://github.com/CloudPirates-io/helm-charts/commit/488fba4))
+
+## 0.7.1 (2025-10-29)
+
+* fix: use metrics service targetPort configuration (#493) ([bd3cc53](https://github.com/CloudPirates-io/helm-charts/commit/bd3cc53))
+* chore: update CHANGELOG.md for merged changes ([8260788](https://github.com/CloudPirates-io/helm-charts/commit/8260788))
+* chore: update CHANGELOG.md for merged changes ([402f7bd](https://github.com/CloudPirates-io/helm-charts/commit/402f7bd))
+
+## 0.7.0 (2025-10-28)
+
+* chore: update CHANGELOG.md for merged changes ([aec2fd6](https://github.com/CloudPirates-io/helm-charts/commit/aec2fd6))
+* chore: update CHANGELOG.md for merged changes ([8e4ff4a](https://github.com/CloudPirates-io/helm-charts/commit/8e4ff4a))
+* chore: auto-generate values.schema.json (#473) ([d9a38d4](https://github.com/CloudPirates-io/helm-charts/commit/d9a38d4))
+* chore: update CHANGELOG.md for merged changes ([293ae00](https://github.com/CloudPirates-io/helm-charts/commit/293ae00))
+* chore: update CHANGELOG.md for merged changes ([ae9c37b](https://github.com/CloudPirates-io/helm-charts/commit/ae9c37b))
+
+## 0.6.8 (2025-10-27)
+
+* add mssql support (#469) ([11cdbfb](https://github.com/CloudPirates-io/helm-charts/commit/11cdbfb))
+* chore: update CHANGELOG.md for merged changes ([6813d85](https://github.com/CloudPirates-io/helm-charts/commit/6813d85))
+* chore: update CHANGELOG.md for merged changes ([2e40f13](https://github.com/CloudPirates-io/helm-charts/commit/2e40f13))
+
+## 0.6.7 (2025-10-26)
+
+* [keycloak/keycloak] Update charts/keycloak/values.yaml keycloak/keycloak to v26.4.2 (patch) (#453) ([52a01c8](https://github.com/CloudPirates-io/helm-charts/commit/52a01c8))
+* chore: update CHANGELOG.md for merged changes ([f9c3ff0](https://github.com/CloudPirates-io/helm-charts/commit/f9c3ff0))
+* chore: update CHANGELOG.md for merged changes ([db2d800](https://github.com/CloudPirates-io/helm-charts/commit/db2d800))
+
+## 0.6.6 (2025-10-23)
+
+* chore: update CHANGELOG.md for merged changes ([051ad83](https://github.com/CloudPirates-io/helm-charts/commit/051ad83))
+* chore: update CHANGELOG.md for merged changes ([1a50307](https://github.com/CloudPirates-io/helm-charts/commit/1a50307))
+
+## 0.6.5 (2025-10-22)
+
+* chore: update CHANGELOG.md for merged changes ([c80ea42](https://github.com/CloudPirates-io/helm-charts/commit/c80ea42))
+* chore: update CHANGELOG.md for merged changes ([8ccb4bb](https://github.com/CloudPirates-io/helm-charts/commit/8ccb4bb))
+* chore: update CHANGELOG.md for merged changes ([5d1f01a](https://github.com/CloudPirates-io/helm-charts/commit/5d1f01a))
+* chore: update CHANGELOG.md for merged changes ([fc47c5d](https://github.com/CloudPirates-io/helm-charts/commit/fc47c5d))
+* chore: update CHANGELOG.md for merged changes ([1a4f87b](https://github.com/CloudPirates-io/helm-charts/commit/1a4f87b))
+* chore: update CHANGELOG.md for merged changes ([da866ca](https://github.com/CloudPirates-io/helm-charts/commit/da866ca))
+* chore: update CHANGELOG.md for merged changes ([b06a24e](https://github.com/CloudPirates-io/helm-charts/commit/b06a24e))
+* chore: update CHANGELOG.md for merged changes ([b70f02c](https://github.com/CloudPirates-io/helm-charts/commit/b70f02c))
+* chore: update CHANGELOG.md for merged changes ([94c7881](https://github.com/CloudPirates-io/helm-charts/commit/94c7881))
+
+## 0.6.4 (2025-10-17)
+
+* realm import (#402) ([4257b8b](https://github.com/CloudPirates-io/helm-charts/commit/4257b8b))
+* chore: update CHANGELOG.md for merged changes ([1184994](https://github.com/CloudPirates-io/helm-charts/commit/1184994))
+* chore: update CHANGELOG.md for merged changes ([8b0e613](https://github.com/CloudPirates-io/helm-charts/commit/8b0e613))
+
+## 0.6.3 (2025-10-17)
+
+* [keycloak/keycloak] Update charts/keycloak/values.yaml keycloak/keycloak to v26.4.1 (patch) (#400) ([c6f2ca2](https://github.com/CloudPirates-io/helm-charts/commit/c6f2ca2))
+* chore: update CHANGELOG.md for merged changes ([b54c4f1](https://github.com/CloudPirates-io/helm-charts/commit/b54c4f1))
+* chore: update CHANGELOG.md for merged changes ([5a2ed20](https://github.com/CloudPirates-io/helm-charts/commit/5a2ed20))
+* chore: update CHANGELOG.md for merged changes ([48c9191](https://github.com/CloudPirates-io/helm-charts/commit/48c9191))
+* chore: update CHANGELOG.md for merged changes ([46b32bf](https://github.com/CloudPirates-io/helm-charts/commit/46b32bf))
+
+## 0.6.2 (2025-10-14)
+
+* Add support for templating hostname and hostnameAdmin (#390) ([133f4d5](https://github.com/CloudPirates-io/helm-charts/commit/133f4d5))
+* chore: update CHANGELOG.md for merged changes ([848e965](https://github.com/CloudPirates-io/helm-charts/commit/848e965))
+* chore: update CHANGELOG.md for merged changes ([353c0fc](https://github.com/CloudPirates-io/helm-charts/commit/353c0fc))
+
+## 0.6.1 (2025-10-14)
+
+* [keycloak]: Implement TLS in keycloak (#373) ([04abaee](https://github.com/CloudPirates-io/helm-charts/commit/04abaee))
+* chore: update CHANGELOG.md for merged changes ([4b02e57](https://github.com/CloudPirates-io/helm-charts/commit/4b02e57))
+* chore: update CHANGELOG.md for merged changes ([bf2e3b2](https://github.com/CloudPirates-io/helm-charts/commit/bf2e3b2))
+* chore: update CHANGELOG.md for merged changes ([2f87d0e](https://github.com/CloudPirates-io/helm-charts/commit/2f87d0e))
+
+## 0.6.0 (2025-10-14)
+
+* chore: update CHANGELOG.md for merged changes ([84cf67b](https://github.com/CloudPirates-io/helm-charts/commit/84cf67b))
+* chore: update CHANGELOG.md for all charts via manual trigger ([6974964](https://github.com/CloudPirates-io/helm-charts/commit/6974964))
+* chore: update CHANGELOG.md for merged changes ([63b7bfa](https://github.com/CloudPirates-io/helm-charts/commit/63b7bfa))
+* chore: update CHANGELOG.md for merged changes ([da69e0e](https://github.com/CloudPirates-io/helm-charts/commit/da69e0e))
+* chore: update CHANGELOG.md for merged changes ([5da1b15](https://github.com/CloudPirates-io/helm-charts/commit/5da1b15))
+
+## 0.5.1 (2025-10-13)
+
+* chore: update CHANGELOG.md for merged changes ([a67d12a](https://github.com/CloudPirates-io/helm-charts/commit/a67d12a))
+* chore: update CHANGELOG.md for merged changes ([a4bd5ac](https://github.com/CloudPirates-io/helm-charts/commit/a4bd5ac))
+
+## 0.5.0 (2025-10-13)
+
+* feat: add metrics (#368) ([cf5aba0](https://github.com/CloudPirates-io/helm-charts/commit/cf5aba0))
+
+## 0.4.0 (2025-10-10)
+
+* Import realm (#219) ([f7ff0cf](https://github.com/CloudPirates-io/helm-charts/commit/f7ff0cf))
+* add tests for openshift (#226) ([c80c98a](https://github.com/CloudPirates-io/helm-charts/commit/c80c98a))
+* [keycloak]: Fix invalid documentation (#283) ([59f3d3c](https://github.com/CloudPirates-io/helm-charts/commit/59f3d3c))
+
## 0.3.2 (2025-10-09)
-* [mongodb] feat: add metrics exporter ([#243](https://github.com/CloudPirates-io/helm-charts/pull/243))
+* [keycloak/keycloak] Update charts/keycloak/values.yaml keycloak/keycloak to v26.4.0 (minor) (#270) ([b107e1b](https://github.com/CloudPirates-io/helm-charts/commit/b107e1b))
+
+## 0.3.1 (2025-10-09)
+
+* [keycloak/keycloak] Update charts/keycloak/values.yaml keycloak/keycloak to v26.3.5 (patch) (#261) ([360de40](https://github.com/CloudPirates-io/helm-charts/commit/360de40))
+
+## 0.3.0 (2025-10-08)
+
+* make keycloak run on openshift (#225) ([9b4f896](https://github.com/CloudPirates-io/helm-charts/commit/9b4f896))
+
+## 0.2.1 (2025-10-07)
+
+* default http relative path to '/' to fix argocd deployment (#221) ([bdb1946](https://github.com/CloudPirates-io/helm-charts/commit/bdb1946))
+
+## 0.2.0 (2025-10-06)
+
+* Add support for extra volumes, volumeMounts and initContainers (#215) ([16afcfe](https://github.com/CloudPirates-io/helm-charts/commit/16afcfe))
+
+## 0.1.12 (2025-10-06)
+
+
+## 0.1.11 (2025-10-06)
+
+* Allow keycloak to have a relative path (#216) ([0237457](https://github.com/CloudPirates-io/helm-charts/commit/0237457))
+
+## 0.1.10 (2025-10-02)
+
+
+## 0.1.9 (2025-10-02)
+
+* add topologySpreadConstraints and trafficDistribution optiโฆ (#209) ([c777fca](https://github.com/CloudPirates-io/helm-charts/commit/c777fca))
+
+## 0.1.8 (2025-09-30)
+
+* Feature/command customize (#186) ([a458e15](https://github.com/CloudPirates-io/helm-charts/commit/a458e15))
+
+## 0.1.7 (2025-09-29)
+
+* replace deprecated 'proxy' with new proxy parameters (#183) ([d850b7b](https://github.com/CloudPirates-io/helm-charts/commit/d850b7b))
+
+## 0.1.6 (2025-09-26)
+
+
+## 0.1.5 (2025-09-25)
+
+* add support for extra env vars from an existing secret (#158) ([263604f](https://github.com/CloudPirates-io/helm-charts/commit/263604f))
+* Update CHANGELOG.md ([b7572a8](https://github.com/CloudPirates-io/helm-charts/commit/b7572a8))
+* Update CHANGELOG.md ([245f9b6](https://github.com/CloudPirates-io/helm-charts/commit/245f9b6))
+* Update CHANGELOG.md ([0bf9f75](https://github.com/CloudPirates-io/helm-charts/commit/0bf9f75))
+
+## 0.1.4 (2025-09-24)
+
+* Update CHANGELOG.md ([03d476e](https://github.com/CloudPirates-io/helm-charts/commit/03d476e))
+* Bump the correct thing ([35e7901](https://github.com/CloudPirates-io/helm-charts/commit/35e7901))
+* Update CHANGELOG.md ([20c19bb](https://github.com/CloudPirates-io/helm-charts/commit/20c19bb))
+
+## 0.1.3 (2025-09-23)
+
+* Update CHANGELOG.md ([68435aa](https://github.com/CloudPirates-io/helm-charts/commit/68435aa))
+* Fix resolving template expressions in extraobjects ([12a1cb5](https://github.com/CloudPirates-io/helm-charts/commit/12a1cb5))
+
+## 0.1.2 (2025-09-22)
+
+* Update CHANGELOG.md ([b8adca8](https://github.com/CloudPirates-io/helm-charts/commit/b8adca8))
+* Fix chart version bump ([aae07b1](https://github.com/CloudPirates-io/helm-charts/commit/aae07b1))
+* Fix deprecated env vars warning ([50d9fa0](https://github.com/CloudPirates-io/helm-charts/commit/50d9fa0))
+
+## 0.1.1 (2025-09-19)
+
+* Update CHANGELOG.md ([62e51b9](https://github.com/CloudPirates-io/helm-charts/commit/62e51b9))
+* add readme documentation and values.schema.json ([369448b](https://github.com/CloudPirates-io/helm-charts/commit/369448b))
+* Update CHANGELOG.md ([54f725e](https://github.com/CloudPirates-io/helm-charts/commit/54f725e))
+* chore: fix changelog ([bd9f1a8](https://github.com/CloudPirates-io/helm-charts/commit/bd9f1a8))
+* Update CHANGELOG.md ([2ed9b3f](https://github.com/CloudPirates-io/helm-charts/commit/2ed9b3f))
+* Update CHANGELOG.md ([2178148](https://github.com/CloudPirates-io/helm-charts/commit/2178148))
+
+## 0.1.0 (2025-09-17)
+
+* Initial tagged release
diff --git a/charts/keycloak/Chart.lock b/charts/keycloak/Chart.lock
index 85b2f901..0cd60f93 100644
--- a/charts/keycloak/Chart.lock
+++ b/charts/keycloak/Chart.lock
@@ -1,12 +1,12 @@
dependencies:
- name: common
repository: oci://registry-1.docker.io/cloudpirates
- version: 1.1.1
+ version: 2.0.0
- name: postgres
repository: oci://registry-1.docker.io/cloudpirates
- version: 0.7.2
+ version: 0.9.0
- name: mariadb
repository: oci://registry-1.docker.io/cloudpirates
- version: 0.3.2
-digest: sha256:886649f9f78f7bf1f296dabcca5eb8cd0dbd9d0fdb540a327e6a299817fd4b53
-generated: "2025-10-07T21:13:04.453964+02:00"
+ version: 0.4.0
+digest: sha256:463f4ba9998938275a7f067fe0d027654755735c164f48285ebc219f025d28b9
+generated: "2025-10-14T13:20:51.905266+02:00"
diff --git a/charts/keycloak/Chart.yaml b/charts/keycloak/Chart.yaml
index 2e61bbc7..54442212 100644
--- a/charts/keycloak/Chart.yaml
+++ b/charts/keycloak/Chart.yaml
@@ -2,8 +2,8 @@ apiVersion: v2
name: keycloak
description: Open Source Identity and Access Management Solution
type: application
-version: 0.3.2
-appVersion: "26.3.4"
+version: 0.8.2
+appVersion: "26.4.2"
keywords:
- keycloak
- identity
@@ -13,22 +13,46 @@ keywords:
- oauth
- openid-connect
- saml
-home: https://www.cloudpirates.io
+home: https://www.keycloak.org
sources:
- https://github.com/CloudPirates-io/helm-charts/tree/main/charts/keycloak
+ - https://github.com/keycloak/keycloak
maintainers:
- name: CloudPirates GmbH & Co. KG
+ email: hello@cloudpirates.io
url: https://www.cloudpirates.io
dependencies:
- name: common
- version: "1.x.x"
+ version: "2.x.x"
repository: oci://registry-1.docker.io/cloudpirates
- name: postgres
- version: "0.x.x"
+ version: "0.9.x"
repository: oci://registry-1.docker.io/cloudpirates
condition: postgres.enabled
- name: mariadb
- version: "0.x.x"
+ version: "0.4.x"
repository: oci://registry-1.docker.io/cloudpirates
condition: mariadb.enabled
icon: https://a.storyblok.com/f/143071/512x512/6a85e594b2/keycloak-logo.svg
+annotations:
+ license: Apache-2.0
+ artifacthub.io/category: security
+ artifacthub.io/containsSecurityUpdates: "false"
+ artifacthub.io/signKey: |
+ fingerprint: 6917f1a88c122cbb1de5aa55457752135bdcf95a
+ url: https://raw.githubusercontent.com/CloudPirates-io/helm-charts/refs/heads/main/cosign.pub
+ artifacthub.io/links: |
+ - name: Keycloak
+ url: https://www.keycloak.org
+ - name: Helm Chart
+ url: https://github.com/CloudPirates-io/helm-charts/tree/main/charts/keycloak
+ - name: Application
+ url: https://github.com/keycloak/keycloak
+ - name: Maintainer CloudPirates
+ url: https://www.cloudpirates.io
+ artifacthub.io/changes: |2
+ - kind: changed
+ description: "[keycloak]: Fix mariadb configuration (#544)"
+ links:
+ - name: "Commit 6cec40c"
+ url: "https://github.com/CloudPirates-io/helm-charts/commit/6cec40c"
diff --git a/charts/keycloak/LICENSE b/charts/keycloak/LICENSE
new file mode 100644
index 00000000..261eeb9e
--- /dev/null
+++ b/charts/keycloak/LICENSE
@@ -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.
diff --git a/charts/keycloak/README.md b/charts/keycloak/README.md
index 10372ca3..872bf10d 100644
--- a/charts/keycloak/README.md
+++ b/charts/keycloak/README.md
@@ -108,9 +108,9 @@ The following table lists the configurable parameters of the Keycloak chart and
### Extra init containers for Keycloak pod
-| Parameter | Description | Default |
-| --------------------- | ----------------------------------------------------- | ------- |
-| `extraInitContainers` | Array of initContainer to add to the keycloak pod | `[]` |
+| Parameter | Description | Default |
+| --------------------- | ------------------------------------------------- | ------- |
+| `extraInitContainers` | Array of initContainer to add to the keycloak pod | `[]` |
### Security
@@ -144,21 +144,49 @@ The following table lists the configurable parameters of the Keycloak chart and
| `keycloak.proxyTrustedAddresses` | A comma separated list of trusted proxy addresses | `""` |
| `keycloak.production` | Enable production mode | `false` |
| `keycloak.httpRelativePath` | Set relative path for serving resources; must start with a / | `""` |
+| `keycloak.extraArgs` | Additional arguments to pass to the Keycloak startup command | `[]` |
+
+### TLS Configuration
+
+| Parameter | Description | Default |
+| --------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------- |
+| `tls.enabled` | Enable TLS/HTTPS support using custom certificates | `false` |
+| `tls.existingSecret` | Name of existing secret containing TLS certificate and key (PEM format, keys: tls.crt, tls.key) | `""` |
+| `tls.certificateFile` | Path where the TLS certificate file will be mounted (internal) | `"/opt/keycloak/certs/tls.crt"` |
+| `tls.certificateKeyFile` | Path where the TLS certificate key file will be mounted (internal) | `"/opt/keycloak/certs/tls.key"` |
+| `tls.certManager.enabled` | Enable cert-manager integration for automatic certificate provisioning | `false` |
+| `tls.certManager.issuerRef.name` | Name of the cert-manager Issuer or ClusterIssuer | `""` |
+| `tls.certManager.issuerRef.kind` | Kind of the cert-manager issuer (Issuer or ClusterIssuer) | `ClusterIssuer` |
+| `tls.certManager.issuerRef.group` | Group of the cert-manager issuer | `cert-manager.io` |
+| `tls.certManager.duration` | Certificate duration (e.g., 2160h for 90 days) | `""` |
+| `tls.certManager.renewBefore` | Time before expiry to renew certificate (e.g., 360h for 15 days) | `""` |
+| `tls.certManager.commonName` | Certificate common name (defaults to first dnsName if not specified) | `""` |
+| `tls.certManager.dnsNames` | List of DNS names for the certificate (uses ingress.hosts if not specified) | `[]` |
+| `tls.certManager.ipAddresses` | List of IP addresses for the certificate | `[]` |
+| `tls.certManager.secretName` | Name for the generated secret (defaults to `-tls`) | `""` |
+| `tls.certManager.usages` | Certificate key usages | `["digital signature", "key encipherment"]` |
+| `tls.certManager.annotations` | Additional annotations for the Certificate resource | `{}` |
+| `tls.truststoreEnabled` | Enable truststore for client certificate validation or outgoing HTTPS requests | `false` |
+| `tls.truststoreExistingSecret` | Name of existing secret containing truststore file (Java Keystore format, key: truststore.jks) | `""` |
+| `tls.truststorePassword` | Password for the truststore (use with caution - consider using existing secret) | `""` |
+| `tls.truststoreFile` | Path where the truststore file will be mounted (internal) | `"/opt/keycloak/truststore/truststore.jks"` |
### Database Configuration
-| Parameter | Description | Default |
-| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | --------------- |
-| `database.type` | Database type (postgres, mysql, mariadb). Note: H2 databases are not supported due to readonly filesystem restrictions | `postgres` |
-| `database.host` | Database host (only used when not using embedded database) | `""` |
-| `database.port` | Database port (only used when not using embedded database, defaults: postgres=5432, mysql/mariadb=3306) | `""` |
-| `database.name` | Database name (only used when not using embedded database) | `keycloak` |
-| `database.username` | Database username (only used when not using embedded database) | `keycloak` |
-| `database.password` | Database password (only used when not using embedded database) | `""` |
-| `database.existingSecret` | Name of existing secret for database credentials (only used when not using embedded database) | `""` |
-| `database.secretKeys.passwordKey` | Name of key in existing secret for database password | `"db-password"` |
-| `database.secretKeys.usernameKey` | Name of key in existing secret for database username | `"db-username"` |
-| `database.jdbcParams` | Additional JDBC parameters | `""` |
+| Parameter | Description | Default |
+| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | --------------- |
+| `database.type` | Database type (postgres, mysql, mariadb, mssql). Note: H2 databases are not supported due to readonly filesystem restrictions | `postgres` |
+| `database.host` | Database host (only used when not using embedded database) | `""` |
+| `database.port` | Database port (only used when not using embedded database, defaults: postgres=5432, mysql/mariadb=3306, mssql=1433) | `""` |
+| `database.schema` | Database schema | `""` |
+| `database.urlProperties` | Additional database url properties | `""` |
+| `database.name` | Database name (only used when not using embedded database) | `keycloak` |
+| `database.username` | Database username (only used when not using embedded database) | `keycloak` |
+| `database.password` | Database password (only used when not using embedded database) | `""` |
+| `database.existingSecret` | Name of existing secret for database credentials (only used when not using embedded database) | `""` |
+| `database.secretKeys.passwordKey` | Name of key in existing secret for database password | `"db-password"` |
+| `database.secretKeys.usernameKey` | Name of key in existing secret for database username | `"db-username"` |
+| `database.jdbcParams` | Additional JDBC parameters | `""` |
### Cache Configuration
@@ -167,6 +195,13 @@ The following table lists the configurable parameters of the Keycloak chart and
| `cache.stack` | Cache stack (local, ispn, default) | `local` |
| `cache.configFile` | Custom cache configuration file | `""` |
+### Realm Configuration
+
+| Parameter | Description | Default |
+| ------------------ | -------------------------------------------------------------------------------------- | ------- |
+| `realm.import` | Enable import of realms from /opt/keycloak/data/import (production mode must be false) | `false` |
+| `realm.configFile` | Json config for initial realm configuration, mounted in /opt/keycloak/data/import | `""` |
+
### Features Configuration
| Parameter | Description | Default |
@@ -215,6 +250,27 @@ The following table lists the configurable parameters of the Keycloak chart and
| `persistence.accessModes` | Persistent Volume access modes | `["ReadWriteOnce"]` |
| `persistence.existingClaim` | The name of an existing PVC to use for persistence | `""` |
+### Metrics
+
+| Parameter | Description | Default |
+| ------------------------------------------ | -------------------------------------------------------------------------------- | -------------- |
+| `metrics.enabled` | Enable metrics endpoint on Keycloak | `false` |
+| `metrics.service.type` | Metrics service type | `ClusterIP` |
+| `metrics.service.port` | Metrics service port | `9000` |
+| `metrics.service.targetPort` | Metrics service target port | `http-metrics` |
+| `metrics.service.annotations` | Additional annotations for metrics service | `{}` |
+| `metrics.service.labels` | Additional labels for metrics service | `{}` |
+| `metrics.serviceMonitor.enabled` | Create ServiceMonitor resource for scraping metrics using PrometheusOperator | `false` |
+| `metrics.serviceMonitor.namespace` | Namespace in which ServiceMonitor is created | `""` |
+| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped | `30s` |
+| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `""` |
+| `metrics.serviceMonitor.additionalLabels` | Additional labels for ServiceMonitor | `{}` |
+| `metrics.serviceMonitor.annotations` | Additional annotations for ServiceMonitor | `{}` |
+| `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 | `""` |
+
### Liveness and readiness probes
| Parameter | Description | Default |
@@ -260,7 +316,7 @@ The following table lists the configurable parameters of the Keycloak chart and
| Parameter | Description | Default |
| -------------------- | ---------------------------------------------------------------------- | ------- |
-| `extraEnv` | Additional environment variables from key-value pairs | `{}` |
+| `extraEnvVars` | Additional environment variables to set | `[]` |
| `extraEnvVarsSecret` | Name of an existing secret containing additional environment variables | `` |
### Extra Configuration Parameters
@@ -460,6 +516,171 @@ kubectl create secret generic keycloak-db-credentials \
--from-literal=db-username=keycloak
```
+### Realm import
+
+```yaml
+realm:
+ import: true
+ configFile: |
+ {
+ "realm": "my-realm",
+ "enabled": true
+ }
+```
+
+### Using Custom Themes and Providers
+
+The Keycloak deployment automatically mounts empty directories at `/opt/keycloak/themes` and `/opt/keycloak/providers`. You can use initContainers to copy custom themes and providers into these directories.
+
+**Example: Adding custom themes and providers with an initContainer**
+
+```yaml
+# values-custom-themes.yaml
+extraInitContainers:
+ - name: add-custom-themes
+ image: your-registry/keycloak-themes:latest
+ imagePullPolicy: Always
+ command:
+ - sh
+ - -c
+ - |
+ cp -r /themes/* /opt/keycloak/themes/
+ cp -r /providers/* /opt/keycloak/providers/
+ volumeMounts:
+ - name: keycloak-themes
+ mountPath: /opt/keycloak/themes
+ - name: keycloak-providers
+ mountPath: /opt/keycloak/providers
+```
+
+In this example:
+- Create a Docker image containing your custom themes in `/themes` and providers in `/providers`
+- The initContainer copies these files to the mounted volumes
+- Keycloak will automatically detect and use them on startup
+
+You can also use this approach to download themes/providers from external sources:
+
+```yaml
+extraInitContainers:
+ - name: download-themes
+ image: curlimages/curl:latest
+ command:
+ - sh
+ - -c
+ - |
+ curl -L -o /tmp/theme.zip https://example.com/theme.zip
+ unzip /tmp/theme.zip -d /opt/keycloak/themes/
+ volumeMounts:
+ - name: keycloak-themes
+ mountPath: /opt/keycloak/themes
+```
+
+### Using Custom TLS Certificates
+
+#### Option 1: Using cert-manager (Recommended)
+
+Automatically provision and renew certificates using cert-manager:
+
+```yaml
+# values-tls-certmanager.yaml
+tls:
+ enabled: true
+ certManager:
+ enabled: true
+ issuerRef:
+ name: "letsencrypt-prod"
+ kind: ClusterIssuer
+ # dnsNames will be automatically populated from ingress.hosts if not specified
+ dnsNames:
+ - auth.yourdomain.com
+
+keycloak:
+ httpEnabled: false # Disable HTTP when using TLS
+ production: true
+ hostname: "auth.yourdomain.com"
+
+ingress:
+ enabled: true
+ className: "nginx"
+ hosts:
+ - host: auth.yourdomain.com
+ paths:
+ - path: /
+ pathType: Prefix
+```
+
+**Prerequisites:**
+- cert-manager must be installed in your cluster
+- A ClusterIssuer or Issuer must be configured (e.g., Let's Encrypt)
+
+Install cert-manager if not already installed:
+
+```bash
+kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml
+```
+
+Create a ClusterIssuer for Let's Encrypt:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-prod
+spec:
+ acme:
+ server: https://acme-v02.api.letsencrypt.org/directory
+ email: your-email@example.com
+ privateKeySecretRef:
+ name: letsencrypt-prod
+ solvers:
+ - http01:
+ ingress:
+ class: nginx
+```
+
+#### Option 2: Using Existing TLS Certificates
+
+Use pre-existing certificates:
+
+```yaml
+# values-tls.yaml
+tls:
+ enabled: true
+ existingSecret: "keycloak-tls-certs"
+
+keycloak:
+ httpEnabled: false # Disable HTTP when using TLS
+ production: true
+ hostname: "auth.yourdomain.com"
+```
+
+Create the TLS secret first with your certificate and key in PEM format:
+
+```bash
+kubectl create secret tls keycloak-tls-certs \
+ --cert=/path/to/certificate.pem \
+ --key=/path/to/private-key.pem
+```
+
+#### Using Truststore for Client Certificates or Outgoing HTTPS
+
+```yaml
+# values-tls-truststore.yaml
+tls:
+ enabled: true
+ existingSecret: "keycloak-tls-certs"
+ truststoreEnabled: true
+ truststoreExistingSecret: "keycloak-truststore"
+ truststorePassword: "changeit"
+```
+
+Create the truststore secret:
+
+```bash
+kubectl create secret generic keycloak-truststore \
+ --from-file=truststore.jks=/path/to/truststore.jks
+```
+
### High Availability Setup
```yaml
@@ -594,4 +815,4 @@ For issues related to this Helm chart, please check:
- [Keycloak Documentation](https://www.keycloak.org/documentation)
- [Keycloak Server Administration Guide](https://www.keycloak.org/docs/latest/server_admin/)
- [Kubernetes Documentation](https://kubernetes.io/docs/)
-- Chart repository issues
+- Chart repository issues
\ No newline at end of file
diff --git a/charts/keycloak/templates/_helpers.tpl b/charts/keycloak/templates/_helpers.tpl
index 4b26f025..7b64ba9a 100644
--- a/charts/keycloak/templates/_helpers.tpl
+++ b/charts/keycloak/templates/_helpers.tpl
@@ -2,7 +2,7 @@
Expand the name of the chart.
*/}}
{{- define "keycloak.name" -}}
-{{- include "common.name" . -}}
+{{- include "cloudpirates.name" . -}}
{{- end }}
{{/*
@@ -11,21 +11,21 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
If release name contains chart name it will be used as a full name.
*/}}
{{- define "keycloak.fullname" -}}
-{{- include "common.fullname" . -}}
+{{- include "cloudpirates.fullname" . -}}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "keycloak.chart" -}}
-{{- include "common.chart" . -}}
+{{- include "cloudpirates.chart" . -}}
{{- end }}
{{/*
Common labels
*/}}
{{- define "keycloak.labels" -}}
-{{- include "common.labels" . -}}
+{{- include "cloudpirates.labels" . -}}
{{- end }}
{{/*
@@ -41,14 +41,14 @@ Common annotations
Selector labels
*/}}
{{- define "keycloak.selectorLabels" -}}
-{{- include "common.selectorLabels" . -}}
+{{- include "cloudpirates.selectorLabels" . -}}
{{- end }}
{{/*
Return the proper Keycloak image name
*/}}
{{- define "keycloak.image" -}}
-{{- include "common.image" (dict "image" .Values.image "global" .Values.global) -}}
+{{- include "cloudpirates.image" (dict "image" .Values.image "global" .Values.global) -}}
{{- end }}
{{/*
@@ -56,7 +56,7 @@ Return Keycloak admin credentials secret name
*/}}
{{- define "keycloak.secretName" -}}
{{- if .Values.keycloak.existingSecret -}}
- {{- .Values.keycloak.existingSecret -}}
+ {{- include "cloudpirates.tplvalues.render" (dict "value" .Values.keycloak.existingSecret "context" .) -}}
{{- else -}}
{{- include "keycloak.fullname" . -}}
{{- end -}}
@@ -110,7 +110,7 @@ db-username
Return the proper Docker Image Registry Secret Names
*/}}
{{- define "keycloak.imagePullSecrets" -}}
-{{ include "common.images.renderPullSecrets" (dict "images" (list .Values.image) "context" .) }}
+{{ include "cloudpirates.images.renderPullSecrets" (dict "images" (list .Values.image) "context" .) }}
{{- end -}}
{{/*
@@ -129,7 +129,7 @@ Return the Keycloak hostname
*/}}
{{- define "keycloak.hostname" -}}
{{- if .Values.keycloak.hostname -}}
-{{- .Values.keycloak.hostname -}}
+{{- tpl (.Values.keycloak.hostname | toString) $ -}}
{{- else if .Values.ingress.enabled -}}
{{- (index .Values.ingress.hosts 0).host -}}
{{- else -}}
@@ -142,7 +142,7 @@ Return the Keycloak admin hostname
*/}}
{{- define "keycloak.hostnameAdmin" -}}
{{- if .Values.keycloak.hostnameAdmin -}}
-{{- .Values.keycloak.hostnameAdmin -}}
+{{- tpl (.Values.keycloak.hostnameAdmin | toString) $ -}}
{{- else -}}
{{- include "keycloak.hostname" . -}}
{{- end -}}
@@ -175,10 +175,12 @@ Return the database JDBC URL
{{- end -}}
{{- else if or (eq .Values.database.type "mysql") (eq .Values.database.type "mariadb") -}}
{{- if .Values.mariadb.enabled -}}
-{{- printf "jdbc:mysql://%s-mariadb:%s/%s%s" .Release.Name "3306" (default "keycloak" .Values.mariadb.auth.database) (ternary (printf "?%s" .Values.database.jdbcParams) "" (ne .Values.database.jdbcParams "")) -}}
+{{- printf "jdbc:%s://%s-mariadb:%s/%s%s" .Values.database.type .Release.Name "3306" (default "keycloak" .Values.mariadb.auth.database) (ternary (printf "?%s" .Values.database.jdbcParams) "" (ne .Values.database.jdbcParams "")) -}}
{{- else -}}
-{{- printf "jdbc:mysql://%s:%s/%s%s" .Values.database.host (default "3306" (.Values.database.port | toString)) .Values.database.name (ternary (printf "?%s" .Values.database.jdbcParams) "" (ne .Values.database.jdbcParams "")) -}}
+{{- printf "jdbc:%s://%s:%s/%s%s" .Values.database.type .Values.database.host (default "3306" (.Values.database.port | toString)) .Values.database.name (ternary (printf "?%s" .Values.database.jdbcParams) "" (ne .Values.database.jdbcParams "")) -}}
{{- end -}}
+{{- else if eq .Values.database.type "mssql" -}}
+{{- printf "jdbc:mssql://%s:%s/%s%s" .Values.database.host (default "1433" (.Values.database.port | toString)) .Values.database.name (ternary (printf "?%s" .Values.database.jdbcParams) "" (ne .Values.database.jdbcParams "")) -}}
{{- end -}}
{{- end }}
@@ -191,4 +193,45 @@ Return the url to use for probes
{{- else -}}
{{- printf "%s/realms/master" .Values.keycloak.httpRelativePath -}}
{{- end -}}
-{{- end }}
\ No newline at end of file
+{{- end }}
+
+{{/*
+Return TLS certificate secret name
+*/}}
+{{- define "keycloak.tlsSecretName" -}}
+{{- if .Values.tls.certManager.enabled -}}
+ {{- .Values.tls.certManager.secretName | default (printf "%s-tls" (include "keycloak.fullname" .)) -}}
+{{- else if .Values.tls.existingSecret -}}
+ {{- .Values.tls.existingSecret -}}
+{{- else -}}
+ {{- printf "%s-tls" (include "keycloak.fullname" .) -}}
+{{- end -}}
+{{- end }}
+
+{{/*
+Return TLS truststore secret name
+*/}}
+{{- define "keycloak.truststoreSecretName" -}}
+{{- if .Values.tls.truststoreExistingSecret -}}
+ {{- .Values.tls.truststoreExistingSecret -}}
+{{- else -}}
+ {{- printf "%s-truststore" (include "keycloak.fullname" .) -}}
+{{- end -}}
+{{- end }}
+
+{{/*
+Return metrics service name
+*/}}
+{{- define "keycloak.metrics.fullname" -}}
+{{- printf "%s-metrics" (include "keycloak.fullname" .) -}}
+{{- end -}}
+
+{{/*
+Return ServiceMonitor labels
+*/}}
+{{- define "keycloak.metrics.serviceMonitor.labels" -}}
+{{- include "keycloak.labels" . }}
+{{- with .Values.metrics.serviceMonitor.additionalLabels }}
+{{ toYaml . }}
+{{- end }}
+{{- end -}}
diff --git a/charts/keycloak/templates/certificate.yaml b/charts/keycloak/templates/certificate.yaml
new file mode 100644
index 00000000..d06a13b3
--- /dev/null
+++ b/charts/keycloak/templates/certificate.yaml
@@ -0,0 +1,55 @@
+{{- if and .Values.tls.enabled .Values.tls.certManager.enabled }}
+{{- $fullName := include "keycloak.fullname" . -}}
+{{- $secretName := .Values.tls.certManager.secretName | default (printf "%s-tls" $fullName) -}}
+{{- $dnsNames := .Values.tls.certManager.dnsNames -}}
+{{- if and (not $dnsNames) .Values.ingress.enabled }}
+ {{- $dnsNames = list }}
+ {{- range .Values.ingress.hosts }}
+ {{- $dnsNames = append $dnsNames .host }}
+ {{- end }}
+{{- end }}
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: {{ $fullName }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "keycloak.labels" . | nindent 4 }}
+ {{- with .Values.tls.certManager.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ secretName: {{ $secretName }}
+ {{- if .Values.tls.certManager.duration }}
+ duration: {{ .Values.tls.certManager.duration }}
+ {{- end }}
+ {{- if .Values.tls.certManager.renewBefore }}
+ renewBefore: {{ .Values.tls.certManager.renewBefore }}
+ {{- end }}
+ issuerRef:
+ name: {{ .Values.tls.certManager.issuerRef.name | required "tls.certManager.issuerRef.name is required when cert-manager is enabled" }}
+ kind: {{ .Values.tls.certManager.issuerRef.kind }}
+ {{- if .Values.tls.certManager.issuerRef.group }}
+ group: {{ .Values.tls.certManager.issuerRef.group }}
+ {{- end }}
+ {{- if .Values.tls.certManager.commonName }}
+ commonName: {{ .Values.tls.certManager.commonName }}
+ {{- else if $dnsNames }}
+ commonName: {{ index $dnsNames 0 }}
+ {{- end }}
+ {{- if $dnsNames }}
+ dnsNames:
+ {{- range $dnsNames }}
+ - {{ . }}
+ {{- end }}
+ {{- end }}
+ {{- with .Values.tls.certManager.ipAddresses }}
+ ipAddresses:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.tls.certManager.usages }}
+ usages:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/charts/keycloak/templates/configmap.yaml b/charts/keycloak/templates/configmap.yaml
index 34160321..dd18c08a 100644
--- a/charts/keycloak/templates/configmap.yaml
+++ b/charts/keycloak/templates/configmap.yaml
@@ -13,4 +13,21 @@ metadata:
data:
cache-ispn.xml: |
{{- .Values.cache.configFile | nindent 4 }}
-{{- end }}
\ No newline at end of file
+{{- end }}
+{{- if .Values.realm.configFile }}
+---
+kind: ConfigMap
+apiVersion: v1
+metadata:
+ name: {{ include "keycloak.fullname" . }}-realm
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "keycloak.labels" . | nindent 4 }}
+ {{- with (include "keycloak.annotations" .) }}
+ annotations:
+ {{- . | nindent 4 }}
+ {{- end }}
+data:
+ realm.json: |
+ {{ .Values.realm.configFile | nindent 4 }}
+{{- end }}
diff --git a/charts/keycloak/templates/deployment.yaml b/charts/keycloak/templates/deployment.yaml
index 6c309346..c8d2865c 100644
--- a/charts/keycloak/templates/deployment.yaml
+++ b/charts/keycloak/templates/deployment.yaml
@@ -29,12 +29,12 @@ spec:
serviceAccountName: {{ include "keycloak.serviceAccountName" . }}
automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
{{- with (include "keycloak.imagePullSecrets" .) }}
-{{ . | nindent 6 }}
+{{- . | nindent 6 }}
{{- end }}
- securityContext: {{ include "common.renderPodSecurityContext" . | nindent 8 }}
+ securityContext: {{ include "cloudpirates.renderPodSecurityContext" . | nindent 8 }}
initContainers:
- name: copy-quarkus-lib
- securityContext: {{ include "common.renderContainerSecurityContext" . | nindent 12 }}
+ securityContext: {{ include "cloudpirates.renderContainerSecurityContext" . | nindent 12 }}
image: {{ include "keycloak.image" . }}
imagePullPolicy: {{ .Values.image.imagePullPolicy }}
command: ["sh", "-c", "cp -r /opt/keycloak/lib/quarkus/* /shared-quarkus/"]
@@ -43,21 +43,21 @@ spec:
mountPath: /shared-quarkus
{{- if .Values.postgres.enabled }}
- name: wait-for-postgres
- securityContext: {{ include "common.renderContainerSecurityContext" . | nindent 12 }}
+ securityContext: {{ include "cloudpirates.renderContainerSecurityContext" . | nindent 12 }}
image: {{ .Values.initContainers.waitForPostgres.image }}
command: ["sh", "-c", "until pg_isready -h {{ .Release.Name }}-postgres -p 5432 -U postgres; do echo waiting for database; sleep 2; done;"]
{{- else if .Values.mariadb.enabled }}
- name: wait-for-mariadb
- securityContext: {{ include "common.renderContainerSecurityContext" . | nindent 12 }}
+ securityContext: {{ include "cloudpirates.renderContainerSecurityContext" . | nindent 12 }}
image: {{ .Values.initContainers.waitForMariadb.image }}
- command: ["sh", "-c", "until mysqladmin ping -h {{ .Release.Name }}-mariadb -P 3306 --silent; do echo waiting for database; sleep 2; done;"]
+ command: ["sh", "-c", "until mariadb-admin ping -h {{ .Release.Name }}-mariadb -P 3306 --silent; do echo waiting for database; sleep 2; done;"]
{{- end }}
{{- if .Values.extraInitContainers }}
{{- toYaml .Values.extraInitContainers | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
- securityContext: {{ include "common.renderContainerSecurityContext" . | nindent 12 }}
+ securityContext: {{ include "cloudpirates.renderContainerSecurityContext" . | nindent 12 }}
image: {{ include "keycloak.image" . }}
imagePullPolicy: {{ .Values.image.imagePullPolicy }}
command:
@@ -67,6 +67,9 @@ spec:
- start
{{- else }}
- start-dev
+ {{- if .Values.realm.import }}
+ - --import-realm
+ {{- end }}
{{- end }}
{{- if .Values.keycloak.httpEnabled }}
- --http-enabled=true
@@ -109,6 +112,22 @@ spec:
{{- if .Values.features.disabled }}
- --features-disabled={{ join "," .Values.features.disabled }}
{{- end }}
+ {{- if .Values.metrics.enabled }}
+ - --metrics-enabled=true
+ {{- end }}
+ {{- with .Values.keycloak.extraArgs }}
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ {{- if .Values.tls.enabled }}
+ - --https-certificate-file={{ .Values.tls.certificateFile }}
+ - --https-certificate-key-file={{ .Values.tls.certificateKeyFile }}
+ {{- end }}
+ {{- if .Values.tls.truststoreEnabled }}
+ - --https-trust-store-file={{ .Values.tls.truststoreFile }}
+ {{- if .Values.tls.truststorePassword }}
+ - --https-trust-store-password={{ .Values.tls.truststorePassword }}
+ {{- end }}
+ {{- end }}
env:
- name: KC_HTTP_RELATIVE_PATH
value: {{ .Values.keycloak.httpRelativePath | quote | default "/" }}
@@ -119,6 +138,18 @@ spec:
secretKeyRef:
name: {{ include "keycloak.secretName" . }}
key: {{ include "keycloak.adminPasswordKey" . }}
+ {{- if .Values.database.type }}
+ - name: KC_DB
+ value: {{ .Values.database.type }}
+ {{- end }}
+ {{- if .Values.database.schema }}
+ - name: KC_DB_SCHEMA
+ value: {{ .Values.database.schema }}
+ {{- end }}
+ {{- if .Values.database.urlProperties }}
+ - name: KC_DB_URL_PROPERTIES
+ value: {{ .Values.database.urlProperties | quote }}
+ {{- end }}
{{- if or (eq .Values.database.type "postgres") (eq .Values.database.type "mysql") (eq .Values.database.type "mariadb") }}
- name: KC_DB_USERNAME
{{- if and (eq .Values.database.type "postgres") .Values.postgres.enabled }}
@@ -149,9 +180,8 @@ spec:
key: {{ include "keycloak.databasePasswordKey" . }}
{{- end }}
{{- end }}
- {{- range $key, $value := .Values.extraEnv }}
- - name: {{ $key }}
- value: {{ $value | quote }}
+ {{- with .Values.extraEnvVars }}
+{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.extraEnvVarsSecret }}
envFrom:
@@ -159,20 +189,31 @@ spec:
name: {{ .Values.extraEnvVarsSecret }}
{{- end }}
ports:
+ {{- if .Values.keycloak.httpEnabled }}
- name: http
containerPort: {{ .Values.keycloak.httpPort }}
protocol: TCP
- {{- if .Values.keycloak.httpsPort }}
+ {{- else }}
- name: https
containerPort: {{ .Values.keycloak.httpsPort }}
protocol: TCP
{{- end }}
+ {{- if .Values.metrics.enabled }}
+ - name: {{ .Values.metrics.service.targetPort }}
+ containerPort: {{ .Values.metrics.service.port }}
+ protocol: TCP
+ {{- end }}
{{- if .Values.livenessProbe.enabled }}
livenessProbe:
httpGet:
path: {{ include "keycloak.probeUrl" . }}
+ {{- if .Values.keycloak.httpEnabled }}
port: http
scheme: HTTP
+ {{- else }}
+ port: https
+ scheme: HTTPS
+ {{- end }}
initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
@@ -183,8 +224,13 @@ spec:
readinessProbe:
httpGet:
path: {{ include "keycloak.probeUrl" . }}
+ {{- if .Values.keycloak.httpEnabled }}
port: http
scheme: HTTP
+ {{- else }}
+ port: https
+ scheme: HTTPS
+ {{- end }}
initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
@@ -195,8 +241,13 @@ spec:
startupProbe:
httpGet:
path: {{ include "keycloak.probeUrl" . }}
+ {{- if .Values.keycloak.httpEnabled }}
port: http
scheme: HTTP
+ {{- else }}
+ port: https
+ scheme: HTTPS
+ {{- end }}
initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.startupProbe.periodSeconds }}
timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }}
@@ -220,10 +271,28 @@ spec:
mountPath: /opt/keycloak/work
- name: keycloak-lib-quarkus
mountPath: /opt/keycloak/lib/quarkus
+ - name: keycloak-themes
+ mountPath: /opt/keycloak/themes
+ - name: keycloak-providers
+ mountPath: /opt/keycloak/providers
+ {{- if .Values.realm.configFile }}
+ - name: realm-config
+ mountPath: /opt/keycloak/data/import
+ readOnly: true
+ {{- end }}
+ {{- if .Values.tls.enabled }}
+ - name: tls-certs
+ mountPath: /opt/keycloak/certs
+ readOnly: true
+ {{- end }}
+ {{- if .Values.tls.truststoreEnabled }}
+ - name: tls-truststore
+ mountPath: /opt/keycloak/truststore
+ readOnly: true
+ {{- end }}
{{- if .Values.extraVolumeMounts }}
{{- toYaml .Values.extraVolumeMounts | nindent 12}}
{{- end }}
-
volumes:
{{- if .Values.persistence.enabled }}
- name: data
@@ -244,9 +313,36 @@ spec:
emptyDir: {}
- name: keycloak-lib-quarkus
emptyDir: {}
- {{- if .Values.extraVolumes }}
- {{- toYaml .Values.extraVolumes | nindent 8 }}
- {{- end }}
+ - name: keycloak-themes
+ emptyDir: {}
+ - name: keycloak-providers
+ emptyDir: {}
+ {{- if .Values.realm.configFile }}
+ - name: realm-config
+ configMap:
+ name: {{ include "keycloak.fullname" . }}-realm
+ {{- end }}
+ {{- if .Values.tls.enabled }}
+ - name: tls-certs
+ secret:
+ secretName: {{ include "keycloak.tlsSecretName" . }}
+ items:
+ - key: tls.crt
+ path: tls.crt
+ - key: tls.key
+ path: tls.key
+ {{- end }}
+ {{- if .Values.tls.truststoreEnabled }}
+ - name: tls-truststore
+ secret:
+ secretName: {{ .Values.tls.truststoreExistingSecret }}
+ items:
+ - key: truststore.jks
+ path: truststore.jks
+ {{- end }}
+ {{- if .Values.extraVolumes }}
+ {{- toYaml .Values.extraVolumes | nindent 8 }}
+ {{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
diff --git a/charts/keycloak/templates/extraobjects.yaml b/charts/keycloak/templates/extraobjects.yaml
index fd7643e4..7f5ede80 100644
--- a/charts/keycloak/templates/extraobjects.yaml
+++ b/charts/keycloak/templates/extraobjects.yaml
@@ -1,4 +1,4 @@
{{- range .Values.extraObjects }}
---
-{{- include "common.tplvalues.render" (dict "value" . "context" $) }}
+{{- include "cloudpirates.tplvalues.render" (dict "value" . "context" $) }}
{{- end }}
\ No newline at end of file
diff --git a/charts/keycloak/templates/ingress.yaml b/charts/keycloak/templates/ingress.yaml
index 7fee0bd1..04dfce8b 100644
--- a/charts/keycloak/templates/ingress.yaml
+++ b/charts/keycloak/templates/ingress.yaml
@@ -1,6 +1,7 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "keycloak.fullname" . -}}
{{- $httpPort := .Values.service.httpPort -}}
+{{- $httpsPort := .Values.service.httpsPort -}}
{{- if and .Values.ingress.className (not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class")) }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
@@ -11,9 +12,13 @@ metadata:
namespace: {{ .Release.Namespace }}
labels:
{{- include "keycloak.labels" . | nindent 4 }}
- {{- with .Values.ingress.annotations }}
+ {{- $annotations := merge .Values.ingress.annotations .Values.commonAnnotations }}
+ {{- with $annotations }}
annotations:
{{- toYaml . | nindent 4 }}
+ {{- if not $.Values.keycloak.httpEnabled }}
+ nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
+ {{- end }}
{{- end }}
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
@@ -44,10 +49,18 @@ spec:
service:
name: {{ $fullName }}
port:
+ {{- if $.Values.keycloak.httpEnabled }}
number: {{ $httpPort }}
+ {{- else }}
+ number: {{ $httpsPort }}
+ {{- end }}
{{- else }}
serviceName: {{ $fullName }}
+ {{- if $.Values.keycloak.httpEnabled }}
servicePort: {{ $httpPort }}
+ {{- else }}
+ servicePort: {{ $httpsPort }}
+ {{- end }}
{{- end }}
{{- end }}
{{- end }}
diff --git a/charts/keycloak/templates/metrics-service.yaml b/charts/keycloak/templates/metrics-service.yaml
new file mode 100644
index 00000000..7245452a
--- /dev/null
+++ b/charts/keycloak/templates/metrics-service.yaml
@@ -0,0 +1,27 @@
+{{- if .Values.metrics.enabled }}
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "keycloak.metrics.fullname" . }}
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "keycloak.labels" . | nindent 4 }}
+ app.kubernetes.io/component: metrics
+ {{- with .Values.metrics.service.labels }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- $annotations := merge .Values.metrics.service.annotations .Values.commonAnnotations }}
+ {{- with $annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ type: {{ .Values.metrics.service.type }}
+ ports:
+ - port: {{ .Values.metrics.service.port }}
+ targetPort: {{ .Values.metrics.service.targetPort }}
+ protocol: TCP
+ name: {{ .Values.metrics.service.targetPort }}
+ selector:
+ {{- include "keycloak.selectorLabels" . | nindent 4 }}
+{{- end }}
diff --git a/charts/keycloak/templates/metrics-servicemonitor.yaml b/charts/keycloak/templates/metrics-servicemonitor.yaml
new file mode 100644
index 00000000..71b71531
--- /dev/null
+++ b/charts/keycloak/templates/metrics-servicemonitor.yaml
@@ -0,0 +1,49 @@
+{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+ name: {{ include "keycloak.fullname" . }}
+ {{- if .Values.metrics.serviceMonitor.namespace }}
+ namespace: {{ .Values.metrics.serviceMonitor.namespace | quote }}
+ {{- else }}
+ namespace: {{ .Release.Namespace | quote }}
+ {{- end }}
+ labels:
+ {{- include "keycloak.metrics.serviceMonitor.labels" . | nindent 4 }}
+ {{- $annotations := merge .Values.metrics.serviceMonitor.annotations .Values.commonAnnotations }}
+ {{- with $annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if .Values.metrics.serviceMonitor.jobLabel }}
+ jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "keycloak.selectorLabels" . | nindent 6 }}
+ app.kubernetes.io/component: metrics
+ namespaceSelector:
+ matchNames:
+ - {{ .Release.Namespace | quote }}
+ endpoints:
+ - port: {{ .Values.metrics.service.targetPort }}
+ {{- 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.honorLabels }}
+ honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }}
+ {{- end }}
+ path: /metrics
+ {{- with .Values.metrics.serviceMonitor.relabelings }}
+ relabelings:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.metrics.serviceMonitor.metricRelabelings }}
+ metricRelabelings:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+{{- end }}
diff --git a/charts/keycloak/templates/pvc.yaml b/charts/keycloak/templates/pvc.yaml
index 7facd396..a614af17 100644
--- a/charts/keycloak/templates/pvc.yaml
+++ b/charts/keycloak/templates/pvc.yaml
@@ -6,7 +6,8 @@ metadata:
namespace: {{ .Release.Namespace }}
labels:
{{- include "keycloak.labels" . | nindent 4 }}
- {{- with .Values.persistence.annotations }}
+ {{- $annotations := merge .Values.persistence.annotations .Values.commonAnnotations }}
+ {{- with $annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
diff --git a/charts/keycloak/templates/service.yaml b/charts/keycloak/templates/service.yaml
index ce4cafb4..a5e541cf 100644
--- a/charts/keycloak/templates/service.yaml
+++ b/charts/keycloak/templates/service.yaml
@@ -5,18 +5,20 @@ metadata:
namespace: {{ .Release.Namespace }}
labels:
{{- include "keycloak.labels" . | nindent 4 }}
- {{- with .Values.service.annotations }}
+ {{- $annotations := merge .Values.service.annotations .Values.commonAnnotations }}
+ {{- with $annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.service.type }}
ports:
+ {{- if .Values.keycloak.httpEnabled }}
- port: {{ .Values.service.httpPort }}
targetPort: {{ .Values.service.httpTargetPort }}
protocol: TCP
name: http
- {{- if .Values.keycloak.httpsPort }}
+ {{- else }}
- port: {{ .Values.service.httpsPort }}
targetPort: {{ .Values.service.httpsTargetPort }}
protocol: TCP
diff --git a/charts/keycloak/templates/serviceaccount.yaml b/charts/keycloak/templates/serviceaccount.yaml
index 63749406..faa06329 100644
--- a/charts/keycloak/templates/serviceaccount.yaml
+++ b/charts/keycloak/templates/serviceaccount.yaml
@@ -6,7 +6,8 @@ metadata:
namespace: {{ .Release.Namespace }}
labels:
{{- include "keycloak.labels" . | nindent 4 }}
- {{- with .Values.serviceAccount.annotations }}
+ {{- $annotations := merge .Values.serviceAccount.annotations .Values.commonAnnotations }}
+ {{- with $annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
diff --git a/charts/keycloak/tests/common-parameters_test.yaml b/charts/keycloak/tests/common-parameters_test.yaml
index 7bebee84..17cd7b90 100644
--- a/charts/keycloak/tests/common-parameters_test.yaml
+++ b/charts/keycloak/tests/common-parameters_test.yaml
@@ -22,7 +22,7 @@ tests:
template: templates/deployment.yaml
- equal:
path: spec.template.spec.containers[0].image
- value: docker.io/keycloak/keycloak:26.4.0@sha256:5f3fb534cde6bf006d79f5912473e5d2c828c707cdfc52e16972803aca9d43dd
+ value: docker.io/keycloak/keycloak:26.4.2@sha256:3617b09bb4b7510a8d8d9b9fc5707399e2d70688dbcc2f8fb013a144829be1b9
template: templates/deployment.yaml
- it: should render custom name and fullname overrides
@@ -62,7 +62,7 @@ tests:
asserts:
- equal:
path: spec.template.spec.containers[0].image
- value: custom-registry.io/keycloak/keycloak:26.4.0@sha256:5f3fb534cde6bf006d79f5912473e5d2c828c707cdfc52e16972803aca9d43dd
+ value: custom-registry.io/keycloak/keycloak:26.4.2@sha256:3617b09bb4b7510a8d8d9b9fc5707399e2d70688dbcc2f8fb013a144829be1b9
template: templates/deployment.yaml
- it: should render custom replica count
diff --git a/charts/keycloak/tests/deployment-parameters_test.yaml b/charts/keycloak/tests/deployment-parameters_test.yaml
index 4261ae6f..4c1f869a 100644
--- a/charts/keycloak/tests/deployment-parameters_test.yaml
+++ b/charts/keycloak/tests/deployment-parameters_test.yaml
@@ -14,4 +14,38 @@ tests:
asserts:
- equal:
path: spec.template.spec.containers[0].readinessProbe.httpGet.path
- value: /auth/realms/master
\ No newline at end of file
+ value: /auth/realms/master
+ - it: hostname explicitly set should be unchanged
+ set:
+ keycloak:
+ hostname: keycloak.example.com
+ asserts:
+ - equal:
+ path: spec.template.spec.containers[0].args[2]
+ value: --hostname=keycloak.example.com
+ - it: hostname with template should be rendered
+ set:
+ keycloak:
+ hostname: keycloak.{{ .Values.myDomain }}
+ myDomain: mydomain.com
+ asserts:
+ - equal:
+ path: spec.template.spec.containers[0].args[2]
+ value: --hostname=keycloak.mydomain.com
+ - it: hostnameAdmin explicitly set should be unchanged
+ set:
+ keycloak:
+ hostnameAdmin: keycloak.example.com
+ asserts:
+ - equal:
+ path: spec.template.spec.containers[0].args[2]
+ value: --hostname-admin=keycloak.example.com
+ - it: hostname with template should be rendered
+ set:
+ keycloak:
+ hostnameAdmin: keycloak.{{ .Values.myDomain }}
+ myDomain: mydomain.com
+ asserts:
+ - equal:
+ path: spec.template.spec.containers[0].args[2]
+ value: --hostname-admin=keycloak.mydomain.com
\ No newline at end of file
diff --git a/charts/keycloak/tests/tls-certmanager_test.yaml b/charts/keycloak/tests/tls-certmanager_test.yaml
new file mode 100644
index 00000000..dd317ffe
--- /dev/null
+++ b/charts/keycloak/tests/tls-certmanager_test.yaml
@@ -0,0 +1,265 @@
+suite: test cert-manager integration
+templates:
+ - certificate.yaml
+ - deployment.yaml
+tests:
+ - it: should create Certificate when cert-manager is enabled
+ set:
+ tls:
+ enabled: true
+ certManager:
+ enabled: true
+ issuerRef:
+ name: letsencrypt-prod
+ kind: ClusterIssuer
+ dnsNames:
+ - keycloak.example.com
+ template: certificate.yaml
+ asserts:
+ - isKind:
+ of: Certificate
+ - equal:
+ path: metadata.name
+ value: RELEASE-NAME-keycloak
+ - equal:
+ path: spec.secretName
+ value: RELEASE-NAME-keycloak-tls
+ - equal:
+ path: spec.issuerRef.name
+ value: letsencrypt-prod
+ - equal:
+ path: spec.issuerRef.kind
+ value: ClusterIssuer
+ - equal:
+ path: spec.dnsNames[0]
+ value: keycloak.example.com
+ - equal:
+ path: spec.commonName
+ value: keycloak.example.com
+
+ - it: should not create Certificate when cert-manager is disabled
+ set:
+ tls:
+ enabled: true
+ certManager:
+ enabled: false
+ existingSecret: my-tls-secret
+ template: certificate.yaml
+ asserts:
+ - hasDocuments:
+ count: 0
+
+ - it: should not create Certificate when tls is disabled
+ set:
+ tls:
+ enabled: false
+ certManager:
+ enabled: true
+ template: certificate.yaml
+ asserts:
+ - hasDocuments:
+ count: 0
+
+ - it: should use custom secretName when specified
+ set:
+ tls:
+ enabled: true
+ certManager:
+ enabled: true
+ issuerRef:
+ name: my-issuer
+ kind: Issuer
+ secretName: custom-secret-name
+ dnsNames:
+ - auth.example.com
+ template: certificate.yaml
+ asserts:
+ - equal:
+ path: spec.secretName
+ value: custom-secret-name
+
+ - it: should populate dnsNames from ingress.hosts when not specified
+ set:
+ tls:
+ enabled: true
+ certManager:
+ enabled: true
+ issuerRef:
+ name: letsencrypt-prod
+ kind: ClusterIssuer
+ ingress:
+ enabled: true
+ hosts:
+ - host: auth.example.com
+ paths:
+ - path: /
+ pathType: Prefix
+ - host: auth2.example.com
+ paths:
+ - path: /
+ pathType: Prefix
+ template: certificate.yaml
+ asserts:
+ - equal:
+ path: spec.dnsNames[0]
+ value: auth.example.com
+ - equal:
+ path: spec.dnsNames[1]
+ value: auth2.example.com
+ - equal:
+ path: spec.commonName
+ value: auth.example.com
+
+ - it: should set duration and renewBefore when specified
+ set:
+ tls:
+ enabled: true
+ certManager:
+ enabled: true
+ issuerRef:
+ name: letsencrypt-prod
+ kind: ClusterIssuer
+ duration: 2160h
+ renewBefore: 360h
+ dnsNames:
+ - auth.example.com
+ template: certificate.yaml
+ asserts:
+ - equal:
+ path: spec.duration
+ value: 2160h
+ - equal:
+ path: spec.renewBefore
+ value: 360h
+
+ - it: should set custom commonName when specified
+ set:
+ tls:
+ enabled: true
+ certManager:
+ enabled: true
+ issuerRef:
+ name: letsencrypt-prod
+ kind: ClusterIssuer
+ commonName: custom.example.com
+ dnsNames:
+ - auth.example.com
+ - auth2.example.com
+ template: certificate.yaml
+ asserts:
+ - equal:
+ path: spec.commonName
+ value: custom.example.com
+
+ - it: should set ipAddresses when specified
+ set:
+ tls:
+ enabled: true
+ certManager:
+ enabled: true
+ issuerRef:
+ name: letsencrypt-prod
+ kind: ClusterIssuer
+ dnsNames:
+ - auth.example.com
+ ipAddresses:
+ - 192.168.1.100
+ - 10.0.0.1
+ template: certificate.yaml
+ asserts:
+ - equal:
+ path: spec.ipAddresses[0]
+ value: 192.168.1.100
+ - equal:
+ path: spec.ipAddresses[1]
+ value: 10.0.0.1
+
+ - it: should set custom usages when specified
+ set:
+ tls:
+ enabled: true
+ certManager:
+ enabled: true
+ issuerRef:
+ name: letsencrypt-prod
+ kind: ClusterIssuer
+ dnsNames:
+ - auth.example.com
+ usages:
+ - server auth
+ - client auth
+ template: certificate.yaml
+ asserts:
+ - equal:
+ path: spec.usages[0]
+ value: server auth
+ - equal:
+ path: spec.usages[1]
+ value: client auth
+
+ - it: should add annotations when specified
+ set:
+ tls:
+ enabled: true
+ certManager:
+ enabled: true
+ issuerRef:
+ name: letsencrypt-prod
+ kind: ClusterIssuer
+ dnsNames:
+ - auth.example.com
+ annotations:
+ custom.annotation/key: value
+ template: certificate.yaml
+ asserts:
+ - equal:
+ path: metadata.annotations["custom.annotation/key"]
+ value: value
+
+ - it: deployment should use cert-manager generated secret
+ set:
+ tls:
+ enabled: true
+ certManager:
+ enabled: true
+ issuerRef:
+ name: letsencrypt-prod
+ kind: ClusterIssuer
+ dnsNames:
+ - auth.example.com
+ template: deployment.yaml
+ asserts:
+ - equal:
+ path: spec.template.spec.volumes[?(@.name=="tls-certs")].secret.secretName
+ value: RELEASE-NAME-keycloak-tls
+
+ - it: deployment should use custom cert-manager secret name
+ set:
+ tls:
+ enabled: true
+ certManager:
+ enabled: true
+ issuerRef:
+ name: letsencrypt-prod
+ kind: ClusterIssuer
+ secretName: my-custom-secret
+ dnsNames:
+ - auth.example.com
+ template: deployment.yaml
+ asserts:
+ - equal:
+ path: spec.template.spec.volumes[?(@.name=="tls-certs")].secret.secretName
+ value: my-custom-secret
+
+ - it: should fail when issuerRef.name is not provided
+ set:
+ tls:
+ enabled: true
+ certManager:
+ enabled: true
+ dnsNames:
+ - auth.example.com
+ template: certificate.yaml
+ asserts:
+ - failedTemplate:
+ errorMessage: "tls.certManager.issuerRef.name is required when cert-manager is enabled"
diff --git a/charts/keycloak/values.schema.json b/charts/keycloak/values.schema.json
index 19e86a41..16f01347 100644
--- a/charts/keycloak/values.schema.json
+++ b/charts/keycloak/values.schema.json
@@ -1,686 +1,659 @@
{
- "$schema": "https://json-schema.org/draft/2020-12/schema",
- "type": "object",
- "properties": {
- "global": {
- "type": "object",
- "properties": {
- "imageRegistry": {
- "type": "string",
- "description": "Global Docker Image registry"
- },
- "imagePullSecrets": {
- "type": "array",
- "items": {
- "type": "string"
- },
- "description": "Global Docker registry secret names as an array"
- }
- }
- },
- "nameOverride": {
- "type": "string",
- "description": "String to partially override keycloak.fullname"
- },
- "fullnameOverride": {
- "type": "string",
- "description": "String to fully override keycloak.fullname"
- },
- "commonLabels": {
- "type": "object",
- "description": "Labels to add to all deployed objects"
- },
- "commonAnnotations": {
- "type": "object",
- "description": "Annotations to add to all deployed objects"
- },
- "image": {
- "type": "object",
- "properties": {
- "registry": {
- "type": "string",
- "description": "Keycloak image registry"
- },
- "repository": {
- "type": "string",
- "description": "Keycloak image repository"
- },
- "tag": {
- "type": "string",
- "description": "Keycloak image tag (immutable tags are recommended)"
- },
- "command": {
- "type": "string",
- "description": "Keycloak container startup command"
- },
- "imagePullPolicy": {
- "type": "string",
- "enum": ["Always", "IfNotPresent", "Never"],
- "description": "Keycloak image pull policy"
- }
- }
- },
- "replicaCount": {
- "type": "integer",
- "minimum": 1,
- "description": "Number of Keycloak replicas to deploy"
- },
- "podAnnotations": {
- "type": "object",
- "description": "Map of annotations to add to the pods"
- },
- "podLabels": {
- "type": "object",
- "description": "Map of labels to add to the pods"
- },
- "extraVolumes": {
- "type": "array",
- "items": {
- "type": "object"
- },
- "description": "Array of Volume to add to the keycloak pod"
- },
- "extraVolumeMounts": {
- "type": "array",
- "items": {
- "type": "object"
- },
- "description": "Array of VolumeMount to add to the keycloak container"
- },
- "extraInitContainers": {
- "type": "array",
- "items": {
- "type": "object"
- },
- "description": "Array of initContainer to add to the keycloak pod"
- },
- "podSecurityContext": {
- "type": "object",
- "properties": {
- "fsGroup": {
- "type": "integer",
- "description": "Group ID for the volumes of the pod"
- }
- }
- },
- "containerSecurityContext": {
- "type": "object",
- "properties": {
- "allowPrivilegeEscalation": {
- "type": "boolean",
- "description": "Enable container privilege escalation"
- },
- "runAsNonRoot": {
- "type": "boolean",
- "description": "Configure the container to run as a non-root user"
- },
- "runAsUser": {
- "type": "integer",
- "description": "User ID for the Keycloak container"
- },
- "runAsGroup": {
- "type": "integer",
- "description": "Group ID for the Keycloak container"
- },
- "readOnlyRootFilesystem": {
- "type": "boolean",
- "description": "Mount container root filesystem as read-only"
- },
- "capabilities": {
- "type": "object",
- "properties": {
- "drop": {
- "type": "array",
- "items": {
- "type": "string"
- },
- "description": "Linux capabilities to be dropped"
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "type": "object",
+ "properties": {
+ "affinity": {
+ "type": "object"
+ },
+ "cache": {
+ "type": "object",
+ "properties": {
+ "configFile": {
+ "type": "string"
+ },
+ "stack": {
+ "type": "string"
+ }
}
- }
- }
- }
- },
- "keycloak": {
- "type": "object",
- "properties": {
- "adminUser": {
- "type": "string",
- "description": "Keycloak admin username"
- },
- "adminPassword": {
- "type": "string",
- "description": "Keycloak admin password"
- },
- "existingSecret": {
- "type": "string",
- "description": "Name of existing secret to use for Keycloak admin credentials"
- },
- "secretKeys": {
- "type": "object",
- "properties": {
- "adminPasswordKey": {
- "type": "string",
- "description": "Secret key for admin password"
+ },
+ "commonAnnotations": {
+ "type": "object"
+ },
+ "commonLabels": {
+ "type": "object"
+ },
+ "containerSecurityContext": {
+ "type": "object",
+ "properties": {
+ "allowPrivilegeEscalation": {
+ "type": "boolean"
+ },
+ "capabilities": {
+ "type": "object",
+ "properties": {
+ "drop": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "readOnlyRootFilesystem": {
+ "type": "boolean"
+ },
+ "runAsGroup": {
+ "type": "integer"
+ },
+ "runAsNonRoot": {
+ "type": "boolean"
+ },
+ "runAsUser": {
+ "type": "integer"
+ }
}
- }
- },
- "hostname": {
- "type": "string",
- "description": "Keycloak hostname"
- },
- "hostnameAdmin": {
- "type": "string",
- "description": "Keycloak admin hostname"
- },
- "hostnameStrict": {
- "type": "boolean",
- "description": "Enable strict hostname resolution"
- },
- "hostnameBackchannel": {
- "type": "string",
- "description": "Keycloak backchannel hostname"
- },
- "httpEnabled": {
- "type": "boolean",
- "description": "Enable HTTP listener"
- },
- "httpPort": {
- "type": "integer",
- "minimum": 1,
- "maximum": 65535,
- "description": "HTTP port"
- },
- "httpsPort": {
- "type": "integer",
- "minimum": 1,
- "maximum": 65535,
- "description": "HTTPS port"
- },
- "proxyHeaders": {
- "type": "string",
- "enum": ["", "forwarded", "xforwarded"],
- "description": "The proxy headers that should be accepted by the server. (forwarded, xforwarded)"
- },
- "proxyProtocolEnabled": {
- "type": "boolean",
- "description": "Whether the server should use the HA PROXY protocol when serving requests from behind a proxy."
- },
- "proxyTrustedAddresses": {
- "type": "string",
- "description": "A comma separated list of trusted proxy addresses"
- },
- "production": {
- "type": "boolean",
- "description": "Enable production mode"
- },
- "httpRelativePath": {
- "type": "string",
- "description": "Set relative path for serving resources; must start with a /"
- }
- }
- },
- "database": {
- "type": "object",
- "properties": {
- "type": {
- "type": "string",
- "enum": ["postgres", "mysql", "mariadb"],
- "description": "Database type (postgres, mysql, mariadb)"
- },
- "host": {
- "type": "string",
- "description": "Database host (only used when not using embedded database)"
- },
- "port": {
- "type": "string",
- "description": "Database port (only used when not using embedded database)"
- },
- "name": {
- "type": "string",
- "description": "Database name (only used when not using embedded database)"
- },
- "username": {
- "type": "string",
- "description": "Database username (only used when not using embedded database)"
- },
- "password": {
- "type": "string",
- "description": "Database password (only used when not using embedded database)"
- },
- "existingSecret": {
- "type": "string",
- "description": "Name of existing secret for database credentials"
- },
- "secretKeys": {
- "type": "object",
- "properties": {
- "passwordKey": {
- "type": "string",
- "description": "Secret key for database password"
- },
- "usernameKey": {
- "type": "string",
- "description": "Secret key for database username"
+ },
+ "database": {
+ "type": "object",
+ "properties": {
+ "existingSecret": {
+ "type": "string"
+ },
+ "host": {
+ "type": "string"
+ },
+ "jdbcParams": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "port": {
+ "type": "string"
+ },
+ "schema": {
+ "type": "string"
+ },
+ "secretKeys": {
+ "type": "object",
+ "properties": {
+ "passwordKey": {
+ "type": "string"
+ },
+ "usernameKey": {
+ "type": "string"
+ }
+ }
+ },
+ "type": {
+ "type": "string"
+ },
+ "urlProperties": {
+ "type": "string"
+ },
+ "username": {
+ "type": "string"
+ }
}
- }
},
- "jdbcParams": {
- "type": "string",
- "description": "Additional JDBC parameters"
- }
- }
- },
- "cache": {
- "type": "object",
- "properties": {
- "stack": {
- "type": "string",
- "enum": ["local", "ispn", "default"],
- "description": "Cache stack (local, ispn, default)"
- },
- "configFile": {
- "type": "string",
- "description": "Custom cache configuration file"
- }
- }
- },
- "features": {
- "type": "object",
- "properties": {
- "enabled": {
- "type": "array",
- "items": {
+ "extraEnvVars": {
+ "type": "array"
+ },
+ "extraEnvVarsSecret": {
"type": "string"
- },
- "description": "List of enabled features"
},
- "disabled": {
- "type": "array",
- "items": {
+ "extraInitContainers": {
+ "type": "array"
+ },
+ "extraObjects": {
+ "type": "array"
+ },
+ "extraVolumeMounts": {
+ "type": "array"
+ },
+ "extraVolumes": {
+ "type": "array"
+ },
+ "features": {
+ "type": "object",
+ "properties": {
+ "disabled": {
+ "type": "array"
+ },
+ "enabled": {
+ "type": "array"
+ }
+ }
+ },
+ "fullnameOverride": {
"type": "string"
- },
- "description": "List of disabled features"
- }
- }
- },
- "service": {
- "type": "object",
- "properties": {
- "type": {
- "type": "string",
- "enum": ["ClusterIP", "NodePort", "LoadBalancer", "ExternalName"],
- "description": "Keycloak service type"
- },
- "httpPort": {
- "type": "integer",
- "minimum": 1,
- "maximum": 65535,
- "description": "Keycloak HTTP service port"
- },
- "httpsPort": {
- "type": "integer",
- "minimum": 1,
- "maximum": 65535,
- "description": "Keycloak HTTPS service port"
- },
- "httpTargetPort": {
- "type": "integer",
- "minimum": 1,
- "maximum": 65535,
- "description": "Keycloak HTTP container port"
- },
- "httpsTargetPort": {
- "type": "integer",
- "minimum": 1,
- "maximum": 65535,
- "description": "Keycloak HTTPS container port"
- },
- "annotations": {
- "type": "object",
- "description": "Service annotations"
- },
- "trafficDistribution": {
- "type": "string",
- "description": "Traffic distribution policy"
- }
- }
- },
- "ingress": {
- "type": "object",
- "properties": {
- "enabled": {
- "type": "boolean",
- "description": "Enable ingress record generation for Keycloak"
- },
- "className": {
- "type": "string",
- "description": "IngressClass that will be used to implement the Ingress"
- },
- "annotations": {
- "type": "object",
- "description": "Additional annotations for the Ingress resource"
- },
- "hosts": {
- "type": "array",
- "items": {
+ },
+ "global": {
"type": "object",
"properties": {
- "host": {
- "type": "string",
- "description": "Hostname for Keycloak ingress"
- },
- "paths": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "path": {
- "type": "string",
- "description": "Path for Keycloak ingress"
- },
- "pathType": {
- "type": "string",
- "enum": ["Exact", "Prefix", "ImplementationSpecific"],
- "description": "Path type for Keycloak ingress"
+ "imagePullSecrets": {
+ "type": "array"
+ },
+ "imageRegistry": {
+ "type": "string"
+ }
+ }
+ },
+ "image": {
+ "type": "object",
+ "properties": {
+ "command": {
+ "type": "string"
+ },
+ "imagePullPolicy": {
+ "type": "string"
+ },
+ "registry": {
+ "type": "string"
+ },
+ "repository": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ }
+ }
+ },
+ "ingress": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object"
+ },
+ "className": {
+ "type": "string"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "hosts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "host": {
+ "type": "string"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "pathType": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
}
- }
+ },
+ "tls": {
+ "type": "array"
}
- }
}
- }
},
- "tls": {
- "type": "array",
- "items": {
+ "initContainers": {
"type": "object",
"properties": {
- "secretName": {
- "type": "string"
- },
- "hosts": {
- "type": "array",
- "items": {
- "type": "string"
+ "waitForMariadb": {
+ "type": "object",
+ "properties": {
+ "image": {
+ "type": "string"
+ }
+ }
+ },
+ "waitForPostgres": {
+ "type": "object",
+ "properties": {
+ "image": {
+ "type": "string"
+ }
+ }
}
- }
}
- },
- "description": "TLS configuration for Keycloak ingress"
- }
- }
- },
- "resources": {
- "type": "object",
- "description": "Resource limits and requests for the container"
- },
- "persistence": {
- "type": "object",
- "properties": {
- "enabled": {
- "type": "boolean",
- "description": "Enable persistence using Persistent Volume Claims"
- },
- "storageClass": {
- "type": "string",
- "description": "Persistent Volume storage class"
- },
- "annotations": {
- "type": "object",
- "description": "Persistent Volume Claim annotations"
- },
- "size": {
- "type": "string",
- "description": "Persistent Volume size"
- },
- "accessModes": {
- "type": "array",
- "items": {
- "type": "string",
- "enum": ["ReadWriteOnce", "ReadOnlyMany", "ReadWriteMany"]
- },
- "description": "Persistent Volume access modes"
- },
- "existingClaim": {
- "type": "string",
- "description": "The name of an existing PVC to use for persistence"
- }
- }
- },
- "livenessProbe": {
- "type": "object",
- "properties": {
- "enabled": {
- "type": "boolean",
- "description": "Enable livenessProbe on Keycloak containers"
- },
- "initialDelaySeconds": {
- "type": "integer",
- "minimum": 0,
- "description": "Initial delay seconds for livenessProbe"
- },
- "periodSeconds": {
- "type": "integer",
- "minimum": 1,
- "description": "Period seconds for livenessProbe"
- },
- "timeoutSeconds": {
- "type": "integer",
- "minimum": 1,
- "description": "Timeout seconds for livenessProbe"
- },
- "failureThreshold": {
- "type": "integer",
- "minimum": 1,
- "description": "Failure threshold for livenessProbe"
- },
- "successThreshold": {
- "type": "integer",
- "minimum": 1,
- "description": "Success threshold for livenessProbe"
- }
- }
- },
- "readinessProbe": {
- "type": "object",
- "properties": {
- "enabled": {
- "type": "boolean",
- "description": "Enable readinessProbe on Keycloak containers"
- },
- "initialDelaySeconds": {
- "type": "integer",
- "minimum": 0,
- "description": "Initial delay seconds for readinessProbe"
- },
- "periodSeconds": {
- "type": "integer",
- "minimum": 1,
- "description": "Period seconds for readinessProbe"
- },
- "timeoutSeconds": {
- "type": "integer",
- "minimum": 1,
- "description": "Timeout seconds for readinessProbe"
- },
- "failureThreshold": {
- "type": "integer",
- "minimum": 1,
- "description": "Failure threshold for readinessProbe"
- },
- "successThreshold": {
- "type": "integer",
- "minimum": 1,
- "description": "Success threshold for readinessProbe"
- }
- }
- },
- "startupProbe": {
- "type": "object",
- "properties": {
- "enabled": {
- "type": "boolean",
- "description": "Enable startupProbe on Keycloak containers"
- },
- "initialDelaySeconds": {
- "type": "integer",
- "minimum": 0,
- "description": "Initial delay seconds for startupProbe"
- },
- "periodSeconds": {
- "type": "integer",
- "minimum": 1,
- "description": "Period seconds for startupProbe"
- },
- "timeoutSeconds": {
- "type": "integer",
- "minimum": 1,
- "description": "Timeout seconds for startupProbe"
- },
- "failureThreshold": {
- "type": "integer",
- "minimum": 1,
- "description": "Failure threshold for startupProbe"
- },
- "successThreshold": {
- "type": "integer",
- "minimum": 1,
- "description": "Success threshold for startupProbe"
- }
- }
- },
- "nodeSelector": {
- "type": "object",
- "description": "Node labels for pod assignment"
- },
- "tolerations": {
- "type": "array",
- "description": "Toleration labels for pod assignment"
- },
- "affinity": {
- "type": "object",
- "description": "Affinity settings for pod assignment"
- },
- "topologySpreadConstraints": {
- "type": "array",
- "description": "Topology Spread Constraints for pod assignment"
- },
- "serviceAccount": {
- "type": "object",
- "properties": {
- "create": {
- "type": "boolean",
- "description": "Specifies whether a service account should be created"
- },
- "annotations": {
- "type": "object",
- "description": "Annotations to add to the service account"
- },
- "name": {
- "type": "string",
- "description": "The name of the service account to use"
- },
- "automountServiceAccountToken": {
- "type": "boolean",
- "description": "Whether to automount the SA token inside the pod"
- }
- }
- },
- "extraEnv": {
- "type": "object",
- "description": "Additional environment variables from key-value pairs"
- },
- "extraEnvVarsSecret": {
- "type": "string",
- "title": "Extra Environment Secret",
- "description": "Name of an existing Secret containing additional environment variables"
- },
- "extraObjects": {
- "type": "array",
- "title": "Extra Objects",
- "description": "A list of additional Kubernetes objects to deploy alongside the release. Helm templating is supported in any field, but all template expressions must be quoted. Each item should be a valid Kubernetes manifest object.",
- "items": {
- "type": "object",
- "description": "A Kubernetes manifest object. All fields are allowed."
- }
- },
- "initContainers": {
- "type": "object",
- "properties": {
- "waitForPostgres": {
- "type": "object",
- "properties": {
- "image": {
- "type": "string",
- "description": "PostgreSQL init container image for waiting"
+ },
+ "keycloak": {
+ "type": "object",
+ "properties": {
+ "adminPassword": {
+ "type": "string"
+ },
+ "adminUser": {
+ "type": "string"
+ },
+ "existingSecret": {
+ "type": "string"
+ },
+ "extraArgs": {
+ "type": "array"
+ },
+ "hostname": {
+ "type": "string"
+ },
+ "hostnameAdmin": {
+ "type": "string"
+ },
+ "hostnameBackchannel": {
+ "type": "string"
+ },
+ "hostnameStrict": {
+ "type": "boolean"
+ },
+ "httpEnabled": {
+ "type": "boolean"
+ },
+ "httpPort": {
+ "type": "integer"
+ },
+ "httpRelativePath": {
+ "type": "string"
+ },
+ "httpsPort": {
+ "type": "integer"
+ },
+ "production": {
+ "type": "boolean"
+ },
+ "proxyHeaders": {
+ "type": "string"
+ },
+ "proxyProtocolEnabled": {
+ "type": "boolean"
+ },
+ "proxyTrustedAddresses": {
+ "type": "string"
+ },
+ "secretKeys": {
+ "type": "object",
+ "properties": {
+ "adminPasswordKey": {
+ "type": "string"
+ }
+ }
+ }
}
- }
- },
- "waitForMariadb": {
- "type": "object",
- "properties": {
- "image": {
- "type": "string",
- "description": "MariaDB init container image for waiting"
+ },
+ "livenessProbe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ }
}
- }
- }
- }
- },
- "postgres": {
- "type": "object",
- "properties": {
- "enabled": {
- "type": "boolean",
- "description": "Enable embedded PostgreSQL database"
- },
- "auth": {
- "type": "object",
- "properties": {
- "database": {
- "type": "string",
- "description": "PostgreSQL database name"
- },
- "username": {
- "type": "string",
- "description": "PostgreSQL database user (leave empty for default 'postgres')"
- },
- "password": {
- "type": "string",
- "description": "PostgreSQL database password"
+ },
+ "mariadb": {
+ "type": "object",
+ "properties": {
+ "auth": {
+ "type": "object",
+ "properties": {
+ "database": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "rootPassword": {
+ "type": "string"
+ },
+ "username": {
+ "type": "string"
+ }
+ }
+ },
+ "enabled": {
+ "type": "boolean"
+ }
}
- }
- }
- }
- },
- "mariadb": {
- "type": "object",
- "properties": {
- "enabled": {
- "type": "boolean",
- "description": "Enable embedded MariaDB database (set to false when using postgres)"
- },
- "auth": {
- "type": "object",
- "properties": {
- "database": {
- "type": "string",
- "description": "MariaDB database name"
- },
- "username": {
- "type": "string",
- "description": "MariaDB database user (leave empty for root user)"
- },
- "password": {
- "type": "string",
- "description": "MariaDB database password"
- },
- "rootPassword": {
- "type": "string",
- "description": "MariaDB root password"
+ },
+ "metrics": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "service": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object"
+ },
+ "labels": {
+ "type": "object"
+ },
+ "port": {
+ "type": "integer"
+ },
+ "targetPort": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ }
+ }
+ },
+ "serviceMonitor": {
+ "type": "object",
+ "properties": {
+ "additionalLabels": {
+ "type": "object"
+ },
+ "annotations": {
+ "type": "object"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "honorLabels": {
+ "type": "boolean"
+ },
+ "interval": {
+ "type": "string"
+ },
+ "jobLabel": {
+ "type": "string"
+ },
+ "metricRelabelings": {
+ "type": "array"
+ },
+ "namespace": {
+ "type": "string"
+ },
+ "relabelings": {
+ "type": "array"
+ },
+ "scrapeTimeout": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "nameOverride": {
+ "type": "string"
+ },
+ "nodeSelector": {
+ "type": "object"
+ },
+ "persistence": {
+ "type": "object",
+ "properties": {
+ "accessModes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "annotations": {
+ "type": "object"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "existingClaim": {
+ "type": "string"
+ },
+ "size": {
+ "type": "string"
+ },
+ "storageClass": {
+ "type": "string"
+ }
+ }
+ },
+ "podAnnotations": {
+ "type": "object"
+ },
+ "podLabels": {
+ "type": "object"
+ },
+ "podSecurityContext": {
+ "type": "object",
+ "properties": {
+ "fsGroup": {
+ "type": "integer"
+ }
+ }
+ },
+ "postgres": {
+ "type": "object",
+ "properties": {
+ "auth": {
+ "type": "object",
+ "properties": {
+ "database": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "username": {
+ "type": "string"
+ }
+ }
+ },
+ "enabled": {
+ "type": "boolean"
+ }
+ }
+ },
+ "readinessProbe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ }
+ }
+ },
+ "realm": {
+ "type": "object",
+ "properties": {
+ "configFile": {
+ "type": "string"
+ },
+ "import": {
+ "type": "boolean"
+ }
+ }
+ },
+ "replicaCount": {
+ "type": "integer"
+ },
+ "resources": {
+ "type": "object"
+ },
+ "service": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object"
+ },
+ "httpPort": {
+ "type": "integer"
+ },
+ "httpTargetPort": {
+ "type": "integer"
+ },
+ "httpsPort": {
+ "type": "integer"
+ },
+ "httpsTargetPort": {
+ "type": "integer"
+ },
+ "trafficDistribution": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ }
+ }
+ },
+ "serviceAccount": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object"
+ },
+ "automountServiceAccountToken": {
+ "type": "boolean"
+ },
+ "create": {
+ "type": "boolean"
+ },
+ "name": {
+ "type": "string"
+ }
}
- }
+ },
+ "startupProbe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ }
+ }
+ },
+ "tls": {
+ "type": "object",
+ "properties": {
+ "certManager": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object"
+ },
+ "commonName": {
+ "type": "string"
+ },
+ "dnsNames": {
+ "type": "array"
+ },
+ "duration": {
+ "type": "string"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "ipAddresses": {
+ "type": "array"
+ },
+ "issuerRef": {
+ "type": "object",
+ "properties": {
+ "group": {
+ "type": "string"
+ },
+ "kind": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ }
+ }
+ },
+ "renewBefore": {
+ "type": "string"
+ },
+ "secretName": {
+ "type": "string"
+ },
+ "usages": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "certificateFile": {
+ "type": "string"
+ },
+ "certificateKeyFile": {
+ "type": "string"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "existingSecret": {
+ "type": "string"
+ },
+ "truststoreEnabled": {
+ "type": "boolean"
+ },
+ "truststoreExistingSecret": {
+ "type": "string"
+ },
+ "truststoreFile": {
+ "type": "string"
+ },
+ "truststorePassword": {
+ "type": "string"
+ }
+ }
+ },
+ "tolerations": {
+ "type": "array"
+ },
+ "topologySpreadConstraints": {
+ "type": "array"
}
- }
}
- }
}
diff --git a/charts/keycloak/values.yaml b/charts/keycloak/values.yaml
index 6b2799d5..b56fe7dc 100644
--- a/charts/keycloak/values.yaml
+++ b/charts/keycloak/values.yaml
@@ -22,7 +22,7 @@ image:
## @param image.repository Keycloak image repository
repository: keycloak/keycloak
## @param image.tag Keycloak image tag (immutable tags are recommended)
- tag: "26.4.0@sha256:5f3fb534cde6bf006d79f5912473e5d2c828c707cdfc52e16972803aca9d43dd"
+ tag: "26.4.2@sha256:3617b09bb4b7510a8d8d9b9fc5707399e2d70688dbcc2f8fb013a144829be1b9"
## @param image.imagePullPolicy Keycloak image pull policy
imagePullPolicy: Always
## @param image.command Keycloak container command
@@ -110,17 +110,78 @@ keycloak:
production: false
## @param keycloak.httpRelativePath Set relative path for serving resources; must start with a /
httpRelativePath: /
+ ## @param keycloak.extraArgs Additional arguments to pass to the Keycloak startup command
+ extraArgs: []
+
+## @section TLS Configuration
+tls:
+ ## @param tls.enabled Enable TLS/HTTPS support using custom certificates
+ enabled: false
+ ## @param tls.existingSecret Name of existing secret containing TLS certificate and key (PEM format)
+ ## The secret should contain 'tls.crt' and 'tls.key' keys
+ ## Note: If certManager.enabled is true, this will be auto-generated
+ existingSecret: ""
+ ## @param tls.certificateFile Path where the TLS certificate file will be mounted (internal)
+ certificateFile: "/opt/keycloak/certs/tls.crt"
+ ## @param tls.certificateKeyFile Path where the TLS certificate key file will be mounted (internal)
+ certificateKeyFile: "/opt/keycloak/certs/tls.key"
+ ## @section cert-manager Configuration
+ ## @descriptionStart
+ ## Configure cert-manager to automatically provision and renew TLS certificates
+ ## Requires cert-manager to be installed in the cluster
+ ## @descriptionEnd
+ certManager:
+ ## @param tls.certManager.enabled Enable cert-manager integration for automatic certificate provisioning
+ enabled: false
+ ## @param tls.certManager.issuerRef.name Name of the cert-manager Issuer or ClusterIssuer
+ ## @param tls.certManager.issuerRef.kind Kind of the cert-manager issuer (Issuer or ClusterIssuer)
+ ## @param tls.certManager.issuerRef.group Group of the cert-manager issuer (default: cert-manager.io)
+ issuerRef:
+ name: ""
+ kind: ClusterIssuer
+ group: cert-manager.io
+ ## @param tls.certManager.duration Certificate duration (default: 2160h - 90 days)
+ duration: ""
+ ## @param tls.certManager.renewBefore Time before expiry to renew certificate (default: 360h - 15 days)
+ renewBefore: ""
+ ## @param tls.certManager.commonName Certificate common name (defaults to first dnsName if not specified)
+ commonName: ""
+ ## @param tls.certManager.dnsNames List of DNS names for the certificate (uses ingress.hosts if not specified)
+ dnsNames: []
+ ## @param tls.certManager.ipAddresses List of IP addresses for the certificate
+ ipAddresses: []
+ ## @param tls.certManager.secretName Name for the generated secret (defaults to -tls)
+ secretName: ""
+ ## @param tls.certManager.usages Certificate key usages
+ usages:
+ - digital signature
+ - key encipherment
+ ## @param tls.certManager.annotations Additional annotations for the Certificate resource
+ annotations: {}
+ ## @param tls.truststoreEnabled Enable truststore for client certificate validation or outgoing HTTPS requests
+ truststoreEnabled: false
+ ## @param tls.truststoreExistingSecret Name of existing secret containing truststore file (Java Keystore format)
+ ## The secret should contain 'truststore.jks' key
+ truststoreExistingSecret: ""
+ ## @param tls.truststorePassword Password for the truststore (use with caution - consider using existingSecret)
+ truststorePassword: ""
+ ## @param tls.truststoreFile Path where the truststore file will be mounted (internal)
+ truststoreFile: "/opt/keycloak/truststore/truststore.jks"
## @section Database Configuration
database:
- ## @param database.type Database type (postgres, mysql, mariadb)
+ ## @param database.type Database type (postgres, mysql, mariadb, mssql)
## Note: H2 databases (h2-file, h2-mem) are not supported due to readonly filesystem restrictions
## Use embedded postgres or mariadb instead
type: postgres
## @param database.host Database host (only used when not using embedded database)
host: ""
- ## @param database.port Database port (only used when not using embedded database, defaults: postgres=5432, mysql/mariadb=3306)
+ ## @param database.port Database port (only used when not using embedded database, defaults: postgres=5432, mysql/mariadb=3306, mssql=1443)
port: ""
+ ## @param database.schema Database schema
+ schema: ""
+ ## @param database.urlProperties Additional database url properties
+ urlProperties: ""
## @param database.name Database name (only used when not using embedded database)
name: keycloak
## @param database.username Database username (only used when not using embedded database)
@@ -143,6 +204,13 @@ cache:
## @param cache.configFile Custom cache configuration file
configFile: ""
+## @section Realm Configuration
+realm:
+ ## @param realm.import Enable import of realms from /opt/keycloak/data/import (production mode must be false)
+ import: false
+ ## @param realm.configFile Json config for initial realm configuration, mounted in /opt/keycloak/data/import
+ configFile: ""
+
## @section Features Configuration
features:
## @param features.enabled List of enabled features
@@ -174,8 +242,7 @@ ingress:
## @param ingress.className IngressClass that will be used to implement the Ingress
className: ""
## @param ingress.annotations Additional annotations for the Ingress resource
- annotations:
- {}
+ annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
# nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
@@ -194,8 +261,7 @@ ingress:
# - keycloak.local
## @section Resources
-resources:
- {}
+resources: {}
## We usually recommend not to specify default resources and to leave this as a conscious
## choice for the user. This also increases chances charts run on environments with little
## resources, such as Minikube. If you do want to specify resources, uncomment the following
@@ -223,6 +289,45 @@ persistence:
## @param persistence.existingClaim The name of an existing PVC to use for persistence
existingClaim: ""
+## @section Metrics Configuration
+metrics:
+ ## @param metrics.enabled Enable metrics endpoint on Keycloak
+ enabled: false
+ ## @section Metrics service parameters
+ service:
+ ## @param metrics.service.type Metrics service type
+ type: ClusterIP
+ ## @param metrics.service.port Metrics service port
+ port: 9000
+ ## @param metrics.service.targetPort Metrics service target port
+ targetPort: http-metrics
+ ## @param metrics.service.annotations Additional annotations for metrics service
+ annotations: {}
+ ## @param metrics.service.labels Additional labels for metrics service
+ labels: {}
+ ## @section ServiceMonitor parameters
+ serviceMonitor:
+ ## @param metrics.serviceMonitor.enabled Create ServiceMonitor resource for scraping metrics using PrometheusOperator
+ enabled: false
+ ## @param metrics.serviceMonitor.namespace Namespace in which ServiceMonitor is created
+ namespace: ""
+ ## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped
+ interval: 30s
+ ## @param metrics.serviceMonitor.scrapeTimeout Timeout after which the scrape is ended
+ scrapeTimeout: ""
+ ## @param metrics.serviceMonitor.additionalLabels Additional labels for ServiceMonitor
+ additionalLabels: {}
+ ## @param metrics.serviceMonitor.annotations Additional annotations for ServiceMonitor
+ annotations: {}
+ ## @param metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping
+ relabelings: []
+ ## @param metrics.serviceMonitor.metricRelabelings MetricRelabelConfigs to apply to samples before ingestion
+ metricRelabelings: []
+ ## @param metrics.serviceMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint
+ honorLabels: false
+ ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in prometheus
+ jobLabel: ""
+
## @section Liveness and readiness probes
livenessProbe:
## @param livenessProbe.enabled Enable livenessProbe on Keycloak containers
@@ -290,10 +395,15 @@ serviceAccount:
## @param serviceAccount.automountServiceAccountToken whether to automount the SA token inside the pod
automountServiceAccountToken: false
-## @param extraEnv Additional environment variables from key-value pairs
-extraEnv: {}
-# VARNAME1: value1
-# VARNAME2: value2
+## @param extraEnvVars Additional environment variables to set
+extraEnvVars: []
+ # - name: CUSTOM_VAR
+ # value: "custom-value"
+ # - name: SECRET_VAR
+ # valueFrom:
+ # secretKeyRef:
+ # name: my-secret
+ # key: secret-key
## @param extraEnvVarsSecret Name of a secret containing additional environment variables
extraEnvVarsSecret: ""
diff --git a/charts/mariadb/CHANGELOG.md b/charts/mariadb/CHANGELOG.md
index 6893a4ce..ed2b5c23 100644
--- a/charts/mariadb/CHANGELOG.md
+++ b/charts/mariadb/CHANGELOG.md
@@ -1,5 +1,135 @@
# Changelog
-## 0.3.3 (2025-10-09)
-* [mongodb] feat: add metrics exporter ([#243](https://github.com/CloudPirates-io/helm-charts/pull/243))
+## 0.6.0 (2025-10-28)
+
+* chore: update CHANGELOG.md for merged changes ([f9c3ff0](https://github.com/CloudPirates-io/helm-charts/commit/f9c3ff0))
+* chore: update CHANGELOG.md for merged changes ([db2d800](https://github.com/CloudPirates-io/helm-charts/commit/db2d800))
+
+## 0.5.4 (2025-10-23)
+
+* chore: update CHANGELOG.md for merged changes ([051ad83](https://github.com/CloudPirates-io/helm-charts/commit/051ad83))
+* chore: update CHANGELOG.md for merged changes ([1a50307](https://github.com/CloudPirates-io/helm-charts/commit/1a50307))
+
+## 0.5.3 (2025-10-22)
+
+* chore: update CHANGELOG.md for merged changes ([3974b19](https://github.com/CloudPirates-io/helm-charts/commit/3974b19))
+* chore: update CHANGELOG.md for merged changes ([db075e4](https://github.com/CloudPirates-io/helm-charts/commit/db075e4))
+
+## 0.5.2 (2025-10-21)
+
+* enhance stateful set with extra mounts (#420) ([d0bae40](https://github.com/CloudPirates-io/helm-charts/commit/d0bae40))
+* chore: update CHANGELOG.md for merged changes ([5d1f01a](https://github.com/CloudPirates-io/helm-charts/commit/5d1f01a))
+* chore: update CHANGELOG.md for merged changes ([fc47c5d](https://github.com/CloudPirates-io/helm-charts/commit/fc47c5d))
+* chore: update CHANGELOG.md for merged changes ([1a4f87b](https://github.com/CloudPirates-io/helm-charts/commit/1a4f87b))
+* chore: update CHANGELOG.md for merged changes ([da866ca](https://github.com/CloudPirates-io/helm-charts/commit/da866ca))
+* chore: update CHANGELOG.md for merged changes ([b54c4f1](https://github.com/CloudPirates-io/helm-charts/commit/b54c4f1))
+* chore: update CHANGELOG.md for merged changes ([5a2ed20](https://github.com/CloudPirates-io/helm-charts/commit/5a2ed20))
+* chore: update CHANGELOG.md for merged changes ([949de2b](https://github.com/CloudPirates-io/helm-charts/commit/949de2b))
+* chore: update CHANGELOG.md for merged changes ([388263e](https://github.com/CloudPirates-io/helm-charts/commit/388263e))
+
+## 0.5.1 (2025-10-15)
+
+* Bugfix/redis non cloudpirates prefix (#394) ([02e03ed](https://github.com/CloudPirates-io/helm-charts/commit/02e03ed))
+* chore: update CHANGELOG.md for merged changes ([2ed8b75](https://github.com/CloudPirates-io/helm-charts/commit/2ed8b75))
+* chore: update CHANGELOG.md for merged changes ([3361964](https://github.com/CloudPirates-io/helm-charts/commit/3361964))
+* chore: update CHANGELOG.md for merged changes ([7f61172](https://github.com/CloudPirates-io/helm-charts/commit/7f61172))
+
+## 0.5.0 (2025-10-14)
+
+* add galera cluster support for mariadb (#348) ([b7a63ee](https://github.com/CloudPirates-io/helm-charts/commit/b7a63ee))
+* chore: update CHANGELOG.md for merged changes ([c9ff4ec](https://github.com/CloudPirates-io/helm-charts/commit/c9ff4ec))
+* chore: update CHANGELOG.md for merged changes ([86f1d25](https://github.com/CloudPirates-io/helm-charts/commit/86f1d25))
+
+## 0.4.0 (2025-10-14)
+
+* Update chart.yaml dependencies for indepentent charts (#382) ([87acfb1](https://github.com/CloudPirates-io/helm-charts/commit/87acfb1))
+* chore: update CHANGELOG.md for merged changes ([84cf67b](https://github.com/CloudPirates-io/helm-charts/commit/84cf67b))
+* chore: update CHANGELOG.md for all charts via manual trigger ([6974964](https://github.com/CloudPirates-io/helm-charts/commit/6974964))
+* chore: update CHANGELOG.md for merged changes ([63b7bfa](https://github.com/CloudPirates-io/helm-charts/commit/63b7bfa))
+* chore: update CHANGELOG.md for merged changes ([da69e0e](https://github.com/CloudPirates-io/helm-charts/commit/da69e0e))
+* chore: update CHANGELOG.md for merged changes ([5da1b15](https://github.com/CloudPirates-io/helm-charts/commit/5da1b15))
+
+## 0.3.5 (2025-10-13)
+
+
+## 0.3.4 (2025-10-10)
+
+* Update charts/mariadb/values.yaml mariadb (#315) ([07101fe](https://github.com/CloudPirates-io/helm-charts/commit/07101fe))
+* add tests for openshift (#226) ([c80c98a](https://github.com/CloudPirates-io/helm-charts/commit/c80c98a))
+* Hotfix schemas.json (#247) ([0900f81](https://github.com/CloudPirates-io/helm-charts/commit/0900f81))
+
+## 0.3.3 (2025-10-08)
+
+* Add support for readOnlyRootFilesystem (#228) ([cdb58b2](https://github.com/CloudPirates-io/helm-charts/commit/cdb58b2))
+
+## 0.3.2 (2025-10-06)
+
+* chore(deps): update docker.io/mariadb:12.0.2 Docker digest to 03a03a6 (#207) ([e51e995](https://github.com/CloudPirates-io/helm-charts/commit/e51e995))
+
+## 0.3.1 (2025-10-06)
+
+* use tpl to return existingConfigMap (#217) ([c7c2f4c](https://github.com/CloudPirates-io/helm-charts/commit/c7c2f4c))
+
+## 0.3.0 (2025-09-29)
+
+* make mariadb run on openshift (#176) ([e2c3afb](https://github.com/CloudPirates-io/helm-charts/commit/e2c3afb))
+
+## 0.2.7 (2025-09-16)
+
+* Update CHANGELOG.md ([bb96d54](https://github.com/CloudPirates-io/helm-charts/commit/bb96d54))
+* Bump chart version ([ea85028](https://github.com/CloudPirates-io/helm-charts/commit/ea85028))
+* chore(deps): update docker.io/mariadb:12.0.2 Docker digest to 8a061ef ([ba48f7a](https://github.com/CloudPirates-io/helm-charts/commit/ba48f7a))
+
+## 0.2.6 (2025-09-15)
+
+* Update CHANGELOG.md ([858838d](https://github.com/CloudPirates-io/helm-charts/commit/858838d))
+* fix pvc-labels ([aaf1b20](https://github.com/CloudPirates-io/helm-charts/commit/aaf1b20))
+* bump version to 0.2.6 ([51bcd26](https://github.com/CloudPirates-io/helm-charts/commit/51bcd26))
+* change statefulset pvc-template labels to not use common.labels ([780386b](https://github.com/CloudPirates-io/helm-charts/commit/780386b))
+
+## 0.2.5 (2025-09-15)
+
+* Update CHANGELOG.md ([e5c8efd](https://github.com/CloudPirates-io/helm-charts/commit/e5c8efd))
+* fix statefulset pvc template ([b600627](https://github.com/CloudPirates-io/helm-charts/commit/b600627))
+
+## 0.2.4 (2025-09-09)
+
+* Update CHANGELOG.md ([79570ff](https://github.com/CloudPirates-io/helm-charts/commit/79570ff))
+* Implement init script ([4b6ee98](https://github.com/CloudPirates-io/helm-charts/commit/4b6ee98))
+* Reverse version bump ([379dbfe](https://github.com/CloudPirates-io/helm-charts/commit/379dbfe))
+
+## 0.2.3 (2025-09-09)
+
+* Update CHANGELOG.md ([7517a21](https://github.com/CloudPirates-io/helm-charts/commit/7517a21))
+* Bump MariaDB chart version to 0.2.3 ([10b1b7d](https://github.com/CloudPirates-io/helm-charts/commit/10b1b7d))
+* Bump chart version ([d2863aa](https://github.com/CloudPirates-io/helm-charts/commit/d2863aa))
+* Update docker.io/mariadb:12.0.2 Docker digest to a5af517 ([6322f06](https://github.com/CloudPirates-io/helm-charts/commit/6322f06))
+
+## 0.2.2 (2025-09-08)
+
+* updated chart version ([f7b6496](https://github.com/CloudPirates-io/helm-charts/commit/f7b6496))
+* mariadb now respects full custom container security context settings memcached readme fixed, this option was not available ([770ea69](https://github.com/CloudPirates-io/helm-charts/commit/770ea69))
+
+## 0.2.1 (2025-09-04)
+
+* Update CHANGELOG.md ([bcd1d8a](https://github.com/CloudPirates-io/helm-charts/commit/bcd1d8a))
+* add empty linting rule ([8be9283](https://github.com/CloudPirates-io/helm-charts/commit/8be9283))
+* Fix helpers.tpl ([201ecc7](https://github.com/CloudPirates-io/helm-charts/commit/201ecc7))
+* Update CHANGELOG.md ([9af2905](https://github.com/CloudPirates-io/helm-charts/commit/9af2905))
+* Implement default password ([c858a6b](https://github.com/CloudPirates-io/helm-charts/commit/c858a6b))
+
+## 0.2.0 (2025-09-02)
+
+* bump all chart versions for new extraObjects feature ([aaa57f9](https://github.com/CloudPirates-io/helm-charts/commit/aaa57f9))
+* add extraObject array to all charts ([34772b7](https://github.com/CloudPirates-io/helm-charts/commit/34772b7))
+
+## 0.1.6 (2025-08-27)
+
+* Fix linting for values.yaml ([504ac61](https://github.com/CloudPirates-io/helm-charts/commit/504ac61))
+* Fix values.yaml / Chart.yaml linting issues ([043c7e0](https://github.com/CloudPirates-io/helm-charts/commit/043c7e0))
+* Add initial Changelogs to all Charts ([68f10ca](https://github.com/CloudPirates-io/helm-charts/commit/68f10ca))
+
+## 0.1.5 (2025-08-26)
+
+* Initial tagged release
diff --git a/charts/mariadb/Chart.lock b/charts/mariadb/Chart.lock
index 902221bd..283cb703 100644
--- a/charts/mariadb/Chart.lock
+++ b/charts/mariadb/Chart.lock
@@ -1,6 +1,6 @@
dependencies:
- name: common
repository: oci://registry-1.docker.io/cloudpirates
- version: 1.1.1
-digest: sha256:8da3c04e2c4a1ebfff4f21936399938e0f3fcf9fbd2f7135e7e907ce725b8f00
-generated: "2025-09-28T21:12:26.682987+02:00"
+ version: 2.0.0
+digest: sha256:ae9378e0dcfd09a35b7f994007db99c2d6fe02ef7634f424d5233237c209a1c7
+generated: "2025-10-14T11:14:19.520784+02:00"
diff --git a/charts/mariadb/Chart.yaml b/charts/mariadb/Chart.yaml
index c1344435..d588c04c 100644
--- a/charts/mariadb/Chart.yaml
+++ b/charts/mariadb/Chart.yaml
@@ -1,8 +1,8 @@
apiVersion: v2
name: mariadb
-description: MariaDB is a high-performance, open-source relational database server that is a drop-in replacement for MySQL
+description: MariaDB is a high-performance, open-source relational database server that is a drop-in replacement for MySQL. Supports both single-node and Galera Cluster deployments.
type: application
-version: 0.3.3
+version: 0.6.0
appVersion: "12.0.2"
keywords:
- mariadb
@@ -10,18 +10,46 @@ keywords:
- database
- sql
- relational
-home: https://www.cloudpirates.io
-
+ - galera
+ - cluster
+ - replication
+home: https://mariadb.org
sources:
- https://github.com/CloudPirates-io/helm-charts/tree/main/charts/mariadb
-
+ - https://github.com/MariaDB/server
+ - https://github.com/MariaDB/mariadb-docker
maintainers:
- name: CloudPirates GmbH & Co. KG
+ email: hello@cloudpirates.io
url: https://www.cloudpirates.io
-
+ - name: Gianni Carafa
+ email: gianni.carafa@srf.ch
+ url: https://www.srf.ch
dependencies:
- name: common
- version: "1.x.x"
+ version: "2.x.x"
repository: oci://registry-1.docker.io/cloudpirates
-
icon: https://a.storyblok.com/f/143071/512x512/6512dd22ee/mariadb-logo.svg
+annotations:
+ license: Apache-2.0
+ artifacthub.io/category: database
+ artifacthub.io/containsSecurityUpdates: "false"
+ artifacthub.io/signKey: |
+ fingerprint: 6917f1a88c122cbb1de5aa55457752135bdcf95a
+ url: https://raw.githubusercontent.com/CloudPirates-io/helm-charts/refs/heads/main/cosign.pub
+ artifacthub.io/links: |
+ - name: MariaDB
+ url: https://mariadb.org
+ - name: Helm Chart
+ url: https://github.com/CloudPirates-io/helm-charts/tree/main/charts/mariadb
+ - name: Application
+ url: https://github.com/MariaDB/server
+ - name: Docker Image
+ url: https://github.com/MariaDB/mariadb-docker
+ - name: Galera Cluster
+ url: https://galeracluster.com
+ - name: Maintainer CloudPirates
+ url: https://www.cloudpirates.io
+ artifacthub.io/changes: |2
+ - kind: changed
+ description: "Chart updated"
diff --git a/charts/mariadb/README.md b/charts/mariadb/README.md
index 51401aa3..b141c4d6 100644
--- a/charts/mariadb/README.md
+++ b/charts/mariadb/README.md
@@ -4,7 +4,9 @@
# MariaDB
-MariaDB is a high-performance, open-source relational database server that is a drop-in replacement for MySQL. This Helm chart deploys MariaDB as a StatefulSet on Kubernetes with comprehensive configuration options for development and production environments, providing stable network identities and persistent storage.
+MariaDB is a high-performance, open-source relational database server that is a drop-in replacement for MySQL. This Helm chart deploys MariaDB as a StatefulSet on Kubernetes with comprehensive configuration options for development and production environments, providing stable network identities and persistent storage.
+
+The chart supports both single-node deployments and multi-node Galera cluster configurations for high availability and automatic failover.
## Installing the Chart
@@ -127,6 +129,41 @@ The following table lists the configurable parameters of the MariaDB chart and t
| `config.customConfiguration` | Custom configuration for MariaDB | `""` |
| `config.existingConfigMap` | Name of existing ConfigMap with MariaDB configuration | `""` |
+### Galera Cluster Parameters
+
+For a detailed explanation of Galera parameters and usage, see [README_GALERA.md](README_GALERA.md).
+
+> [!WARNING]
+> You must migrate from a standalone MariaDB to Galera carefully. Do not enable Galera on an existing standalone database without following proper migration steps.
+
+| Parameter | Description | Default |
+| ----------------------------------- | ------------------------------------------------------------------- | ---------------------------------- |
+| `galera.enabled` | Enable Galera Cluster mode | `false` |
+| `galera.name` | Galera cluster name | `"galera"` |
+| `galera.bootstrap.enabled` | Enable bootstrap mode for the first node in the cluster | `true` |
+| `galera.replicaCount` | Number of nodes in the Galera cluster | `3` |
+| `galera.wsrepProvider` | Path to wsrep provider library | `/usr/lib/galera/libgalera_smm.so` |
+| `galera.wsrepMethod` | Method for state snapshot transfers (mariabackup, mysqldump, rsync) | `mariabackup` |
+| `galera.forceSafeToBootstrap` | Force safe_to_bootstrap=1 in grastate.dat | `false` |
+| `galera.wsrepSlaveThreads` | Number of slave threads for applying writesets | `1` |
+| `galera.wsrepCertifyNonPK` | Require primary key for replication | `true` |
+| `galera.wsrepMaxWsRows` | Maximum number of rows in writeset | `0` |
+| `galera.wsrepMaxWsSize` | Maximum size of writeset in bytes | `1073741824` |
+| `galera.wsrepDebug` | Enable wsrep debugging | `false` |
+| `galera.wsrepRetryAutocommit` | Number of times to retry autocommit | `1` |
+| `galera.wsrepAutoIncrementControl` | Enable auto increment control | `true` |
+| `galera.wsrepDrupalHack` | Enable Drupal compatibility hack | `false` |
+| `galera.wsrepLogConflicts` | Log conflicts to error log | `false` |
+| `galera.innodb.flushLogAtTrxCommit` | InnoDB flush log at transaction commit | `0` |
+| `galera.innodb.bufferPoolSize` | InnoDB buffer pool size | `"128M"` |
+| `galera.sst.user` | SST user for authentication | `"sstuser"` |
+| `galera.sst.password` | SST password for authentication | `""` |
+| `galera.sst.existingSecret` | Existing secret containing SST credentials | `""` |
+| `galera.sst.secretKeys.userKey` | Secret key for SST user | `sst-user` |
+| `galera.sst.secretKeys.passwordKey` | Secret key for SST password | `sst-password` |
+| `galera.recovery.enabled` | Enable automatic recovery | `true` |
+| `galera.recovery.clusterBootstrap` | Enable cluster bootstrap in recovery | `true` |
+
### Service Parameters
| Parameter | Description | Default |
@@ -169,7 +206,7 @@ The following table lists the configurable parameters of the MariaDB chart and t
| Parameter | Description | Default |
| -------------- | -------------------------------------------------------------------------------- | ------- |
-| `env` | A list of additional environment variables | `[]` |
+| `extraEnvVars` | Additional environment variables to set | `[]` |
| `extraSecrets` | A list of additional existing secrets that will be mounted into the container | `[]` |
| `extraConfigs` | A list of additional existing configMaps that will be mounted into the container | `[]` |
| `extraVolumes` | A list of additional existing volumes that will be mounted into the container | `[]` |
@@ -351,7 +388,7 @@ config:
```yaml
# Additional environment variables
-env:
+extraEnvVars:
- name: MYSQL_INIT_ONLY
value: "0"
- name: MARIADB_AUTO_UPGRADE
@@ -376,27 +413,6 @@ extraVolumes:
pvcName: mariadb-backup-pvc
```
-### With Ingress (for development only)
-
-**Note**: MariaDB ingress should only be used for development purposes. In production, use direct service connections.
-
-```yaml
-ingress:
- enabled: true
- className: "nginx"
- annotations:
- nginx.ingress.kubernetes.io/tcp-services-configmap: "default/tcp-services"
- hosts:
- - host: mariadb.local
- paths:
- - path: /
- pathType: Prefix
-
-service:
- type: NodePort
- nodePort: 30306
-```
-
## Troubleshooting
### Connection Issues
diff --git a/charts/mariadb/README_GALERA.md b/charts/mariadb/README_GALERA.md
new file mode 100644
index 00000000..78bbd3bd
--- /dev/null
+++ b/charts/mariadb/README_GALERA.md
@@ -0,0 +1,238 @@
+# Galera Cluster with MariaDB
+
+This document provides detailed instructions and best practices for deploying and managing a MariaDB Galera Cluster using the Helm chart available in this repository. Galera Cluster is a synchronous multi-master replication solution for MariaDB, providing high availability and scalability.
+
+```mermaid
+architecture-beta
+ group api[MariaDB Galera Cluster Statefulset]
+
+ service db1(database)[Node1] in api
+ service db2(database)[Node2] in api
+ service db3(database)[Node3] in api
+
+ service gateway(internet)[Service Loadbalancer]
+ service app(internet)[Application]
+
+ junction junctionCenter in api
+ junction junctionRight in api
+ junction junctionLeft in api
+
+ db1:T -- B:junctionRight
+ db2:T -- B:junctionCenter
+ db3:T -- B:junctionLeft
+
+ junctionRight:L -- R:junctionCenter
+ junctionLeft:R -- L:junctionCenter
+ junctionCenter:T -- B:gateway
+ gateway:T -- B:app
+```
+
+
+
+### Galera Cluster Setup
+
+#### Basic Galera Cluster
+
+Deploy a 3-node Galera cluster with automatic bootstrap:
+
+```yaml
+galera:
+ enabled: true
+ name: "mycluster"
+ replicaCount: 3
+ bootstrap:
+ enabled: true
+
+auth:
+ rootPassword: "mySecurePassword"
+ database: "mydatabase"
+ username: "myuser"
+ password: "myUserPassword"
+```
+
+#### Production Galera Setup
+
+```yaml
+galera:
+ enabled: true
+ name: "production-cluster"
+ replicaCount: 3
+ wsrepSlaveThreads: 4
+ sst:
+ user: "sstuser"
+ password: "secureSST_Password"
+ innodb:
+ flushLogAtTrxCommit: 2
+ bufferPoolSize: "2G"
+
+auth:
+ rootPassword: "verySecureRootPassword"
+ database: "production_db"
+ username: "app_user"
+ password: "secureUserPassword"
+
+# Pod anti-affinity for spreading nodes across different hosts
+affinity:
+ podAntiAffinity:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ - weight: 100
+ podAffinityTerm:
+ labelSelector:
+ matchLabels:
+ app.kubernetes.io/name: mariadb
+ topologyKey: kubernetes.io/hostname
+```
+
+#### Galera with Existing SST Secret
+
+```yaml
+galera:
+ enabled: true
+ name: "secure-cluster"
+ replicaCount: 3
+ sst:
+ existingSecret: "galera-sst-credentials"
+ secretKeys:
+ userKey: "sst-user"
+ passwordKey: "sst-password"
+
+# Create the secret separately:
+# kubectl create secret generic galera-sst-credentials \
+# --from-literal=sst-user=sstuser \
+# --from-literal=sst-password=your-secure-password
+```
+
+#### Cluster Recovery
+
+For cluster recovery scenarios, you may need to force bootstrap:
+
+```yaml
+galera:
+ enabled: true
+ forceSafeToBootstrap: true # Use only in recovery scenarios
+ recovery:
+ enabled: true
+ clusterBootstrap: true
+```
+
+#### Connecting to Galera Cluster
+
+Connect to the cluster through the main service (load balanced):
+
+```bash
+kubectl exec -it pod/mdb-mariadb-0 -- mariadb -uroot -p$MARIADB_ROOT_PASSWORD -e \"SHOW GLOBAL STATUS LIKE 'wsrep_cluster%'\"
+```
+
+
+#### Galera Cluster Monitoring
+
+Check cluster status inside the database:
+
+```sql
+SHOW STATUS LIKE 'wsrep_ready';
+SHOW STATUS LIKE 'wsrep_cluster_size';
+SHOW STATUS LIKE 'wsrep_local_state_comment';
+```
+
+Key status variables to monitor:
+- `wsrep_cluster_size`: Number of nodes in cluster
+- `wsrep_local_state_comment`: Should be "Synced" for healthy nodes
+- `wsrep_ready`: Should be "ON" for ready nodes
+
+### Galera Cluster Troubleshooting
+
+#### Check Cluster Status
+
+1. **Verify all nodes are running**:
+ ```bash
+ kubectl get pods -l app.kubernetes.io/name=mariadb
+ kubectl get statefulset -l app.kubernetes.io/name=mariadb
+ ```
+
+2. **Check cluster status from database**:
+ ```bash
+ kubectl exec -it -- mysql -uroot -p -e "SHOW STATUS LIKE 'wsrep_%'"
+ ```
+
+3. **Check individual node status**:
+ ```sql
+ SHOW STATUS LIKE 'wsrep_local_state_comment'; -- Should show "Synced"
+ SHOW STATUS LIKE 'wsrep_cluster_size'; -- Should show total node count
+ SHOW STATUS LIKE 'wsrep_ready'; -- Should be "ON"
+ ```
+
+4. **Check logs for errors**:
+ ```bash
+ kubectl exec -- tail -n 300 /var/lib/mysql/mariabackup.backup.log
+ ```
+
+5. **Check SST user permissions**:
+ ```bash
+ SHOW GRANTS FOR 'sstuser'@'%'; grep wsrep_sst_auth
+ ```
+
+ expected output:
+ ```sql
+ GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT ON *.* TO 'sstuser'@'%';
+ GRANT ALL PRIVILEGES ON *.* TO 'sstuser'@'localhost';
+ ```
+
+#### Common Issues and Solutions
+
+1. **Cluster won't start (split-brain scenario)**:
+ ```bash
+ # Check grastate.dat on all nodes
+ kubectl exec -- cat /var/lib/mysql/grastate.dat
+
+ # Force bootstrap on the most advanced node
+ helm upgrade charts/mariadb --set galera.forceSafeToBootstrap=true
+ # After cluster starts, disable force bootstrap
+ helm upgrade charts/mariadb --set galera.forceSafeToBootstrap=false
+ ```
+
+2. **Node stuck in joining state**:
+ ```bash
+ # Check SST logs
+ kubectl logs | grep -i sst
+
+ # Verify SST user credentials
+ kubectl get secret -mariadb-galera -o yaml
+ ```
+
+3. **Slow state transfers**:
+ ```yaml
+ galera:
+ wsrepMethod: "mariabackup" # Faster than mysqldump
+ innodb:
+ bufferPoolSize: "2G" # Increase buffer pool
+ ```
+
+4. **Network connectivity issues**:
+ ```bash
+ # Test connectivity between pods
+ kubectl exec -- nc -zv 4567
+ kubectl exec -- nc -zv 4568
+ kubectl exec -- nc -zv 4444
+ ```
+
+5. **Recovery from complete cluster shutdown**:
+ ```bash
+ # Find the most advanced node (highest seqno)
+ kubectl exec -- cat /var/lib/mysql/grastate.dat
+
+ # Set safe_to_bootstrap=1 on the most advanced node
+ kubectl exec -- sed -i 's/safe_to_bootstrap: 0/safe_to_bootstrap: 1/' /var/lib/mysql/grastate.dat
+
+ # Or use force bootstrap flag
+ helm upgrade charts/mariadb --set galera.forceSafeToBootstrap=true
+ ```
+
+#### Galera Best Practices
+
+- **Always use odd number of nodes** (3, 5, 7) to avoid split-brain
+- **Enable pod anti-affinity** to spread nodes across different hosts
+- **Monitor cluster size** regularly to detect node failures
+- **Use dedicated storage** with good I/O performance
+- **Configure proper resource limits** based on your workload
+- **Regular backups** are essential even with clustering
+- **Test recovery procedures** in non-production environments
\ No newline at end of file
diff --git a/charts/mariadb/templates/_helpers.tpl b/charts/mariadb/templates/_helpers.tpl
index c3994c85..ce9c7f30 100644
--- a/charts/mariadb/templates/_helpers.tpl
+++ b/charts/mariadb/templates/_helpers.tpl
@@ -2,7 +2,7 @@
Expand the name of the chart.
*/}}
{{- define "mariadb.name" -}}
-{{- include "common.name" . -}}
+{{- include "cloudpirates.name" . -}}
{{- end }}
{{/*
@@ -11,49 +11,49 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
If release name contains chart name it will be used as a full name.
*/}}
{{- define "mariadb.fullname" -}}
-{{- include "common.fullname" . -}}
+{{- include "cloudpirates.fullname" . -}}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "mariadb.chart" -}}
-{{- include "common.chart" . -}}
+{{- include "cloudpirates.chart" . -}}
{{- end }}
{{/*
Common labels
*/}}
{{- define "mariadb.labels" -}}
-{{- include "common.labels" . -}}
+{{- include "cloudpirates.labels" . -}}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "mariadb.selectorLabels" -}}
-{{- include "common.selectorLabels" . -}}
+{{- include "cloudpirates.selectorLabels" . -}}
{{- end }}
{{/*
Return the proper MariaDB image name
*/}}
{{- define "mariadb.image" -}}
-{{- include "common.image" (dict "image" .Values.image "global" .Values.global) -}}
+{{- include "cloudpirates.image" (dict "image" .Values.image "global" .Values.global) -}}
{{- end }}
{{/*
Return the proper Docker Image Registry Secret Names
*/}}
{{- define "mariadb.imagePullSecrets" -}}
-{{ include "common.images.renderPullSecrets" (dict "images" (list .Values.image) "context" .) }}
+{{ include "cloudpirates.images.renderPullSecrets" (dict "images" (list .Values.image) "context" .) }}
{{- end -}}
{{/*
Get the secret name for MariaDB root password
*/}}
{{- define "mariadb.secretName" -}}
{{- if .Values.auth.existingSecret }}
-{{- .Values.auth.existingSecret }}
+{{- include "cloudpirates.tplvalues.render" (dict "value" .Values.auth.existingSecret "context" .) }}
{{- else }}
{{- include "mariadb.fullname" . }}
{{- end }}
@@ -77,3 +77,48 @@ Return the MariaDB ConfigMap Name
{{- end }}
{{- end }}
+{{/*
+Get the secret name for Galera SST authentication
+*/}}
+{{- define "mariadb.galeraSecretName" -}}
+{{- if .Values.galera.sst.existingSecret }}
+{{- .Values.galera.sst.existingSecret }}
+{{- else }}
+{{- printf "%s-galera" (include "mariadb.fullname" .) }}
+{{- end }}
+{{- end }}
+
+{{/*
+Generate Galera cluster address list
+*/}}
+{{- define "mariadb.galeraClusterAddress" -}}
+{{- $fullname := include "mariadb.fullname" . -}}
+{{- $replicaCount := int .Values.galera.replicaCount -}}
+{{- $namespace := .Release.Namespace -}}
+{{- $addresses := list -}}
+{{- range $i := until $replicaCount -}}
+{{- $addresses = append $addresses (printf "%s-%d.%s.%s.svc.cluster.local:4567" $fullname $i $fullname $namespace) -}}
+{{- end -}}
+{{- join "," $addresses -}}
+{{- end }}
+
+{{/*
+Generate Galera cluster name with release context
+*/}}
+{{- define "mariadb.galeraClusterName" -}}
+{{- printf "%s-%s" .Release.Name .Values.galera.name -}}
+{{- end }}
+
+{{/*
+Generate Galera node name with pod name
+*/}}
+{{- define "mariadb.galeraNodeName" -}}
+{{- printf "%s-%s" (include "mariadb.fullname" .) "REPLICA_NUM" -}}
+{{- end }}
+
+{{/*
+Generate Galera node address
+*/}}
+{{- define "mariadb.galeraNodeAddress" -}}
+{{- printf "%s-%s.%s.%s.svc.cluster.local" (include "mariadb.fullname" .) "REPLICA_NUM" (include "mariadb.fullname" .) .Release.Namespace -}}
+{{- end }}
diff --git a/charts/mariadb/templates/configmap.yaml b/charts/mariadb/templates/configmap.yaml
index faeaaaa7..9559ebc6 100644
--- a/charts/mariadb/templates/configmap.yaml
+++ b/charts/mariadb/templates/configmap.yaml
@@ -1,4 +1,4 @@
-{{- if and .Values.config.customConfiguration (not .Values.config.existingConfigMap) }}
+{{- if and (or .Values.config.customConfiguration .Values.galera.enabled) (not .Values.config.existingConfigMap) }}
apiVersion: v1
kind: ConfigMap
metadata:
@@ -11,6 +11,12 @@ metadata:
{{- toYaml . | nindent 4 }}
{{- end }}
data:
+ {{- if .Values.config.customConfiguration }}
my.cnf: |
{{ .Values.config.customConfiguration | nindent 4 }}
+ {{- end }}
+ {{- if .Values.galera.enabled }}
+ 00-galera.cnf: |
+ !include /etc/mysql/galera.cnf
+ {{- end }}
{{- end }}
\ No newline at end of file
diff --git a/charts/mariadb/templates/extraobjects.yaml b/charts/mariadb/templates/extraobjects.yaml
index fd7643e4..7f5ede80 100644
--- a/charts/mariadb/templates/extraobjects.yaml
+++ b/charts/mariadb/templates/extraobjects.yaml
@@ -1,4 +1,4 @@
{{- range .Values.extraObjects }}
---
-{{- include "common.tplvalues.render" (dict "value" . "context" $) }}
+{{- include "cloudpirates.tplvalues.render" (dict "value" . "context" $) }}
{{- end }}
\ No newline at end of file
diff --git a/charts/mariadb/templates/galera/configmap.yaml b/charts/mariadb/templates/galera/configmap.yaml
new file mode 100644
index 00000000..ad603eb9
--- /dev/null
+++ b/charts/mariadb/templates/galera/configmap.yaml
@@ -0,0 +1,58 @@
+{{- if .Values.galera.enabled }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ include "mariadb.fullname" . }}-galera
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "mariadb.labels" . | nindent 4 }}
+ {{- with .Values.commonAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+data:
+ galera.cnf: |
+ [galera]
+ # Galera Provider Configuration
+ wsrep_on=ON
+ wsrep_provider={{ .Values.galera.wsrepProvider }}
+ wsrep_cluster_name={{ include "mariadb.galeraClusterName" . }}
+ wsrep_cluster_address=gcomm://{{ include "mariadb.galeraClusterAddress" . }}
+ wsrep_node_name={{ include "mariadb.galeraNodeName" . }}
+ wsrep_node_address={{ include "mariadb.galeraNodeAddress" . }}
+
+ # Replication settings
+ binlog_format=ROW
+ default_storage_engine=InnoDB
+ innodb_autoinc_lock_mode=2
+
+ # InnoDB settings for Galera
+ innodb_flush_log_at_trx_commit={{ .Values.galera.innodb.flushLogAtTrxCommit }}
+ innodb_buffer_pool_size={{ .Values.galera.innodb.bufferPoolSize }}
+
+ # Galera performance tuning
+ wsrep_slave_threads={{ .Values.galera.wsrepSlaveThreads }}
+ wsrep_certify_nonPK={{ .Values.galera.wsrepCertifyNonPK }}
+ wsrep_max_ws_rows={{ .Values.galera.wsrepMaxWsRows }}
+ wsrep_max_ws_size={{ .Values.galera.wsrepMaxWsSize }}
+ wsrep_retry_autocommit={{ .Values.galera.wsrepRetryAutocommit }}
+ wsrep_auto_increment_control={{ .Values.galera.wsrepAutoIncrementControl }}
+ wsrep_drupal_282555_workaround={{ .Values.galera.wsrepDrupalHack }}
+ wsrep_log_conflicts={{ .Values.galera.wsrepLogConflicts }}
+
+ # State Snapshot Transfer (SST) settings
+ wsrep_sst_method={{ .Values.galera.wsrepMethod }}
+ {{- if .Values.galera.sst.user }}
+ wsrep_sst_auth={{ .Values.galera.sst.user }}:{{ .Values.galera.sst.password }}
+ {{- end }}
+
+ {{- if .Values.galera.wsrepDebug }}
+ # Debug settings
+ wsrep_debug=ON
+ {{- end }}
+
+ # Additional settings for cluster consistency
+ innodb_doublewrite=1
+ query_cache_type=0
+ query_cache_size=0
+{{- end }}
\ No newline at end of file
diff --git a/charts/mariadb/templates/galera/scripts-configmap.yaml b/charts/mariadb/templates/galera/scripts-configmap.yaml
new file mode 100644
index 00000000..d6bb70d5
--- /dev/null
+++ b/charts/mariadb/templates/galera/scripts-configmap.yaml
@@ -0,0 +1,104 @@
+{{- if .Values.galera.enabled }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ include "mariadb.fullname" . }}-galera-scripts
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "mariadb.labels" . | nindent 4 }}
+ {{- with .Values.commonAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+data:
+ galera-entrypoint.sh: |
+ #!/bin/bash
+ set -eo pipefail
+
+ # Galera entrypoint script for MariaDB
+
+ echo "Starting Galera cluster initialization..."
+
+ # Check if this is the bootstrap node (first replica)
+ HOSTNAME=$(hostname)
+ echo "Current hostname: $HOSTNAME"
+
+ # Extract replica number from hostname
+ REPLICA_NUM=$(echo $HOSTNAME | grep -o '[0-9]*$')
+ echo "Replica number: $REPLICA_NUM"
+
+ # Check if data directory exists and is empty
+ DATA_DIR="/var/lib/mysql"
+ if [ ! -d "$DATA_DIR/mysql" ]; then
+ echo "Data directory is empty, this is a new installation"
+ NEW_CLUSTER=true
+ else
+ echo "Data directory exists, checking cluster state"
+ NEW_CLUSTER=false
+ fi
+
+ # Check grastate.dat for cluster state
+ GRASTATE_FILE="$DATA_DIR/grastate.dat"
+ SAFE_TO_BOOTSTRAP=false
+
+ if [ -f "$GRASTATE_FILE" ]; then
+ echo "Found grastate.dat file"
+ if grep -q "safe_to_bootstrap: 1" "$GRASTATE_FILE"; then
+ SAFE_TO_BOOTSTRAP=true
+ echo "Node is safe to bootstrap"
+ fi
+ fi
+
+ # Determine if we should bootstrap or join
+ BOOTSTRAP_CLUSTER=false
+
+ if [ "$NEW_CLUSTER" = true ] && [ "$REPLICA_NUM" = "0" ]; then
+ echo "First node in new cluster - will bootstrap"
+ BOOTSTRAP_CLUSTER=true
+ elif [ "$MARIADB_GALERA_FORCE_SAFETOBOOTSTRAP" = "true" ]; then
+ echo "Force bootstrap enabled"
+ BOOTSTRAP_CLUSTER=true
+ # Set safe_to_bootstrap=1 in grastate.dat
+ if [ -f "$GRASTATE_FILE" ]; then
+ sed -i 's/safe_to_bootstrap: 0/safe_to_bootstrap: 1/' "$GRASTATE_FILE"
+ fi
+ elif [ "$SAFE_TO_BOOTSTRAP" = true ]; then
+ echo "Node is safe to bootstrap based on grastate.dat"
+ BOOTSTRAP_CLUSTER=true
+ fi
+
+ # Start MariaDB with appropriate options
+ if [ "$BOOTSTRAP_CLUSTER" = true ]; then
+ echo "Bootstrapping new Galera cluster..."
+ #exec mariadb-install-db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
+ #mariadb-install-db
+ #sleep 3
+ #exec mariadbd --wsrep-new-cluster "$@"
+ exec /usr/local/bin/docker-entrypoint.sh --wsrep-new-cluster "$@"
+
+ else
+ echo "Joining existing Galera cluster..."
+ exec mariadbd "$@"
+ #exec /usr/local/bin/docker-entrypoint.sh "$@"
+ fi
+
+ galera-recovery.sh: |
+ #!/bin/bash
+ set -eo pipefail
+
+ # Galera recovery script
+ echo "Starting Galera recovery process..."
+
+ DATA_DIR="/var/lib/mysql"
+ GRASTATE_FILE="$DATA_DIR/grastate.dat"
+
+ if [ ! -f "$GRASTATE_FILE" ]; then
+ echo "No grastate.dat found, nothing to recover"
+ exit 0
+ fi
+
+ echo "Checking cluster state..."
+ mariadbd --wsrep-recover
+
+ echo "Recovery completed"
+{{- end }}
\ No newline at end of file
diff --git a/charts/mariadb/templates/galera/secret.yaml b/charts/mariadb/templates/galera/secret.yaml
new file mode 100644
index 00000000..000dfcf5
--- /dev/null
+++ b/charts/mariadb/templates/galera/secret.yaml
@@ -0,0 +1,19 @@
+{{- if and .Values.galera.enabled .Values.galera.sst.password (not .Values.galera.sst.existingSecret) }}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ include "mariadb.fullname" . }}-galera
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "mariadb.labels" . | nindent 4 }}
+ {{- with .Values.commonAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+type: Opaque
+data:
+ {{- if .Values.galera.sst.user }}
+ {{ .Values.galera.sst.secretKeys.userKey }}: {{ .Values.galera.sst.user | b64enc | quote }}
+ {{- end }}
+ {{ .Values.galera.sst.secretKeys.passwordKey }}: {{ .Values.galera.sst.password | b64enc | quote }}
+{{- end }}
\ No newline at end of file
diff --git a/charts/mariadb/templates/galera/service.yaml b/charts/mariadb/templates/galera/service.yaml
new file mode 100644
index 00000000..91427f61
--- /dev/null
+++ b/charts/mariadb/templates/galera/service.yaml
@@ -0,0 +1,38 @@
+
+{{- if .Values.galera.enabled }}
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "mariadb.fullname" . }}-headless
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "mariadb.labels" . | nindent 4 }}
+ app.kubernetes.io/component: headless
+ {{- with .Values.commonAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ type: ClusterIP
+ clusterIP: None
+ publishNotReadyAddresses: true
+ ports:
+ - port: {{ .Values.service.port }}
+ targetPort: mysql
+ protocol: TCP
+ name: mysql
+ - port: 4567
+ targetPort: galera-repl
+ protocol: TCP
+ name: galera-repl
+ - port: 4568
+ targetPort: galera-ist
+ protocol: TCP
+ name: galera-ist
+ - port: 4444
+ targetPort: galera-sst
+ protocol: TCP
+ name: galera-sst
+ selector:
+ {{- include "mariadb.selectorLabels" . | nindent 4 }}
+{{- end }}
\ No newline at end of file
diff --git a/charts/mariadb/templates/pvc.yaml b/charts/mariadb/templates/pvc.yaml
index ccc96a24..03545c07 100644
--- a/charts/mariadb/templates/pvc.yaml
+++ b/charts/mariadb/templates/pvc.yaml
@@ -10,7 +10,8 @@ metadata:
namespace: {{ .Release.Namespace }}
labels:
{{- include "mariadb.labels" . | nindent 4 }}
- {{- with .Values.persistence.annotations }}
+ {{- $annotations := merge .Values.persistence.annotations .Values.commonAnnotations }}
+ {{- with $annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
diff --git a/charts/mariadb/templates/service.yaml b/charts/mariadb/templates/service.yaml
index e532912f..374803b6 100644
--- a/charts/mariadb/templates/service.yaml
+++ b/charts/mariadb/templates/service.yaml
@@ -23,5 +23,19 @@ spec:
{{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) .Values.service.nodePort }}
nodePort: {{ .Values.service.nodePort }}
{{- end }}
+ {{- if .Values.galera.enabled }}
+ - port: 4567
+ targetPort: galera-repl
+ protocol: TCP
+ name: galera-repl
+ - port: 4568
+ targetPort: galera-ist
+ protocol: TCP
+ name: galera-ist
+ - port: 4444
+ targetPort: galera-sst
+ protocol: TCP
+ name: galera-sst
+ {{- end }}
selector:
- {{- include "mariadb.selectorLabels" . | nindent 4 }}
\ No newline at end of file
+ {{- include "mariadb.selectorLabels" . | nindent 4 }}
diff --git a/charts/mariadb/templates/statefulset.yaml b/charts/mariadb/templates/statefulset.yaml
index 9d900946..56ffd714 100644
--- a/charts/mariadb/templates/statefulset.yaml
+++ b/charts/mariadb/templates/statefulset.yaml
@@ -11,7 +11,11 @@ metadata:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
+ {{- if .Values.galera.enabled }}
+ replicas: {{ .Values.galera.replicaCount }}
+ {{- else }}
replicas: 1
+ {{- end }}
serviceName: {{ include "mariadb.fullname" . }}
selector:
matchLabels:
@@ -31,13 +35,42 @@ spec:
{{- with (include "mariadb.imagePullSecrets" .) }}
{{- . | nindent 6 }}
{{- end }}
- securityContext: {{ include "common.renderPodSecurityContext" . | nindent 8 }}
+ securityContext: {{ include "cloudpirates.renderPodSecurityContext" . | nindent 8 }}
+ {{- if .Values.galera.enabled }}
+ initContainers:
+ - name: galera-config-init
+ image: {{ include "mariadb.image" . }}
+ imagePullPolicy: {{ .Values.image.imagePullPolicy }}
+ securityContext: {{ include "cloudpirates.renderContainerSecurityContext" . | nindent 12 }}
+ command:
+ - /bin/bash
+ - -c
+ - |
+ REPLICA_NUM=$(echo $HOSTNAME | grep -o '[0-9]*$')
+ cp /tmp/galera-config-ro/galera.cnf /tmp/galera-config-rw/galera.cnf
+ sed -i "s/REPLICA_NUM/$REPLICA_NUM/g" /tmp/galera-config-rw/galera.cnf
+ chmod 644 /tmp/galera-config-rw/galera.cnf
+ volumeMounts:
+ - mountPath: /tmp
+ name: tmp-volume
+ - name: galera-config
+ mountPath: /tmp/galera-config-ro
+ readOnly: true
+ - name: galera-config-rw
+ mountPath: /tmp/galera-config-rw
+ {{- end }}
containers:
- name: mariadb
image: {{ include "mariadb.image" . }}
imagePullPolicy: {{ .Values.image.imagePullPolicy }}
- securityContext: {{ include "common.renderContainerSecurityContext" . | nindent 12 }}
- {{- if or .Values.auth.enabled .Values.auth.database .Values.auth.username .Values.auth.allowEmptyRootPassword .Values.env }}
+ securityContext: {{ include "cloudpirates.renderContainerSecurityContext" . | nindent 12 }}
+ {{- if .Values.galera.enabled }}
+ command:
+ - /bin/bash
+ - -c
+ - source /usr/local/bin/galera-entrypoint.sh
+ {{- end }}
+ {{- if or .Values.auth.enabled .Values.auth.database .Values.auth.username .Values.auth.allowEmptyRootPassword .Values.extraEnvVars .Values.galera.enabled }}
env:
{{- if and .Values.auth.enabled }}
- name: MARIADB_ROOT_PASSWORD
@@ -63,7 +96,32 @@ spec:
- name: MARIADB_ALLOW_EMPTY_ROOT_PASSWORD
value: "1"
{{- end }}
- {{- with .Values.env }}
+ {{- if .Values.galera.enabled }}
+ - name: MARIADB_GALERA_CLUSTER
+ value: "true"
+ - name: MARIADB_GALERA_CLUSTER_NAME
+ value: {{ .Values.galera.name | quote }}
+ - name: MARIADB_GALERA_NODE_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: MARIADB_GALERA_NODE_ADDRESS
+ valueFrom:
+ fieldRef:
+ fieldPath: status.podIP
+ {{- if .Values.galera.sst.password }}
+ - name: MARIADB_GALERA_SST_USER
+ value: {{ .Values.galera.sst.user | quote }}
+ - name: MARIADB_GALERA_SST_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: {{ include "mariadb.galeraSecretName" . }}
+ key: {{ .Values.galera.sst.secretKeys.passwordKey }}
+ {{- end }}
+ - name: MARIADB_GALERA_FORCE_SAFETOBOOTSTRAP
+ value: {{ .Values.galera.forceSafeToBootstrap | quote }}
+ {{- end }}
+ {{- with .Values.extraEnvVars }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
@@ -71,20 +129,43 @@ spec:
- name: mysql
containerPort: 3306
protocol: TCP
+ {{- if .Values.galera.enabled }}
+ - name: galera-repl
+ containerPort: 4567
+ protocol: TCP
+ - name: galera-ist
+ containerPort: 4568
+ protocol: TCP
+ - name: galera-sst
+ containerPort: 4444
+ protocol: TCP
+ {{- end }}
{{- if .Values.livenessProbe.enabled }}
livenessProbe:
exec:
command:
- bash
- -c
+ {{- if and .Values.galera.enabled .Values.auth.enabled }}
+ - |
+ if mariadb -uroot -p"$MARIADB_ROOT_PASSWORD" -e "SHOW STATUS LIKE 'wsrep_ready'" | grep -q ON; then
+ exit 0
+ else
+ mariadb -uroot -p"$MARIADB_ROOT_PASSWORD" -e "SHOW STATUS LIKE 'wsrep_local_state_comment'"
+ mariadb -uroot -p"$MARIADB_ROOT_PASSWORD" -e "SHOW STATUS LIKE 'wsrep_ready'"
+ echo "healthcheck failed: Galera not alive"
+ exit 1
+ fi
+ {{- else }}
- healthcheck.sh --connect --innodb_initialized
+ {{- end }}
initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
successThreshold: {{ .Values.livenessProbe.successThreshold }}
failureThreshold: {{ .Values.livenessProbe.failureThreshold }}
{{- end }}
- {{- if .Values.readinessProbe.enabled }}
+ {{- if and .Values.readinessProbe.enabled (not .Values.galera.enabled)}}
readinessProbe:
exec:
command:
@@ -97,7 +178,7 @@ spec:
successThreshold: {{ .Values.readinessProbe.successThreshold }}
failureThreshold: {{ .Values.readinessProbe.failureThreshold }}
{{- end }}
- {{- if .Values.startupProbe.enabled }}
+ {{- if and .Values.startupProbe.enabled (not .Values.galera.enabled)}}
startupProbe:
exec:
command:
@@ -119,10 +200,18 @@ spec:
mountPath: /var/lib/mysql
- mountPath: /tmp
name: tmp-volume
- {{- if or .Values.config.customConfiguration .Values.config.existingConfigMap }}
+ {{- if or .Values.config.customConfiguration .Values.config.existingConfigMap .Values.galera.enabled }}
- name: config
mountPath: /etc/mysql/conf.d
{{- end }}
+ {{- if .Values.galera.enabled }}
+ - name: galera-config-rw
+ mountPath: /etc/mysql/mariadb.conf.d/60-galera.cnf
+ subPath: galera.cnf
+ - name: galera-scripts
+ mountPath: /usr/local/bin/galera-entrypoint.sh
+ subPath: galera-entrypoint.sh
+ {{- end }}
{{- if .Values.initdbScriptsConfigMap }}
- name: custom-init-scripts
mountPath: /docker-entrypoint-initdb.d
@@ -131,6 +220,18 @@ spec:
- name: run
mountPath: /var/run/mysqld/
{{- end }}
+ {{- range $secret := .Values.extraSecrets }}
+ - name: {{ $secret.name }}
+ mountPath: {{ $secret.mountPath }}
+ {{- end }}
+ {{- range $config := .Values.extraConfigs }}
+ - name: {{ $config.name }}
+ mountPath: {{ $config.mountPath }}
+ {{- end }}
+ {{- range $storage := .Values.extraVolumes }}
+ - name: {{ $storage.name }}
+ mountPath: {{ $storage.mountPath }}
+ {{- end }}
volumes:
- name: tmp-volume
emptyDir: {}
@@ -142,11 +243,22 @@ spec:
- name: run
emptyDir: {}
{{- end }}
- {{- if or .Values.config.customConfiguration .Values.config.existingConfigMap }}
+ {{- if or .Values.config.customConfiguration .Values.config.existingConfigMap .Values.galera.enabled }}
- name: config
configMap:
name: {{ include "mariadb.configMapName" . }}
{{- end }}
+ {{- if .Values.galera.enabled }}
+ - name: galera-config
+ configMap:
+ name: {{ include "mariadb.fullname" . }}-galera
+ - name: galera-config-rw
+ emptyDir: {}
+ - name: galera-scripts
+ configMap:
+ name: {{ include "mariadb.fullname" . }}-galera-scripts
+ defaultMode: 0755
+ {{- end }}
{{- if .Values.initdbScriptsConfigMap }}
- name: custom-init-scripts
configMap:
diff --git a/charts/mariadb/values.schema.json b/charts/mariadb/values.schema.json
index 529f9720..ae2b2c81 100644
--- a/charts/mariadb/values.schema.json
+++ b/charts/mariadb/values.schema.json
@@ -1,736 +1,453 @@
{
- "$schema": "https://json-schema.org/draft-07/schema#",
- "type": "object",
- "title": "MariaDB Helm Chart Values Schema",
- "description": "Schema for MariaDB Helm chart values",
- "properties": {
- "global": {
- "type": "object",
- "title": "Global Parameters",
- "description": "Global Docker image parameters",
- "properties": {
- "imageRegistry": {
- "type": "string",
- "title": "Global Docker Image Registry",
- "description": "Global Docker Image registry"
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "type": "object",
+ "properties": {
+ "affinity": {
+ "type": "object"
},
- "imagePullSecrets": {
- "type": "array",
- "title": "Global Image Pull Secrets",
- "description": "Global Docker registry secret names as an array of objects",
- "items": {
+ "auth": {
"type": "object",
"properties": {
- "name": {
- "type": "string",
- "title": "Secret Name",
- "description": "Name of the image pull secret"
- }
- },
- "required": ["name"]
- }
- }
- }
- },
- "nameOverride": {
- "type": "string",
- "title": "Name Override",
- "description": "String to partially override mariadb.fullname"
- },
- "fullnameOverride": {
- "type": "string",
- "title": "Full Name Override",
- "description": "String to fully override mariadb.fullname"
- },
- "commonLabels": {
- "type": "object",
- "title": "Common Labels",
- "description": "Labels to add to all deployed objects",
- "additionalProperties": {
- "type": "string"
- }
- },
- "commonAnnotations": {
- "type": "object",
- "title": "Common Annotations",
- "description": "Annotations to add to all deployed objects",
- "additionalProperties": {
- "type": "string"
- }
- },
- "image": {
- "type": "object",
- "title": "MariaDB Image Configuration",
- "description": "MariaDB container image parameters",
- "properties": {
- "registry": {
- "type": "string",
- "title": "MariaDB Image Registry",
- "description": "MariaDB image registry"
- },
- "repository": {
- "type": "string",
- "title": "MariaDB Image Repository",
- "description": "MariaDB image repository"
+ "allowEmptyRootPassword": {
+ "type": "string"
+ },
+ "database": {
+ "type": "string"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "existingSecret": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "rootPassword": {
+ "type": "string"
+ },
+ "secretKeys": {
+ "type": "object",
+ "properties": {
+ "rootPasswordKey": {
+ "type": "string"
+ },
+ "userPasswordKey": {
+ "type": "string"
+ }
+ }
+ },
+ "username": {
+ "type": "string"
+ }
+ }
},
- "tag": {
- "type": "string",
- "title": "MariaDB Image Tag",
- "description": "MariaDB image tag with digest"
+ "commonAnnotations": {
+ "type": "object"
},
- "imagePullPolicy": {
- "type": "string",
- "title": "MariaDB Image Pull Policy",
- "description": "MariaDB image pull policy",
- "enum": ["Always", "Never", "IfNotPresent"]
+ "commonLabels": {
+ "type": "object"
},
- "pullSecrets": {
- "type": "array",
- "title": "MariaDB Image Pull Secrets",
- "description": "MariaDB image pull secrets",
- "items": {
+ "config": {
"type": "object",
"properties": {
- "name": {
- "type": "string",
- "title": "Secret Name",
- "description": "Name of the image pull secret"
- }
- },
- "required": ["name"]
- }
- }
- }
- },
- "auth": {
- "type": "object",
- "title": "MariaDB Authentication",
- "description": "Authentication parameters",
- "properties": {
- "rootPassword": {
- "type": "string",
- "title": "MariaDB Root Password",
- "description": "MariaDB root password"
- },
- "database": {
- "type": "string",
- "title": "MariaDB Custom Database",
- "description": "MariaDB custom database"
- },
- "username": {
- "type": "string",
- "title": "MariaDB Custom Username",
- "description": "MariaDB custom user name"
- },
- "password": {
- "type": "string",
- "title": "MariaDB Custom Password",
- "description": "MariaDB custom user password"
- },
- "existingSecret": {
- "type": "string",
- "title": "Existing Secret",
- "description": "Name of existing secret to use for MariaDB credentials"
- },
- "secretKeys": {
- "type": "object",
- "title": "Secret Keys",
- "description": "Keys in existing secret",
- "properties": {
- "rootPasswordKey": {
- "type": "string",
- "title": "Root Password Key",
- "description": "Name of key in existing secret to use for root password"
- },
- "userPasswordKey": {
- "type": "string",
- "title": "User Password Key",
- "description": "Name of key in existing secret to use for user password"
+ "customConfiguration": {
+ "type": "string"
+ },
+ "existingConfigMap": {
+ "type": "string"
+ }
}
- }
- }
- }
- },
- "config": {
- "type": "object",
- "title": "MariaDB Configuration",
- "description": "MariaDB configuration parameters",
- "properties": {
- "customConfiguration": {
- "type": "string",
- "title": "Custom Configuration",
- "description": "Custom configuration for MariaDB"
- },
- "existingConfigMap": {
- "type": "string",
- "title": "Existing ConfigMap",
- "description": "Name of existing ConfigMap with MariaDB configuration"
- }
- }
- },
- "service": {
- "type": "object",
- "title": "Service Configuration",
- "description": "MariaDB service parameters",
- "properties": {
- "type": {
- "type": "string",
- "title": "Service Type",
- "description": "MariaDB service type",
- "enum": ["ClusterIP", "NodePort", "LoadBalancer", "ExternalName"]
- },
- "port": {
- "type": "integer",
- "title": "Service Port",
- "description": "MariaDB service port",
- "minimum": 1,
- "maximum": 65535
},
- "nodePort": {
- "type": "string",
- "title": "Node Port",
- "description": "Node port for MariaDB service"
- },
- "clusterIP": {
- "type": "string",
- "title": "Cluster IP",
- "description": "Static cluster IP or None for headless service"
+ "containerSecurityContext": {
+ "type": "object",
+ "properties": {
+ "allowPrivilegeEscalation": {
+ "type": "boolean"
+ },
+ "readOnlyRootFilesystem": {
+ "type": "boolean"
+ },
+ "runAsNonRoot": {
+ "type": "boolean"
+ },
+ "runAsUser": {
+ "type": "integer"
+ }
+ }
},
- "annotations": {
- "type": "object",
- "title": "Service Annotations",
- "description": "Additional custom annotations for MariaDB service",
- "additionalProperties": {
- "type": "string"
- }
- }
- }
- },
- "persistence": {
- "type": "object",
- "title": "Persistence Configuration",
- "description": "Persistence parameters",
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable Persistence",
- "description": "Enable MariaDB data persistence using PVC"
+ "extraConfigs": {
+ "type": "array"
},
- "storageClass": {
- "type": "string",
- "title": "Storage Class",
- "description": "PVC Storage Class for MariaDB data volume"
+ "extraEnvVars": {
+ "type": "array"
},
- "accessModes": {
- "type": "array",
- "title": "Access Modes",
- "description": "PVC Access modes",
- "items": {
- "type": "string",
- "enum": ["ReadWriteOnce", "ReadOnlyMany", "ReadWriteMany", "ReadWriteOncePod"]
- }
+ "extraObjects": {
+ "type": "array"
},
- "size": {
- "type": "string",
- "title": "Storage Size",
- "description": "PVC Storage Request for MariaDB data volume",
- "pattern": "^\\d+(Ei|Pi|Ti|Gi|Mi|Ki|E|P|T|G|M|K)?$"
+ "extraSecrets": {
+ "type": "array"
},
- "annotations": {
- "type": "object",
- "title": "PVC Annotations",
- "description": "Additional custom annotations for the PVC",
- "additionalProperties": {
- "type": "string"
- }
+ "extraVolumes": {
+ "type": "array"
},
- "selector": {
- "type": "object",
- "title": "PVC Selector",
- "description": "Additional labels for the PVC",
- "additionalProperties": {
+ "fullnameOverride": {
"type": "string"
- }
- }
- }
- },
- "podSecurityContext": {
- "type": "object",
- "title": "Pod Security Context",
- "description": "MariaDB Pod Security Context",
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable Pod Security Context",
- "description": "Enabled MariaDB pod Security Context"
},
- "fsGroup": {
- "type": "integer",
- "title": "FS Group",
- "description": "Set MariaDB pod's Security Context fsGroup",
- "minimum": 0
- }
- }
- },
- "containerSecurityContext": {
- "type": "object",
- "title": "Container Security Context",
- "description": "MariaDB Container Security Context",
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable Container Security Context",
- "description": "Enabled MariaDB container's Security Context"
- },
- "runAsUser": {
- "type": "integer",
- "title": "Run As User",
- "description": "Set MariaDB container's Security Context runAsUser",
- "minimum": 0
- },
- "runAsNonRoot": {
- "type": "boolean",
- "title": "Run As Non-Root",
- "description": "Set MariaDB container's Security Context runAsNonRoot"
+ "galera": {
+ "type": "object",
+ "properties": {
+ "bootstrap": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ }
+ }
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "forceSafeToBootstrap": {
+ "type": "boolean"
+ },
+ "innodb": {
+ "type": "object",
+ "properties": {
+ "bufferPoolSize": {
+ "type": "string"
+ },
+ "flushLogAtTrxCommit": {
+ "type": "integer"
+ }
+ }
+ },
+ "name": {
+ "type": "string"
+ },
+ "recovery": {
+ "type": "object",
+ "properties": {
+ "clusterBootstrap": {
+ "type": "boolean"
+ },
+ "enabled": {
+ "type": "boolean"
+ }
+ }
+ },
+ "replicaCount": {
+ "type": "integer"
+ },
+ "sst": {
+ "type": "object",
+ "properties": {
+ "existingSecret": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "secretKeys": {
+ "type": "object",
+ "properties": {
+ "passwordKey": {
+ "type": "string"
+ },
+ "userKey": {
+ "type": "string"
+ }
+ }
+ },
+ "user": {
+ "type": "string"
+ }
+ }
+ },
+ "wsrepAutoIncrementControl": {
+ "type": "boolean"
+ },
+ "wsrepCertifyNonPK": {
+ "type": "boolean"
+ },
+ "wsrepDebug": {
+ "type": "boolean"
+ },
+ "wsrepDrupalHack": {
+ "type": "boolean"
+ },
+ "wsrepLogConflicts": {
+ "type": "boolean"
+ },
+ "wsrepMaxWsRows": {
+ "type": "integer"
+ },
+ "wsrepMaxWsSize": {
+ "type": "string"
+ },
+ "wsrepMethod": {
+ "type": "string"
+ },
+ "wsrepProvider": {
+ "type": "string"
+ },
+ "wsrepRetryAutocommit": {
+ "type": "integer"
+ },
+ "wsrepSlaveThreads": {
+ "type": "integer"
+ }
+ }
},
- "allowPrivilegeEscalation": {
- "type": "boolean",
- "title": "Allow Privilege Escalation",
- "description": "Set MariaDB container's privilege escalation"
+ "global": {
+ "type": "object",
+ "properties": {
+ "imagePullSecrets": {
+ "type": "array"
+ },
+ "imageRegistry": {
+ "type": "string"
+ }
+ }
},
- "readOnlyRootFilesystem": {
- "type": "boolean",
- "title": "Read-Only root filesystem",
- "description": "Set MariaDB container's Security Context readOnlyRootFilesystem"
- }
- }
- },
- "resources": {
- "type": "object",
- "title": "Resource Configuration",
- "description": "Resources parameters",
- "properties": {
- "limits": {
- "type": "object",
- "title": "Resource Limits",
- "description": "The resources limits for the MariaDB containers",
- "properties": {
- "cpu": {
- "oneOf": [
- {"type": "string"},
- {"type": "number"}
- ],
- "title": "CPU Limit",
- "description": "CPU resource limit"
- },
- "memory": {
- "type": "string",
- "title": "Memory Limit",
- "description": "Memory resource limit"
+ "image": {
+ "type": "object",
+ "properties": {
+ "imagePullPolicy": {
+ "type": "string"
+ },
+ "registry": {
+ "type": "string"
+ },
+ "repository": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ }
}
- }
},
- "requests": {
- "type": "object",
- "title": "Resource Requests",
- "description": "The requested resources for the MariaDB containers",
- "properties": {
- "cpu": {
- "oneOf": [
- {"type": "string"},
- {"type": "number"}
- ],
- "title": "CPU Request",
- "description": "CPU resource request"
- },
- "memory": {
- "type": "string",
- "title": "Memory Request",
- "description": "Memory resource request"
+ "ingress": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object",
+ "properties": {
+ "kubernetes.io/hostname": {
+ "type": "string"
+ }
+ }
+ },
+ "className": {
+ "type": "string"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "hosts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "host": {
+ "type": "string"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "pathType": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tls": {
+ "type": "array"
+ }
}
- }
- }
- }
- },
- "env": {
- "type": "array",
- "title": "Environment Variables",
- "description": "A list of additional environment Variables",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string",
- "title": "Variable Name",
- "description": "Environment variable name"
- },
- "value": {
- "type": "string",
- "title": "Variable Value",
- "description": "Environment variable value"
- }
},
- "required": ["name"]
- }
- },
- "extraSecrets": {
- "type": "array",
- "title": "Extra Secrets",
- "description": "A list of additional existing secrets that will be mounted into the container",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string"
- },
- "defaultMode": {
- "type": "integer"
- },
- "mountPath": {
- "type": "string"
- }
- }
- }
- },
- "extraConfigs": {
- "type": "array",
- "title": "Extra Configs",
- "description": "A list of additional existing configMaps that will be mounted into the container",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string"
- },
- "defaultMode": {
- "type": "integer"
- },
- "mountPath": {
+ "initdbScriptsConfigMap": {
"type": "string"
- }
- }
- }
- },
- "extraVolumes": {
- "type": "array",
- "title": "Extra Volumes",
- "description": "A list of additional existing volumes that will be mounted into the container",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string"
- },
- "mountPath": {
- "type": "string"
- },
- "pvcName": {
- "type": "string"
- }
- }
- }
- },
- "livenessProbe": {
- "type": "object",
- "title": "Liveness Probe Configuration",
- "description": "MariaDB container's liveness probe parameters",
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable Liveness Probe",
- "description": "Enable livenessProbe on MariaDB containers"
- },
- "initialDelaySeconds": {
- "type": "integer",
- "title": "Initial Delay Seconds",
- "description": "Initial delay seconds for livenessProbe",
- "minimum": 0
- },
- "periodSeconds": {
- "type": "integer",
- "title": "Period Seconds",
- "description": "Period seconds for livenessProbe",
- "minimum": 1
- },
- "timeoutSeconds": {
- "type": "integer",
- "title": "Timeout Seconds",
- "description": "Timeout seconds for livenessProbe",
- "minimum": 1
- },
- "failureThreshold": {
- "type": "integer",
- "title": "Failure Threshold",
- "description": "Failure threshold for livenessProbe",
- "minimum": 1
- },
- "successThreshold": {
- "type": "integer",
- "title": "Success Threshold",
- "description": "Success threshold for livenessProbe",
- "minimum": 1
- }
- }
- },
- "readinessProbe": {
- "type": "object",
- "title": "Readiness Probe Configuration",
- "description": "MariaDB container's readiness probe parameters",
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable Readiness Probe",
- "description": "Enable readinessProbe on MariaDB containers"
- },
- "initialDelaySeconds": {
- "type": "integer",
- "title": "Initial Delay Seconds",
- "description": "Initial delay seconds for readinessProbe",
- "minimum": 0
- },
- "periodSeconds": {
- "type": "integer",
- "title": "Period Seconds",
- "description": "Period seconds for readinessProbe",
- "minimum": 1
- },
- "timeoutSeconds": {
- "type": "integer",
- "title": "Timeout Seconds",
- "description": "Timeout seconds for readinessProbe",
- "minimum": 1
- },
- "failureThreshold": {
- "type": "integer",
- "title": "Failure Threshold",
- "description": "Failure threshold for readinessProbe",
- "minimum": 1
},
- "successThreshold": {
- "type": "integer",
- "title": "Success Threshold",
- "description": "Success threshold for readinessProbe",
- "minimum": 1
- }
- }
- },
- "startupProbe": {
- "type": "object",
- "title": "Startup Probe Configuration",
- "description": "MariaDB container's startup probe parameters",
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable Startup Probe",
- "description": "Enable startupProbe on MariaDB containers"
- },
- "initialDelaySeconds": {
- "type": "integer",
- "title": "Initial Delay Seconds",
- "description": "Initial delay seconds for startupProbe",
- "minimum": 0
+ "livenessProbe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ }
+ }
},
- "periodSeconds": {
- "type": "integer",
- "title": "Period Seconds",
- "description": "Period seconds for startupProbe",
- "minimum": 1
+ "nameOverride": {
+ "type": "string"
},
- "timeoutSeconds": {
- "type": "integer",
- "title": "Timeout Seconds",
- "description": "Timeout seconds for startupProbe",
- "minimum": 1
+ "networkPolicy": {
+ "type": "object",
+ "properties": {
+ "allowExternal": {
+ "type": "boolean"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "ingressNSMatchLabels": {
+ "type": "object"
+ },
+ "ingressNSPodMatchLabels": {
+ "type": "object"
+ }
+ }
},
- "failureThreshold": {
- "type": "integer",
- "title": "Failure Threshold",
- "description": "Failure threshold for startupProbe",
- "minimum": 1
+ "nodeSelector": {
+ "type": "object"
},
- "successThreshold": {
- "type": "integer",
- "title": "Success Threshold",
- "description": "Success threshold for startupProbe",
- "minimum": 1
- }
- }
- },
- "podDisruptionBudget": {
- "type": "object",
- "title": "Pod Disruption Budget Configuration",
- "description": "Pod Disruption Budget configuration",
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable Pod Disruption Budget",
- "description": "Enable a Pod Disruption Budget creation"
+ "persistence": {
+ "type": "object",
+ "properties": {
+ "accessModes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "annotations": {
+ "type": "object"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "selector": {
+ "type": "object"
+ },
+ "size": {
+ "type": "string"
+ },
+ "storageClass": {
+ "type": "string"
+ }
+ }
},
- "minAvailable": {
- "oneOf": [
- {"type": "integer", "minimum": 0},
- {"type": "string"}
- ],
- "title": "Min Available",
- "description": "Min number of pods that must still be available after the eviction"
+ "podAnnotations": {
+ "type": "object"
},
- "maxUnavailable": {
- "oneOf": [
- {"type": "integer", "minimum": 0},
- {"type": "string"}
- ],
- "title": "Max Unavailable",
- "description": "Max number of pods that can be unavailable after the eviction"
- }
- }
- },
- "ingress": {
- "type": "object",
- "title": "Ingress Configuration",
- "description": "Ingress parameters",
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable Ingress",
- "description": "Enable ingress record generation for MariaDB"
+ "podDisruptionBudget": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "maxUnavailable": {
+ "type": "string"
+ },
+ "minAvailable": {
+ "type": "integer"
+ }
+ }
},
- "className": {
- "type": "string",
- "title": "Ingress Class Name",
- "description": "IngressClass that will be used to implement the Ingress"
+ "podLabels": {
+ "type": "object"
},
- "annotations": {
- "type": "object",
- "title": "Ingress Annotations",
- "description": "Additional annotations for the Ingress resource",
- "additionalProperties": {
- "type": "string"
- }
+ "podSecurityContext": {
+ "type": "object",
+ "properties": {
+ "fsGroup": {
+ "type": "integer"
+ }
+ }
},
- "hosts": {
- "type": "array",
- "title": "Ingress Hosts",
- "description": "An array with hosts and paths",
- "items": {
+ "readinessProbe": {
"type": "object",
"properties": {
- "host": {
- "type": "string",
- "title": "Host",
- "description": "Hostname for the ingress"
- },
- "paths": {
- "type": "array",
- "title": "Paths",
- "description": "Paths configuration for the host",
- "items": {
- "type": "object",
- "properties": {
- "path": {
- "type": "string",
- "title": "Path",
- "description": "Path for the ingress"
- },
- "pathType": {
- "type": "string",
- "title": "Path Type",
- "description": "Path type for the ingress",
- "enum": ["Exact", "Prefix", "ImplementationSpecific"]
- }
- }
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
}
- }
}
- }
},
- "tls": {
- "type": "array",
- "title": "TLS Configuration",
- "description": "TLS configuration for the Ingress",
- "items": {
+ "resources": {
"type": "object"
- }
- }
- }
- },
- "networkPolicy": {
- "type": "object",
- "title": "Network Policy Configuration",
- "description": "Network Policy configuration",
- "properties": {
- "enabled": {
- "type": "boolean",
- "title": "Enable Network Policy",
- "description": "Specifies whether a NetworkPolicy should be created"
},
- "allowExternal": {
- "type": "boolean",
- "title": "Allow External",
- "description": "Don't require client label for connections"
+ "service": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object"
+ },
+ "clusterIP": {
+ "type": "string"
+ },
+ "nodePort": {
+ "type": "string"
+ },
+ "port": {
+ "type": "integer"
+ },
+ "type": {
+ "type": "string"
+ }
+ }
},
- "ingressNSMatchLabels": {
- "type": "object",
- "title": "Ingress Namespace Match Labels",
- "description": "Labels to match to allow traffic from other namespaces",
- "additionalProperties": {
- "type": "string"
- }
+ "startupProbe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ }
+ }
},
- "ingressNSPodMatchLabels": {
- "type": "object",
- "title": "Ingress Namespace Pod Match Labels",
- "description": "Pod labels to match to allow traffic from other namespaces",
- "additionalProperties": {
- "type": "string"
- }
+ "tolerations": {
+ "type": "array"
}
- }
- },
- "podAnnotations": {
- "type": "object",
- "title": "Pod Annotations",
- "description": "Pod configuration annotations",
- "additionalProperties": {
- "type": "string"
- }
- },
- "podLabels": {
- "type": "object",
- "title": "Pod Labels",
- "description": "Pod configuration labels",
- "additionalProperties": {
- "type": "string"
- }
- },
- "nodeSelector": {
- "type": "object",
- "title": "Node Selector",
- "description": "Node selector for pod assignment",
- "additionalProperties": {
- "type": "string"
- }
- },
- "tolerations": {
- "type": "array",
- "title": "Tolerations",
- "description": "Tolerations for pod assignment",
- "items": {
- "type": "object"
- }
- },
- "affinity": {
- "type": "object",
- "title": "Affinity Configuration",
- "description": "Affinity settings for pod assignment"
- },
- "extraObjects": {
- "type": "array",
- "title": "Extra Objects",
- "description": "A list of additional Kubernetes objects to deploy alongside the release. Helm templating is supported in any field, but all template expressions must be quoted. Each item should be a valid Kubernetes manifest object.",
- "items": {
- "type": "object",
- "description": "A Kubernetes manifest object. All fields are allowed."
- }
}
- }
-}
\ No newline at end of file
+}
diff --git a/charts/mariadb/values.yaml b/charts/mariadb/values.yaml
index c2bcf586..6c60abcf 100644
--- a/charts/mariadb/values.yaml
+++ b/charts/mariadb/values.yaml
@@ -22,7 +22,7 @@ image:
## @param image.repository MariaDB image repository
repository: mariadb
## @param image.tag MariaDB image tag (immutable tags are recommended)
- tag: "12.0.2@sha256:03a03a6817bb9eaa21e5aed1b734d432ec3f80021f5a2de1795475f158217545"
+ tag: "12.0.2@sha256:5b6a1eac15b85b981a61afb89aea2a22bf76b5f58809d05f0bcc13ab6ec44cb8"
## @param image.pullPolicy MariaDB image pull policy
imagePullPolicy: Always
@@ -55,6 +55,67 @@ config:
## @param config.existingConfigMap Name of existing ConfigMap with MariaDB configuration
existingConfigMap: ""
+## @section Galera Cluster parameters
+galera:
+ ## @param galera.enabled Enable Galera Cluster mode
+ enabled: false
+ ## @param galera.name Galera cluster name
+ name: "galera"
+ ## @param galera.bootstrap.enabled Enable bootstrap mode for the first node in the cluster
+ bootstrap:
+ enabled: true
+ ## @param galera.replicaCount Number of nodes in the Galera cluster
+ replicaCount: 3
+ ## @param galera.wsrepProvider Path to wsrep provider library
+ wsrepProvider: "/usr/lib/galera/libgalera_smm.so"
+ ## @param galera.wsrepMethod Method for state snapshot transfers
+ ## Options: mariabackup, mysqldump, rsync
+ wsrepMethod: "mariabackup"
+ ## @param galera.forceSafeToBootstrap Force safe_to_bootstrap=1 in grastate.dat
+ forceSafeToBootstrap: false
+ ## @param galera.wsrepSlaveThreads Number of slave threads for applying writesets
+ wsrepSlaveThreads: 1
+ ## @param galera.wsrepCertifyNonPK Require primary key for replication
+ wsrepCertifyNonPK: true
+ ## @param galera.wsrepMaxWsRows Maximum number of rows in writeset
+ wsrepMaxWsRows: 0
+ ## @param galera.wsrepMaxWsSize Maximum size of writeset in bytes
+ wsrepMaxWsSize: "1073741824"
+ ## @param galera.wsrepDebug Enable wsrep debugging
+ wsrepDebug: false
+ ## @param galera.wsrepRetryAutocommit Number of times to retry autocommit
+ wsrepRetryAutocommit: 1
+ ## @param galera.wsrepAutoIncrementControl Enable auto increment control
+ wsrepAutoIncrementControl: true
+ ## @param galera.wsrepDrupalHack Enable Drupal compatibility hack
+ wsrepDrupalHack: false
+ ## @param galera.wsrepLogConflicts Log conflicts to error log
+ wsrepLogConflicts: false
+ ## @param galera.innodb.flushLogAtTrxCommit InnoDB flush log at transaction commit
+ innodb:
+ flushLogAtTrxCommit: 0
+ ## @param galera.innodb.bufferPoolSize InnoDB buffer pool size
+ bufferPoolSize: "128M"
+ ## @param galera.sst SST specific configuration
+ sst:
+ ## @param galera.sst.user SST user for authentication
+ user: ""
+ ## @param galera.sst.password SST password for authentication
+ password: ""
+ ## @param galera.sst.existingSecret Existing secret containing SST credentials
+ existingSecret: ""
+ ## @param galera.sst.secretKeys.userKey Secret key for SST user
+ ## @param galera.sst.secretKeys.passwordKey Secret key for SST password
+ secretKeys:
+ userKey: sst-user
+ passwordKey: sst-password
+ ## @param galera.recovery Enable Galera recovery options
+ recovery:
+ ## @param galera.recovery.enabled Enable automatic recovery
+ enabled: true
+ ## @param galera.recovery.clusterBootstrap Enable cluster bootstrap in recovery
+ clusterBootstrap: true
+
## @section MariaDB service parameters
service:
## @param service.type MariaDB service type
@@ -112,10 +173,15 @@ resources:
## cpu: 100m
## @section Extra Configs
-## @param env A list of additional environment Variables
-env: []
-## - name: ENV_VARIABLE
-## value: "value"
+## @param extraEnvVars Additional environment variables to set
+extraEnvVars: []
+ # - name: CUSTOM_VAR
+ # value: "custom-value"
+ # - name: SECRET_VAR
+ # valueFrom:
+ # secretKeyRef:
+ # name: my-secret
+ # key: secret-key
## @param extraSecrets A list of additional existing secrets that will be mounted into the container
extraSecrets: []
## - name: secret
diff --git a/charts/memcached/CHANGELOG.md b/charts/memcached/CHANGELOG.md
index 54e971e4..8cb1da34 100644
--- a/charts/memcached/CHANGELOG.md
+++ b/charts/memcached/CHANGELOG.md
@@ -1,5 +1,123 @@
# Changelog
-## 0.2.1 (2025-10-09)
-* [mongodb] feat: add metrics exporter ([#243](https://github.com/CloudPirates-io/helm-charts/pull/243))
+## 0.5.3 (2025-11-05)
+
+* Add support for pod labels (#550) ([6071930](https://github.com/CloudPirates-io/helm-charts/commit/6071930))
+* chore: update CHANGELOG.md for merged changes ([d944483](https://github.com/CloudPirates-io/helm-charts/commit/d944483))
+* chore: update CHANGELOG.md for merged changes ([6038560](https://github.com/CloudPirates-io/helm-charts/commit/6038560))
+
+## 0.5.2 (2025-11-04)
+
+* Update charts/memcached/values.yaml memcached (#543) ([8653b45](https://github.com/CloudPirates-io/helm-charts/commit/8653b45))
+* chore: update CHANGELOG.md for merged changes ([b1b5bea](https://github.com/CloudPirates-io/helm-charts/commit/b1b5bea))
+* chore: update CHANGELOG.md for merged changes ([09264e3](https://github.com/CloudPirates-io/helm-charts/commit/09264e3))
+
+## 0.5.1 (2025-11-04)
+
+* Update charts/memcached/values.yaml memcached (#540) ([80a134a](https://github.com/CloudPirates-io/helm-charts/commit/80a134a))
+* chore: update CHANGELOG.md for merged changes ([a45d016](https://github.com/CloudPirates-io/helm-charts/commit/a45d016))
+* chore: update CHANGELOG.md for merged changes ([c8a10d1](https://github.com/CloudPirates-io/helm-charts/commit/c8a10d1))
+* chore: auto-generate values.schema.json (#525) ([82bb370](https://github.com/CloudPirates-io/helm-charts/commit/82bb370))
+* chore: update CHANGELOG.md for merged changes ([d897e41](https://github.com/CloudPirates-io/helm-charts/commit/d897e41))
+* chore: update CHANGELOG.md for merged changes ([1a540b0](https://github.com/CloudPirates-io/helm-charts/commit/1a540b0))
+
+## 0.5.0 (2025-11-02)
+
+* Add metrics support (#512) ([5ea2397](https://github.com/CloudPirates-io/helm-charts/commit/5ea2397))
+* chore: update CHANGELOG.md for merged changes ([8260788](https://github.com/CloudPirates-io/helm-charts/commit/8260788))
+* chore: update CHANGELOG.md for merged changes ([402f7bd](https://github.com/CloudPirates-io/helm-charts/commit/402f7bd))
+
+## 0.4.0 (2025-10-28)
+
+* chore: auto-generate values.schema.json for updated charts (#455) ([aec6840](https://github.com/CloudPirates-io/helm-charts/commit/aec6840))
+* chore: update CHANGELOG.md for merged changes ([f9c3ff0](https://github.com/CloudPirates-io/helm-charts/commit/f9c3ff0))
+* chore: update CHANGELOG.md for merged changes ([db2d800](https://github.com/CloudPirates-io/helm-charts/commit/db2d800))
+
+## 0.3.4 (2025-10-23)
+
+* chore: update CHANGELOG.md for merged changes ([95d9741](https://github.com/CloudPirates-io/helm-charts/commit/95d9741))
+* chore: update CHANGELOG.md for merged changes ([ceb2770](https://github.com/CloudPirates-io/helm-charts/commit/ceb2770))
+
+## 0.3.3 (2025-10-22)
+
+* Update charts/memcached/values.yaml memcached (#425) ([de0a4a1](https://github.com/CloudPirates-io/helm-charts/commit/de0a4a1))
+
+## 0.3.2 (2025-10-21)
+
+* Update charts/memcached/values.yaml memcached (#424) ([304f6bd](https://github.com/CloudPirates-io/helm-charts/commit/304f6bd))
+* chore: update CHANGELOG.md for merged changes ([5d1f01a](https://github.com/CloudPirates-io/helm-charts/commit/5d1f01a))
+* chore: update CHANGELOG.md for merged changes ([fc47c5d](https://github.com/CloudPirates-io/helm-charts/commit/fc47c5d))
+* chore: update CHANGELOG.md for merged changes ([1a4f87b](https://github.com/CloudPirates-io/helm-charts/commit/1a4f87b))
+* chore: update CHANGELOG.md for merged changes ([da866ca](https://github.com/CloudPirates-io/helm-charts/commit/da866ca))
+* chore: update CHANGELOG.md for merged changes ([6d3bd93](https://github.com/CloudPirates-io/helm-charts/commit/6d3bd93))
+
+## 0.3.1 (2025-10-15)
+
+* chore: update CHANGELOG.md for merged changes ([b54c4f1](https://github.com/CloudPirates-io/helm-charts/commit/b54c4f1))
+* [memcached]: add missing automountServiceAccountToken key to deployment spec (#395) ([93fee01](https://github.com/CloudPirates-io/helm-charts/commit/93fee01))
+* chore: update CHANGELOG.md for merged changes ([5a2ed20](https://github.com/CloudPirates-io/helm-charts/commit/5a2ed20))
+* chore: update CHANGELOG.md for merged changes ([3361964](https://github.com/CloudPirates-io/helm-charts/commit/3361964))
+* chore: update CHANGELOG.md for merged changes ([7f61172](https://github.com/CloudPirates-io/helm-charts/commit/7f61172))
+* chore: update CHANGELOG.md for merged changes ([1ec9aab](https://github.com/CloudPirates-io/helm-charts/commit/1ec9aab))
+* chore: update CHANGELOG.md for merged changes ([c9ff4ec](https://github.com/CloudPirates-io/helm-charts/commit/c9ff4ec))
+* chore: update CHANGELOG.md for merged changes ([86f1d25](https://github.com/CloudPirates-io/helm-charts/commit/86f1d25))
+
+## 0.3.0 (2025-10-14)
+
+* Update chart.yaml dependencies for indepentent charts (#382) ([87acfb1](https://github.com/CloudPirates-io/helm-charts/commit/87acfb1))
+* chore: update CHANGELOG.md for merged changes ([84cf67b](https://github.com/CloudPirates-io/helm-charts/commit/84cf67b))
+* chore: update CHANGELOG.md for all charts via manual trigger ([6974964](https://github.com/CloudPirates-io/helm-charts/commit/6974964))
+* chore: update CHANGELOG.md for merged changes ([63b7bfa](https://github.com/CloudPirates-io/helm-charts/commit/63b7bfa))
+* chore: update CHANGELOG.md for merged changes ([da69e0e](https://github.com/CloudPirates-io/helm-charts/commit/da69e0e))
+* chore: update CHANGELOG.md for merged changes ([5da1b15](https://github.com/CloudPirates-io/helm-charts/commit/5da1b15))
+
+## 0.2.3 (2025-10-13)
+
+
+## 0.2.2 (2025-10-10)
+
+* [memcached]: Implement PDB (#295) ([b974e8a](https://github.com/CloudPirates-io/helm-charts/commit/b974e8a))
+* add tests for openshift (#226) ([c80c98a](https://github.com/CloudPirates-io/helm-charts/commit/c80c98a))
+
+## 0.2.1 (2025-10-02)
+
+* chore(deps): update docker.io/memcached:1.6.39 Docker digest to 157c563 (#185) ([d55b428](https://github.com/CloudPirates-io/helm-charts/commit/d55b428))
+
+## 0.2.0 (2025-10-01)
+
+* make memcached run on openshift (#194) ([87ffbbf](https://github.com/CloudPirates-io/helm-charts/commit/87ffbbf))
+* Update CHANGELOG.md ([7a828fa](https://github.com/CloudPirates-io/helm-charts/commit/7a828fa))
+* Update CHANGELOG.md ([f9df296](https://github.com/CloudPirates-io/helm-charts/commit/f9df296))
+* Update CHANGELOG.md ([0c85529](https://github.com/CloudPirates-io/helm-charts/commit/0c85529))
+
+## 0.1.3 (2025-09-23)
+
+* Update CHANGELOG.md ([0e5b657](https://github.com/CloudPirates-io/helm-charts/commit/0e5b657))
+* cast verbosity to int before passing to repeat ([518b602](https://github.com/CloudPirates-io/helm-charts/commit/518b602))
+
+## 0.1.2 (2025-09-10)
+
+* Update CHANGELOG.md ([dcabcee](https://github.com/CloudPirates-io/helm-charts/commit/dcabcee))
+* bump version ([884f4ab](https://github.com/CloudPirates-io/helm-charts/commit/884f4ab))
+* chore(deps): update docker.io/memcached:1.6.39 Docker digest to 68c1185 ([3c6ec49](https://github.com/CloudPirates-io/helm-charts/commit/3c6ec49))
+
+## 0.1.1 (2025-09-09)
+
+* Update CHANGELOG.md ([812bd46](https://github.com/CloudPirates-io/helm-charts/commit/812bd46))
+* Bump chart version ([1661d8d](https://github.com/CloudPirates-io/helm-charts/commit/1661d8d))
+* Update docker.io/memcached:1.6.39 Docker digest to 4404f32 ([454eea5](https://github.com/CloudPirates-io/helm-charts/commit/454eea5))
+* mariadb now respects full custom container security context settings memcached readme fixed, this option was not available ([770ea69](https://github.com/CloudPirates-io/helm-charts/commit/770ea69))
+
+## 0.1.0 (2025-09-02)
+
+* bump all chart versions for new extraObjects feature ([aaa57f9](https://github.com/CloudPirates-io/helm-charts/commit/aaa57f9))
+* add extraObject array to all charts ([34772b7](https://github.com/CloudPirates-io/helm-charts/commit/34772b7))
+
+## 0.0.2 (2025-08-27)
+
+* Add initial Changelogs to all Charts ([68f10ca](https://github.com/CloudPirates-io/helm-charts/commit/68f10ca))
+
+## 0.0.1 (2025-08-26)
+
+* Initial tagged release
diff --git a/charts/memcached/Chart.lock b/charts/memcached/Chart.lock
index c79512b3..81b28fe5 100644
--- a/charts/memcached/Chart.lock
+++ b/charts/memcached/Chart.lock
@@ -1,6 +1,6 @@
dependencies:
- name: common
repository: oci://registry-1.docker.io/cloudpirates
- version: 1.1.1
-digest: sha256:8da3c04e2c4a1ebfff4f21936399938e0f3fcf9fbd2f7135e7e907ce725b8f00
-generated: "2025-09-30T21:16:48.901325+02:00"
+ version: 2.0.0
+digest: sha256:ae9378e0dcfd09a35b7f994007db99c2d6fe02ef7634f424d5233237c209a1c7
+generated: "2025-10-14T11:14:25.445997+02:00"
diff --git a/charts/memcached/Chart.yaml b/charts/memcached/Chart.yaml
index c56e7df5..e315ed21 100644
--- a/charts/memcached/Chart.yaml
+++ b/charts/memcached/Chart.yaml
@@ -2,29 +2,44 @@ apiVersion: v2
name: memcached
description: Memcached is an in-memory key-value store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, or page rendering.
type: application
-
-version: 0.2.1
+version: 0.5.3
appVersion: "1.6.39"
-
keywords:
- memcached
- cache
- in-memory
- key-value
- distributed
-
-home: https://www.cloudpirates.io
-
+home: https://memcached.org
sources:
- https://github.com/CloudPirates-io/helm-charts/tree/main/charts/memcached
-
+ - https://github.com/memcached/memcached
maintainers:
- name: CloudPirates GmbH & Co. KG
+ email: hello@cloudpirates.io
url: https://www.cloudpirates.io
-
dependencies:
- name: common
- version: "1.x.x"
+ version: "2.x.x"
repository: oci://registry-1.docker.io/cloudpirates
-
icon: https://a.storyblok.com/f/143071/512x512/0faa83eb34/memcached-logo.svg
+annotations:
+ license: Apache-2.0
+ artifacthub.io/category: database
+ artifacthub.io/containsSecurityUpdates: "false"
+ artifacthub.io/signKey: |
+ fingerprint: 6917f1a88c122cbb1de5aa55457752135bdcf95a
+ url: https://raw.githubusercontent.com/CloudPirates-io/helm-charts/refs/heads/main/cosign.pub
+ artifacthub.io/links: |
+ - name: Memcached
+ url: https://memcached.org
+ - name: Helm Chart
+ url: https://github.com/CloudPirates-io/helm-charts/tree/main/charts/memcached
+ - name: Maintainer CloudPirates
+ url: https://www.cloudpirates.io
+ artifacthub.io/changes: |2
+ - kind: changed
+ description: "Add support for pod labels (#550)"
+ links:
+ - name: "Commit 6071930"
+ url: "https://github.com/CloudPirates-io/helm-charts/commit/6071930"
diff --git a/charts/memcached/README.md b/charts/memcached/README.md
index 32cc5445..47845537 100644
--- a/charts/memcached/README.md
+++ b/charts/memcached/README.md
@@ -62,12 +62,14 @@ The following table lists the configurable parameters of the Memcached chart and
### Common Parameters
-| Parameter | Description | Default |
-| ------------------- | ----------------------------------------------- | ------- |
-| `nameOverride` | String to partially override memcached.fullname | `""` |
-| `fullnameOverride` | String to fully override memcached.fullname | `""` |
-| `commonLabels` | Labels to add to all deployed objects | `{}` |
-| `commonAnnotations` | Annotations to add to all deployed objects | `{}` |
+| Parameter | Description | Default |
+|---------------------|----------------------------------------------------------| ------- |
+| `nameOverride` | String to partially override memcached.fullname | `""` |
+| `fullnameOverride` | String to fully override memcached.fullname | `""` |
+| `commonLabels` | Labels to add to all deployed objects | `{}` |
+| `commonAnnotations` | Annotations to add to all deployed objects | `{}` |
+| `podAnnotations` | Annotations to add to the pods created by the deployment | `{}` |
+| `podLabels` | Labels to add to the pods created by the deployment | `{}` |
### Memcached Image Parameters
@@ -158,11 +160,19 @@ The following table lists the configurable parameters of the Memcached chart and
| `ingress.hosts` | An array with hosts and paths | `[{"host": "memcached.local", "paths": [{"path": "/", "pathType": "ImplementationSpecific"}]}]` |
| `ingress.tls` | TLS configuration for the Ingress | `[]` |
+### Pod Disruption Budget Parameters
+
+| Parameter | Description | Default |
+| -------------------- | -------------------------------------------------------------- | ------- |
+| `pdb.create` | Enable/disable a Pod Disruption Budget creation | `false` |
+| `pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `""` |
+| `pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable | `""` |
+
### Extra Configuration Parameters
| Parameter | Description | Default |
| ------------------- | ----------------------------------------------------------------------------------- | ------- |
-| `extraEnv` | A list of additional environment variables | `[]` |
+| `extraEnvVars` | Additional environment variables to set | `[]` |
| `extraVolumes` | A list of additional existing volumes that will be mounted into the container | `[]` |
| `extraVolumeMounts` | A list of additional existing volume mounts that will be mounted into the container | `[]` |
| `extraObjects` | A list of additional Kubernetes objects to deploy alongside the release | `[]` |
@@ -213,6 +223,34 @@ All objects in `extraObjects` will be rendered and deployed with the release. Yo
| `tolerations` | Tolerations for pod assignment | `[]` |
| `affinity` | Affinity for pod assignment | `{}` |
+### Metrics
+
+| Parameter | Description | Default |
+|--------------------------------------------|----------------------------------------------------------------------------------------|----------------------------|
+| `metrics.enabled` | Start a sidecar Prometheus exporter to expose Memcached metrics | `false` |
+| `metrics.image.registry` | Memcached exporter image registry | `docker.io` |
+| `metrics.image.repository` | Memcached exporter image repository | `prom/memcached-exporter` |
+| `metrics.image.tag` | Memcached exporter image tag | See values.yaml |
+| `metrics.image.pullPolicy` | Memcached exporter image pull policy | `Always` |
+| `metrics.resources.requests.cpu` | CPU request for the metrics container | `50m` |
+| `metrics.resources.requests.memory` | Memory request for the metrics container | `64Mi` |
+| `metrics.resources.limits.cpu` | CPU limit for the metrics container | `nil` |
+| `metrics.resources.limits.memory` | Memory limit for the metrics container | `64Mi` |
+| `metrics.extraArgs` | Extra arguments for Memcached exporter (e.g. `--log.level=debug`, `--log.format=json`) | `[]` |
+| `metrics.service.type` | Metrics service type | `ClusterIP` |
+| `metrics.service.port` | Metrics service port | `9150` |
+| `metrics.service.annotations` | Additional custom annotations for Metrics service | `{}` |
+| `metrics.serviceMonitor.enabled` | Create ServiceMonitor resource for scraping metrics using Prometheus Operator | `false` |
+| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped | `30s` |
+| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `""` |
+| `metrics.serviceMonitor.relabelings` | Relabeling rules to apply the targetโs metadata labels before scraping. | `[]` |
+| `metrics.serviceMonitor.metricRelabelings` | Relabeling rules to apply to the samples before ingestion. | `[]` |
+| `metrics.serviceMonitor.honorLabels` | Honor metrics labels when they collide with Prometheus target labels | `false` |
+| `metrics.serviceMonitor.labels` | Additional service monitor labels | `{}` |
+| `metrics.serviceMonitor.annotations` | Additional custom annotations for the ServiceMonitor | `{}` |
+| `metrics.serviceMonitor.namespaceSelector` | Which namespace(s) Prometheus should discover the services in. | `{}` |
+
+
## Examples
### Basic Installation
@@ -258,6 +296,11 @@ resources:
service:
type: ClusterIP
+# Enable Pod Disruption Budget for high availability
+pdb:
+ create: true
+ minAvailable: 1
+
# Use anti-affinity to spread pods across nodes
affinity:
podAntiAffinity:
diff --git a/charts/memcached/templates/_helpers.tpl b/charts/memcached/templates/_helpers.tpl
index 1ca02689..829e341c 100644
--- a/charts/memcached/templates/_helpers.tpl
+++ b/charts/memcached/templates/_helpers.tpl
@@ -2,56 +2,63 @@
Expand the name of the chart.
*/}}
{{- define "memcached.name" -}}
-{{- include "common.name" . -}}
+{{- include "cloudpirates.name" . -}}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "memcached.fullname" -}}
-{{- include "common.fullname" . -}}
+{{- include "cloudpirates.fullname" . -}}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "memcached.chart" -}}
-{{- include "common.chart" . -}}
+{{- include "cloudpirates.chart" . -}}
{{- end }}
{{/*
Common labels
*/}}
{{- define "memcached.labels" -}}
-{{- include "common.labels" . }}
+{{- include "cloudpirates.labels" . }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "memcached.selectorLabels" -}}
-{{- include "common.selectorLabels" . -}}
+{{- include "cloudpirates.selectorLabels" . -}}
{{- end }}
{{/*
Common annotations
*/}}
{{- define "memcached.annotations" -}}
-{{- include "common.annotations" . -}}
+{{- include "cloudpirates.annotations" . -}}
{{- end }}
{{/*
Return the proper Memcached image name
*/}}
{{- define "memcached.image" -}}
-{{- include "common.image" (dict "image" .Values.image "global" .Values.global) -}}
+{{- include "cloudpirates.image" (dict "image" .Values.image "global" .Values.global) -}}
+{{- end }}
+
+{{/*
+Return the proper Memcached metrics image name
+*/}}
+{{- define "memcached.metrics.image" -}}
+{{- include "cloudpirates.image" (dict "image" .Values.metrics.image "global" .Values.global) -}}
{{- end }}
{{/*
Return the proper Docker Image Registry Secret Names
*/}}
{{- define "memcached.imagePullSecrets" -}}
-{{ include "common.images.renderPullSecrets" (dict "images" (list .Values.image) "context" .) }}
+{{ include "cloudpirates.images.renderPullSecrets" (dict "images" (list .Values.image) "context" .) }}
{{- end -}}
{{/*
@@ -63,4 +70,4 @@ Create the name of the service account to use
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
-{{- end }}
\ No newline at end of file
+{{- end }}
diff --git a/charts/memcached/templates/configmap.yaml b/charts/memcached/templates/configmap.yaml
index b50f030f..6c5d319a 100644
--- a/charts/memcached/templates/configmap.yaml
+++ b/charts/memcached/templates/configmap.yaml
@@ -6,6 +6,10 @@ metadata:
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "memcached.labels" . | nindent 4 }}
+ {{- with (include "memcached.annotations" .) }}
+ annotations:
+{{- . | indent 4 }}
+ {{- end }}
data:
{{- if .Values.configMap.data }}
{{- toYaml .Values.configMap.data | nindent 2 }}
diff --git a/charts/memcached/templates/deployment.yaml b/charts/memcached/templates/deployment.yaml
index 11488aa9..ae3fafd8 100644
--- a/charts/memcached/templates/deployment.yaml
+++ b/charts/memcached/templates/deployment.yaml
@@ -18,17 +18,25 @@ spec:
metadata:
labels:
{{- include "memcached.selectorLabels" . | nindent 8 }}
+ {{- with .Values.podLabels }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
spec:
{{- with (include "memcached.imagePullSecrets" .) }}
{{ . | nindent 6 }}
{{- end }}
+ automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
serviceAccountName: {{ include "memcached.serviceAccountName" . }}
- securityContext: {{ include "common.renderPodSecurityContext" . | nindent 8 }}
+ securityContext: {{ include "cloudpirates.renderPodSecurityContext" . | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
- securityContext: {{ include "common.renderContainerSecurityContext" . | nindent 12 }}
+ securityContext: {{ include "cloudpirates.renderContainerSecurityContext" . | nindent 12 }}
image: {{ include "memcached.image" . | quote }}
- imagePullPolicy: {{ include "common.imagePullPolicy" (dict "image" .Values.image) }}
+ imagePullPolicy: {{ include "cloudpirates.imagePullPolicy" (dict "image" .Values.image) }}
args:
{{- if .Values.config.memoryLimit }}
- "-m"
@@ -48,12 +56,9 @@ spec:
- name: memcached
containerPort: 11211
protocol: TCP
- {{- if .Values.extraEnv }}
+ {{- with .Values.extraEnvVars }}
env:
- {{- range .Values.extraEnv }}
- - name: {{ .name }}
- value: {{ .value | quote }}
- {{- end }}
+{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.livenessProbe.enabled }}
livenessProbe:
@@ -80,6 +85,40 @@ spec:
volumeMounts:
{{- toYaml .Values.extraVolumeMounts | nindent 12 }}
{{- end }}
+ {{- if .Values.metrics.enabled }}
+ - name: metrics
+ image: {{ include "memcached.metrics.image" . | quote }}
+ imagePullPolicy: {{ include "cloudpirates.imagePullPolicy" (dict "image" .Values.metrics.image) }}
+ args:
+ - "--memcached.address=localhost:{{ .Values.service.port }}"
+ - "--web.listen-address=:{{ .Values.metrics.service.port }}"
+ {{- range .Values.metrics.extraArgs }}
+ - {{ . }}
+ {{- end }}
+ ports:
+ - name: metrics
+ containerPort: {{ .Values.metrics.service.port }}
+ protocol: TCP
+ livenessProbe:
+ httpGet:
+ path: /
+ port: metrics
+ initialDelaySeconds: 15
+ periodSeconds: 15
+ timeoutSeconds: 5
+ failureThreshold: 3
+ successThreshold: 1
+ readinessProbe:
+ httpGet:
+ path: /
+ port: metrics
+ initialDelaySeconds: 5
+ periodSeconds: 5
+ timeoutSeconds: 1
+ failureThreshold: 3
+ successThreshold: 1
+ resources: {{ toYaml .Values.metrics.resources | nindent 12 }}
+ {{- end }}
{{- if .Values.extraVolumes }}
volumes:
{{- toYaml .Values.extraVolumes | nindent 8 }}
@@ -95,4 +134,4 @@ spec:
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
- {{- end }}
\ No newline at end of file
+ {{- end }}
diff --git a/charts/memcached/templates/extraobjects.yaml b/charts/memcached/templates/extraobjects.yaml
index fd7643e4..7f5ede80 100644
--- a/charts/memcached/templates/extraobjects.yaml
+++ b/charts/memcached/templates/extraobjects.yaml
@@ -1,4 +1,4 @@
{{- range .Values.extraObjects }}
---
-{{- include "common.tplvalues.render" (dict "value" . "context" $) }}
+{{- include "cloudpirates.tplvalues.render" (dict "value" . "context" $) }}
{{- end }}
\ No newline at end of file
diff --git a/charts/memcached/templates/pdb.yaml b/charts/memcached/templates/pdb.yaml
new file mode 100644
index 00000000..c12b91f0
--- /dev/null
+++ b/charts/memcached/templates/pdb.yaml
@@ -0,0 +1,22 @@
+{{- if .Values.pdb.create }}
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+ name: {{ template "memcached.fullname" . }}-pdb
+ namespace: {{ .Release.Namespace }}
+ labels: {{- include "memcached.labels" . | nindent 4 }}
+ {{- with (include "memcached.annotations" .) }}
+ annotations:
+ {{- . | 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 }}
+ selector:
+ matchLabels:
+ {{- include "memcached.selectorLabels" . | nindent 6 }}
+{{- end }}
diff --git a/charts/memcached/templates/service.yaml b/charts/memcached/templates/service.yaml
index 1aae169a..b17e5ee2 100644
--- a/charts/memcached/templates/service.yaml
+++ b/charts/memcached/templates/service.yaml
@@ -2,9 +2,12 @@ apiVersion: v1
kind: Service
metadata:
name: {{ include "memcached.fullname" . }}
- namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "memcached.labels" . | nindent 4 }}
+ {{- with (include "memcached.annotations" .) }}
+ annotations:
+ {{- . | nindent 4 }}
+ {{- end }}
spec:
type: {{ .Values.service.type }}
ports:
@@ -13,4 +16,28 @@ spec:
protocol: TCP
name: memcached
selector:
- {{- include "memcached.selectorLabels" . | nindent 4 }}
\ No newline at end of file
+ {{- include "memcached.selectorLabels" . | nindent 4 }}
+{{- if .Values.metrics.enabled }}
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "memcached.fullname" . }}-metrics
+ labels:
+ {{- include "memcached.labels" . | nindent 4 }}
+ app.kubernetes.io/component: metrics
+ {{- $annotations := merge .Values.metrics.service.annotations .Values.commonAnnotations }}
+ {{- with $annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ type: {{ .Values.metrics.service.type }}
+ ports:
+ - port: {{ .Values.metrics.service.port }}
+ targetPort: metrics
+ protocol: TCP
+ name: metrics
+ selector:
+ {{- include "memcached.selectorLabels" . | nindent 4 }}
+{{- end }}
diff --git a/charts/memcached/templates/serviceaccount.yaml b/charts/memcached/templates/serviceaccount.yaml
index 71f31ee2..37194275 100644
--- a/charts/memcached/templates/serviceaccount.yaml
+++ b/charts/memcached/templates/serviceaccount.yaml
@@ -6,7 +6,8 @@ metadata:
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "memcached.labels" . | nindent 4 }}
- {{- with .Values.serviceAccount.annotations }}
+ {{- $annotations := merge .Values.serviceAccount.annotations .Values.commonAnnotations }}
+ {{- with $annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
diff --git a/charts/memcached/templates/servicemonitor.yaml b/charts/memcached/templates/servicemonitor.yaml
new file mode 100644
index 00000000..f5abdf24
--- /dev/null
+++ b/charts/memcached/templates/servicemonitor.yaml
@@ -0,0 +1,46 @@
+{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+ name: {{ include "memcached.fullname" . }}
+ labels:
+ {{- include "memcached.labels" . | nindent 4 }}
+ app.kubernetes.io/component: metrics
+ {{- with .Values.metrics.serviceMonitor.labels }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.metrics.serviceMonitor.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ jobLabel: {{ include "memcached.fullname" . }}
+ selector:
+ matchLabels:
+ {{- include "memcached.selectorLabels" . | nindent 6 }}
+ app.kubernetes.io/component: metrics
+ endpoints:
+ - port: metrics
+ {{- with .Values.metrics.serviceMonitor.interval }}
+ interval: {{ . }}
+ {{- end }}
+ {{- with .Values.metrics.serviceMonitor.scrapeTimeout }}
+ scrapeTimeout: {{ . }}
+ {{- end }}
+ path: /metrics
+ {{- with .Values.metrics.serviceMonitor.honorLabels }}
+ honorLabels: {{ . }}
+ {{- end }}
+ {{- with .Values.metrics.serviceMonitor.relabelings }}
+ relabelings:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.metrics.serviceMonitor.metricRelabelings }}
+ metricRelabelings:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.metrics.serviceMonitor.namespaceSelector }}
+ namespaceSelector:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/charts/memcached/tests/metrics_test.yaml b/charts/memcached/tests/metrics_test.yaml
new file mode 100644
index 00000000..54c061f8
--- /dev/null
+++ b/charts/memcached/tests/metrics_test.yaml
@@ -0,0 +1,84 @@
+suite: test Memcached metrics
+templates:
+ - deployment.yaml
+set:
+ metrics.enabled: true
+
+tests:
+ - it: should use default values when nothing is overridden
+ asserts:
+ - equal:
+ path: spec.template.spec.containers[1].image
+ value: docker.io/prom/memcached-exporter:v0.15.4@sha256:b6763ecb3c47f2408e0398518851b7f8c5fc46232b2649f8c78a321130c54266
+ - equal:
+ path: spec.template.spec.containers[1].imagePullPolicy
+ value: Always
+ - equal:
+ path: spec.template.spec.containers[1].args
+ value:
+ - --memcached.address=localhost:11211
+ - --web.listen-address=:9150
+ - equal:
+ path: spec.template.spec.containers[1].ports[0].containerPort
+ value: 9150
+ - equal:
+ path: spec.template.spec.containers[1].resources
+ value:
+ limits:
+ memory: 64Mi
+ requests:
+ cpu: 50m
+ memory: 64Mi
+
+ - it: should respect config change
+ set:
+ metrics.image.registry: my-registry.com
+ metrics.image.repository: prefix/prom/memcached-exporter
+ metrics.image.tag: 1.6.31@sha256:testdigest123
+ metrics.image.pullPolicy: IfNotPresent
+ metrics.resources:
+ limits:
+ cpu: 150m
+ memory: 128Mi
+ requests:
+ cpu: 25m
+ memory: 32Mi
+ metrics.extraArgs:
+ - --log.level=debug
+ - --log.format=json
+ metrics.service.port: 9151
+ asserts:
+ - equal:
+ path: spec.template.spec.containers[1].image
+ value: my-registry.com/prefix/prom/memcached-exporter:1.6.31@sha256:testdigest123
+ - equal:
+ path: spec.template.spec.containers[1].imagePullPolicy
+ value: IfNotPresent
+ - equal:
+ path: spec.template.spec.containers[1].imagePullPolicy
+ value: IfNotPresent
+ - equal:
+ path: spec.template.spec.containers[1].resources
+ value:
+ limits:
+ cpu: 150m
+ memory: 128Mi
+ requests:
+ cpu: 25m
+ memory: 32Mi
+ - equal:
+ path: spec.template.spec.containers[1].resources
+ value:
+ limits:
+ cpu: 150m
+ memory: 128Mi
+ requests:
+ cpu: 25m
+ memory: 32Mi
+ - equal:
+ path: spec.template.spec.containers[1].args
+ value:
+ - --memcached.address=localhost:11211
+ - --web.listen-address=:9151
+ - --log.level=debug
+ - --log.format=json
diff --git a/charts/memcached/tests/service_test.yaml b/charts/memcached/tests/service_test.yaml
new file mode 100644
index 00000000..ac292fd0
--- /dev/null
+++ b/charts/memcached/tests/service_test.yaml
@@ -0,0 +1,102 @@
+suite: test Memcached services
+templates:
+ - service.yaml
+release:
+ name: release-name
+
+tests:
+ - it: should be a Service
+ asserts:
+ - isKind:
+ of: Service
+ - hasDocuments:
+ count: 1
+ - equal:
+ path: metadata.name
+ value: release-name-memcached
+
+ - it: should use default values when nothing is overridden
+ asserts:
+ - equal:
+ path: spec.type
+ value: ClusterIP
+ - equal:
+ path: spec.ports[0].port
+ value: 11211
+
+ - it: should respect config change
+ set:
+ service:
+ type: NodePort
+ port: 11222
+ asserts:
+ - equal:
+ path: spec.type
+ value: NodePort
+ - equal:
+ path: spec.ports[0].port
+ value: 11222
+
+ - it: should have a service for metrics when enabled
+ set:
+ metrics.enabled: true
+ asserts:
+ - isKind:
+ of: Service
+ - hasDocuments:
+ count: 2
+ - equal:
+ path: metadata.name
+ value: release-name-memcached-metrics
+ documentIndex: 1
+
+ - it: should use default metrics values when nothing is overridden
+ set:
+ metrics.enabled: true
+ documentSelector:
+ path: metadata.name
+ value: release-name-memcached-metrics
+ asserts:
+ - equal:
+ path: metadata.labels["app.kubernetes.io/component"]
+ value: metrics
+ - equal:
+ path: spec.type
+ value: ClusterIP
+ - equal:
+ path: spec.ports[0].port
+ value: 9150
+ - equal:
+ path: spec.ports[0].name
+ value: metrics
+
+ - it: should respect config change in metrics
+ set:
+ metrics.enabled: true
+ metrics.service:
+ type: LoadBalancer
+ port: 8080
+ annotations:
+ service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
+ service.beta.kubernetes.io/aws-load-balancer-internal: "true"
+ service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "8080"
+ commonAnnotations:
+ kubernetes.io/test: "true"
+
+ documentSelector:
+ path: metadata.name
+ value: release-name-memcached-metrics
+ asserts:
+ - equal:
+ path: spec.type
+ value: LoadBalancer
+ - equal:
+ path: spec.ports[0].port
+ value: 8080
+ - equal:
+ path: metadata.annotations
+ value:
+ service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
+ service.beta.kubernetes.io/aws-load-balancer-internal: "true"
+ service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "8080"
+ kubernetes.io/test: "true"
diff --git a/charts/memcached/tests/servicemonitor_test.yaml b/charts/memcached/tests/servicemonitor_test.yaml
new file mode 100644
index 00000000..7d7f123b
--- /dev/null
+++ b/charts/memcached/tests/servicemonitor_test.yaml
@@ -0,0 +1,110 @@
+suite: test Memcached service monitor
+templates:
+ - servicemonitor.yaml
+release:
+ name: release-name
+set:
+ metrics.enabled: true
+ metrics.serviceMonitor.enabled: true
+
+tests:
+ - it: should be a ServiceMonitor
+ asserts:
+ - isKind:
+ of: ServiceMonitor
+ - isAPIVersion:
+ of: monitoring.coreos.com/v1
+ - hasDocuments:
+ count: 1
+ - equal:
+ path: metadata.name
+ value: release-name-memcached
+ - equal:
+ path: metadata.labels["app.kubernetes.io/component"]
+ value: metrics
+
+ - it: should use default values when nothing is overridden
+ asserts:
+ - equal:
+ path: spec.jobLabel
+ value: release-name-memcached
+ - equal:
+ path: spec.selector.matchLabels
+ value:
+ app.kubernetes.io/name: memcached
+ app.kubernetes.io/instance: release-name
+ app.kubernetes.io/component: metrics
+ - contains:
+ path: spec.endpoints
+ content:
+ port: metrics
+ interval: 30s
+ path: /metrics
+
+ - it: should respect config change
+ set:
+ metrics.serviceMonitor:
+ interval: 60s
+ ## @param metrics.serviceMonitor.scrapeTimeout Timeout after which the scrape is ended
+ scrapeTimeout: 1s
+ relabelings:
+ - sourceLabels: [ one, two ]
+ metricRelabelings:
+ - targetLabel: something
+ honorLabels: true
+ labels:
+ kubernetes.io/test-1: "true"
+ kubernetes.io/test-2: "true"
+ annotations:
+ kubernetes.io/test-annotation-1: "true"
+ kubernetes.io/test-annotation-2: "true"
+ namespaceSelector:
+ matchNames:
+ - one
+ - two
+ asserts:
+ - equal:
+ path: metadata.labels["app.kubernetes.io/instance"]
+ value: release-name
+ - equal:
+ path: metadata.labels["app.kubernetes.io/name"]
+ value: memcached
+ - equal:
+ path: metadata.labels["app.kubernetes.io/component"]
+ value: metrics
+ - equal:
+ path: metadata.labels["kubernetes.io/test-1"]
+ value: "true"
+ - equal:
+ path: metadata.labels["kubernetes.io/test-2"]
+ value: "true"
+ - equal:
+ path: metadata.annotations
+ value:
+ kubernetes.io/test-annotation-1: "true"
+ kubernetes.io/test-annotation-2: "true"
+ - equal:
+ path: spec.endpoints[0].interval
+ value: 60s
+ - equal:
+ path: spec.endpoints[0].scrapeTimeout
+ value: 1s
+ - equal:
+ path: spec.endpoints[0].honorLabels
+ value: true
+ - equal:
+ path: spec.endpoints[0].relabelings
+ value:
+ - sourceLabels:
+ - one
+ - two
+ - equal:
+ path: spec.endpoints[0].metricRelabelings
+ value:
+ - targetLabel: something
+ - equal:
+ path: spec.namespaceSelector
+ value:
+ matchNames:
+ - one
+ - two
diff --git a/charts/memcached/values.schema.json b/charts/memcached/values.schema.json
index 460acfe7..8a042301 100644
--- a/charts/memcached/values.schema.json
+++ b/charts/memcached/values.schema.json
@@ -1,148 +1,357 @@
{
- "$schema": "https://json-schema.org/draft-07/schema#",
- "type": "object",
- "title": "Memcached Helm Chart Values Schema",
- "description": "Schema for Memcached Helm chart values",
- "properties": {
- "global": {
- "type": "object",
- "title": "Global parameters",
- "description": "Global Docker image parameters",
- "properties": {
- "imageRegistry": {
- "type": "string",
- "title": "Global Docker Image Registry",
- "description": "Global Docker image registry"
- },
- "imagePullSecrets": {
- "type": "array",
- "title": "Global Image Pull Secrets",
- "description": "Global Docker registry secret names as an array of objects",
- "items": {
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "type": "object",
+ "properties": {
+ "affinity": {
+ "type": "object"
+ },
+ "commonAnnotations": {
+ "type": "object"
+ },
+ "commonLabels": {
+ "type": "object"
+ },
+ "config": {
"type": "object",
"properties": {
- "name": {
- "type": "string",
- "title": "Secret Name",
- "description": "Name of the image pull secret"
- }
- },
- "required": [
- "name"
- ]
- }
- }
- }
- },
- "image": {
- "type": "object",
- "title": "Memcached image configuration",
- "description": "Configuration for Memcached container image",
- "properties": {
- "registry": {
- "type": "string",
- "title": "Memcached Image Registry",
- "description": "Memcached image registry"
- },
- "repository": {
- "type": "string",
- "title": "Memcached Image Repository",
- "description": "Memcached image repository"
- },
- "tag": {
- "type": "string",
- "title": "Memcached Image Tag",
- "description": "Memcached image tag"
- },
- "pullPolicy": {
- "type": "string",
- "title": "Image Pull Policy",
- "description": "Image pull policy",
- "enum": [
- "Always",
- "IfNotPresent",
- "Never"
- ]
- }
- }
- },
- "replicaCount": {
- "type": "integer",
- "title": "Replica Count",
- "description": "Number of Memcached replicas",
- "minimum": 1
- },
- "service": {
- "type": "object",
- "title": "Service configuration",
- "description": "Kubernetes service configuration",
- "properties": {
- "type": {
- "type": "string",
- "title": "Service Type",
- "description": "Kubernetes service type",
- "enum": [
- "ClusterIP",
- "NodePort",
- "LoadBalancer"
- ]
- },
- "port": {
- "type": "integer",
- "title": "Service Port",
- "description": "Service port",
- "minimum": 1,
- "maximum": 65535
- }
- }
- },
- "config": {
- "type": "object",
- "title": "Memcached configuration",
- "description": "Memcached configuration options",
- "properties": {
- "memoryLimit": {
- "type": "integer",
- "title": "Memory Limit",
- "description": "Maximum amount of memory to use for cache (in MB)",
- "minimum": 1
- },
- "maxConnections": {
- "type": "integer",
- "title": "Max Connections",
- "description": "Maximum number of simultaneous connections",
- "minimum": 1
- },
- "verbosity": {
- "type": "integer",
- "title": "Verbosity",
- "description": "Verbosity level",
- "minimum": 0,
- "maximum": 2
- },
- "extraArgs": {
- "type": "array",
- "title": "Extra Arguments",
- "description": "Additional command-line arguments",
- "items": {
+ "extraArgs": {
+ "type": "array"
+ },
+ "maxConnections": {
+ "type": "integer"
+ },
+ "memoryLimit": {
+ "type": "integer"
+ },
+ "verbosity": {
+ "type": "integer"
+ }
+ }
+ },
+ "configMap": {
+ "type": "object",
+ "properties": {
+ "create": {
+ "type": "boolean"
+ },
+ "data": {
+ "type": "object"
+ }
+ }
+ },
+ "containerSecurityContext": {
+ "type": "object",
+ "properties": {
+ "allowPrivilegeEscalation": {
+ "type": "boolean"
+ },
+ "runAsNonRoot": {
+ "type": "boolean"
+ },
+ "runAsUser": {
+ "type": "integer"
+ }
+ }
+ },
+ "extraEnvVars": {
+ "type": "array"
+ },
+ "extraObjects": {
+ "type": "array"
+ },
+ "extraVolumeMounts": {
+ "type": "array"
+ },
+ "extraVolumes": {
+ "type": "array"
+ },
+ "fullnameOverride": {
"type": "string"
- }
+ },
+ "global": {
+ "type": "object",
+ "properties": {
+ "imagePullSecrets": {
+ "type": "array"
+ },
+ "imageRegistry": {
+ "type": "string"
+ }
+ }
+ },
+ "image": {
+ "type": "object",
+ "properties": {
+ "pullPolicy": {
+ "type": "string"
+ },
+ "registry": {
+ "type": "string"
+ },
+ "repository": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ }
+ }
+ },
+ "ingress": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object"
+ },
+ "className": {
+ "type": "string"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "hosts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "host": {
+ "type": "string"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "pathType": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tls": {
+ "type": "array"
+ }
+ }
+ },
+ "livenessProbe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ }
+ }
+ },
+ "metrics": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "extraArgs": {
+ "type": "array"
+ },
+ "image": {
+ "type": "object",
+ "properties": {
+ "pullPolicy": {
+ "type": "string"
+ },
+ "registry": {
+ "type": "string"
+ },
+ "repository": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ }
+ }
+ },
+ "resources": {
+ "type": "object",
+ "properties": {
+ "limits": {
+ "type": "object",
+ "properties": {
+ "memory": {
+ "type": "string"
+ }
+ }
+ },
+ "requests": {
+ "type": "object",
+ "properties": {
+ "cpu": {
+ "type": "string"
+ },
+ "memory": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "service": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object"
+ },
+ "port": {
+ "type": "integer"
+ },
+ "type": {
+ "type": "string"
+ }
+ }
+ },
+ "serviceMonitor": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object"
+ },
+ "enabled": {
+ "type": "boolean"
+ },
+ "honorLabels": {
+ "type": "boolean"
+ },
+ "interval": {
+ "type": "string"
+ },
+ "labels": {
+ "type": "object"
+ },
+ "metricRelabelings": {
+ "type": "array"
+ },
+ "namespaceSelector": {
+ "type": "object"
+ },
+ "relabelings": {
+ "type": "array"
+ },
+ "scrapeTimeout": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "nameOverride": {
+ "type": "string"
+ },
+ "nodeSelector": {
+ "type": "object"
+ },
+ "pdb": {
+ "type": "object",
+ "properties": {
+ "create": {
+ "type": "boolean"
+ },
+ "maxUnavailable": {
+ "type": "string"
+ },
+ "minAvailable": {
+ "type": "string"
+ }
+ }
+ },
+ "podAnnotations": {
+ "type": "object"
+ },
+ "podLabels": {
+ "type": "object"
+ },
+ "podSecurityContext": {
+ "type": "object",
+ "properties": {
+ "fsGroup": {
+ "type": "integer"
+ }
+ }
+ },
+ "readinessProbe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ }
+ }
+ },
+ "replicaCount": {
+ "type": "integer"
+ },
+ "resources": {
+ "type": "object"
+ },
+ "service": {
+ "type": "object",
+ "properties": {
+ "port": {
+ "type": "integer"
+ },
+ "type": {
+ "type": "string"
+ }
+ }
+ },
+ "serviceAccount": {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "object"
+ },
+ "automountServiceAccountToken": {
+ "type": "boolean"
+ },
+ "create": {
+ "type": "boolean"
+ },
+ "name": {
+ "type": "string"
+ }
+ }
+ },
+ "tolerations": {
+ "type": "array"
}
- }
- },
- "resources": {
- "type": "object",
- "title": "Resource configuration",
- "description": "Pod resource configuration"
- },
- "extraObjects": {
- "type": "array",
- "title": "Extra Objects",
- "description": "A list of additional Kubernetes objects to deploy alongside the release. Helm templating is supported in any field, but all template expressions must be quoted. Each item should be a valid Kubernetes manifest object.",
- "items": {
- "type": "object",
- "description": "A Kubernetes manifest object. All fields are allowed."
- }
}
- }
-}
\ No newline at end of file
+}
diff --git a/charts/memcached/values.yaml b/charts/memcached/values.yaml
index bf2429d1..7360ae7e 100644
--- a/charts/memcached/values.yaml
+++ b/charts/memcached/values.yaml
@@ -15,6 +15,12 @@ commonLabels: {}
## @param commonAnnotations Annotations to add to all deployed objects
commonAnnotations: {}
+## @param podAnnotations Annotations to add to the pods created by the deployment
+podAnnotations: {}
+
+## @param podLabels Labels to add to the pods created by the deployment
+podLabels: {}
+
## @section Memcached image parameters
image:
## @param image.registry Memcached image registry
@@ -22,7 +28,7 @@ image:
## @param image.repository Memcached image repository
repository: memcached
## @param image.tag Memcached image tag
- tag: "1.6.39@sha256:157c563eef6954ac0bc583c36def96d8ed2d3b3c5b37214f27d210ac53942386"
+ tag: "1.6.39@sha256:050de63e6c082df85f93ffed9c388004b3c6257a06f1904e8628a6f87658eb99"
## @param image.pullPolicy Memcached image pull policy
pullPolicy: Always
@@ -103,6 +109,15 @@ tolerations: []
## @param affinity Affinity rules for pod assignment
affinity: {}
+## @section Pod Disruption Budget parameters
+pdb:
+ ## @param pdb.create Enable/disable a Pod Disruption Budget creation
+ create: false
+ ## @param pdb.minAvailable Minimum number/percentage of pods that should remain scheduled
+ minAvailable: ""
+ ## @param pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable.
+ maxUnavailable: ""
+
containerSecurityContext:
## @param containerSecurityContext.runAsUser User ID to run the container
runAsUser: 11211
@@ -144,10 +159,15 @@ readinessProbe:
## @param readinessProbe.successThreshold Number of successes to mark probe as successful
successThreshold: 1
-## @param extraEnv Additional environment variables to set
-extraEnv: []
-# - name: EXTRA_VAR
-# value: "extra_value"
+## @param extraEnvVars Additional environment variables to set
+extraEnvVars: []
+ # - name: CUSTOM_VAR
+ # value: "custom-value"
+ # - name: SECRET_VAR
+ # valueFrom:
+ # secretKeyRef:
+ # name: my-secret
+ # key: secret-key
## @param extraVolumes Additional volumes to add to the pod
extraVolumes: []
@@ -157,3 +177,59 @@ extraVolumeMounts: []
## @param extraObjects Array of extra objects to deploy with the release
extraObjects: []
+
+
+## @section Metrics parameters
+## Prometheus metrics configuration
+metrics:
+ ## @param metrics.enabled Start a sidecar prometheus exporter to expose Memcached metrics
+ enabled: false
+ ## @param metrics.image.registry Memcached exporter image registry
+ ## @param metrics.image.repository Memcached exporter image repository
+ ## @param metrics.image.tag Memcached exporter image tag
+ ## @param metrics.image.pullPolicy Memcached exporter image pull policy
+ image:
+ registry: docker.io
+ repository: prom/memcached-exporter
+ tag: "v0.15.4@sha256:b6763ecb3c47f2408e0398518851b7f8c5fc46232b2649f8c78a321130c54266"
+ pullPolicy: Always
+ ## @param metrics.resources Resource limits and requests for metrics container
+ resources:
+ limits:
+ memory: 64Mi
+ requests:
+ cpu: 50m
+ memory: 64Mi
+ ## @param metrics.extraArgs Extra arguments for Memcached exporter, for example:
+ ## extraArgs:
+ ## - --log.level=debug
+ ## - --log.format=json
+ extraArgs: []
+ ## Metrics service configuration
+ service:
+ ## @param metrics.service.type Metrics service type
+ type: ClusterIP
+ ## @param metrics.service.port Metrics service port
+ port: 9150
+ ## @param metrics.service.annotations Additional custom annotations for Metrics service
+ annotations: {}
+ ## Prometheus ServiceMonitor configuration
+ serviceMonitor:
+ ## @param metrics.serviceMonitor.enabled Create ServiceMonitor resource(s) for scraping metrics using PrometheusOperator
+ enabled: false
+ ## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped
+ interval: 30s
+ ## @param metrics.serviceMonitor.scrapeTimeout Timeout after which the scrape is ended
+ scrapeTimeout: ""
+ ## @param metrics.serviceMonitor.relabelings Specify additional relabeling of metrics
+ relabelings: []
+ ## @param metrics.serviceMonitor.metricRelabelings Specify additional metric relabeling of metrics
+ metricRelabelings: []
+ ## @param metrics.serviceMonitor.honorLabels Honor metrics labels
+ honorLabels: false
+ ## @param metrics.serviceMonitor.labels Additional service monitor labels
+ labels: {}
+ ## @param metrics.serviceMonitor.annotations Additional custom annotations for the ServiceMonitor
+ annotations: {}
+ ## @param metrics.serviceMonitor.namespaceSelector Namespace selector for ServiceMonitor
+ namespaceSelector: {}
diff --git a/charts/minio/CHANGELOG.md b/charts/minio/CHANGELOG.md
index 9299a528..a8d90baf 100644
--- a/charts/minio/CHANGELOG.md
+++ b/charts/minio/CHANGELOG.md
@@ -1,5 +1,104 @@
# Changelog
-## 0.3.0 (2025-10-09)
-* [mongodb] feat: add metrics exporter ([#243](https://github.com/CloudPirates-io/helm-charts/pull/243))
\ No newline at end of file
+## 0.5.5 (2025-11-02)
+
+* Add NodePort support for API and Console in Service configuration (#527) ([57b84d8](https://github.com/CloudPirates-io/helm-charts/commit/57b84d8))
+* chore: update CHANGELOG.md for merged changes ([c593bd8](https://github.com/CloudPirates-io/helm-charts/commit/c593bd8))
+* chore: update CHANGELOG.md for merged changes ([5cd1a41](https://github.com/CloudPirates-io/helm-charts/commit/5cd1a41))
+
+## 0.5.4 (2025-10-27)
+
+* Remove securitycontext on empty obejct (#474) ([3c288c8](https://github.com/CloudPirates-io/helm-charts/commit/3c288c8))
+* chore: update CHANGELOG.md for merged changes ([f9c3ff0](https://github.com/CloudPirates-io/helm-charts/commit/f9c3ff0))
+* chore: update CHANGELOG.md for merged changes ([db2d800](https://github.com/CloudPirates-io/helm-charts/commit/db2d800))
+
+## 0.5.3 (2025-10-23)
+
+* chore: update CHANGELOG.md for merged changes ([051ad83](https://github.com/CloudPirates-io/helm-charts/commit/051ad83))
+* chore: update CHANGELOG.md for merged changes ([1a50307](https://github.com/CloudPirates-io/helm-charts/commit/1a50307))
+
+## 0.5.2 (2025-10-22)
+
+* chore: update CHANGELOG.md for merged changes ([5d1f01a](https://github.com/CloudPirates-io/helm-charts/commit/5d1f01a))
+* chore: update CHANGELOG.md for merged changes ([fc47c5d](https://github.com/CloudPirates-io/helm-charts/commit/fc47c5d))
+* chore: update CHANGELOG.md for merged changes ([1a4f87b](https://github.com/CloudPirates-io/helm-charts/commit/1a4f87b))
+* chore: update CHANGELOG.md for merged changes ([da866ca](https://github.com/CloudPirates-io/helm-charts/commit/da866ca))
+* chore: update CHANGELOG.md for merged changes ([9af0a8e](https://github.com/CloudPirates-io/helm-charts/commit/9af0a8e))
+* chore: update CHANGELOG.md for merged changes ([de994a7](https://github.com/CloudPirates-io/helm-charts/commit/de994a7))
+
+## 0.5.1 (2025-10-17)
+
+* [minio] Fix bucketname trimming whitespaces in MinIO post-job configuration script. (#406) ([bf250e2](https://github.com/CloudPirates-io/helm-charts/commit/bf250e2))
+* chore: update CHANGELOG.md for merged changes ([b54c4f1](https://github.com/CloudPirates-io/helm-charts/commit/b54c4f1))
+* chore: update CHANGELOG.md for merged changes ([5a2ed20](https://github.com/CloudPirates-io/helm-charts/commit/5a2ed20))
+* chore: update CHANGELOG.md for merged changes ([3361964](https://github.com/CloudPirates-io/helm-charts/commit/3361964))
+* chore: update CHANGELOG.md for merged changes ([7f61172](https://github.com/CloudPirates-io/helm-charts/commit/7f61172))
+* chore: update CHANGELOG.md for merged changes ([1ec9aab](https://github.com/CloudPirates-io/helm-charts/commit/1ec9aab))
+* chore: update CHANGELOG.md for merged changes ([c9ff4ec](https://github.com/CloudPirates-io/helm-charts/commit/c9ff4ec))
+* chore: update CHANGELOG.md for merged changes ([86f1d25](https://github.com/CloudPirates-io/helm-charts/commit/86f1d25))
+
+## 0.5.0 (2025-10-14)
+
+* Update chart.yaml dependencies for indepentent charts (#382) ([87acfb1](https://github.com/CloudPirates-io/helm-charts/commit/87acfb1))
+* chore: update CHANGELOG.md for merged changes ([84cf67b](https://github.com/CloudPirates-io/helm-charts/commit/84cf67b))
+* chore: update CHANGELOG.md for all charts via manual trigger ([6974964](https://github.com/CloudPirates-io/helm-charts/commit/6974964))
+* chore: update CHANGELOG.md for merged changes ([63b7bfa](https://github.com/CloudPirates-io/helm-charts/commit/63b7bfa))
+* chore: update CHANGELOG.md for merged changes ([da69e0e](https://github.com/CloudPirates-io/helm-charts/commit/da69e0e))
+* chore: update CHANGELOG.md for merged changes ([5da1b15](https://github.com/CloudPirates-io/helm-charts/commit/5da1b15))
+
+## 0.4.1 (2025-10-13)
+
+
+## 0.4.0 (2025-10-09)
+
+* add auto bucket creation through k8s job and option to create ServiceAccount for Deployment (#288) ([47d3947](https://github.com/CloudPirates-io/helm-charts/commit/47d3947))
+* add tests for openshift (#226) ([c80c98a](https://github.com/CloudPirates-io/helm-charts/commit/c80c98a))
+* [minio, mongodb, postgres, timescaledb] Update securityContext to containerSecurityContext in the values schema (#213) ([8a4003f](https://github.com/CloudPirates-io/helm-charts/commit/8a4003f))
+
+## 0.3.0 (2025-10-02)
+
+* make minio run on openshift (#203) ([18c7be5](https://github.com/CloudPirates-io/helm-charts/commit/18c7be5))
+
+## 0.2.4 (2025-09-30)
+
+* add more configuration options for the minio server (#189) ([8066d07](https://github.com/CloudPirates-io/helm-charts/commit/8066d07))
+
+## 0.2.3 (2025-09-15)
+
+* Update CHANGELOG.md ([55a987f](https://github.com/CloudPirates-io/helm-charts/commit/55a987f))
+* bump verion to 0.2.3 ([af6beca](https://github.com/CloudPirates-io/helm-charts/commit/af6beca))
+* set strategy to recreate in deployment ([6e01f97](https://github.com/CloudPirates-io/helm-charts/commit/6e01f97))
+
+## 0.2.2 (2025-09-15)
+
+* Update CHANGELOG.md ([f31d5a5](https://github.com/CloudPirates-io/helm-charts/commit/f31d5a5))
+* update minio README.md ([cbca20c](https://github.com/CloudPirates-io/helm-charts/commit/cbca20c))
+* bump version to 0.2.2 ([afaf2d1](https://github.com/CloudPirates-io/helm-charts/commit/afaf2d1))
+* add option to use cpu-v1 image ([91bfd29](https://github.com/CloudPirates-io/helm-charts/commit/91bfd29))
+
+## 0.2.1 (2025-09-08)
+
+* Update CHANGELOG.md ([bb8e730](https://github.com/CloudPirates-io/helm-charts/commit/bb8e730))
+* Update appVersion ([5c23cb1](https://github.com/CloudPirates-io/helm-charts/commit/5c23cb1))
+* Update CHANGELOG.md ([82fe11f](https://github.com/CloudPirates-io/helm-charts/commit/82fe11f))
+* Upgrade minio to latest stable ([94ab830](https://github.com/CloudPirates-io/helm-charts/commit/94ab830))
+* revert 3 ([d8ced5c](https://github.com/CloudPirates-io/helm-charts/commit/d8ced5c))
+* revert 2 ([b64c81d](https://github.com/CloudPirates-io/helm-charts/commit/b64c81d))
+* Update CHANGELOG.md ([808cae0](https://github.com/CloudPirates-io/helm-charts/commit/808cae0))
+* revert ([ba71354](https://github.com/CloudPirates-io/helm-charts/commit/ba71354))
+* Upgrade minio to latest stable ([b199ea4](https://github.com/CloudPirates-io/helm-charts/commit/b199ea4))
+
+## 0.2.0 (2025-09-02)
+
+* bump all chart versions for new extraObjects feature ([aaa57f9](https://github.com/CloudPirates-io/helm-charts/commit/aaa57f9))
+* add extraObject array to all charts ([34772b7](https://github.com/CloudPirates-io/helm-charts/commit/34772b7))
+
+## 0.1.8 (2025-08-27)
+
+* Fix values.yaml / Chart.yaml linting issues ([043c7e0](https://github.com/CloudPirates-io/helm-charts/commit/043c7e0))
+* Add initial Changelogs to all Charts ([68f10ca](https://github.com/CloudPirates-io/helm-charts/commit/68f10ca))
+
+## 0.1.7 (2025-08-26)
+
+* Initial tagged release
diff --git a/charts/minio/Chart.lock b/charts/minio/Chart.lock
index e0e6255f..cb566e2d 100644
--- a/charts/minio/Chart.lock
+++ b/charts/minio/Chart.lock
@@ -1,6 +1,6 @@
dependencies:
- name: common
repository: oci://registry-1.docker.io/cloudpirates
- version: 1.1.1
-digest: sha256:8da3c04e2c4a1ebfff4f21936399938e0f3fcf9fbd2f7135e7e907ce725b8f00
-generated: "2025-10-01T22:07:26.882147+02:00"
+ version: 2.0.0
+digest: sha256:ae9378e0dcfd09a35b7f994007db99c2d6fe02ef7634f424d5233237c209a1c7
+generated: "2025-10-14T11:14:31.45206+02:00"
diff --git a/charts/minio/Chart.yaml b/charts/minio/Chart.yaml
index 936ea106..4577de09 100644
--- a/charts/minio/Chart.yaml
+++ b/charts/minio/Chart.yaml
@@ -2,7 +2,7 @@ apiVersion: v2
name: minio
description: High Performance Object Storage compatible with Amazon S3 APIs
type: application
-version: 0.4.0
+version: 0.5.5
appVersion: "2025.09.07"
keywords:
- minio
@@ -10,14 +10,38 @@ keywords:
- s3
- storage
- cloud-native
-home: https://www.cloudpirates.io
+home: https://min.io
sources:
- https://github.com/CloudPirates-io/helm-charts/tree/main/charts/minio
+ - https://github.com/minio/minio
maintainers:
- name: CloudPirates GmbH & Co. KG
+ email: hello@cloudpirates.io
url: https://www.cloudpirates.io
dependencies:
- name: common
- version: "1.x.x"
+ version: "2.x.x"
repository: oci://registry-1.docker.io/cloudpirates
icon: https://a.storyblok.com/f/143071/512x512/5d3310f00d/minio-logo.svg
+annotations:
+ license: Apache-2.0
+ artifacthub.io/category: storage
+ artifacthub.io/containsSecurityUpdates: "false"
+ artifacthub.io/signKey: |
+ fingerprint: 6917f1a88c122cbb1de5aa55457752135bdcf95a
+ url: https://raw.githubusercontent.com/CloudPirates-io/helm-charts/refs/heads/main/cosign.pub
+ artifacthub.io/links: |
+ - name: MinIO
+ url: https://min.io
+ - name: Helm Chart
+ url: https://github.com/CloudPirates-io/helm-charts/tree/main/charts/minio
+ - name: Application
+ url: https://github.com/minio/minio
+ - name: Maintainer CloudPirates
+ url: https://www.cloudpirates.io
+ artifacthub.io/changes: |2
+ - kind: changed
+ description: "Add NodePort support for API and Console in Service configuration (#527)"
+ links:
+ - name: "Commit 57b84d8"
+ url: "https://github.com/CloudPirates-io/helm-charts/commit/57b84d8"
diff --git a/charts/minio/README.md b/charts/minio/README.md
index e42954ab..b8dabc00 100644
--- a/charts/minio/README.md
+++ b/charts/minio/README.md
@@ -4,7 +4,8 @@
# MinIO
-A Helm chart for MinIO - High Performance Object Storage compatible with Amazon S3 APIs. MinIO is a high-performance, distributed object storage server designed for large-scale data infrastructure.
+A Helm chart for MinIO - High Performance Object Storage compatible with Amazon S3 APIs. MinIO is a high-performance,
+distributed object storage server designed for large-scale data infrastructure.
## Prerequisites
@@ -32,7 +33,8 @@ Or install directly from the local chart:
helm install my-minio ./charts/minio
```
-The command deploys MinIO on the Kubernetes cluster in the default configuration. The [Configuration](#configuration) section lists the parameters that can be configured during installation.
+The command deploys MinIO on the Kubernetes cluster in the default configuration. The [Configuration](#configuration)
+section lists the parameters that can be configured during installation.
## Uninstalling the Chart
@@ -70,14 +72,14 @@ The following table lists the configurable parameters of the MinIO chart and the
### Global parameters
| Parameter | Description | Default |
-| ------------------------- | ----------------------------------------------- | ------- |
+|---------------------------|-------------------------------------------------|---------|
| `global.imageRegistry` | Global Docker image registry | `""` |
| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` |
### MinIO image configuration
| Parameter | Description | Default |
-| ----------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
+|-------------------------|-----------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
| `image.registry` | MinIO image registry | `docker.io` |
| `image.repository` | MinIO image repository | `minio/minio` |
| `image.tag` | MinIO image tag (immutable tags are recommended) | `"RELEASE.2024-08-17T01-24-54Z"` |
@@ -88,7 +90,7 @@ The following table lists the configurable parameters of the MinIO chart and the
### MinIO Authentication
| Parameter | Description | Default |
-| -------------------------------- | -------------------------------------------------------------------- | ------------ |
+|----------------------------------|----------------------------------------------------------------------|--------------|
| `auth.rootUser` | MinIO root username | `"admin"` |
| `auth.rootPassword` | MinIO root password. If not set, a random password will be generated | `""` |
| `auth.existingSecret` | Name of existing secret containing MinIO credentials | `""` |
@@ -98,7 +100,7 @@ The following table lists the configurable parameters of the MinIO chart and the
### MinIO configuration
| Parameter | Description | Default |
-| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
+|------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
| `config.region` | MinIO server default region | `""` |
| `config.browserEnabled` | Enable MinIO web browser | `true` |
| `config.domain` | MinIO server domain | `""` |
@@ -116,7 +118,7 @@ The following table lists the configurable parameters of the MinIO chart and the
### Deployment configuration
| Parameter | Description | Default |
-| ------------------ | ------------------------------------------- | ------- |
+|--------------------|---------------------------------------------|---------|
| `replicaCount` | Number of MinIO replicas to deploy | `1` |
| `nameOverride` | String to partially override minio.fullname | `""` |
| `fullnameOverride` | String to fully override minio.fullname | `""` |
@@ -124,15 +126,15 @@ The following table lists the configurable parameters of the MinIO chart and the
### Pod annotations and labels
| Parameter | Description | Default |
-| ---------------- | ------------------------------------- | ------- |
+|------------------|---------------------------------------|---------|
| `podAnnotations` | Map of annotations to add to the pods | `{}` |
| `podLabels` | Map of labels to add to the pods | `{}` |
### Security Context
-| Parameter | Description | Default |
-| ------------------------------------------ | ------------------------------------------------- | --------- |
-| `podSecurityContext.fsGroup` | Group ID for the volumes of the pod | `1000` |
+| Parameter | Description | Default |
+|-----------------------------------------------------|---------------------------------------------------|-----------|
+| `podSecurityContext.fsGroup` | Group ID for the volumes of the pod | `1000` |
| `containerSecurityContext.allowPrivilegeEscalation` | Enable container privilege escalation | `false` |
| `containerSecurityContext.runAsNonRoot` | Configure the container to run as a non-root user | `true` |
| `containerSecurityContext.runAsUser` | User ID for the MinIO container | `1000` |
@@ -142,17 +144,19 @@ The following table lists the configurable parameters of the MinIO chart and the
### Service configuration
-| Parameter | Description | Default |
-| --------------------- | -------------------------- | ----------- |
-| `service.type` | MinIO service type | `ClusterIP` |
-| `service.port` | MinIO service port | `9000` |
-| `service.consolePort` | MinIO console service port | `9090` |
-| `service.annotations` | Service annotations | `{}` |
+| Parameter | Description | Default |
+|-----------------------------|----------------------------|-------------|
+| `service.type` | MinIO service type | `ClusterIP` |
+| `service.port` | MinIO service port | `9000` |
+| `service.consolePort` | MinIO console service port | `9090` |
+| `service.annotations` | Service annotations | `{}` |
+| `service.nodePorts.api` | Service api node port | `""` |
+| `service.nodePorts.console` | Service console node port | `""` |
### Ingress configuration
| Parameter | Description | Default |
-| ------------------------------------ | ------------------------------------------------------- | ------------- |
+|--------------------------------------|---------------------------------------------------------|---------------|
| `ingress.enabled` | Enable ingress record generation for MinIO | `false` |
| `ingress.className` | IngressClass that will be used to implement the Ingress | `""` |
| `ingress.annotations` | Additional annotations for the Ingress resource | `{}` |
@@ -164,7 +168,7 @@ The following table lists the configurable parameters of the MinIO chart and the
### Console Ingress configuration
| Parameter | Description | Default |
-| ------------------------------------------- | ------------------------------------------------------- | --------------------- |
+|---------------------------------------------|---------------------------------------------------------|-----------------------|
| `consoleIngress.enabled` | Enable ingress record generation for MinIO Console | `false` |
| `consoleIngress.className` | IngressClass that will be used to implement the Ingress | `""` |
| `consoleIngress.annotations` | Additional annotations for the Console Ingress resource | `{}` |
@@ -176,13 +180,13 @@ The following table lists the configurable parameters of the MinIO chart and the
### Resources
| Parameter | Description | Default |
-| ----------- | ------------------------------------------- | ------- |
+|-------------|---------------------------------------------|---------|
| `resources` | The resources to allocate for the container | `{}` |
### Persistence
| Parameter | Description | Default |
-| --------------------------- | -------------------------------------------------- | ------------------- |
+|-----------------------------|----------------------------------------------------|---------------------|
| `persistence.enabled` | Enable persistence using Persistent Volume Claims | `true` |
| `persistence.storageClass` | Persistent Volume storage class | `""` |
| `persistence.annotations` | Persistent Volume Claim annotations | `{}` |
@@ -193,7 +197,7 @@ The following table lists the configurable parameters of the MinIO chart and the
### Liveness and readiness probes
| Parameter | Description | Default |
-| ------------------------------------ | ----------------------------------------- | ------- |
+|--------------------------------------|-------------------------------------------|---------|
| `livenessProbe.enabled` | Enable livenessProbe on MinIO containers | `true` |
| `livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` |
| `livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` |
@@ -216,7 +220,7 @@ The following table lists the configurable parameters of the MinIO chart and the
### Node Selection
| Parameter | Description | Default |
-| -------------- | ------------------------------------ | ------- |
+|----------------|--------------------------------------|---------|
| `nodeSelector` | Node labels for pod assignment | `{}` |
| `tolerations` | Toleration labels for pod assignment | `[]` |
| `affinity` | Affinity settings for pod assignment | `{}` |
@@ -224,14 +228,17 @@ The following table lists the configurable parameters of the MinIO chart and the
### Extra Configuration Parameters
| Parameter | Description | Default |
-| -------------- | ----------------------------------------------------------------------- | ------- |
+|----------------|-------------------------------------------------------------------------|---------|
| `extraObjects` | A list of additional Kubernetes objects to deploy alongside the release | `[]` |
#### Extra Objects
-You can use the `extraObjects` array to deploy additional Kubernetes resources (such as NetworkPolicies, ConfigMaps, etc.) alongside the release. This is useful for customizing your deployment with extra manifests that are not covered by the default chart options.
+You can use the `extraObjects` array to deploy additional Kubernetes resources (such as NetworkPolicies, ConfigMaps,
+etc.) alongside the release. This is useful for customizing your deployment with extra manifests that are not covered by
+the default chart options.
-**Helm templating is supported in any field, but all template expressions must be quoted.** For example, to use the release namespace, write `namespace: "{{ .Release.Namespace }}"`.
+**Helm templating is supported in any field, but all template expressions must be quoted.** For example, to use the
+release namespace, write `namespace: "{{ .Release.Namespace }}"`.
**Example: Deploy a NetworkPolicy with templating**
@@ -243,7 +250,7 @@ extraObjects:
name: allow-dns
namespace: "{{ .Release.Namespace }}"
spec:
- podSelector: {}
+ podSelector: { }
policyTypes:
- Egress
egress:
@@ -261,7 +268,8 @@ extraObjects:
protocol: TCP
```
-All objects in `extraObjects` will be rendered and deployed with the release. You can use any valid Kubernetes manifest, and reference Helm values or built-in objects as needed (just remember to quote template expressions).
+All objects in `extraObjects` will be rendered and deployed with the release. You can use any valid Kubernetes manifest,
+and reference Helm values or built-in objects as needed (just remember to quote template expressions).
## Examples
@@ -329,14 +337,17 @@ helm install my-minio ./charts/minio -f values-production.yaml
### Exposing a Bucket Publicly (โCDN Serverโ Setup)
-You can make a MinIO bucket publicly accessible (e.g. as a CDN endpoint) using Ingress and MinIO's CLI tool (`mc`). Below is an example configuration
+You can make a MinIO bucket publicly accessible (e.g. as a CDN endpoint) using Ingress and MinIO's CLI tool (`mc`).
+Below is an example configuration
and the commands needed to set this up.
#### 1. Install the Helm Chart with Public Ingress
-Ensure the **Ingress controller** (like [ingress-nginx](https://kubernetes.github.io/ingress-nginx/)) is deployed in your cluster.
+Ensure the **Ingress controller** (like [ingress-nginx](https://kubernetes.github.io/ingress-nginx/)) is deployed in
+your cluster.
-Example `values.yaml` snippet for Helm install (replace `cdn.my-domain.local` and `my-bucket-name` with your own values):
+Example `values.yaml` snippet for Helm install (replace `cdn.my-domain.local` and `my-bucket-name` with your own
+values):
```yaml
ingress:
@@ -369,7 +380,8 @@ helm install my-minio -f values.yaml
#### 2. Configure Your Bucket for Public Access
-You need the [MinIO Client (`mc`)](https://min.io/docs/minio/linux/reference/minio-mc.html) to manage bucket policies. You can access `mc` directly in the MinIO pod:
+You need the [MinIO Client (`mc`)](https://min.io/docs/minio/linux/reference/minio-mc.html) to manage bucket policies.
+You can access `mc` directly in the MinIO pod:
```bash
kubectl exec -it -n -- bash
@@ -389,7 +401,8 @@ Inside the pod, configure as follows (replace `my-bucket-name` as needed):
mc mb local/my-bucket-name
```
-3. Create a custom policy in `/tmp/policy.json` to only allow `GetObject`, alternatively use the predefined `download` policy:
+3. Create a custom policy in `/tmp/policy.json` to only allow `GetObject`, alternatively use the predefined `download`
+ policy:
```bash
echo '
{
@@ -423,8 +436,8 @@ Inside the pod, configure as follows (replace `my-bucket-name` as needed):
```
**Summary:**
-After these steps, your bucket (`my-bucket-name`) will be accessible via `https://cdn.my-domain.local/