feat(common): Release v4.1.2 (#430)

Signed-off-by: Dan Manners <daniel.a.manners@gmail.com>
Co-authored-by: Daniel Manners <daniel.a.manners@gmail.com>
This commit is contained in:
Bernd Schorgers 2025-06-23 15:47:18 +02:00
parent de383dc580
commit 42354af45b
No known key found for this signature in database
69 changed files with 1431 additions and 668 deletions

View file

@ -1,3 +1,4 @@
---
name: str()
home: str(required=False)
version: str()

View file

@ -1,3 +1,4 @@
---
chart-yaml-schema: .ci/ct/chart_schema.yaml
lint-conf: .yamllint.yml

View file

@ -1,4 +1,6 @@
---
# yaml-language-server: $schema=https://squidfunk.github.io/mkdocs-material/schema.json
# Project information
site_name: bjw-s Helm Charts
site_url: https://bjw-s-labs.github.io/helm-charts/
@ -42,7 +44,8 @@ theme:
# Plugins
plugins:
- search:
separator: '[\s\u200b\-_,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'
separator: >-
[\s\u200b\-_,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])
- minify:
minify_html: true

View file

@ -1,3 +1,4 @@
---
# See https://pre-commit.com for more information
exclude: |
(?x)^(
@ -5,18 +6,18 @@ exclude: |
)$
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: fix-byte-order-marker
- id: mixed-line-ending
- id: check-merge-conflict
- id: check-case-conflict
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: fix-byte-order-marker
- id: mixed-line-ending
- id: check-merge-conflict
- id: check-case-conflict
- repo: https://github.com/Lucas-C/pre-commit-hooks
rev: v1.1.10
hooks:
- id: remove-crlf
- id: remove-tabs
- repo: https://github.com/Lucas-C/pre-commit-hooks
rev: v1.1.10
hooks:
- id: remove-crlf
- id: remove-tabs

View file

@ -1,4 +0,0 @@
.direnv
.private
.vscode
*.sops.*

View file

@ -1,6 +0,0 @@
---
trailingComma: "es5"
tabWidth: 2
semi: false
singleQuote: false
bracketSpacing: false

View file

@ -2,14 +2,11 @@ root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.{sh,json}]
indent_size = 4
[*.md]
max_line_length = off
trim_trailing_whitespace = true

53
.github/copilot-instructions.md vendored Normal file
View file

@ -0,0 +1,53 @@
# GitHub Copilot Instructions for helm-charts
## Instruction Files Reference
When helping with this repository, use these instruction files for specific guidance:
- [Project Purpose and Goals](.github/instructions/project-purpose.instructions.md) - Use to understand the core purpose and design philosophy of the repository
- [Common Library Development](.github/instructions/common-library.instructions.md) - Use when modifying or extending the common library chart
- [Chart Testing](.github/instructions/chart-testing.instructions.md) - Use when testing charts or adding new tests
- [Documentation](.github/instructions/documentation.instructions.md) - Use when updating or creating documentation
- [Examples](.github/instructions/examples.instructions.md) - Use when working with example configurations
- [Version Management](.github/instructions/versioning.instructions.md) - Use when updating chart versions
## Overview
This repository contains a collection of Helm charts used for deploying applications in Kubernetes clusters. The primary components are:
1. A `common` library chart that provides reusable Helm templates and functions
2. An `app-template` chart that leverages the common library for easy application deployment
## Repository Structure
- `charts/`: Contains the Helm charts
- `library/common/`: The common library chart with reusable templates and functions
- `other/app-template/`: A generic application template chart for deploying various applications
- `docs/`: Documentation for the charts
- `examples/`: Example configurations for using the charts with different tools (Helm, Flux, Kustomize)
## Common Tasks
When working with this repository, you'll typically need to:
1. Understand the chart structure and how components relate to each other
2. Create or modify Helm templates
3. Update chart versions following semantic versioning
4. Update Chart.yaml annotations with changelog entries
5. Test chart changes
## Development Guidelines
- Chart versions must follow [semver](https://semver.org/) principles
- Any change to a chart requires a version bump
- Chart releases must be immutable
- Follow the [Charts best practices](https://helm.sh/docs/topics/chart_best_practices/)
- Sign off all commits with `git commit -s`
## Tools and Commands
This repository uses [Task](https://taskfile.dev/) for automation. The main task commands include:
- `task charts:lint`: Lint all charts
- `task charts:test`: Test charts
- `task docs:serve`: Serve the documentation locally

View file

@ -0,0 +1,50 @@
# Chart Testing Instructions
Testing is a critical part of chart development to ensure reliability and compatibility.
## Testing Structure
- `charts/library/common/test-chart/`: Contains a test chart for validating the common library
- `charts/library/common/test-chart/unittests/`: Contains unit tests for different resource types
- `charts/library/common/test-chart/ci/`: Contains CI test values
## Testing Tools
This repository uses:
1. **Helm lint**: For syntax validation
2. **Schema validation**: For values validation
3. **Unit tests**: For template functionality validation
## Testing Guidelines
### Running Tests Locally
To run tests locally:
1. `task charts:lint`: Run linting on all charts
2. `task charts:test`: Run chart tests
### Adding New Tests
When adding new features, always add corresponding tests:
1. For new resource types, add unit tests in the appropriate directory
2. For new value options, add test cases that exercise those options
3. For edge cases, add specific test values to validate behavior
### Testing Best Practices
1. Test both valid and invalid configurations
2. Test resource generation with different combinations of values
3. Test template functions with various inputs
4. Test backward compatibility when making changes
### Testing with Real Applications
Beyond automated tests, it's valuable to test with real applications:
1. Deploy sample applications using the app-template chart
2. Verify that all resources are created correctly
3. Test the application functionality
4. Test upgrades from previous versions to ensure compatibility

View file

@ -0,0 +1,56 @@
# Common Library Development Instructions
The `common` library chart is the foundation of this repository. It provides reusable templates and functions for Kubernetes resource generation.
## Structure
- `templates/classes/`: Contains template definitions for various Kubernetes resources
- `templates/lib/`: Contains library functions used across templates
- `templates/loader/`: Contains code for loading and initializing templates
- `templates/render/`: Contains code for rendering resources
- `templates/values/`: Contains code for value validation
- `schemas/`: JSON schemas for validating values
## Key Concepts
1. **Template Classes**: These are blueprint templates for Kubernetes resources like Deployments, Services, etc.
2. **Library Functions**: Helper functions that can be used across templates
3. **Values Schema**: JSON schema definitions for validating chart values
## Development Guidelines
### Adding New Features
When adding new features to the common library:
1. Determine which resource type(s) the feature applies to
2. Add appropriate parameters to the values schema
3. Update the relevant template class(es)
4. Update documentation as needed
5. Increment the chart version in `Chart.yaml` following semver principles
### Modifying Existing Features
When modifying existing features:
1. Ensure backward compatibility or document breaking changes
2. Update the relevant template class(es)
3. Update the values schema if needed
4. Update documentation
5. Increment the chart version appropriately
### Testing Changes
After making changes:
1. Run `task charts:lint` to validate chart syntax
2. Run `task charts:test` to run chart tests
3. Deploy a test chart using the library to verify functionality
### Common Library Best Practices
1. Keep template functions focused and reusable
2. Use clear naming conventions for functions and parameters
3. Document function parameters and behavior
4. Maintain backward compatibility where possible
5. Update version numbers in accordance with semver principles

View file

@ -0,0 +1,242 @@
# Documentation Instructions
Good documentation is essential for this project as it helps users understand how to use the charts effectively.
## Documentation Structure
- `docs/`: Main documentation directory
- `index.md`: Home page (includes README.md content)
- `app-template/`: Documentation for the app-template chart
- `index.md`: Overview of the app-template chart
- `upgrade-instructions.md`: Instructions for upgrading between major versions
- `examples/`: Example configurations for the app-template
- `howto/`: Guides for specific tasks with the app-template
- `common-library/`: Documentation for the common library chart
- `index.md`: Overview of the common library chart
- `howto/`: Guides for specific tasks with the common library
- `resources/`: Documentation for specific resource types
- `storage/`: Documentation for storage options
- `overrides/`: Custom MkDocs template overrides
- `requirements.txt`: Python dependencies for building the documentation
## Documentation Tools
This repository uses:
1. **MkDocs**: For generating the documentation site
2. **Material for MkDocs**: For styling and enhanced features
3. **PyMdown Extensions**: For extended markdown capabilities
4. **README.md.gotmpl**: Template files for generating README files
5. **mkdocs-minify-plugin**: For minifying the generated HTML
## Documentation Guidelines
### Writing Documentation
When documenting charts and features:
1. Use clear, concise language
2. Provide examples for common use cases
3. Document all available options and their default values
4. Include diagrams or screenshots where helpful
5. Link to relevant external documentation
### Markdown Formatting
All documentation should use consistent Markdown formatting:
1. **Headers**: Use proper hierarchy (H1 → H2 → H3)
```markdown
# Page Title (H1)
## Section (H2)
### Subsection (H3)
```
2. **Code Blocks**: Use fenced code blocks with language specification
```markdown
```yaml
controllers:
main:
containers:
main:
image:
repository: ghcr.io/example/app
tag: latest
```
```
3. **File Inclusions**: Use the `--8<--` syntax to include files
```markdown
--8<--
examples/helm/vaultwarden/values.yaml
--8<--
```
4. **Admonitions**: Use admonition blocks for notes, warnings, etc.
```markdown
!!! note
This is a note admonition.
!!! warning
This is a warning admonition.
```
5. **Line Numbers**: Use line numbers for longer code blocks
```markdown
```yaml linenums="1"
# Code with line numbers
```
```
6. **Annotations**: Use annotations to highlight specific parts of code
```markdown
```yaml
image:
repository: nginx # (1)!
tag: latest
```
1. This is an annotation explaining the repository value
```
### Chart Documentation
Each chart should have at minimum:
1. **Overview**: Brief description of the chart's purpose
2. **Background**: Context or reasoning behind the chart
3. **Usage**: Instructions for using the chart
4. **Examples**: Practical examples with configurations
5. **Source code**: Link to the chart's source code
### Updating Documentation
When making changes to charts:
1. Update the corresponding documentation files
2. Update examples if the change affects how users would use the chart
3. Document breaking changes prominently
4. Add upgrade instructions for major version changes
5. Ensure cross-references between docs remain valid
### Version-Specific Documentation
For version-specific features or changes:
1. Clearly indicate the version where the feature was introduced
2. Use admonitions to highlight version requirements
```markdown
!!! info "Version requirement"
This feature is available in version 4.0.0 and later.
```
3. For major version changes, update `upgrade-instructions.md` with migration steps
4. Use version comparison conditionals when appropriate
### Serving Documentation Locally
To preview documentation locally:
1. Run `task docs:serve`
2. Open a browser to the URL displayed in the terminal (typically http://localhost:8000)
3. Make changes to documentation files and see live updates
### Building the Documentation
To build the documentation for production:
1. Run `task docs:build`
2. The static site will be generated in the `site/` directory
### Documentation Best Practices
1. Keep documentation up to date with code changes
2. Use consistent formatting and style
3. Organize content in a logical hierarchy
4. Include both basic and advanced usage examples
5. Document common gotchas and troubleshooting tips
6. Use code blocks with syntax highlighting for examples
7. Add explanatory comments within code examples
8. Link to related documentation sections
## Folder-Specific Documentation
### App Template Documentation
For the app-template chart, ensure documentation covers:
1. How to use the chart for basic applications
2. Common customization patterns
3. Examples for popular applications
4. Integration with different environments (Flux, Kustomize, etc.)
5. Upgrade paths between major versions
### Common Library Documentation
For the common library, documentation should focus on:
1. Available templates and functions
2. How to use each resource type
3. Advanced configuration options
4. Best practices for extending or customizing
## Example Templates
### Basic Chart Example
```markdown
# Chart Name
## Background
Brief explanation of what this chart does and why it exists.
## Usage
Instructions on how to use this chart, including:
```yaml
# Example values.yaml
controllers:
main:
containers:
main:
image:
repository: nginx
tag: latest
```
## Source code
The source code for this chart can be found [here](link/to/chart).
```
### How-To Guide Template
```markdown
# How to Accomplish X
This guide explains how to accomplish X using the chart.
## Prerequisites
- List prerequisites
- Required knowledge
## Steps
1. First step with explanation
2. Second step with explanation
```yaml
# Example configuration
```
3. Third step with explanation
## Examples
Provide complete examples
## See Also
- [Related guide](link/to/related)
- [External resource](link/to/external)
```

View file

@ -0,0 +1,46 @@
# Example Development Instructions
Examples are crucial for helping users understand how to use the charts in real-world scenarios.
## Example Structure
- `examples/`: Main examples directory
- `helm/`: Examples for using charts with plain Helm
- `flux/`: Examples for using charts with Flux CD
- `kustomize/`: Examples for using charts with Kustomize
## Example Guidelines
### Creating New Examples
When creating new examples:
1. Choose realistic applications that demonstrate chart capabilities
2. Structure examples clearly with comments explaining key configuration options
3. Include all necessary files for the deployment method
4. Add a README.md explaining the purpose and usage of the example
### Updating Examples
When updating chart features:
1. Update relevant examples to demonstrate the new features
2. Ensure examples continue to work with the latest chart versions
3. Document any breaking changes that would affect existing users
### Example Best Practices
1. Keep examples simple enough to understand but comprehensive enough to be useful
2. Include comments that explain why certain configuration options are chosen
3. Demonstrate both basic and advanced usage patterns
4. Include examples for different types of applications (stateless, stateful, etc.)
5. Show integration with common tools and platforms (Flux, Kustomize, etc.)
### Testing Examples
Before committing examples:
1. Deploy the example in a test environment
2. Verify that all resources are created correctly
3. Test the functionality of the deployed application
4. Ensure the example is compatible with the latest chart version

View file

@ -0,0 +1,118 @@
# Project Purpose and Goals
This document outlines the core purpose, design philosophy, and goals of the helm-charts repository.
## Core Purpose
The helm-charts repository provides a standardized approach to Kubernetes application deployment through a reusable library chart pattern. It follows the DRY (Don't Repeat Yourself) principle for Helm charting, recognizing that many applications require similar Kubernetes resources with only slight variations.
## Design Philosophy
The repository is built around these key principles:
### 1. Abstraction through Library Charts
Helm's [library charts](https://helm.sh/docs/topics/library_charts/) allow for sharing chart primitives across multiple charts. This repository leverages this concept by:
- Centralizing common templates and functions in a single library chart
- Providing consistent interfaces for resource generation
- Exposing a simplified API for application deployment
### 2. Configuration over Code
Rather than requiring users to write custom templates for each application, this repository:
- Provides a declarative configuration approach
- Uses values.yaml for defining application requirements
- Generates appropriate Kubernetes resources based on configuration
### 3. Convention over Configuration
The charts implement sensible defaults while allowing for customization:
- Standard resource naming conventions
- Common label patterns
- Predictable resource relationships
- Escape hatches for advanced scenarios
## Repository Goals
The helm-charts repository aims to:
### 1. Standardization
Create a consistent approach to defining Kubernetes resources by:
- Establishing uniform resource naming
- Applying common labeling patterns
- Maintaining consistent relationship patterns between resources
- Providing standardized validation through JSON schemas
### 2. Reusability
Avoid duplicating code across multiple Helm charts by:
- Centralizing template logic in a common library
- Sharing helper functions across different resource types
- Creating reusable patterns for common deployment scenarios
- Building composable components
### 3. Simplicity
Make it easier to deploy applications to Kubernetes by:
- Reducing boilerplate configuration
- Providing intuitive defaults
- Creating a streamlined interface for common scenarios
- Minimizing the learning curve for users
### 4. Flexibility
Support a wide range of application types and deployment scenarios through:
- Extensible templates that handle various application requirements
- Support for different Kubernetes resource types
- Configurability through values files
- Escape hatches for complex use cases
### 5. Maintainability
Centralize common functionality to simplify updates and fixes by:
- Consolidating resource generation logic
- Standardizing validation
- Using shared templates for common patterns
- Implementing consistent testing approaches
## Components and Their Purpose
### Common Library Chart
The `common` library chart (`charts/library/common/`) is the foundation of the repository, providing:
- **Template Classes**: Blueprint templates for Kubernetes resources like Deployments, Services, etc.
- **Library Functions**: Helper functions that simplify resource generation
- **Value Validation**: JSON schemas that validate chart values
- **Resource Rendering**: Logic for rendering various Kubernetes resources
### App Template Chart
The `app-template` chart (`charts/other/app-template/`) is a companion chart that:
- Leverages the common library to provide a turnkey solution for application deployment
- Offers a consistent interface for deploying various applications
- Reduces the barrier to entry for deploying applications on Kubernetes
- Provides a reference implementation of the common library
## Use Cases
The helm-charts repository is designed for:
1. **Application Deployment**: Simplifying the process of deploying applications on Kubernetes
2. **GitOps Workflows**: Supporting declarative configuration for GitOps tools like Flux
3. **Standardized Operations**: Enabling consistent operational patterns across applications
4. **Learning and Reference**: Providing examples of Helm best practices and patterns
## Related Documentation
The helm-charts repository contains several types of documentation to help users and contributors understand and use the charts effectively. The documentation covers aspects such as:
- **Common Library Development**: Details on modifying or extending the common library chart
- **App Template Development**: Guidance for working with the app-template chart
- **Documentation Guidelines**: Instructions for maintaining repository documentation
- **Examples**: Information about example configurations and use cases

View file

@ -0,0 +1,55 @@
# Version Management Instructions
Proper versioning is critical for maintaining compatibility and communicating changes to users.
## Versioning Principles
This repository follows [Semantic Versioning (SemVer)](https://semver.org/):
1. **MAJOR**: Incompatible API changes
2. **MINOR**: Functionality added in a backward compatible manner
3. **PATCH**: Backward compatible bug fixes
## Version Management Guidelines
### When to Increment Versions
- **MAJOR**: When making breaking changes like:
- Removing or renaming values
- Changing default behavior significantly
- Requiring a newer Kubernetes version
- **MINOR**: When adding new features like:
- New resource types
- New configuration options
- Extended functionality
- **PATCH**: When making non-breaking fixes like:
- Bug fixes
- Documentation updates
- Optimization improvements
### Chart Dependencies
When updating chart dependencies:
1. Update the dependency version in `Chart.yaml`
2. Update the chart's own version appropriately
3. Document the change and any implications
### Release Notes
For each version change:
1. Document what changed
2. Highlight any breaking changes
3. Provide upgrade instructions if needed
4. Tag the repository with the new version
### Version Management Best Practices
1. Always increment versions for any chart changes
2. Be conservative in MAJOR version increments
3. Document breaking changes thoroughly
4. Provide upgrade paths for users on older versions
5. Test upgrades from previous versions to ensure compatibility

View file

@ -6,8 +6,7 @@ on:
inputs:
chart:
description: >
Json encoded list of Helm charts to release.
Defaults to releasing everything.
Json encoded list of Helm charts to release. Defaults to releasing everything.
required: true
type: string
createGithubRelease:
@ -34,12 +33,6 @@ on:
default: false
required: false
type: boolean
helmVersion:
description: >
Helm version to use.
default: "latest"
required: false
type: string
permissions:
contents: read
@ -64,10 +57,8 @@ jobs:
with:
path: src
- name: Install Helm
uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0
with:
version: ${{ inputs.helmVersion }}
- name: Install Mise and required tools
uses: jdx/mise-action@13abe502c30c1559a5c37dff303831bab82c9402 # v2.2.3
- name: Login to OCI Registry
if: ${{ inputs.publishToOciRegistry }}
@ -226,10 +217,6 @@ jobs:
# ----------------------------
# Publish chart to bjw-s OCI registry
# ----------------------------
- name: Install Cosign
if: ${{ inputs.publishToOciRegistry }}
uses: sigstore/cosign-installer@fb28c2b6339dcd94da6e4cbcbc5e888961f6f8c3 # v3.9.0
- name: Push Helm charts to OCI registry
if: ${{ inputs.publishToOciRegistry }}
shell: bash
@ -240,7 +227,7 @@ jobs:
CHART_TAG_BASE: ghcr.io/bjw-s-labs/helm
CHART_TAG: ${{ steps.chart-details.outputs.name }}:${{ steps.chart-details.outputs.version }}
GITHUB_REF: ${{ github.ref }}
run: |
run: |-
helm push "${PACKAGE_FILE}" oci://${CHART_TAG_BASE} &> push-metadata.txt
cat push-metadata.txt
CHART_DIGEST=$(awk '/Digest: /{print $2}' push-metadata.txt)

View file

@ -1,3 +1,4 @@
---
name: "Charts: Lint (Reusable)"
on:
@ -5,17 +6,10 @@ on:
inputs:
charts:
description: >
Json encoded list of Helm charts to release.
Defaults to releasing everything.
Json encoded list of Helm charts to release. Defaults to releasing everything.
default: "[]"
required: true
type: string
helmVersion:
description: >
Helm version to use.
default: "latest"
required: false
type: string
permissions:
contents: read
@ -63,20 +57,19 @@ jobs:
allowChartToNotExist: true
validateChartYaml: false
requireChangelog: false
# - name: Check version update
# if: ${{ steps.chart-details-pr.outputs.version == steps.chart-details-default.outputs.version }}
# uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
# with:
# script: |
# core.setFailed("Chart version has not been updated for ${{ matrix.chart }}");
# - name: Check version update
# if: ${{ steps.chart-details-pr.outputs.version == steps.chart-details-default.outputs.version }}
# uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
# with:
# script: |
# core.setFailed("Chart version has not been updated for ${{ matrix.chart }}");
# - name: Check changelog update
# if: ${{ steps.chart-details-pr.outputs.changes == steps.chart-details-default.outputs.changes }}
# uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
# with:
# script: |
# core.setFailed("Changelog has not been updated for ${{ matrix.chart }}");
# - name: Check changelog update
# if: ${{ steps.chart-details-pr.outputs.changes == steps.chart-details-default.outputs.changes }}
# uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
# with:
# script: |
# core.setFailed("Changelog has not been updated for ${{ matrix.chart }}");
validate_success:
needs:
@ -109,15 +102,8 @@ jobs:
with:
persist-credentials: false
- name: Install Kubernetes tools
uses: yokawasa/action-setup-kube-tools@9e25a4277af127b60011c95b6ed2da7e3b3613b1 # v0.11.2
with:
setup-tools: |
helmv3
helm: "${{ inputs.helmVersion }}"
- name: Set up chart-testing
uses: helm/chart-testing-action@0d28d3144d3a25ea2cc349d6e59901c4ff469b3b # v2.7.0
- name: Install Mise and required tools
uses: jdx/mise-action@13abe502c30c1559a5c37dff303831bab82c9402 # v2.2.3
- name: Dereference JSON schema
uses: bjw-s-labs/helm-charts-actions/dereference-json-schema@89e58e0499f87d46d1fc67d8a0e409127f86a3dd

View file

@ -36,6 +36,9 @@ jobs:
with:
persist-credentials: false
- name: Install Mise and set up tool cache
uses: jdx/mise-action@13abe502c30c1559a5c37dff303831bab82c9402 # v2.2.3
- name: Grab repository configuration
id: repo-config
shell: bash

View file

@ -1,3 +1,4 @@
---
name: "Charts: Test (Reusable)"
on:
@ -5,17 +6,10 @@ on:
inputs:
charts:
description: >
Json encoded list of Helm charts to release.
Defaults to releasing everything.
Json encoded list of Helm charts to release. Defaults to releasing everything.
default: "[]"
required: true
type: string
helmVersion:
description: >
Helm version to use.
default: "latest"
required: false
type: string
permissions:
contents: read
@ -29,14 +23,12 @@ jobs:
matrix:
chart: ${{ fromJSON(inputs.charts) }}
k8s_version:
[
"v1.28.15",
"v1.29.13",
"v1.30.11",
"v1.31.7",
"v1.32.3",
"v1.33.0",
]
- "v1.28.15"
- "v1.29.13"
- "v1.30.11"
- "v1.31.7"
- "v1.32.3"
- "v1.33.0"
fail-fast: false
steps:
- name: Checkout
@ -53,19 +45,15 @@ jobs:
exit 1
fi
- name: Install Kubernetes tools
- name: Install kubectl matching k8s version
uses: yokawasa/action-setup-kube-tools@9e25a4277af127b60011c95b6ed2da7e3b3613b1 # v0.11.2
with:
setup-tools: |
helmv3
kubectl
helm: "${{ inputs.helmVersion }}"
kubectl: "${{ matrix.k8s_version }}"
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
- name: Set up chart-testing
uses: helm/chart-testing-action@0d28d3144d3a25ea2cc349d6e59901c4ff469b3b # v2.7.0
- name: Install Mise and required tools
uses: jdx/mise-action@13abe502c30c1559a5c37dff303831bab82c9402 # v2.2.3
- name: Create k3d cluster
uses: nolar/setup-k3d-k3s@293b8e5822a20bc0d5bcdd4826f1a665e72aba96 # v1.0.9
@ -141,12 +129,8 @@ jobs:
exit 1
fi
- name: Install Kubernetes tools
uses: yokawasa/action-setup-kube-tools@9e25a4277af127b60011c95b6ed2da7e3b3613b1 # v0.11.2
with:
setup-tools: |
helmv3
helm: "${{ inputs.helmVersion }}"
- name: Install Mise and required tools
uses: jdx/mise-action@13abe502c30c1559a5c37dff303831bab82c9402 # v2.2.3
- name: Dereference JSON schema
uses: bjw-s-labs/helm-charts-actions/dereference-json-schema@89e58e0499f87d46d1fc67d8a0e409127f86a3dd

View file

@ -11,7 +11,7 @@ on:
branches:
- main
schedule:
- cron: '30 6 * * *'
- cron: "30 6 * * *"
permissions:
contents: read
@ -54,4 +54,4 @@ jobs:
id: analyze
uses: github/codeql-action/analyze@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0
with:
category: '/language:${{matrix.language}}'
category: "/language:${{matrix.language}}"

View file

@ -1,3 +1,4 @@
---
name: "Docs: Release to GitHub pages"
on:
@ -28,13 +29,15 @@ jobs:
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
- name: Install requirements
run: pip install -r docs/requirements.txt
- name: Install Mise and required tools
uses: jdx/mise-action@13abe502c30c1559a5c37dff303831bab82c9402 # v2.2.3
with:
cache: false
- name: Build and publish docs
run: mkdocs build -f .ci/mkdocs/mkdocs.yml
run: |
source .venv/bin/activate
mkdocs build -f .ci/mkdocs/mkdocs.yml
- name: Generate Token
uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6

View file

@ -1,3 +1,4 @@
---
name: "Pull Request: Validate"
on:
@ -30,6 +31,9 @@ jobs:
with:
persist-credentials: false
- name: Install Mise and set up tool cache
uses: jdx/mise-action@13abe502c30c1559a5c37dff303831bab82c9402 # v2.2.3
- name: Grab repository configuration
id: repo-config
shell: bash

24
.mise.toml Normal file
View file

@ -0,0 +1,24 @@
[env]
_.python.venv = { path = ".venv", create = true }
[settings]
experimental = true
pipx_uvx = true
python.uv_venv_auto = true
[tools]
python = "3.13" # Required for documentation generation
rust = "1.87" # Required for schematools
cosign = "2.5.2"
"aqua:astral-sh/uv" = "0.7.13"
"aqua:go-task/task" = "3.44.0"
"aqua:google/yamlfmt" = "0.17.1"
"aqua:helm" = "3.18.3"
"aqua:helm/chart-testing" = "3.13.0"
"aqua:mikefarah/yq" = "4.45.4"
"cargo:schematools-cli" = "0.22.0"
"pipx:yamllint" = "1.37.1"
"pipx:yamale" = "6.0.0"
[hooks]
postinstall = "uv pip install --upgrade -r docs/requirements.txt"

View file

@ -1 +0,0 @@
3.13

View file

@ -28,14 +28,15 @@ tasks:
desc: Test chart [CHART=required]
preconditions:
# Requires https://github.com/kstasik/schema-tools
- which helm schematools yq
- which helm schematools-cli yq
- test -d "{{.CHART_DIR}}"
- test -d "{{.CHART_TEST_DIR}}"
requires:
vars:
- CHART
vars:
GLOB: "{{.GLOB | default \"**/*_test.yaml\"}}"
GLOB: >-
{{.GLOB | default "**/*_test.yaml"}}
CHART_DIR: "{{.PROJECT_DIR}}/charts/{{.CHART}}"
CHART_TYPE:
sh: yq eval '.type // "application"' {{.PROJECT_DIR}}/charts/{{.CHART}}/Chart.yaml
@ -43,17 +44,17 @@ tasks:
{{.CHART_DIR}}{{- if eq .CHART_TYPE "library" -}}/test-chart{{- end -}}
dir: "{{.CHART_TEST_DIR}}"
cmds:
- cp "{{.CHART_DIR}}/values.schema.json" "{{.CHART_DIR}}/values.schema.bak"
- schematools process dereference "{{.CHART_DIR}}/values.schema.json" --to-file "{{.CHART_DIR}}/values.schema.json"
- defer: mv "{{.CHART_DIR}}/values.schema.bak" "{{.CHART_DIR}}/values.schema.json"
- helm dep update
- helm unittest --color -f "unittests/{{.GLOB}}" .
- cp "{{.CHART_DIR}}/values.schema.json" "{{.CHART_DIR}}/values.schema.bak"
- schematools-cli process dereference "{{.CHART_DIR}}/values.schema.json" --to-file "{{.CHART_DIR}}/values.schema.json"
- defer: mv "{{.CHART_DIR}}/values.schema.bak" "{{.CHART_DIR}}/values.schema.json"
- helm dep update
- helm unittest --color -f "unittests/{{.GLOB}}" .
silent: true
dependency-cleanup:
desc: clean up chart dependencies
dir: "{{.PROJECT_DIR}}/charts"
cmds:
- find {{.PROJECT_DIR}}/charts/ -mindepth 1 -type f -name 'Chart.lock' -print0 | xargs -r -0 rm
- find {{.PROJECT_DIR}}/charts/ -mindepth 1 -type d -name 'charts' -print0 | xargs -r -0 rm -rf
- find {{.PROJECT_DIR}}/charts/ -mindepth 1 -type f -name 'Chart.lock' -print0 | xargs -r -0 rm
- find {{.PROJECT_DIR}}/charts/ -mindepth 1 -type d -name 'charts' -print0 | xargs -r -0 rm -rf
silent: true

3
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
"recommendations": ["editorconfig.editorconfig", "bluebrown.yamlfmt"]
}

24
.vscode/settings.json vendored
View file

@ -1,23 +1,5 @@
{
"prettier.configPath": ".ci/prettier/.prettierrc.yaml",
"prettier.ignorePath": ".ci/prettier/.prettierignore",
"yaml.schemas": {
"https://json.schemastore.org/taskfile.json": [
"Taskfile.yaml",
".taskfiles/*.yaml"
],
"http://json.schemastore.org/github-workflow.json": [
".github/workflows/*.yaml"
],
"https://squidfunk.github.io/mkdocs-material/schema.json": [
"mkdocs.yml"
]
},
"yaml.customTags": [
"!ENV scalar",
"!ENV sequence",
"tag:yaml.org,2002:python/name:material.extensions.emoji.to_svg",
"tag:yaml.org,2002:python/name:material.extensions.emoji.twemoji",
"tag:yaml.org,2002:python/name:pymdownx.superfences.fence_code_format"
]
"[yaml]": {
"editor.defaultFormatter": "bluebrown.yamlfmt"
}
}

13
.yamlfmt.yaml Normal file
View file

@ -0,0 +1,13 @@
---
formatter:
type: basic
disable_alias_key_correction: true
eof_newline: true
force_array_style: block
include_document_start: true
indent: 2
indentless_arrays: false
line_ending: lf
retain_line_breaks_single: true
scan_folded_as_literal: true
trim_trailing_whitespace: true

View file

@ -1,42 +1,18 @@
---
extends: default
rules:
braces:
min-spaces-inside: 0
max-spaces-inside: 0
min-spaces-inside-empty: -1
max-spaces-inside-empty: -1
brackets:
max-spaces-inside: 1
min-spaces-inside: 0
max-spaces-inside: 0
min-spaces-inside-empty: -1
max-spaces-inside-empty: -1
colons:
max-spaces-before: 0
max-spaces-after: 1
commas:
max-spaces-before: 0
min-spaces-after: 1
max-spaces-after: 1
comments:
require-starting-space: true
min-spaces-from-content: 1
document-end: disable
document-start: disable # No --- to start a file
empty-lines:
max: 2
max-start: 0
max-end: 0
hyphens:
max-spaces-after: 1
indentation:
spaces: consistent
indent-sequences: whatever # - list indentation will handle both indentation and without
indent-sequences: consistent
check-multi-line-strings: false
key-duplicates: enable
line-length: disable # Lines can be any length
new-line-at-end-of-file: enable
new-lines:
type: unix
trailing-spaces: enable
truthy:
level: warning
line-length: disable
quoted-strings:
quote-type: double
required: false

View file

@ -29,13 +29,18 @@ See `git help commit`:
1. Remember to sign off your commits as described above
1. Submit a pull request
***NOTE***: In order to make testing and merging of PRs easier, please submit changes to multiple charts in separate PRs.
**_NOTE_**: In order to make testing and merging of PRs easier, please submit changes to multiple charts in separate PRs.
### Setting up a local development environment
I rely on [mise-en-place](https://mise.jdx.dev) to set up my development environment. Once you have installed mise-en-place, you can run the `mise up` command which will then install all the required tools.
To see which tools are installed you can take a look at the [mise configuration](.mise.toml) file.
### Technical Requirements
* Must follow [Charts best practices](https://helm.sh/docs/topics/chart_best_practices/).
* Must pass CI jobs for linting and installing changed charts.
* Any change to a chart requires a version bump following [semver](https://semver.org/) principles. See [Immutability](#immutability) and [Versioning](#versioning) below.
- Must follow [Charts best practices](https://helm.sh/docs/topics/chart_best_practices/).
- Must pass CI jobs for linting and installing changed charts.
- Any change to a chart requires a version bump following [semver](https://semver.org/) principles. See [Immutability](#immutability) and [Versioning](#versioning) below.
Once changes have been merged, the release job will automatically run to package and release changed charts.

View file

@ -45,6 +45,12 @@ If you like this project, please consider supporting my work through my [GitHub
---
### Contributing
If you wish to contribute to this repository, take a look at the [contributing instructions](CONTRIBUTING.md).
---
## How do I find people running these charts?
### Discord

View file

@ -1,4 +1,5 @@
---
# yaml-language-server: $schema=https://taskfile.dev/schema.json
version: "3"
vars:

View file

@ -3,7 +3,7 @@ apiVersion: v2
name: common
description: Function library for Helm charts
type: library
version: 4.1.1
version: 4.1.2
kubeVersion: ">=1.28.0-0"
keywords:
- common
@ -16,9 +16,12 @@ sources:
- https://github.com/bjw-s-labs/helm-charts
annotations:
artifacthub.io/changes: |-
- kind: changed
description: |-
Improved and standardized descriptions for JSONSchema properties.
- kind: fixed
description: |-
Fixed an edge-case bug where specifying a merge defaultPodOptionsStrategy could crash the chart.
Fixed Route validation when relying on automatic Service detection when multiple services are present.
- kind: fixed
description: |-
Fixed Route automatic service detection if there are no rules defined.
Fixed namespace validation when setting non-ServiceAccount subject in RoleBinding.

View file

@ -1,6 +1,6 @@
# common
![Version: 4.1.1](https://img.shields.io/badge/Version-4.1.1-informational?style=flat-square) ![Type: library](https://img.shields.io/badge/Type-library-informational?style=flat-square)
![Version: 4.1.2](https://img.shields.io/badge/Version-4.1.2-informational?style=flat-square) ![Type: library](https://img.shields.io/badge/Type-library-informational?style=flat-square)
Function library for Helm charts
@ -31,7 +31,7 @@ Include this chart as a dependency in your `Chart.yaml` e.g.
# Chart.yaml
dependencies:
- name: common
version: 4.1.1
version: 4.1.2
repository: https://bjw-s-labs.github.io/helm-charts/
```

View file

@ -1,7 +1,7 @@
{
"instance": {
"allOf": [
{ "$ref": "definitions.json#/resourceIdentifier" },
{"$ref": "definitions.json#/resourceIdentifier"},
{
"type": "object",
"additionalProperties": false,
@ -10,10 +10,12 @@
"prefix": {},
"suffix": {},
"enabled": {
"description": "Set to false to disable the ConfigMap.",
"type": "boolean",
"default": true
},
"includeInChecksum": {
"description": "Set to true to include this ConfigMap in the checksum calculation for rolling updates.",
"type": "boolean",
"default": true
},
@ -24,22 +26,21 @@
"$ref": "definitions.json#/labels"
},
"data": {
"description": "ConfigMap data content. Helm templates are supported.",
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"binaryData": {
"description": "ConfigMap binaryData content.",
"type": "object",
"additionalProperties": {
"type": "string"
}
}
},
"oneOf": [
{"required": ["data"]},
{"required": ["binaryData"]}
]
"oneOf": [{"required": ["data"]}, {"required": ["binaryData"]}]
}
]
}

View file

@ -5,85 +5,102 @@
"properties": {
"enabled": {
"description": "Set to false to disable the container.",
"type": "boolean",
"default": true
},
"args": {
"description": "Arguments for the container entrypoint.",
"$ref": "#/args"
},
"command": {
"description": "Command for the container entrypoint.",
"$ref": "#/command"
},
"dependsOn": {
"description": "Specify container dependencies to determine render order.",
"oneOf": [
{
"type": "array",
"items": {"type": "string"}
},
{"type": "array", "items": {"type": "string"}},
{"type": "string"}
]
},
"env": {
"description": "Environment variables for the container.",
"$ref": "#/env"
},
"envFrom": {
"description": "Secrets and/or ConfigMaps to load as environment variables.",
"$ref": "#/envFrom"
},
"image": {
"description": "Image configuration for the container.",
"$ref": "#/image"
},
"lifecycle": {
"description": "Lifecycle event hooks for the container.",
"$ref": "k8s-api.json#/core.v1.Lifecycle"
},
"nameOverride": {
"description": "Override the container name.",
"type": "string"
},
"ports": {
"description": "Ports to expose from the container.",
"type": "array",
"items": {
"$ref": "k8s-api.json#/core.v1.ContainerPort"
}
"items": {"$ref": "k8s-api.json#/core.v1.ContainerPort"}
},
"probes": {
"description": "Probe settings for the container.",
"type": "object",
"additionalProperties": false,
"properties": {
"liveness": {
"description": "Liveness probe configuration.",
"$ref": "#/probe"
},
"readiness": {
"description": "Readiness probe configuration.",
"$ref": "#/probe"
},
"startup": {
"description": "Startup probe configuration.",
"$ref": "#/probe"
}
}
},
"resources": {
"description": "Resource requests and limits for the container.",
"$ref": "k8s-api.json#/core.v1.ResourceRequirements"
},
"restartPolicy": {
"description": "Restart policy for the container.",
"type": "string"
},
"securityContext": {
"description": "Security context for the container.",
"$ref": "k8s-api.json#/core.v1.ContainerSecurityContext"
},
"stdin": {
"description": "Keep the standard input open on the container.",
"type": "boolean",
"default": false
},
"terminationMessagePath": {
"description": "Path for the container's termination message file.",
"type": "string"
},
"terminationMessagePolicy": {
"description": "How the container's termination message should be populated. Supported values: 'File', 'FallbackToLogsOnError'.",
"type": "string",
"enum": ["File", "FallbackToLogsOnError"]
},
"tty": {
"description": "Allocate a TTY for the container.",
"type": "boolean",
"default": false
},
"workingDir": {
"description": "Working directory for the container.",
"type": "string"
}
}

View file

@ -1,7 +1,7 @@
{
"instance": {
"allOf": [
{ "$ref": "definitions.json#/resourceIdentifier" },
{"$ref": "definitions.json#/resourceIdentifier"},
{
"type": "object",
"additionalProperties": false,
@ -10,112 +10,96 @@
"prefix": {},
"suffix": {},
"enabled": {
"description": "Set to false to disable the controller.",
"type": "boolean",
"default": true
},
"type": {
"description": "Controller type. Supported values: deployment, daemonset, statefulset, cronjob, job.",
"type": "string",
"enum": [
"deployment",
"statefulset",
"daemonset",
"cronjob",
"job"
],
"enum": ["deployment", "statefulset", "daemonset", "cronjob", "job"],
"default": "deployment"
},
"annotations": {
"$ref": "definitions.json#/annotations"
},
"labels": {
"$ref": "definitions.json#/labels"
},
"annotations": {"$ref": "definitions.json#/annotations"},
"labels": {"$ref": "definitions.json#/labels"},
"pod": {
"description": "Pod-level options for this controller.",
"$ref": "pod.json#/options"
},
"replicas": {
"type": [
"integer",
"null"
],
"description": "Number of desired pods. Set to null when using a HorizontalPodAutoscaler.",
"type": ["integer", "null"],
"default": 1
},
"revisionHistoryLimit": {
"description": "ReplicaSet revision history limit.",
"type": "integer"
},
"rollingUpdate": {
"description": "Controller upgrade strategy options.",
"type": "object"
},
"strategy": {
"description": "Controller upgrade strategy.",
"type": "string"
},
"cronjob": {
"description": "CronJob-specific options. Required when type is cronjob.",
"$ref": "#/cronjob"
},
"job": {
"description": "Job-specific options. Required when type is job.",
"$ref": "#/job"
},
"statefulset": {
"description": "StatefulSet-specific options. Required when type is statefulset.",
"$ref": "#/statefulset"
},
"applyDefaultContainerOptionsToInitContainers": {
"description": "Apply defaultContainerOptions to initContainers.",
"type": "boolean",
"default": true
},
"defaultContainerOptionsStrategy": {
"description": "Strategy for default container options.\noverwrite: use container-level options if set.\nmerge: merge container-level options with defaults.",
"type": "string",
"default": "overwrite",
"enum": [
"overwrite",
"merge"
]
"enum": ["overwrite", "merge"]
},
"defaultContainerOptions": {
"description": "Default options for all (init)Containers. Each can be overridden on a container level.",
"type": "object",
"additionalProperties": false,
"properties": {
"args": {
"$ref": "containers.json#/args"
},
"command": {
"$ref": "containers.json#/command"
},
"env": {
"$ref": "containers.json#/env"
},
"envFrom": {
"$ref": "containers.json#/envFrom"
},
"image": {
"$ref": "containers.json#/image"
},
"resources": {
"$ref": "k8s-api.json#/core.v1.ResourceRequirements"
},
"securityContext": {
"$ref": "k8s-api.json#/core.v1.ContainerSecurityContext"
}
"args": {"$ref": "containers.json#/args"},
"command": {"$ref": "containers.json#/command"},
"env": {"$ref": "containers.json#/env"},
"envFrom": {"$ref": "containers.json#/envFrom"},
"image": {"$ref": "containers.json#/image"},
"resources": {"$ref": "k8s-api.json#/core.v1.ResourceRequirements"},
"securityContext": {"$ref": "k8s-api.json#/core.v1.ContainerSecurityContext"}
}
},
"initContainers": {
"description": "InitContainers as dictionary items.",
"type": "object",
"additionalProperties": {
"$ref": "containers.json#/container"
}
"additionalProperties": {"$ref": "containers.json#/container"}
},
"containers": {
"description": "Containers as dictionary items.",
"type": "object",
"additionalProperties": {
"$ref": "containers.json#/container"
}
"additionalProperties": {"$ref": "containers.json#/container"}
},
"serviceAccount": {
"description": "ServiceAccount used by the controller.",
"type": "object",
"properties": {
"name": {
"description": "Reference a serviceAccount by its name. Helm templates are supported.",
"type": "string"
},
"identifier": {
"description": "Reference a serviceAccount configured in this chart by its key.",
"type": "string"
}
}
@ -134,24 +118,16 @@
"not": {
"anyOf": [
{
"required": [
"statefulset"
]
"required": ["statefulset"]
},
{
"required": [
"cronjob"
]
"required": ["cronjob"]
},
{
"required": [
"job"
]
"required": ["job"]
},
{
"required": [
"daemonset"
]
"required": ["daemonset"]
}
]
}
@ -164,27 +140,19 @@
"const": "statefulset"
}
},
"required": [
"type"
]
"required": ["type"]
},
"then": {
"not": {
"anyOf": [
{
"required": [
"cronjob"
]
"required": ["cronjob"]
},
{
"required": [
"job"
]
"required": ["job"]
},
{
"required": [
"daemonset"
]
"required": ["daemonset"]
}
]
}
@ -197,9 +165,7 @@
"const": "cronjob"
}
},
"required": [
"type"
]
"required": ["type"]
},
"then": {
"allOf": [
@ -207,27 +173,19 @@
"not": {
"anyOf": [
{
"required": [
"statefulset"
]
"required": ["statefulset"]
},
{
"required": [
"job"
]
"required": ["job"]
},
{
"required": [
"daemonset"
]
"required": ["daemonset"]
}
]
}
},
{
"required": [
"cronjob"
]
"required": ["cronjob"]
}
]
}
@ -239,27 +197,19 @@
"const": "job"
}
},
"required": [
"type"
]
"required": ["type"]
},
"then": {
"not": {
"anyOf": [
{
"required": [
"statefulset"
]
"required": ["statefulset"]
},
{
"required": [
"cronjob"
]
"required": ["cronjob"]
},
{
"required": [
"daemonset"
]
"required": ["daemonset"]
}
]
}
@ -283,18 +233,12 @@
"properties": {
"whenDeleted": {
"type": "string",
"enum": [
"Delete",
"Retain"
],
"enum": ["Delete", "Retain"],
"default": "Retain"
},
"whenScaled": {
"type": "string",
"enum": [
"Delete",
"Retain"
],
"enum": ["Delete", "Retain"],
"default": "Retain"
}
}
@ -366,10 +310,7 @@
"type": "string"
}
},
"required": [
"name",
"size"
]
"required": ["name", "size"]
},
"cronjob": {
@ -416,9 +357,7 @@
"type": "integer"
}
},
"required": [
"schedule"
]
"required": ["schedule"]
},
"job": {

View file

@ -3,38 +3,36 @@
"type": "object",
"properties": {
"forceRename": {
"type": "string",
"description": "Override the default resource name. This field is mutually exclusive with the prefix and suffix fields."
"description": "Override the default resource name. Mutually exclusive with prefix and suffix.",
"type": "string"
},
"prefix": {
"description": "Prefix to prepend to the resource name. Mutually exclusive with forceRename.",
"type": "string",
"description": "Prefix to prepend to the resource name. This field is mutually exclusive with the forceRename field.",
"default": ""
},
"suffix": {
"type": "string",
"description": "Suffix to append to the resource name. Defaults to the resource identifier if there are multiple items, otherwise it defaults to empty. This field is mutually exclusive with the forceRename field."
"description": "Suffix to append to the resource name. Defaults to the resource identifier if there are multiple items, otherwise empty. Mutually exclusive with forceRename.",
"type": "string"
}
},
"not" : {
"anyOf" : [
{"required" : ["forceRename", "suffix"]},
{"required" : ["forceRename", "prefix"]}
"not": {
"anyOf": [
{"required": ["forceRename", "suffix"]},
{"required": ["forceRename", "prefix"]}
]
}
},
"annotations": {
"description": "Annotations to set on the item.",
"type": ["object", "null"],
"additionalProperties": {
"type": ["string", "null"]
}
"additionalProperties": {"type": ["string", "null"]}
},
"labels": {
"description": "Labels to set on the item.",
"type": ["object", "null"],
"additionalProperties": {
"type": ["string", "null"]
}
"additionalProperties": {"type": ["string", "null"]}
}
}

View file

@ -1,29 +1,40 @@
{
"envVarName": {
"description": "Environment variable name.",
"type": "string"
},
"envVarValue": {
"description": "Environment variable value.",
"type": ["string", "number", "boolean", "null"]
},
"envVarListItem": {
"description": "Environment variable as a name/value pair.",
"type": "object",
"additionalProperties": false,
"properties": {
"name": {"type": "string"},
"name": {"$ref": "#/envVarName"},
"value": {"$ref": "#/envVarValue"}
},
"required": ["name", "value"]
},
"envVarItem": {
"description": "Define an environment variable value as a dictionary item with optional dependencies.",
"type": "object",
"additionalProperties": false,
"properties": {
"value": {"$ref": "#/envVarValue"},
"dependsOn": {"$ref": "#/envVarDependsOn"}
"dependsOn": {
"$ref": "#/envVarDependsOn"
}
},
"required": ["value"]
},
"valueFromListItem": {
"description": "Define an environment variable using valueFrom syntax.",
"oneOf": [
{"$ref": "#/valueFromListItemExplicit"},
{"$ref": "#/valueFromListItemImplicit"}
@ -31,20 +42,22 @@
},
"valueFromListItemExplicit": {
"description": "Explicit valueFrom environment variable.",
"type": "object",
"additionalProperties": false,
"properties": {
"name": {"type": "string"},
"name": {"$ref": "#/envVarName"},
"valueFrom": {"$ref": "#/valueFromOptions"}
},
"required": ["name", "valueFrom"]
},
"valueFromListItemImplicit": {
"description": "Implicit valueFrom environment variable.",
"type": "object",
"additionalProperties": false,
"properties": {
"name": {"type": "string"},
"name": {"$ref": "#/envVarName"},
"fieldRef": {"$ref": "#/fieldRefSelector"},
"resourceFieldRef": {"$ref": "#/resourceFieldRefSelector"},
"secretKeyRef": {"$ref": "#/objectKeySelector"},
@ -87,10 +100,12 @@
"oneOf": [
{"$ref": "#/valueFromItemExplicit"},
{"$ref": "#/valueFromItemImplicit"}
]
],
"description": "Define an environment variable using valueFrom syntax (map style)."
},
"valueFromItemExplicit": {
"description": "Explicit valueFrom environment variable.",
"type": "object",
"additionalProperties": false,
"properties": {
@ -101,6 +116,7 @@
},
"valueFromItemImplicit": {
"description": "Implicit valueFrom environment variable.",
"type": "object",
"additionalProperties": false,
"properties": {
@ -144,6 +160,7 @@
"valueFromOptions": {
"type": "object",
"description": "Set the valueFrom options for the environment variable.",
"oneOf": [
{"$ref": "#/fieldRef"},
{"$ref": "#/resourceFieldRef"},
@ -153,6 +170,7 @@
},
"secretKeyRef": {
"description": "Reference a key from a Secret using secretKeyRef syntax.",
"type": "object",
"additionalProperties": false,
"properties": {
@ -162,6 +180,7 @@
},
"configMapKeyRef": {
"description": "Reference a key from a ConfigMap using configMapKeyRef syntax.",
"type": "object",
"additionalProperties": false,
"properties": {
@ -171,6 +190,7 @@
},
"fieldRef": {
"description": "Reference a field from the pod spec using fieldRef syntax.",
"type": "object",
"additionalProperties": false,
"properties": {
@ -180,13 +200,16 @@
},
"fieldRefSelector": {
"description": "Selector for a fieldRef.",
"type": "object",
"additionalProperties": false,
"properties": {
"apiVersion": {
"description": "Set the API version for the fieldRef.",
"type": "string"
},
"fieldPath": {
"description": "Set the field path for the fieldRef.",
"type": "string"
}
},
@ -194,6 +217,7 @@
},
"resourceFieldRef": {
"description": "Reference a resource field from the pod spec using resourceFieldRef syntax.",
"type": "object",
"additionalProperties": false,
"properties": {
@ -203,16 +227,20 @@
},
"resourceFieldRefSelector": {
"description": "Selector for a resourceFieldRef.",
"type": "object",
"additionalProperties": false,
"properties": {
"containerName": {
"description": "Set the container name for the resource field reference.",
"type": "string"
},
"divisor": {
"description": "Set the divisor for the resource field reference.",
"oneOf": [{"type": "string"}, {"type": "number"}]
},
"resource": {
"description": "Set the resource name for the resource field reference.",
"type": "string"
}
},
@ -220,6 +248,7 @@
},
"envVarDependsOn": {
"description": "Specify other environment variables that the environment variable depends on.",
"oneOf": [
{"type": "string"},
{
@ -230,13 +259,16 @@
},
"objectKeySelector": {
"description": "Selector for a key in a Secret or ConfigMap.",
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"description": "Set the name of the Secret or ConfigMap.",
"type": "string"
},
"key": {
"description": "Set the key within the Secret or ConfigMap.",
"type": "string"
}
},

View file

@ -1,7 +1,7 @@
{
"instance": {
"allOf": [
{ "$ref": "definitions.json#/resourceIdentifier" },
{"$ref": "definitions.json#/resourceIdentifier"},
{
"type": "object",
"additionalProperties": false,
@ -10,32 +10,29 @@
"prefix": {},
"suffix": {},
"enabled": {
"description": "Set to false to disable the Ingress.",
"type": "boolean",
"default": true
},
"annotations": {
"$ref": "definitions.json#/annotations"
},
"annotations": {"$ref": "definitions.json#/annotations"},
"labels": {"$ref": "definitions.json#/labels"},
"className": {
"description": "Set the ingressClass used for this Ingress.",
"type": "string"
},
"defaultBackend": {
"description": "Set the defaultBackend for this Ingress. This disables any other rules.",
"$ref": "k8s-api.json#/networking.v1.ingressBackend"
},
"hosts": {
"description": "Configure the hosts for the Ingress.",
"type": "array",
"items": {
"$ref": "#/hostEntry"
}
},
"labels": {
"$ref": "definitions.json#/labels"
"items": {"$ref": "#/hostEntry"}
},
"tls": {
"description": "Configure TLS for the Ingress.",
"type": "array",
"items": {
"$ref": "#/tlsEntry"
}
"items": {"$ref": "#/tlsEntry"}
}
}
}
@ -46,20 +43,18 @@
"additionalProperties": false,
"properties": {
"host": {
"description": "Set the host address. Helm templates are supported.",
"type": "string"
},
"paths": {
"description": "Configure the paths for the host.",
"type": "array",
"title": "paths",
"items": {
"additionalProperties": false,
"properties": {
"path": {
"type": "string"
},
"pathType": {
"type": "string",
"default": "Prefix"
},
"path": {"type": "string"},
"pathType": {"type": "string", "default": "Prefix"},
"service": {
"oneOf": [
{"$ref": "#/serviceReferenceByName"},
@ -68,9 +63,7 @@
}
},
"required": ["path"]
},
"title": "paths",
"type": "array"
}
}
},
"required": ["host", "paths"]
@ -80,12 +73,12 @@
"additionalProperties": false,
"properties": {
"hosts": {
"description": "Set the hosts for the TLS entry. Helm templates are supported.",
"type": "array",
"items": {
"type": ["string"]
}
"items": {"type": ["string"]}
},
"secretName": {
"description": "Set the secretName for the TLS entry. Helm templates are supported.",
"type": "string"
}
},
@ -96,12 +89,8 @@
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
},
"port": {
"type": ["integer"]
}
"name": {"type": "string"},
"port": {"type": ["integer"]}
},
"required": ["name", "port"]
},
@ -110,12 +99,8 @@
"type": "object",
"additionalProperties": false,
"properties": {
"identifier": {
"type": "string"
},
"port": {
"type": ["string", "integer"]
}
"identifier": {"type": "string"},
"port": {"type": ["string", "integer"]}
}
}
}

View file

@ -1,7 +1,7 @@
{
"instance": {
"allOf": [
{ "$ref": "definitions.json#/resourceIdentifier" },
{"$ref": "definitions.json#/resourceIdentifier"},
{
"type": "object",
"additionalProperties": false,
@ -11,26 +11,26 @@
"prefix": {},
"suffix": {},
"enabled": {
"description": "Set to false to disable the NetworkPolicy.",
"type": "boolean",
"default": true
},
"annotations": {
"$ref": "definitions.json#/annotations"
},
"annotations": {"$ref": "definitions.json#/annotations"},
"controller": {
"description": "Controller this NetworkPolicy should target.",
"type": "string"
},
"labels": {
"$ref": "definitions.json#/labels"
"labels": {"$ref": "definitions.json#/labels"},
"podSelector": {
"description": "Custom podSelector for the NetworkPolicy. Takes precedence over targeting a controller."
},
"podSelector": {},
"policyTypes": {
"description": "Policy types for the NetworkPolicy.",
"type": "array",
"items": {
"type": "string"
}
"items": {"type": "string"}
},
"rules": {
"description": "Ingress and egress rules for the NetworkPolicy.",
"type": "object",
"additionalProperties": false,

View file

@ -14,7 +14,7 @@
"persistentVolumeClaimItem": {
"allOf": [
{ "$ref": "definitions.json#/resourceIdentifier" },
{"$ref": "definitions.json#/resourceIdentifier"},
{
"type": "object",
"additionalProperties": false,
@ -28,37 +28,50 @@
"suffix": {},
"enabled": {
"type": "boolean",
"default": true
"default": true,
"description": "Set to false to disable the persistence item."
},
"accessMode": {
"type": "string"
"type": "string",
"description": "AccessMode for the persistent volume. Make sure to select an access mode that is supported by your storage provider!\nSee https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes"
},
"annotations": {
"$ref": "definitions.json#/annotations"
},
"dataSource": {
"$ref": "#/dataSourceReference"
"$ref": "#/dataSourceReference",
"description": "The optional data source for the persistentVolumeClaim.\nSee https://kubernetes.io/docs/concepts/storage/persistent-volumes/#volume-populators-and-data-sources"
},
"dataSourceRef": {
"$ref": "#/dataSourceReference"
"$ref": "#/dataSourceReference",
"description": "The optional volume populator for the persistentVolumeClaim.\nSee https://kubernetes.io/docs/concepts/storage/persistent-volumes/#volume-populators-and-data-sources"
},
"labels": {
"$ref": "definitions.json#/labels"
},
"retain": {
"type": "boolean"
"type": "boolean",
"description": "Set to true to retain the PVC upon helm uninstall."
},
"size": {
"type": "string"
"type": "string",
"description": "The amount of storage that is requested for the persistent volume."
},
"storageClass": {
"type": "string"
"type": "string",
"description": "Storage Class for the config volume.\nIf set to '-', dynamic provisioning is disabled.\nIf set to something else, the given storageClass is used.\nIf undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner."
},
"volumeName": {
"type": "string"
},
"advancedMounts": {"$ref": "#/advancedMounts"},
"globalMounts": {"$ref": "#/globalMounts"}
"advancedMounts": {
"$ref": "#/advancedMounts",
"description": "Explicitly configure mounts for specific controllers and containers.\nSee https://bjw-s-labs.github.io/helm-charts/docs/common-library/storage/globalOptions/#advancedmounts"
},
"globalMounts": {
"$ref": "#/globalMounts",
"description": "Configure mounts to all controllers and containers.\nBy default the persistence item will be mounted to /<name_of_the_peristence_item>.\nSee https://bjw-s-labs.github.io/helm-charts/docs/common-library/storage/globalOptions/#globalmounts"
}
},
"required": ["accessMode", "size"]
}

View file

@ -5,55 +5,67 @@
"properties": {
"affinity": {
"type": "object",
"$ref": "k8s-api.json#/core.v1.Affinity"
"$ref": "k8s-api.json#/core.v1.Affinity",
"description": "Set affinity constraint rules. Helm templates can be used.\nSee https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity"
},
"annotations": {
"$ref": "definitions.json#/annotations"
},
"automountServiceAccountToken": {
"type": "boolean",
"default": true
"default": true,
"description": "Set to true to automatically mount the service account token."
},
"dnsConfig": {
"type": "object",
"$ref": "k8s-api.json#/core.v1.PodDNSConfig"
"$ref": "k8s-api.json#/core.v1.PodDNSConfig",
"description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy."
},
"dnsPolicy": {
"type": "string"
"type": "string",
"description": "Configure the Pod DNS policy. Defaults to 'ClusterFirst' if hostNetwork is false and 'ClusterFirstWithHostNet' if hostNetwork is true."
},
"enableServiceLinks": {
"type": "boolean",
"default": false
"default": false,
"description": "Enable/disable the generation of environment variables for services.\nSee https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/#accessing-the-service"
},
"hostAliases": {
"type": "array",
"items": {
"$ref": "k8s-api.json#/core.v1.HostAlias"
}
},
"description": "Use hostAliases to add custom entries to /etc/hosts - mapping IP addresses to hostnames.\nSee https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/"
},
"hostIPC": {
"type": "boolean",
"default": false
"default": false,
"description": "Set to true to use the host's ipc namespace."
},
"hostNetwork": {
"type": "boolean",
"default": false
"default": false,
"description": "Set to false to disable host networking on the Pod. When using hostNetwork, make sure you set dnsPolicy to 'ClusterFirstWithHostNet'"
},
"hostPID": {
"type": "boolean",
"default": false
"default": false,
"description": "Set to true to use the host's pid namespace."
},
"hostUsers": {
"type": ["boolean", "null"]
"type": ["boolean", "null"],
"description": "Set to false to create a new userns for the Pod. (Requires Kubernetes 1.29 or newer)"
},
"hostname": {
"type": "string"
"type": "string",
"description": "Set the Pod's hostname."
},
"imagePullSecrets": {
"type": "array",
"items": {
"$ref": "k8s-api.json#/core.v1.LocalObjectReference"
}
},
"description": "Set image pull secrets."
},
"labels": {
"$ref": "definitions.json#/annotations"
@ -62,44 +74,55 @@
"type": "object",
"additionalProperties": {
"type": ["string"]
}
},
"description": "Node selection constraint.\nSee https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector"
},
"priorityClassName": {
"type": "string"
"type": "string",
"description": "Custom priority class for different treatment by the scheduler."
},
"resources": {
"$ref": "k8s-api.json#/core.v1.ResourceRequirements"
"$ref": "k8s-api.json#/core.v1.ResourceRequirements",
"description": "Set the resource requests / limits for the Pod. (Requires Kubernetes 1.32 or newer)"
},
"restartPolicy": {
"type": "string"
"type": "string",
"description": "Set container restart policy. Defaults to 'Always'. When controller.type is 'cronjob' it defaults to 'Never'."
},
"runtimeClassName": {
"type": "string"
"type": "string",
"description": "Set a runtimeClassName other than the default one (ie: `nvidia`)."
},
"schedulerName": {
"type": "string"
"type": "string",
"description": "Set a custom scheduler name."
},
"securityContext": {
"$ref": "k8s-api.json#/core.v1.PodSecurityContext"
"$ref": "k8s-api.json#/core.v1.PodSecurityContext",
"description": "Configure the Security Context for the Pod."
},
"shareProcessNamespace": {
"type": ["boolean", "null"],
"default": false
"default": false,
"description": "Allows sharing process namespace between containers in a Pod.\nSee https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/"
},
"terminationGracePeriodSeconds": {
"type": ["integer", "null"]
"type": ["integer", "null"],
"description": "Duration in seconds the pod needs to terminate gracefully.\nSee https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#lifecycle"
},
"tolerations": {
"type": "array",
"items": {
"$ref": "k8s-api.json#/core.v1.Toleration"
}
},
"description": "Specify taint tolerations.\nSee https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/"
},
"topologySpreadConstraints": {
"type": "array",
"items": {
"$ref": "k8s-api.json#/core.v1.TopologySpreadConstraint"
}
},
"description": "Defines topologySpreadConstraint rules.\nSee https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/"
}
}
}

View file

@ -1,7 +1,7 @@
{
"instance": {
"allOf": [
{ "$ref": "definitions.json#/resourceIdentifier" },
{"$ref": "definitions.json#/resourceIdentifier"},
{
"type": "object",
"additionalProperties": false,
@ -10,22 +10,23 @@
"prefix": {},
"suffix": {},
"enabled": {
"description": "Set to false to disable the resource.",
"type": "boolean",
"default": true
},
"apiVersion": {
"description": "apiVersion of the resource.",
"type": "string"
},
"kind": {
"description": "Kind of the resource.",
"type": "string"
},
"annotations": {
"$ref": "definitions.json#/annotations"
},
"labels": {
"$ref": "definitions.json#/labels"
},
"spec": {}
"annotations": {"$ref": "definitions.json#/annotations"},
"labels": {"$ref": "definitions.json#/labels"},
"spec": {
"description": "Contents of the raw resource to be rendered."
}
},
"required": ["apiVersion", "kind", "spec"]
}

View file

@ -1,7 +1,7 @@
{
"role": {
"allOf": [
{ "$ref": "definitions.json#/resourceIdentifier" },
{"$ref": "definitions.json#/resourceIdentifier"},
{
"type": "object",
"additionalProperties": false,
@ -11,15 +11,14 @@
"suffix": {},
"enabled": {
"type": "boolean",
"default": true
"default": true,
"description": "Set to false to disable the Role or ClusterRole."
},
"type": {
"type": "string",
"enum": [
"Role",
"ClusterRole"
],
"default": "Role"
"enum": ["Role", "ClusterRole"],
"default": "Role",
"description": "Set the type of RBAC resource. Supported values: Role, ClusterRole."
},
"annotations": {
"$ref": "definitions.json#/annotations"
@ -28,7 +27,8 @@
"$ref": "definitions.json#/labels"
},
"rules": {
"type": "array"
"type": "array",
"description": "Set the rules for the Role or ClusterRole."
}
},
"required": ["type", "rules"]
@ -38,7 +38,7 @@
"roleBinding": {
"allOf": [
{ "$ref": "definitions.json#/resourceIdentifier" },
{"$ref": "definitions.json#/resourceIdentifier"},
{
"type": "object",
"additionalProperties": false,
@ -48,15 +48,14 @@
"suffix": {},
"enabled": {
"type": "boolean",
"default": true
"default": true,
"description": "Set to false to disable the RoleBinding or ClusterRoleBinding."
},
"type": {
"type": "string",
"enum": [
"RoleBinding",
"ClusterRoleBinding"
],
"default": "RoleBinding"
"enum": ["RoleBinding", "ClusterRoleBinding"],
"default": "RoleBinding",
"description": "Set the type of RBAC binding. Supported values: RoleBinding, ClusterRoleBinding."
},
"annotations": {
"$ref": "definitions.json#/annotations"
@ -66,19 +65,20 @@
},
"roleRef": {
"type": "object",
"description": "Reference the Role or ClusterRole to bind to.",
"properties": {
"identifier": {
"type": "string"
"type": "string",
"description": "Reference an Role or ClusterRole configured in this chart by its key."
},
"name": {
"type": "string"
"type": "string",
"description": "Reference a Role or ClusterRole by its name. Helm template enabled."
},
"kind": {
"type": "string",
"enum": [
"Role",
"ClusterRole"
]
"description": "The kind of the referenced object. Supported values: Role, ClusterRole.",
"enum": ["Role", "ClusterRole"]
}
},
"oneOf": [
@ -88,25 +88,30 @@
},
"subjects": {
"type": "array",
"description": "Set the subjects for the RoleBinding or ClusterRoleBinding.",
"items": {
"type": "object",
"properties": {
"identifier": {
"type": "string"
"type": "string",
"description": "Reference a serviceAccount configured in this chart by its key."
},
"name": {
"type": "string"
"type": "string",
"description": "Reference an subject by its name."
},
"kind": {
"type": "string"
"type": "string",
"description": "The kind of the referenced subject. Supported values: ServiceAccount, User, Group."
},
"namespace": {
"type": "string"
"type": "string",
"description": "The namespace of the referenced subject. Do not define if kind is User or Group."
}
},
"oneOf": [
{"required": ["identifier"]},
{"required": ["name", "kind", "namespace"]}
{"required": ["name", "kind"]}
]
}
}

View file

@ -1,7 +1,7 @@
{
"instance": {
"allOf": [
{ "$ref": "definitions.json#/resourceIdentifier" },
{"$ref": "definitions.json#/resourceIdentifier"},
{
"type": "object",
"additionalProperties": false,
@ -10,95 +10,77 @@
"prefix": {},
"suffix": {},
"enabled": {
"description": "Set to false to disable the Route.",
"type": "boolean",
"default": true
},
"annotations": {
"$ref": "definitions.json#/annotations"
},
"labels": {
"$ref": "definitions.json#/labels"
},
"annotations": {"$ref": "definitions.json#/annotations"},
"labels": {"$ref": "definitions.json#/labels"},
"hostnames": {
"description": "Host addresses for the Route. Helm templates are supported.",
"type": "array",
"items": {"type": "string"}
},
"kind": {
"description": "Route kind. Supported values: GRPCRoute, HTTPRoute, TCPRoute, TLSRoute, UDPRoute.",
"type": "string",
"enum": ["GRPCRoute", "HTTPRoute", "TCPRoute", "TLSRoute", "UDPRoute"]
"enum": [
"GRPCRoute",
"HTTPRoute",
"TCPRoute",
"TLSRoute",
"UDPRoute"
]
},
"parentRefs": {
"description": "Resource the Route attaches to.",
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"group": {
"type": "string"
},
"kind": {
"type": "string"
},
"namespace": {
"type": "string"
},
"name": {
"type": "string"
},
"sectionName": {
"type": "string"
},
"port": {
"type": "integer"
}
"group": {"type": "string"},
"kind": {"type": "string"},
"namespace": {"type": "string"},
"name": {"type": "string"},
"sectionName": {"type": "string"},
"port": {"type": "integer"}
},
"required": ["name"]
}
},
"rules": {
"description": "Rules for routing. Defaults to the primary service.",
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"backendRefs": {
"description": "Backend references.",
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"group": {
"type": "string"
},
"kind": {
"type": "string"
},
"namespace": {
"type": "string"
},
"group": {"type": "string"},
"kind": {"type": "string"},
"namespace": {"type": "string"},
"name": {
"type": "string",
"description": "A reference to a backend Service name."
"description": "Reference to a backend Service name.",
"type": "string"
},
"identifier": {
"type": "string",
"description": "A reference to a service identifier that is defined within the chart values."
"description": "Reference to a service identifier defined within the chart values.",
"type": "string"
},
"port": {
"type": ["string", "integer"]
},
"weight": {
"type": "integer"
}
"port": {"type": ["string", "integer"]},
"weight": {"type": "integer"}
}
}
},
"matches": {
"description": "Match rules.",
"type": "array",
"items": {
"type": "object",
@ -108,26 +90,24 @@
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "string"
},
"value": {
"type": "string"
}
"type": {"type": "string"},
"value": {"type": "string"}
}
}
}
}
},
"filters": {
"description": "Filters for the route.",
"type": "array",
"items": {}
},
"sessionPersistence": {
"description": "SessionPersistence defines the desired state of SessionPersistence",
"description": "SessionPersistence defines the desired state of SessionPersistence.",
"type": "object"
},
"timeouts": {
"description": "Timeouts for the route.",
"type": "object"
}
}

View file

@ -1,7 +1,7 @@
{
"instance": {
"allOf": [
{ "$ref": "definitions.json#/resourceIdentifier" },
{"$ref": "definitions.json#/resourceIdentifier"},
{
"type": "object",
"additionalProperties": false,
@ -10,27 +10,25 @@
"prefix": {},
"suffix": {},
"enabled": {
"description": "Set to false to disable the Secret.",
"type": "boolean",
"default": true
},
"includeInChecksum": {
"description": "Set to true to include this Secret in the checksum calculation for rolling updates.",
"type": "boolean",
"default": true
},
"annotations": {
"$ref": "definitions.json#/annotations"
},
"labels": {
"$ref": "definitions.json#/labels"
},
"annotations": {"$ref": "definitions.json#/annotations"},
"labels": {"$ref": "definitions.json#/labels"},
"type": {
"description": "Secret type.",
"type": "string"
},
"stringData": {
"description": "Secret stringData content. Helm templates are supported.",
"type": "object",
"additionalProperties": {
"type": "string"
}
"additionalProperties": {"type": "string"}
}
},
"required": ["stringData"]

View file

@ -1,7 +1,7 @@
{
"instance": {
"allOf": [
{ "$ref": "definitions.json#/resourceIdentifier" },
{"$ref": "definitions.json#/resourceIdentifier"},
{
"type": "object",
"additionalProperties": false,
@ -10,84 +10,67 @@
"prefix": {},
"suffix": {},
"enabled": {
"description": "Set to false to disable the Service.",
"type": "boolean",
"default": true
},
"annotations": {
"$ref": "definitions.json#/annotations"
},
"labels": {
"$ref": "definitions.json#/labels"
},
"annotations": {"$ref": "definitions.json#/annotations"},
"labels": {"$ref": "definitions.json#/labels"},
"type": {
"type": "string"
},
"clusterIP": {
"type": "string"
},
"externalName": {
"type": "string"
},
"loadBalancerIP": {
"type": "string"
"description": "Service type. Supported values: ClusterIP, NodePort, LoadBalancer, ExternalName.",
"type": "string",
"enum": ["ClusterIP", "NodePort", "LoadBalancer", "ExternalName"]
},
"clusterIP": {"type": "string"},
"externalName": {"type": "string"},
"loadBalancerIP": {"type": "string"},
"loadBalancerSourceRanges": {
"type": "array",
"items": {"type": "string"}
},
"loadBalancerClass": {
"type": "string"
},
"loadBalancerClass": {"type": "string"},
"internalTrafficPolicy": {
"description": "internalTrafficPolicy for the Service. Supported values: Cluster, Local.\nSee https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/",
"type": "string",
"enum": ["Cluster", "Local"]
},
"externalTrafficPolicy": {
"description": "externalTrafficPolicy for the Service. Supported values: Cluster, Local.\nSee https://kubernetes.io/docs/tutorials/services/source-ip/",
"type": "string",
"enum": ["Cluster", "Local"]
},
"allocateLoadBalancerNodePorts": {
"type": "boolean"
},
"sessionAffinity": {
"type": "string",
"enum": ["None", "ClientIP"]
},
"sessionAffinityConfig": {
"type": "object"
},
"externalIPs": {
"type": "array",
"items": {"type": "string"}
},
"publishNotReadyAddresses": {
"type": "boolean"
},
"allocateLoadBalancerNodePorts": {"type": "boolean"},
"sessionAffinity": {"type": "string", "enum": ["None", "ClientIP"]},
"sessionAffinityConfig": {"type": "object"},
"externalIPs": {"type": "array", "items": {"type": "string"}},
"publishNotReadyAddresses": {"type": "boolean"},
"ipFamilyPolicy": {
"description": "ipFamilyPolicy for the Service. Supported values: SingleStack, PreferDualStack, RequireDualStack.",
"type": "string",
"enum": ["SingleStack", "PreferDualStack", "RequireDualStack"]
},
"ipFamilies": {
"description": "IP families for the Service. Supported values: IPv4, IPv6.",
"type": "array",
"items": {
"type": "string",
"enum": ["IPv4", "IPv6"]
}
"items": {"type": "string", "enum": ["IPv4", "IPv6"]}
},
"ports": {
"type": "object",
"additionalProperties": {
"$ref": "#/servicePort"
}
"controller": {
"description": "Controller this Service should target.",
"type": "string"
},
"primary": {
"description": "Set to true to make this the primary Service for the controller (used in probes, notes, etc). Only one Service can be marked as primary.",
"type": "boolean",
"default": false
},
"controller": {
"type": "string"
"extraSelectorLabels": {
"description": "Additional match labels for the Service selector."
},
"extraSelectorLabels": {}
"ports": {
"description": "Service port(s) configuration.",
"type": "object",
"additionalProperties": {"$ref": "#/servicePort"}
}
},
"required": []
}
@ -99,27 +82,34 @@
"additionalProperties": false,
"properties": {
"enabled": {
"description": "Set to false to disable the port.",
"type": "boolean",
"default": true
},
"primary": {
"description": "Set to true to make this the primary port (used in probes, notes, etc).\nOnly one port can be marked as primary.",
"type": "boolean",
"default": false
},
"port": {
"description": "Port name / number.",
"type": ["string", "integer"]
},
"protocol": {
"description": "Port protocol. Supported values: HTTP, HTTPS, TCP, UDP.\nHTTP and HTTPS spawn a TCP service and are used for internal URL and name generation.",
"type": "string",
"enum": ["HTTP", "HTTPS", "TCP", "UDP"]
},
"targetPort": {
"description": "Set the targetPort if you want the Service port to differ from the application port. If set, this value is used in the container definition instead of 'port'.\nNamed ports are not supported for this field.",
"type": ["string", "integer"]
},
"nodePort": {
"description": "nodePort value for LoadBalancer and NodePort Service types.\nSee https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport",
"type": ["string", "integer"]
},
"appProtocol": {
"description": "appProtocol value for the port.\nSee https://kubernetes.io/docs/concepts/services-networking/service/#application-protocol",
"type": "string"
}
},

View file

@ -1,7 +1,7 @@
{
"instance": {
"allOf": [
{ "$ref": "definitions.json#/resourceIdentifier" },
{"$ref": "definitions.json#/resourceIdentifier"},
{
"type": "object",
"additionalProperties": false,
@ -10,16 +10,14 @@
"prefix": {},
"suffix": {},
"enabled": {
"description": "Set to false to disable the ServiceAccount.",
"type": "boolean",
"default": true
},
"annotations": {
"$ref": "definitions.json#/annotations"
},
"labels": {
"$ref": "definitions.json#/labels"
},
"annotations": {"$ref": "definitions.json#/annotations"},
"labels": {"$ref": "definitions.json#/labels"},
"staticToken": {
"description": "Set to true to create a long-lived static token for the ServiceAccount.",
"type": "boolean",
"default": false
}

View file

@ -10,22 +10,16 @@
"prefix": {},
"suffix": {},
"enabled": {
"description": "Whether this ServiceMonitor is enabled or not.",
"description": "Set to false to disable the ServiceMonitor.",
"type": "boolean",
"default": true
},
"annotations": {
"$ref": "definitions.json#/annotations"
},
"labels": {
"$ref": "definitions.json#/labels"
},
"annotations": {"$ref": "definitions.json#/annotations"},
"labels": {"$ref": "definitions.json#/labels"},
"endpoints": {
"description": "A list of endpoints allowed as part of this ServiceMonitor.",
"description": "Endpoints allowed as part of this ServiceMonitor.",
"type": "array",
"items": {
"type": "object"
}
"items": {"type": "object"}
},
"selector": {
"description": "Selector to select Endpoints objects.",
@ -35,9 +29,7 @@
"matchLabels": {
"description": "matchLabels is a map of {key,value} pairs. The requirements are ANDed.",
"type": "object",
"additionalProperties": {
"type": "string"
}
"additionalProperties": {"type": "string"}
},
"matchExpressions": {
"description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.",
@ -58,39 +50,35 @@
}
},
"service": {
"description": "Which service to monitor. Either 'serviceName' or 'service' must be specified.",
"description": "Service to monitor. Either 'serviceName' or 'service' must be specified.",
"oneOf": [
{
"description": "A reference to a Service name. Helm templates can be used.",
"description": "Reference to a Service name. Helm templates are supported.",
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
}
"name": {"type": "string"}
},
"required": ["name"]
},
{
"description": "A reference to a service identifier that is defined within the chart values.",
"description": "Reference to a service identifier defined within the chart values.",
"type": "object",
"additionalProperties": false,
"properties": {
"identifier": {
"type": "string"
}
"identifier": {"type": "string"}
},
"required": ["identifier"]
}
]
},
"serviceName": {
"description": "A reference to a Service name to monitor. Helm templates can be used. Deprecated in favor of 'service'.",
"description": "Reference to a Service name to monitor. Helm templates are supported. Deprecated in favor of 'service'.",
"type": "string",
"deprecated": true
},
"targetLabels": {
"description": "TargetLabels transfers labels from the Kubernetes Service onto the created metrics.",
"description": "Transfers labels from the Kubernetes Service onto the created metrics.",
"type": "array"
}
},

View file

@ -25,7 +25,16 @@ This template serves as a blueprint for generating RoleBinding objects in Kubern
{{- $_ := set $subject "kind" "ServiceAccount" -}}
{{- $_ := set $subject "namespace" $rootContext.Release.Namespace -}}
{{- $subjects = mustAppend $subjects $subject -}}
{{- else if eq .kind "Group" -}}
{{- $subject := dict "name" .name "kind" .kind -}}
{{- $subjects = mustAppend $subjects $subject -}}
{{- else if eq .kind "User" -}}
{{- $subject := dict "name" .name "kind" .kind -}}
{{- $subjects = mustAppend $subjects $subject -}}
{{- else -}}
{{- if not .namespace }}
{{- fail (printf "No namespace provided for subject '%s'. Please provide a namespace." $roleBindingObject.name) -}}
{{- end -}}
{{- $subject := dict "name" .name "kind" .kind "namespace" .namespace -}}
{{- $subjects = mustAppend $subjects $subject -}}
{{- end -}}

View file

@ -0,0 +1,32 @@
{{/*
Validate RoleBinding values
*/}}
{{- define "bjw-s.common.lib.rbac.rolebinding.validate" -}}
{{- $rootContext := .rootContext -}}
{{- $roleBindingValues := .object -}}
{{- $rules := $roleBindingValues.rules -}}
{{/* Verify permutations for RoleBinding subjects */}}
{{- if and (not (empty $roleBindingValues.subjects)) (not (empty $roleBindingValues.roleRef)) -}}
{{- $subjectTypes := list "User" "Group" "ServiceAccount" -}}
{{- $subjectTypeCount := 0 -}}
{{- range $roleBindingValues.subjects -}}
{{- if hasKey . "kind" -}}
{{- if dict $subjectTypes has .kind -}}
{{- $subjectTypeCount = add $subjectTypeCount 1 -}}
{{- else -}}
{{- fail (printf "Invalid subject kind '%s' in RoleBinding '%s'. Valid kinds are: %s" .kind $roleBindingValues.identifier (join ", " $subjectTypes)) -}}
{{- end -}}
{{- else -}}
{{- fail (printf "Subject kind is required in RoleBinding '%s'" $roleBindingValues.identifier) -}}
{{- end -}}
{{- end -}}
{{- if eq $subjectTypeCount 0 -}}
{{- fail (printf "At least one subject with a valid kind is required in RoleBinding '%s'" $roleBindingValues.identifier) -}}
{{- end -}}
{{- else -}}
{{- fail (printf "subjects and roleRef are required for RoleBinding with key \"%v\"" $roleBindingValues.identifier) -}}
{{- end -}}
{{- end -}}

View file

@ -9,6 +9,10 @@ Validate Route values
{{/* Verify automatic Service detection */}}
{{- if not (eq 1 (len $enabledServices)) -}}
{{- if empty $routeObject.rules -}}
{{- fail (printf "An explicit rule is required because automatic Service detection is not possible. (route: %s)" $routeObject.identifier) -}}
{{- end -}}
{{- range $routeObject.rules -}}
{{- $rule := . -}}
{{- range $rule.backendRefs }}
@ -27,7 +31,6 @@ Validate Route values
{{- end }}
{{/* Route Rules */}}
{{- range $routeObject.rules }}
{{- if and (.filters) (.backendRefs) }}
{{- range .filters }}

View file

@ -5,9 +5,9 @@ name: common-test
version: 1.0.0
kubeVersion: ">=1.28.0-0"
maintainers:
- name: bjw-s
email: me@bjw-s.dev
- name: bjw-s
email: me@bjw-s.dev
dependencies:
- name: common
repository: file://../
version: ">0.0.0-0"
- name: common
repository: file://../
version: ">0.0.0-0"

View file

@ -23,8 +23,8 @@ controllers:
a-container:
dependsOn:
- main
- third-container
- main
- third-container
image:
repository: ghcr.io/mendhak/http-https-echo
tag: 31
@ -60,15 +60,15 @@ service:
ingress:
main:
hosts:
- host: "test.local"
paths:
- path: /
service:
identifier: main
port: http
- host: "test.local"
paths:
- path: /
service:
identifier: main
port: http
tls:
- hosts:
- "test.local"
- hosts:
- "test.local"
configMaps:
config:
@ -80,19 +80,24 @@ persistence:
type: configMap
identifier: config
advancedMounts:
main: # the controller with the "main" identifier
main: # the container with the "main" identifier
- path: /data/config.yaml
readOnly: false
subPath: config.yaml
second-container: # the container with the "second-container" identifier
- path: /appdata/config
readOnly: true
second-controller: # the controller with the "second-controller" identifier
main: # the container with the "main" identifier
- path: /data/config.yaml
readOnly: false
subPath: config.yaml
main:
# the controller with the "main" identifier
main:
# the container with the "main" identifier
- path: /data/config.yaml
readOnly: false
subPath: config.yaml
second-container:
# the container with the "second-container" identifier
- path: /appdata/config
readOnly: true
second-controller:
# the controller with the "second-controller" identifier
main:
# the container with the "main" identifier
- path: /data/config.yaml
readOnly: false
subPath: config.yaml
rawResources:
unsupportedPDB:

View file

@ -20,12 +20,12 @@ controllers:
ingress:
main:
hosts:
- host: "test.local"
paths:
- path: /
- host: "test.local"
paths:
- path: /
tls:
- hosts:
- "test.local"
- hosts:
- "test.local"
service:
main:

View file

@ -36,23 +36,23 @@ ingress:
# -- Enable and configure ingress settings for the chart under this key.
main:
hosts:
- host: chart-example.local
paths:
- path: /
pathType: Prefix
service:
name: main
port: http
- path: /notifications/hub/negotiate
pathType: Prefix
service:
name: main
port: http
- path: /notifications/hub
pathType: Prefix
service:
name: main
port: websocket
- host: chart-example.local
paths:
- path: /
pathType: Prefix
service:
name: main
port: http
- path: /notifications/hub/negotiate
pathType: Prefix
service:
name: main
port: http
- path: /notifications/hub
pathType: Prefix
service:
name: main
port: websocket
# -- Configure persistence settings for the chart under this key.
persistence:
@ -61,4 +61,4 @@ persistence:
accessMode: ReadWriteOnce
size: 1Gi
globalMounts:
- path: /config
- path: /config

View file

@ -6,9 +6,9 @@ rbac:
defaultRole:
type: Role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
- apiGroups: [ "" ]
resources: [ "pods" ]
verbs: [ "get", "list" ]
bindings:
defaultBinding:
@ -16,4 +16,4 @@ rbac:
roleRef:
identifier: defaultRole
subjects:
- identifier: default
- identifier: default

View file

@ -1,9 +1,10 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json
suite: rbac - presence
templates:
- common.yaml
tests:
- it: role and rolebinding can be configured are not created by default
- it: role and rolebinding are not created by default
asserts:
- not: true
containsDocument:
@ -25,7 +26,9 @@ tests:
value: release-name
equal:
path: rules[0].verbs
value: ["get", "list"]
value:
- "get"
- "list"
- documentSelector:
path: $[?(@.kind == "RoleBinding")].metadata.name
value: release-name
@ -60,13 +63,22 @@ tests:
rbac.roles.customRole:
type: ClusterRole
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get", "list", "watch"]
- apiGroups:
- "*"
resources:
- "*"
verbs:
- "get"
- "list"
- "watch"
asserts:
- documentSelector:
path: $[?(@.kind == "ClusterRole")].metadata.name
value: release-name-customrole
equal:
path: rules[0].verbs
value: ["get", "list", "watch"]
- containsDocument:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
any: true
name: release-name-defaultrole
- containsDocument:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
any: true
name: release-name-customrole

View file

@ -0,0 +1,26 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json
suite: rbac - role tests
templates:
- common.yaml
values:
- ../_values/rbac_values.yaml
tests:
- it: Role should be namespaced
documentSelector:
path: $[?(@.kind == "Role")].metadata.name
value: release-name
asserts:
- exists:
path: metadata.namespace
- it: ClusterRole should not be namespaced
set:
rbac.roles.defaultRole:
type: ClusterRole
documentSelector:
path: $[?(@.kind == "ClusterRole")].metadata.name
value: release-name
asserts:
- notExists:
path: metadata.namespace

View file

@ -0,0 +1,84 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json
suite: rbac - rolebinding tests
templates:
- common.yaml
set:
rbac:
bindings:
defaultBinding:
enabled: true
type: RoleBinding
roleRef:
name: defaultBinding
kind: Role
subjects:
- kind: Group
name: oidc:/default-group
- kind: User
name: default-username
- kind: ServiceAccount
name: default
namespace: default
tests:
- it: RoleBinding should be namespaced
documentSelector:
path: $[?(@.kind == "RoleBinding")].metadata.name
value: release-name
asserts:
- exists:
path: metadata.namespace
- it: ClusterRoleBinding should not be namespaced
set:
rbac.bindings.defaultBinding:
type: ClusterRoleBinding
documentSelector:
path: $[?(@.kind == "ClusterRoleBinding")].metadata.name
value: release-name
asserts:
- notExists:
path: metadata.namespace
- it: subject must be a valid group
documentSelector:
path: $[?(@.kind == "RoleBinding")].metadata.name
value: release-name
asserts:
- equal:
path: subjects[0].kind
value: Group
- equal:
path: subjects[0].name
value: oidc:/default-group
- notExists:
path: subjects[0].namespace
- it: subject must be a valid user
documentSelector:
path: $[?(@.kind == "RoleBinding")].metadata.name
value: release-name
asserts:
- equal:
path: subjects[1].kind
value: User
- equal:
path: subjects[1].name
value: default-username
- notExists:
path: subjects[0].namespace
- it: subject must be a valid user
documentSelector:
path: $[?(@.kind == "RoleBinding")].metadata.name
value: release-name
asserts:
- equal:
path: subjects[2].kind
value: ServiceAccount
- equal:
path: subjects[2].name
value: default
- equal:
path: subjects[2].namespace
value: default

View file

@ -5,6 +5,7 @@ templates:
- common.yaml
values:
- ../_values/controllers_main_default_container.yaml
- ../_values/service_main_default.yaml
tests:
- it: hostnames shouldn't be used for TCPRoutes and UDPRoutes
set:

View file

@ -5,6 +5,7 @@ templates:
- common.yaml
values:
- ../_values/controllers_main_default_container.yaml
- ../_values/service_main_default.yaml
tests:
- it: setting gateway should pass
set:

View file

@ -5,6 +5,7 @@ templates:
- common.yaml
values:
- ../_values/controllers_main_default_container.yaml
- ../_values/service_main_default.yaml
set:
route.main.parentRefs:
- name: test

View file

@ -5,6 +5,7 @@ templates:
- common.yaml
values:
- ../_values/controllers_main_default_container.yaml
- ../_values/service_main_default.yaml
set:
route.main.parentRefs:
- name: test

View file

@ -5,6 +5,7 @@ templates:
- common.yaml
values:
- ../_values/controllers_main_default_container.yaml
- ../_values/service_main_default.yaml
set:
route.main:
parentRefs:

View file

@ -5,6 +5,7 @@ templates:
- common.yaml
values:
- ../_values/controllers_main_default_container.yaml
- ../_values/service_main_default.yaml
tests:
- it: an HTTPRoute is not created by default
asserts:

View file

@ -78,3 +78,24 @@ tests:
asserts:
- failedTemplate:
errorMessage: "Either name or identifier is required because automatic Service detection is not possible. (route: main)"
- it: automatic service and port reference should fail with absent rules field and when >1 service is enabled
set:
service:
main:
controller: main
ports:
ui:
port: 8082
second:
controller: main
ports:
ui:
port: 8082
route.main:
parentRefs:
- name: parentName
namespace: parentNamespace
asserts:
- failedTemplate:
errorMessage: "An explicit rule is required because automatic Service detection is not possible. (route: main)"

View file

@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://raw.githubusercontent.com/bjw-s-labs/helm-charts/common-4.1.1/charts/library/common/values.schema.json",
"$id": "https://raw.githubusercontent.com/bjw-s-labs/helm-charts/common-4.1.2/charts/library/common/values.schema.json",
"type": "object",
"properties": {
"global": {
@ -8,14 +8,14 @@
"type": "object",
"properties": {
"nameOverride": {
"description": "Override the chart name",
"description": "Set the chart name",
"type": [
"string",
"null"
]
},
"fullnameOverride": {
"description": "Override the chart fullname definition",
"description": "Set the chart fullname definition",
"type": [
"string",
"null"
@ -27,7 +27,7 @@
"default": false
},
"propagateGlobalMetadataToPods": {
"description": "Propagate global metadata to Pod labels",
"description": "Set to true to propagate global metadata to Pod labels.",
"type": "boolean",
"default": false
},
@ -44,7 +44,7 @@
}
},
"defaultPodOptionsStrategy": {
"description": "Set the strategy for the default pod options.\noverwrite: If pod-level options are set, use those instead of the defaults.\nmerge: If pod-level options are set, merge them with the defaults.",
"description": "Set the strategy for the default pod options. Defaults to overwrite.\noverwrite: If pod-level options are set, use those instead of the defaults.\nmerge: If pod-level options are set, merge them with the defaults.",
"type": "string",
"default": "overwrite",
"enum": [
@ -53,7 +53,7 @@
]
},
"defaultPodOptions": {
"description": "Define defaults for pod-level configuration options",
"description": "Set default options for all controllers / pods here. Each of these options can be overridden on a controller level.",
"type": "object",
"$ref": "schemas/pod.json#/options"
},

View file

@ -866,3 +866,7 @@ rbac:
# - kind: ServiceAccount
# name: test
# namespace: "{{ .Release.Namespace }}"
# - kind: Group
# name: oidc:/test-user
# - kind: User
# name: username