https://github.com/idsulik/helm-cel
A Helm plugin that uses Common Expression Language (CEL) to validate values. Instead of using JSON Schema in values.schema.json, you can write more expressive validation rules using CEL in values.cel.yaml.
https://github.com/idsulik/helm-cel
golang helm helm-plugin kubernetes
Last synced: about 1 year ago
JSON representation
A Helm plugin that uses Common Expression Language (CEL) to validate values. Instead of using JSON Schema in values.schema.json, you can write more expressive validation rules using CEL in values.cel.yaml.
- Host: GitHub
- URL: https://github.com/idsulik/helm-cel
- Owner: idsulik
- License: mit
- Created: 2024-11-15T09:31:12.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-12-08T06:19:11.000Z (over 1 year ago)
- Last Synced: 2025-04-02T19:08:06.297Z (about 1 year ago)
- Topics: golang, helm, helm-plugin, kubernetes
- Language: Go
- Homepage: https://pkg.go.dev/github.com/idsulik/helm-cel
- Size: 69.3 KB
- Stars: 81
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://github.com/idsulik/helm-cel/blob/main/LICENSE)
[](https://github.com/idsulik/helm-cel/releases/latest)
[](https://github.com/idsulik/helm-cel/stargazers)
[](https://github.com/idsulik/helm-cel/issues)
[](https://github.com/idsulik/helm-cel/pulls)
[](https://codecov.io/gh/idsulik/helm-cel)
[](https://artifacthub.io/packages/helm-plugin/cel/cel)
# Helm CEL Plugin
A Helm plugin that uses Common Expression Language (CEL) to validate values. Instead of using JSON Schema in `values.schema.json`, you can write more expressive validation rules using CEL in `values.cel.yaml`.
## Installation
### Using Helm Plugin Manager
```bash
helm plugin install https://github.com/idsulik/helm-cel
```
### Using Docker
```bash
# Pull the image
docker pull idsulik/helm-cel:latest # main branch
docker pull idsulik/helm-cel:2.1.2 # specific version
# Run validation
docker run --rm -v $(pwd):/charts idsulik/helm-cel validate /charts/mychart
# Generate validation rules
docker run --rm -v $(pwd):/charts idsulik/helm-cel generate /charts/mychart
```
### Building from Source
```bash
git clone https://github.com/idsulik/helm-cel
cd helm-cel
make install
```
## Usage
### Validation
Validate your chart values using the validate command:
```bash
helm cel validate ./mychart
```
Options:
```bash
--values-file, -v Values files to validate (comma-separated or multiple flags)
Defaults to values.yaml
--rules-file, -r Rules files to validate against (comma-separated or multiple flags)
Defaults to values.cel.yaml
--output, -o Output format: text, json, or yaml
Defaults to text
```
Example with custom files:
```bash
# Using single values and rules files
helm cel validate ./mychart --values-file prod.values.yaml --rules-file prod.cel.yaml
# Using JSON output format
helm cel validate ./mychart -o json
# Using multiple values files (later files take precedence)
helm cel validate ./mychart --values-file common.yaml --values-file prod.yaml
# Using comma-separated values files
helm cel validate ./mychart --values-file common.yaml,prod.yaml,overrides.yaml
# Using multiple rules files
helm cel validate ./mychart --rules-file global.cel.yaml --rules-file ingress.cel.yaml
# Combining multiple values and rules files
helm cel validate ./mychart \
--values-file common.yaml,prod.yaml \
--rules-file global.cel.yaml,ingress.cel.yaml,deployment.cel.yaml
```
### Generating Rules
You can automatically generate validation rules based on your values file structure:
```bash
helm cel generate ./mychart
```
Options:
```bash
--force, -f Force overwrite existing rules file
--values-file, -v Values file to generate rules from (defaults to values.yaml)
--output-file, -o Output file for generated rules (defaults to values.cel.yaml)
```
Example with custom files:
```bash
helm cel generate ./mychart --values-file prod.values.yaml --output-file prod.cel.yaml --force
```
## Rule Organization
You can organize your validation rules into multiple files for better maintainability. Files must have the `.cel.yaml` extension. Example structure:
```
mychart/
├── Chart.yaml
├── values.yaml
└── cel/
├── global.cel.yaml # Global configuration rules
├── ingress.cel.yaml # Ingress-specific rules
└── deployment.cel.yaml # Deployment-specific rules
```
When using multiple rule files, expressions are shared across all files but must be unique (no duplicate expression names allowed).
## Rule Structure
Each rule in `values.cel.yaml` consists of:
- `expr`: A CEL expression that should evaluate to `true` for valid values
- `desc`: A description of what the rule validates
- `severity`: Optional severity level ("error" or "warning", defaults to "error")
Example `values.cel.yaml`:
```yaml
rules:
- expr: "has(values.service) && has(values.service.port)"
desc: "service port is required"
- expr: "values.service.port >= 1 && values.service.port <= 65535"
desc: "service port must be between 1 and 65535"
severity: warning
- expr: "!(has(values.replicaCount)) || values.replicaCount >= 1"
desc: "if replicaCount is set, it must be at least 1"
```
### Severity Levels
Rules can have two severity levels:
- `error`: Validation fails if the rule is not satisfied (default)
- `warning`: Shows a warning but allows validation to pass
### Common Validation Patterns
1. Required fields:
```yaml
- expr: "has(values.fieldName)"
desc: "fieldName is required"
```
2. Value constraints:
```yaml
- expr: "values.number >= 0 && values.number <= 100"
desc: "number must be between 0 and 100"
```
3. Type validation:
```yaml
- expr: "type(values.ports) == list"
desc: "ports must be a list"
```
4. Resource validation:
```yaml
- expr: 'values.resources.requests.memory.matches("^[0-9]+(Mi|Gi)$")'
desc: "memory requests must be in Mi or Gi"
```
5. Port validation:
```yaml
- expr: "values.service.port >= 1 && values.service.port <= 65535"
desc: "port must be valid"
```
### Reusable Expressions
You can define expressions to reuse across rules:
```yaml
expressions:
portRange: 'values.service.port >= 1 && values.service.port <= 65535'
nodePortRange: 'values.service.nodePort >= 30000 && values.service.nodePort <= 32767'
rules:
- expr: "${portRange}"
desc: "Service port must be valid"
- expr: 'values.service.type == "NodePort" ? ${nodePortRange} : true'
desc: "NodePort must be valid when type is NodePort"
```
### Validation Results
If validation fails, you'll get a clear error message:
```
❌ Validation failed: replica count must be at least 1
Rule: values.replicaCount >= 1
Path: replicaCount
Current value: 0
```
With warnings:
```
Found 1 warning(s):
⚠️ Service port must be between 1 and 65535
Rule: values.service.port >= 1 && values.service.port <= 65535
Path: service.port
Current value: 80801
-------------------------------------------------
⚠️✅ Values validation successful with warnings!
```
If all rules pass, you'll see a success message:
```
✅ Values validation successful!
```
### Structured Output Formats
You can output validation results in JSON or YAML format for integration with CI/CD pipelines:
```bash
# JSON output
helm cel validate ./mychart -o json
# YAML output
helm cel validate ./mychart -o yaml
```
JSON output example:
```json
{
"has_errors": true,
"has_warnings": true,
"result": {
"errors": [
{
"description": "replicaCount must be at least 1",
"expression": "values.replicaCount >= 1",
"value": 0,
"path": "replicaCount"
}
],
"warnings": [
{
"description": "service port should be between 1 and 65535",
"expression": "values.service.port >= 1 && values.service.port <= 65535",
"value": 80801,
"path": "service.port"
}
]
}
}
```
YAML output example:
```yaml
has_errors: true
has_warnings: true
result:
errors:
- description: replicaCount must be at least 1
expression: values.replicaCount >= 1
value: 0
path: replicaCount
warnings:
- description: service port should be between 1 and 65535
expression: values.service.port >= 1 && values.service.port <= 65535
value: 80801
path: service.port
```
## Development
Requirements:
- Go 1.22 or later
Build:
```bash
make build
```
Install locally:
```bash
make install
```
Run tests:
```bash
make test
```
## Contributing
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## License
Distributed under the MIT License. See `LICENSE` for more information.