Skip to content

Commit 7acabb0

Browse files
prathamesh0ashwin
authored andcommitted
Add support for generating Helm charts when creating a deployment (#974)
Part of https://plan.wireit.in/deepstack/browse/VUL-265/ - Added a flag `--helm-chart` to `deploy create` command - Uses Kompose CLI wrapper to generate a helm chart from compose files in a stack - To be handled in a follow on PR(s): - Templatize generated charts and generate a `values.yml` file with defaults Reviewed-on: https://git.vdb.to/cerc-io/stack-orchestrator/pulls/974 Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com> Co-committed-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
1 parent 34f3b71 commit 7acabb0

6 files changed

Lines changed: 515 additions & 3 deletions

File tree

docs/helm-chart-generation.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Helm Chart Generation
2+
3+
Generate Kubernetes Helm charts from stack compose files using Kompose.
4+
5+
## Prerequisites
6+
7+
Install Kompose:
8+
9+
```bash
10+
# Linux
11+
curl -L https://github.com/kubernetes/kompose/releases/download/v1.34.0/kompose-linux-amd64 -o kompose
12+
chmod +x kompose
13+
sudo mv kompose /usr/local/bin/
14+
15+
# macOS
16+
brew install kompose
17+
18+
# Verify
19+
kompose version
20+
```
21+
22+
## Usage
23+
24+
### 1. Create spec file
25+
26+
```bash
27+
laconic-so --stack <stack-name> deploy --deploy-to k8s init \
28+
--kube-config ~/.kube/config \
29+
--output spec.yml
30+
```
31+
32+
### 2. Generate Helm chart
33+
34+
```bash
35+
laconic-so --stack <stack-name> deploy create \
36+
--spec-file spec.yml \
37+
--deployment-dir my-deployment \
38+
--helm-chart
39+
```
40+
41+
### 3. Deploy to Kubernetes
42+
43+
```bash
44+
helm install my-release my-deployment/chart
45+
kubectl get pods -n zenith
46+
```
47+
48+
## Output Structure
49+
50+
```bash
51+
my-deployment/
52+
├── spec.yml # Reference
53+
├── stack.yml # Reference
54+
└── chart/ # Helm chart
55+
├── Chart.yaml
56+
├── README.md
57+
└── templates/
58+
└── *.yaml
59+
```
60+
61+
## Example
62+
63+
```bash
64+
# Generate chart for stage1-zenithd
65+
laconic-so --stack stage1-zenithd deploy --deploy-to k8s init \
66+
--kube-config ~/.kube/config \
67+
--output stage1-spec.yml
68+
69+
laconic-so --stack stage1-zenithd deploy create \
70+
--spec-file stage1-spec.yml \
71+
--deployment-dir stage1-deployment \
72+
--helm-chart
73+
74+
# Deploy
75+
helm install stage1-zenithd stage1-deployment/chart
76+
```
77+
78+
## Production Deployment (TODO)
79+
80+
### Local Development
81+
82+
```bash
83+
# Access services using port-forward
84+
kubectl port-forward service/zenithd 26657:26657
85+
kubectl port-forward service/nginx-api-proxy 1317:80
86+
kubectl port-forward service/cosmos-explorer 4173:4173
87+
```
88+
89+
### Production Access Options
90+
91+
- Option 1: Ingress + cert-manager (Recommended)
92+
- Install ingress-nginx + cert-manager
93+
- Point DNS to cluster LoadBalancer IP
94+
- Auto-provisions Let's Encrypt TLS certs
95+
- Access: `https://api.zenith.example.com`
96+
- Option 2: Cloud LoadBalancer
97+
- Use cloud provider's LoadBalancer service type
98+
- Point DNS to assigned external IP
99+
- Manual TLS cert management
100+
- Option 3: Bare Metal (MetalLB + Ingress)
101+
- MetalLB provides LoadBalancer IPs from local network
102+
- Same Ingress setup as cloud
103+
- Option 4: NodePort + External Proxy
104+
- Expose services on 30000-32767 range
105+
- External nginx/Caddy proxies 80/443 → NodePort
106+
- Manual cert management
107+
108+
### Changes Needed
109+
110+
- Add Ingress template to charts
111+
- Add TLS configuration to values.yaml
112+
- Document cert-manager setup
113+
- Add production deployment guide

stack_orchestrator/deploy/deployment_create.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -443,22 +443,31 @@ def _check_volume_definitions(spec):
443443
@click.command()
444444
@click.option("--spec-file", required=True, help="Spec file to use to create this deployment")
445445
@click.option("--deployment-dir", help="Create deployment files in this directory")
446+
@click.option("--helm-chart", is_flag=True, default=False, help="Generate Helm chart instead of deploying (k8s only)")
446447
# TODO: Hack
447448
@click.option("--network-dir", help="Network configuration supplied in this directory")
448449
@click.option("--initial-peers", help="Initial set of persistent peers")
449450
@click.pass_context
450-
def create(ctx, spec_file, deployment_dir, network_dir, initial_peers):
451+
def create(ctx, spec_file, deployment_dir, helm_chart, network_dir, initial_peers):
451452
deployment_command_context = ctx.obj
452-
return create_operation(deployment_command_context, spec_file, deployment_dir, network_dir, initial_peers)
453+
return create_operation(deployment_command_context, spec_file, deployment_dir, helm_chart, network_dir, initial_peers)
453454

454455

455456
# The init command's implementation is in a separate function so that we can
456457
# call it from other commands, bypassing the click decoration stuff
457-
def create_operation(deployment_command_context, spec_file, deployment_dir, network_dir, initial_peers):
458+
def create_operation(deployment_command_context, spec_file, deployment_dir, helm_chart, network_dir, initial_peers):
458459
parsed_spec = Spec(os.path.abspath(spec_file), get_parsed_deployment_spec(spec_file))
459460
_check_volume_definitions(parsed_spec)
460461
stack_name = parsed_spec["stack"]
461462
deployment_type = parsed_spec[constants.deploy_to_key]
463+
464+
# Branch to Helm chart generation flow early if --helm-chart flag is set
465+
if deployment_type == "k8s" and helm_chart:
466+
from stack_orchestrator.deploy.k8s.helm.chart_generator import generate_helm_chart
467+
generate_helm_chart(stack_name, spec_file, deployment_dir)
468+
return # Exit early, completely separate from existing k8s deployment flow
469+
470+
# Existing deployment flow continues unchanged
462471
stack_file = get_stack_path(stack_name).joinpath(constants.stack_file_name)
463472
parsed_stack = get_parsed_stack_config(stack_name)
464473
if opts.o.debug:
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copyright © 2025 Vulcanize
2+
3+
# This program is free software: you can redistribute it and/or modify
4+
# it under the terms of the GNU Affero General Public License as published by
5+
# the Free Software Foundation, either version 3 of the License, or
6+
# (at your option) any later version.
7+
8+
# This program is distributed in the hope that it will be useful,
9+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
# GNU Affero General Public License for more details.
12+
13+
# You should have received a copy of the GNU Affero General Public License
14+
# along with this program. If not, see <http:#www.gnu.org/licenses/>.

0 commit comments

Comments
 (0)