A Python library for rendering Helm charts and Kubernetes resources with optional ArgoCD Application generation. Features an abstract Template base class for consistent template management.
Project description
Kubeman
A Python library for rendering Helm charts and Kubernetes resources with optional ArgoCD Application generation. Features an abstract Template base class for consistent template management.
Features
- Abstract
Templatebase class for all template types HelmChartclass for defining Helm chartsKubernetesResourceclass for raw Kubernetes resources (no Helm required)TemplateRegistryfor managing multiple templates (charts and resources)- Command-line interface (CLI) for rendering and applying manifests
- Automatic Docker image build and load steps (executed sequentially during template registration)
- Git operations for manifest repository management
- Docker image build and push utilities with custom Dockerfile support
- Optional ArgoCD Application manifest generation (opt-in)
Installation
From Source
Using uv (recommended):
uv pip install -e .
Or using pip:
pip install -e .
Development Setup
Install development dependencies and format code:
uv sync --dev
uv tool run black .
Pre-commit Hooks
Install pre-commit globally:
uv tool install pre-commit
pre-commit install
This automatically formats code with black before commits. Run manually:
pre-commit run --all-files
Alternative: Install as dev dependency:
uv sync --dev
uv run python -m pre_commit install
Usage
Template Architecture
Both HelmChart and KubernetesResource inherit from the abstract Template base class, providing common functionality for ArgoCD Application generation (opt-in), manifest directory management, namespace/name properties, rendering to filesystem, and optional Docker image build steps executed sequentially during template registration.
Creating a Helm Chart
Subclass HelmChart and implement the required abstract methods:
from kubeman import HelmChart, TemplateRegistry
@TemplateRegistry.register
class MyChart(HelmChart):
@property
def name(self) -> str:
return "my-chart"
@property
def repository(self) -> dict:
"""Return repository information"""
return {
"type": "classic", # or "oci" or "none"
"remote": "https://charts.example.com"
}
@property
def namespace(self) -> str:
return "my-namespace"
@property
def version(self) -> str:
return "1.0.0"
def generate_values(self) -> dict:
"""Generate values.yaml content"""
return {
"replicaCount": 3,
"image": {
"repository": "my-app",
"tag": "latest"
}
}
Creating a Kubernetes Resource (Without Helm)
For projects that don't need Helm but want optional ArgoCD Application generation and manifest management, use KubernetesResource. Supports two patterns:
Pattern 1: Using Helper Methods (Recommended)
Use built-in helper methods to build Kubernetes resources:
from kubeman import KubernetesResource, TemplateRegistry
@TemplateRegistry.register
class DogBreedsDbChart(KubernetesResource):
"""Dog Breeds PostgreSQL database resources."""
def __init__(self):
super().__init__()
self.namespace = "dog-breeds"
# Add Namespace
self.add_namespace(
name="dog-breeds",
labels={"app": "dog-breeds", "component": "database"},
)
# Add ConfigMap for database configuration
self.add_configmap(
name="dog-breeds-db-config",
namespace="dog-breeds",
data={
"POSTGRES_DB": "dog_breeds_db",
"POSTGRES_USER": "airflow",
},
labels={"app": "dog-breeds", "component": "database"},
)
# Add Secret for database password
self.add_secret(
name="dog-breeds-db-secret",
namespace="dog-breeds",
string_data={
"POSTGRES_PASSWORD": "airflow",
},
labels={"app": "dog-breeds", "component": "database"},
)
# Add PersistentVolumeClaim
self.add_persistent_volume_claim(
name="dog-breeds-db-pvc",
namespace="dog-breeds",
access_modes=["ReadWriteOnce"],
storage="5Gi",
labels={"app": "dog-breeds", "component": "database"},
)
# Add Deployment
self.add_deployment(
name="dog-breeds-db",
namespace="dog-breeds",
replicas=1,
strategy_type="Recreate",
labels={"app": "dog-breeds", "component": "database"},
containers=[
{
"name": "postgres",
"image": "postgres:16-alpine",
"ports": [{"name": "postgres", "containerPort": 5432}],
"env": [
{
"name": "POSTGRES_PASSWORD",
"valueFrom": {
"secretKeyRef": {
"name": "dog-breeds-db-secret",
"key": "POSTGRES_PASSWORD",
},
},
},
],
"volumeMounts": [
{"name": "postgres-storage", "mountPath": "/var/lib/postgresql/data"},
],
}
],
volumes=[
{"name": "postgres-storage", "persistentVolumeClaim": {"claimName": "dog-breeds-db-pvc"}},
],
init_containers=[
{
"name": "init-db",
"image": "busybox:latest",
"command": ["sh", "-c", "echo Initializing database schema"],
}
],
)
# Add Service
self.add_service(
name="dog-breeds-db",
namespace="dog-breeds",
service_type="ClusterIP",
selector={"app": "dog-breeds", "component": "database"},
ports=[{"name": "postgres", "port": 5432, "targetPort": 5432}],
labels={"app": "dog-breeds", "component": "database"},
)
Available Helper Methods: add_namespace(), add_configmap(), add_secret(), add_persistent_volume_claim(), add_deployment(), add_statefulset(), add_service(), add_ingress(), add_service_account(), add_role(), add_role_binding(), add_cluster_role(), add_cluster_role_binding(), add_custom_resource()
Pattern 2: Override manifests() Method
For complex logic or custom manifest generation, override the manifests() method:
from kubeman import KubernetesResource, TemplateRegistry
@TemplateRegistry.register
class MyAppResources(KubernetesResource):
def __init__(self):
super().__init__()
self.namespace = "production"
def manifests(self) -> list[dict]:
"""Return list of Kubernetes manifests"""
return [
{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"name": "my-app-config",
"namespace": "production"
},
"data": {
"DATABASE_URL": "postgres://db:5432/myapp",
}
},
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": "my-app",
"namespace": "production"
},
"spec": {
"replicas": 3,
"selector": {"matchLabels": {"app": "my-app"}},
"template": {
"metadata": {"labels": {"app": "my-app"}},
"spec": {
"containers": [{
"name": "my-app",
"image": "gcr.io/my-project/my-app:v1.0.0",
"envFrom": [{
"configMapRef": {"name": "my-app-config"}
}]
}]
}
}
}
}
]
Build and Load Steps
Templates can define Docker image build and load steps that execute automatically when templates are imported. Steps run sequentially in registration order: build steps first, then load steps.
Build Steps
Override the build() method to add build steps:
from kubeman import KubernetesResource, TemplateRegistry, DockerManager
@TemplateRegistry.register
class MyApp(KubernetesResource):
def __init__(self):
super().__init__()
self.name = "my-app"
self.namespace = "production"
def build(self) -> None:
"""Build Docker images for this template."""
docker = DockerManager()
docker.build_image(
component="my-app",
context_path="./app",
tag="latest",
dockerfile="Dockerfile.prod" # Optional: custom Dockerfile name
)
# Tag with local name for kind clusters
docker.tag_image(
source_image=f"{docker.registry}/my-app",
target_image="my-app",
source_tag="latest"
)
Load Steps
For local development with kind clusters, add load steps:
def load(self) -> None:
"""Load Docker images into kind cluster."""
docker = DockerManager()
docker.kind_load_image("my-app", tag="latest")
Key points: Build steps execute automatically when templates are imported. Load steps execute after build steps. Use --skip-build flag to skip build/load steps during render/apply. If a build or load fails, template registration fails with a clear error message.
Rendering Charts and Resources
Render templates using the CLI or Python API.
Using the CLI (Recommended)
# Render all templates from a Python file
kubeman render --file kubeman.py
# Render without executing build steps
kubeman render --file kubeman.py --skip-build
# Render and apply to Kubernetes cluster (builds execute automatically)
kubeman apply --file kubeman.py
# Apply without executing build steps
kubeman apply --file kubeman.py --skip-build
The CLI imports your template file (containing @TemplateRegistry.register decorated classes), discovers all registered templates, renders each to the manifests/ directory, and for apply, runs kubectl apply on the rendered manifests.
Example template file (kubeman.py):
from kubeman import KubernetesResource, TemplateRegistry
@TemplateRegistry.register
class MyAppResources(KubernetesResource):
def __init__(self):
super().__init__()
self.namespace = "production"
# ... add resources using helper methods ...
Using the Python API
from kubeman import TemplateRegistry
# Get all registered templates (charts and resources)
templates = TemplateRegistry.get_registered_templates()
# Render each template
for template_class in templates:
template = template_class()
template.render() # Generates manifests and ArgoCD Application
For HelmChart: Renders to manifests/{chart-name}/{chart-name}-manifests.yaml, writes extra manifests to manifests/{chart-name}/, and generates ArgoCD Application to manifests/apps/{chart-name}-application.yaml (if enabled).
For KubernetesResource: Writes each manifest to manifests/{name}/{manifest-name}-{kind}.yaml and generates ArgoCD Application to manifests/apps/{name}-application.yaml (if enabled).
Advanced Chart Configuration
Custom Repository Package Name
@property
def repository_package(self) -> str:
return "different-package-name"
OCI Registry Support
@property
def repository(self) -> dict:
return {
"type": "oci",
"remote": "oci://registry.example.com/charts"
}
Extra Manifests
def extra_manifests(self) -> list[dict]:
return [
{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {"name": "my-config"},
"data": {"key": "value"}
}
]
Enabling ArgoCD Application Generation (Opt-In)
ArgoCD Application generation is disabled by default. Enable via environment variable:
export ARGOCD_APP_REPO_URL="https://github.com/org/manifests-repo"
Or override enable_argocd() method:
@TemplateRegistry.register
class MyChart(HelmChart):
def enable_argocd(self) -> bool:
"""Enable ArgoCD Application generation for this chart"""
return True
If ARGOCD_APP_REPO_URL is not set and enable_argocd() returns True, override application_repo_url() to provide the repository URL.
Custom ArgoCD Application Settings
def enable_argocd(self) -> bool:
"""Enable ArgoCD Application generation (opt-in)"""
return True
def application_repo_url(self) -> str:
"""Override the repository URL for ArgoCD applications"""
return "https://github.com/org/manifests-repo"
def application_target_revision(self) -> str:
"""Override the target revision (defaults to current branch)"""
return "main"
def managed_namespace_metadata(self) -> dict:
"""Add labels to managed namespaces"""
return {
"app.kubernetes.io/managed-by": "argocd"
}
def argo_ignore_spec(self) -> list:
"""Configure ArgoCD ignore differences"""
return [
{
"group": "apps",
"kind": "Deployment",
"jsonPointers": ["/spec/replicas"]
}
]
Git Operations
The GitManager class provides utilities for working with Git repositories:
from kubeman import GitManager
git = GitManager()
# Get current commit hash (from STABLE_GIT_COMMIT env var)
commit_hash = git.fetch_commit_hash()
# Get current branch name (from STABLE_GIT_BRANCH env var)
branch_name = git.fetch_branch_name()
# Push rendered manifests to a repository
git.push_manifests(repo_url="https://github.com/org/manifests-repo")
The push_manifests() method clones the manifests repository, checks out or creates the branch matching STABLE_GIT_BRANCH, copies rendered manifests from RENDERED_MANIFEST_DIR, and commits and pushes the changes.
Docker Operations
The DockerManager class helps build and push Docker images:
from kubeman import DockerManager
# Initialize with project ID (or set DOCKER_PROJECT_ID env var)
docker = DockerManager(
project_id="my-project",
repository_name="my-repo" # Optional, defaults to "default"
)
# Build an image
image_name = docker.build_image(
component="frontend",
context_path="./frontend",
tag="v1.0.0"
)
# Build with custom Dockerfile name
image_name = docker.build_image(
component="frontend",
context_path="./frontend",
tag="v1.0.0",
dockerfile="Dockerfile.prod" # Optional: defaults to "Dockerfile"
)
# Tag an image (useful for creating local tags from registry images)
docker.tag_image(
source_image=f"{docker.registry}/frontend",
target_image="frontend",
source_tag="v1.0.0",
target_tag="latest" # Optional: defaults to source_tag
)
# Load image into kind cluster (for local development)
docker.kind_load_image(
image_name="frontend",
tag="latest",
cluster_name="my-cluster" # Optional: auto-detected from kubectl context
)
# Push an image
docker.push_image(component="frontend", tag="v1.0.0")
# Build and push in one step
image_name = docker.build_and_push(
component="backend",
context_path="./backend",
tag="latest",
dockerfile="Dockerfile" # Optional: custom Dockerfile name
)
Environment Variables
Required for Git Operations
STABLE_GIT_COMMIT- Current git commit hashSTABLE_GIT_BRANCH- Current git branch nameRENDERED_MANIFEST_DIR- Path to directory containing rendered manifestsMANIFEST_REPO_URL- Git repository URL for pushing manifests (optional if passed topush_manifests())
Optional for ArgoCD Applications
ArgoCD Application generation is opt-in and disabled by default. To enable:
ARGOCD_APP_REPO_URL- Repository URL for ArgoCD applications (or overrideapplication_repo_url()). Required if ArgoCD is enabled.ARGOCD_APPS_SUBDIR- Subdirectory for applications (defaults to "apps")
You can also enable ArgoCD by overriding the enable_argocd() method in your template class to return True.
Required for Docker Operations
DOCKER_PROJECT_ID- Registry project ID (or pass toDockerManagerconstructor)DOCKER_REGION- Registry region (defaults to "us-central1")DOCKER_REPOSITORY_NAME- Docker repository name (defaults to "default")GITHUB_REPOSITORY- GitHub repository name (optional)
Complete Example
Complete example using both HelmChart and KubernetesResource:
from kubeman import HelmChart, KubernetesResource, TemplateRegistry, GitManager, DockerManager
# Define a Helm chart for a third-party application
@TemplateRegistry.register
class PostgresChart(HelmChart):
@property
def name(self) -> str:
return "postgres"
@property
def repository(self) -> dict:
return {
"type": "classic",
"remote": "https://charts.bitnami.com/bitnami"
}
@property
def namespace(self) -> str:
return "database"
@property
def version(self) -> str:
return "12.5.0"
def generate_values(self) -> dict:
return {
"auth": {
"postgresPassword": "changeme"
},
"persistence": {
"enabled": True,
"size": "10Gi"
}
}
def enable_argocd(self) -> bool:
"""Enable ArgoCD Application generation (opt-in)"""
return True
# Define custom Kubernetes resources for your application
@TemplateRegistry.register
class MyAppResources(KubernetesResource):
@property
def name(self) -> str:
return "my-app"
@property
def namespace(self) -> str:
return "production"
def manifests(self) -> list[dict]:
return [
{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {"name": "my-app-config", "namespace": "production"},
"data": {"DATABASE_HOST": "postgres.database.svc.cluster.local"}
},
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {"name": "my-app", "namespace": "production"},
"spec": {
"replicas": 3,
"selector": {"matchLabels": {"app": "my-app"}},
"template": {
"metadata": {"labels": {"app": "my-app"}},
"spec": {
"containers": [{
"name": "my-app",
"image": "gcr.io/my-project/my-app:v1.0.0",
"envFrom": [{"configMapRef": {"name": "my-app-config"}}]
}]
}
}
}
}
]
# Option 1: Use CLI to render and apply
# Build steps execute automatically when templates are imported
# kubeman render --file kubeman.py
# kubeman apply --file kubeman.py
# Option 2: Skip build steps if images are already built
# kubeman render --file kubeman.py --skip-build
# kubeman apply --file kubeman.py --skip-build
# Option 3: Render programmatically
for template_class in TemplateRegistry.get_registered_templates():
template = template_class()
template.render()
# Push manifests to repository
git = GitManager()
git.push_manifests()
Publishing
This package is automatically published to PyPI via GitHub Actions when:
- A new release is published on GitHub
- Manual trigger via the GitHub Actions workflow
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kubeman-0.5.3.tar.gz.
File metadata
- Download URL: kubeman-0.5.3.tar.gz
- Upload date:
- Size: 34.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
979648c5ca4c80c75f77f0fcbcb95161ca6bdfb180d51e825af84964558c90cc
|
|
| MD5 |
3d42fac87cf9407f35fd288a333a17db
|
|
| BLAKE2b-256 |
fb36734cfc25f5deca427119ef386d642087dd4bc348899340c712453f2816d0
|
Provenance
The following attestation bundles were made for kubeman-0.5.3.tar.gz:
Publisher:
publish.yml on jasonzh0/kubeman
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kubeman-0.5.3.tar.gz -
Subject digest:
979648c5ca4c80c75f77f0fcbcb95161ca6bdfb180d51e825af84964558c90cc - Sigstore transparency entry: 719560475
- Sigstore integration time:
-
Permalink:
jasonzh0/kubeman@1351d9d762dd9194f2780c1598b43cb92ec1ece4 -
Branch / Tag:
refs/tags/v0.5.3 - Owner: https://github.com/jasonzh0
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1351d9d762dd9194f2780c1598b43cb92ec1ece4 -
Trigger Event:
release
-
Statement type:
File details
Details for the file kubeman-0.5.3-py3-none-any.whl.
File metadata
- Download URL: kubeman-0.5.3-py3-none-any.whl
- Upload date:
- Size: 38.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f3a9d8c4275292f83f3d80fc8a5a90c88ad28ac0583881f19f4f627dc615a311
|
|
| MD5 |
d0d34480b4eb11e3d49f884aaf463eee
|
|
| BLAKE2b-256 |
d514a221ca495c05b2390c675977a4a14e068946c4c6a3ee9d5bfbca6e3b7989
|
Provenance
The following attestation bundles were made for kubeman-0.5.3-py3-none-any.whl:
Publisher:
publish.yml on jasonzh0/kubeman
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kubeman-0.5.3-py3-none-any.whl -
Subject digest:
f3a9d8c4275292f83f3d80fc8a5a90c88ad28ac0583881f19f4f627dc615a311 - Sigstore transparency entry: 719560478
- Sigstore integration time:
-
Permalink:
jasonzh0/kubeman@1351d9d762dd9194f2780c1598b43cb92ec1ece4 -
Branch / Tag:
refs/tags/v0.5.3 - Owner: https://github.com/jasonzh0
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1351d9d762dd9194f2780c1598b43cb92ec1ece4 -
Trigger Event:
release
-
Statement type: