mirror of
https://github.com/geoffsee/predict-otron-9001.git
synced 2025-09-08 22:46:44 +00:00
Add Rust-based Helm Chart Generator Tool
- Scaffold `helm-chart-tool` with Cargo project files. - Implement core functionality: parse Cargo.toml, extract Kubernetes metadata, and generate Helm charts. - Include support for deployments, services, ingress, and helper templates. - Add README with detailed usage instructions. - Update `.gitignore` for generated Helm charts and related artifacts.
This commit is contained in:
80
.gitignore
vendored
80
.gitignore
vendored
@@ -1,8 +1,78 @@
|
||||
# IDE and editor files
|
||||
.idea/
|
||||
.fastembed_cache/
|
||||
target/
|
||||
/.output.txt
|
||||
.j**i?/
|
||||
.vscode/
|
||||
*.iml
|
||||
dist
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
.DS_Store
|
||||
|
||||
# Rust build artifacts
|
||||
target/
|
||||
Cargo.lock
|
||||
*.pdb
|
||||
|
||||
# Node.js artifacts
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
package-lock.json
|
||||
.npm
|
||||
.yarn-integrity
|
||||
|
||||
# Web frontend build outputs
|
||||
dist/
|
||||
.trunk/
|
||||
|
||||
# ML model and embedding caches
|
||||
.fastembed_cache/
|
||||
.hf-cache/
|
||||
.cache/
|
||||
|
||||
# Generated Helm charts
|
||||
generated-helm-chart/
|
||||
helm-chart/
|
||||
*.tgz
|
||||
|
||||
# Log files
|
||||
*.log
|
||||
logs/
|
||||
.output.txt
|
||||
|
||||
# Temporary files
|
||||
tmp/
|
||||
temp/
|
||||
.tmp/
|
||||
|
||||
# OS generated files
|
||||
Thumbs.db
|
||||
.DS_Store?
|
||||
ehthumbs.db
|
||||
|
||||
# JetBrains AI Assistant files
|
||||
.j**i?/
|
||||
|
||||
# Test outputs and coverage
|
||||
coverage/
|
||||
.nyc_output/
|
||||
junit.xml
|
||||
|
||||
# Docker artifacts
|
||||
.dockerignore.bak
|
||||
|
||||
# Python artifacts (if any Python tooling is used)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
.Python
|
||||
env/
|
||||
venv/
|
||||
.env
|
||||
.venv/
|
||||
|
||||
# Backup files
|
||||
*.bak
|
||||
*.backup
|
||||
*~
|
||||
|
18
helm-chart-tool/Cargo.toml
Normal file
18
helm-chart-tool/Cargo.toml
Normal file
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "helm-chart-tool"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[workspace]
|
||||
|
||||
[[bin]]
|
||||
name = "helm-chart-tool"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
toml = "0.8"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
anyhow = "1.0"
|
||||
clap = { version = "4.0", features = ["derive"] }
|
||||
walkdir = "2.0"
|
218
helm-chart-tool/README.md
Normal file
218
helm-chart-tool/README.md
Normal file
@@ -0,0 +1,218 @@
|
||||
# Helm Chart Tool
|
||||
|
||||
A Rust-based tool that automatically generates Helm charts from Cargo.toml metadata in Rust workspace projects.
|
||||
|
||||
## Overview
|
||||
|
||||
This tool scans a Rust workspace for crates containing Docker/Kubernetes metadata in their `Cargo.toml` files and generates a complete, production-ready Helm chart with deployments, services, ingress, and configuration templates.
|
||||
|
||||
## Features
|
||||
|
||||
- **Automatic Service Discovery**: Scans all `Cargo.toml` files in a workspace to find services with Kubernetes metadata
|
||||
- **Complete Helm Chart Generation**: Creates Chart.yaml, values.yaml, deployment templates, service templates, ingress template, and helper templates
|
||||
- **Metadata Extraction**: Uses `[package.metadata.kube]` sections from Cargo.toml files to extract:
|
||||
- Docker image names
|
||||
- Service ports
|
||||
- Replica counts
|
||||
- Service names
|
||||
- **Production Ready**: Generated charts include health checks, resource limits, node selectors, affinity rules, and tolerations
|
||||
- **Helm Best Practices**: Follows Helm chart conventions and passes `helm lint` validation
|
||||
|
||||
## Installation
|
||||
|
||||
Build the tool from source:
|
||||
|
||||
```bash
|
||||
cd helm-chart-tool
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
The binary will be available at `target/release/helm-chart-tool`.
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```bash
|
||||
./target/release/helm-chart-tool --workspace /path/to/rust/workspace --output ./my-helm-chart
|
||||
```
|
||||
|
||||
### Command Line Options
|
||||
|
||||
- `--workspace, -w PATH`: Path to the workspace root (default: `.`)
|
||||
- `--output, -o PATH`: Output directory for the Helm chart (default: `./helm-chart`)
|
||||
- `--name, -n NAME`: Name of the Helm chart (default: `predict-otron-9000`)
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
# Generate chart from current workspace
|
||||
./target/release/helm-chart-tool
|
||||
|
||||
# Generate chart from specific workspace with custom output
|
||||
./target/release/helm-chart-tool -w /path/to/my/workspace -o ./charts/my-app -n my-application
|
||||
```
|
||||
|
||||
## Cargo.toml Metadata Format
|
||||
|
||||
The tool expects crates to have Kubernetes metadata in their `Cargo.toml` files:
|
||||
|
||||
```toml
|
||||
[package]
|
||||
name = "my-service"
|
||||
version = "0.1.0"
|
||||
|
||||
# Required: Kubernetes metadata
|
||||
[package.metadata.kube]
|
||||
image = "ghcr.io/myorg/my-service:latest"
|
||||
replicas = 1
|
||||
port = 8080
|
||||
|
||||
# Optional: Docker Compose metadata (currently not used but parsed)
|
||||
[package.metadata.compose]
|
||||
image = "ghcr.io/myorg/my-service:latest"
|
||||
port = 8080
|
||||
```
|
||||
|
||||
### Required Fields
|
||||
|
||||
- `image`: Full Docker image name including registry and tag
|
||||
- `port`: Port number the service listens on
|
||||
- `replicas`: Number of replicas to deploy (optional, defaults to 1)
|
||||
|
||||
## Generated Chart Structure
|
||||
|
||||
The tool generates a complete Helm chart with the following structure:
|
||||
|
||||
```
|
||||
helm-chart/
|
||||
├── Chart.yaml # Chart metadata
|
||||
├── values.yaml # Default configuration values
|
||||
├── .helmignore # Files to ignore when packaging
|
||||
└── templates/
|
||||
├── _helpers.tpl # Template helper functions
|
||||
├── ingress.yaml # Ingress configuration (optional)
|
||||
├── {service}-deployment.yaml # Deployment for each service
|
||||
└── {service}-service.yaml # Service for each service
|
||||
```
|
||||
|
||||
### Generated Files
|
||||
|
||||
#### Chart.yaml
|
||||
- Standard Helm v2 chart metadata
|
||||
- Includes keywords for AI/ML applications
|
||||
- Maintainer information
|
||||
|
||||
#### values.yaml
|
||||
- Individual service configurations
|
||||
- Resource limits and requests
|
||||
- Service types and ports
|
||||
- Node selectors, affinity, and tolerations
|
||||
- Global settings and ingress configuration
|
||||
|
||||
#### Deployment Templates
|
||||
- Kubernetes Deployment manifests
|
||||
- Health checks (liveness and readiness probes)
|
||||
- Resource management
|
||||
- Container port configuration from metadata
|
||||
- Support for node selectors, affinity, and tolerations
|
||||
|
||||
#### Service Templates
|
||||
- Kubernetes Service manifests
|
||||
- ClusterIP services by default
|
||||
- Port mapping from metadata
|
||||
|
||||
#### Ingress Template
|
||||
- Optional ingress configuration
|
||||
- Disabled by default
|
||||
- Configurable through values.yaml
|
||||
|
||||
## Example Output
|
||||
|
||||
When run against the predict-otron-9000 workspace, the tool generates:
|
||||
|
||||
```bash
|
||||
$ ./target/release/helm-chart-tool --workspace .. --output ../generated-helm-chart
|
||||
Parsing workspace at: ..
|
||||
Output directory: ../generated-helm-chart
|
||||
Chart name: predict-otron-9000
|
||||
Found 4 services:
|
||||
- leptos-chat: ghcr.io/geoffsee/leptos-chat:latest (port 8788)
|
||||
- inference-engine: ghcr.io/geoffsee/inference-service:latest (port 8080)
|
||||
- embeddings-engine: ghcr.io/geoffsee/embeddings-service:latest (port 8080)
|
||||
- predict-otron-9000: ghcr.io/geoffsee/predict-otron-9000:latest (port 8080)
|
||||
Helm chart generated successfully!
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
The generated charts pass Helm validation:
|
||||
|
||||
```bash
|
||||
$ helm lint generated-helm-chart
|
||||
==> Linting generated-helm-chart
|
||||
[INFO] Chart.yaml: icon is recommended
|
||||
1 chart(s) linted, 0 chart(s) failed
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
Deploy the generated chart:
|
||||
|
||||
```bash
|
||||
# Install the chart
|
||||
helm install my-release ./generated-helm-chart
|
||||
|
||||
# Upgrade the chart
|
||||
helm upgrade my-release ./generated-helm-chart
|
||||
|
||||
# Uninstall the chart
|
||||
helm uninstall my-release
|
||||
```
|
||||
|
||||
### Customization
|
||||
|
||||
Customize the deployment by modifying `values.yaml`:
|
||||
|
||||
```yaml
|
||||
# Enable ingress
|
||||
ingress:
|
||||
enabled: true
|
||||
className: "nginx"
|
||||
hosts:
|
||||
- host: my-app.example.com
|
||||
|
||||
# Adjust resources for a specific service
|
||||
predict_otron_9000:
|
||||
replicas: 3
|
||||
resources:
|
||||
limits:
|
||||
memory: "4Gi"
|
||||
cpu: "2000m"
|
||||
requests:
|
||||
memory: "2Gi"
|
||||
cpu: "1000m"
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- Rust 2021+ (for building the tool)
|
||||
- Helm 3.x (for deploying the generated charts)
|
||||
- Kubernetes cluster (for deployment)
|
||||
|
||||
## Limitations
|
||||
|
||||
- Currently assumes all services need health checks on `/health` endpoint
|
||||
- Resource limits are hardcoded defaults (can be overridden in values.yaml)
|
||||
- Ingress configuration is basic (can be customized through values.yaml)
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Add new features to the tool
|
||||
2. Test with various Cargo.toml metadata configurations
|
||||
3. Validate generated charts with `helm lint`
|
||||
4. Ensure charts deploy successfully to test clusters
|
||||
|
||||
## License
|
||||
|
||||
This tool is part of the predict-otron-9000 project and follows the same license terms.
|
515
helm-chart-tool/src/main.rs
Normal file
515
helm-chart-tool/src/main.rs
Normal file
@@ -0,0 +1,515 @@
|
||||
use anyhow::{Context, Result};
|
||||
use clap::{Arg, Command};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct CargoToml {
|
||||
package: Option<Package>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Package {
|
||||
name: String,
|
||||
metadata: Option<Metadata>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Metadata {
|
||||
kube: Option<KubeMetadata>,
|
||||
compose: Option<ComposeMetadata>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct KubeMetadata {
|
||||
image: String,
|
||||
replicas: Option<u32>,
|
||||
port: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct ComposeMetadata {
|
||||
image: Option<String>,
|
||||
port: Option<u16>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct ServiceInfo {
|
||||
name: String,
|
||||
image: String,
|
||||
port: u16,
|
||||
replicas: u32,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let matches = Command::new("helm-chart-tool")
|
||||
.about("Generate Helm charts from Cargo.toml metadata")
|
||||
.arg(
|
||||
Arg::new("workspace")
|
||||
.short('w')
|
||||
.long("workspace")
|
||||
.value_name("PATH")
|
||||
.help("Path to the workspace root")
|
||||
.default_value("."),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("output")
|
||||
.short('o')
|
||||
.long("output")
|
||||
.value_name("PATH")
|
||||
.help("Output directory for the Helm chart")
|
||||
.default_value("./helm-chart"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("chart-name")
|
||||
.short('n')
|
||||
.long("name")
|
||||
.value_name("NAME")
|
||||
.help("Name of the Helm chart")
|
||||
.default_value("predict-otron-9000"),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
let workspace_path = matches.get_one::<String>("workspace").unwrap();
|
||||
let output_path = matches.get_one::<String>("output").unwrap();
|
||||
let chart_name = matches.get_one::<String>("chart-name").unwrap();
|
||||
|
||||
println!("Parsing workspace at: {}", workspace_path);
|
||||
println!("Output directory: {}", output_path);
|
||||
println!("Chart name: {}", chart_name);
|
||||
|
||||
let services = discover_services(workspace_path)?;
|
||||
println!("Found {} services:", services.len());
|
||||
for service in &services {
|
||||
println!(" - {}: {} (port {})", service.name, service.image, service.port);
|
||||
}
|
||||
|
||||
generate_helm_chart(output_path, chart_name, &services)?;
|
||||
println!("Helm chart generated successfully!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn discover_services(workspace_path: &str) -> Result<Vec<ServiceInfo>> {
|
||||
let workspace_root = Path::new(workspace_path);
|
||||
let mut services = Vec::new();
|
||||
|
||||
// Find all Cargo.toml files in the workspace
|
||||
for entry in WalkDir::new(workspace_root)
|
||||
.into_iter()
|
||||
.filter_map(|e| e.ok())
|
||||
{
|
||||
if entry.file_name() == "Cargo.toml" && entry.path() != workspace_root.join("Cargo.toml") {
|
||||
if let Ok(service_info) = parse_cargo_toml(entry.path()) {
|
||||
services.push(service_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(services)
|
||||
}
|
||||
|
||||
fn parse_cargo_toml(path: &Path) -> Result<ServiceInfo> {
|
||||
let content = fs::read_to_string(path)
|
||||
.with_context(|| format!("Failed to read Cargo.toml at {:?}", path))?;
|
||||
|
||||
let cargo_toml: CargoToml = toml::from_str(&content)
|
||||
.with_context(|| format!("Failed to parse Cargo.toml at {:?}", path))?;
|
||||
|
||||
let package = cargo_toml.package
|
||||
.ok_or_else(|| anyhow::anyhow!("No package section found in {:?}", path))?;
|
||||
|
||||
let metadata = package.metadata
|
||||
.ok_or_else(|| anyhow::anyhow!("No metadata section found in {:?}", path))?;
|
||||
|
||||
let kube_metadata = metadata.kube
|
||||
.ok_or_else(|| anyhow::anyhow!("No kube metadata found in {:?}", path))?;
|
||||
|
||||
Ok(ServiceInfo {
|
||||
name: package.name,
|
||||
image: kube_metadata.image,
|
||||
port: kube_metadata.port,
|
||||
replicas: kube_metadata.replicas.unwrap_or(1),
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_helm_chart(output_path: &str, chart_name: &str, services: &[ServiceInfo]) -> Result<()> {
|
||||
let chart_dir = Path::new(output_path);
|
||||
let templates_dir = chart_dir.join("templates");
|
||||
|
||||
// Create directories
|
||||
fs::create_dir_all(&templates_dir)?;
|
||||
|
||||
// Generate Chart.yaml
|
||||
generate_chart_yaml(chart_dir, chart_name)?;
|
||||
|
||||
// Generate values.yaml
|
||||
generate_values_yaml(chart_dir, services)?;
|
||||
|
||||
// Generate templates for each service
|
||||
for service in services {
|
||||
generate_deployment_template(&templates_dir, service)?;
|
||||
generate_service_template(&templates_dir, service)?;
|
||||
}
|
||||
|
||||
// Generate ingress template
|
||||
generate_ingress_template(&templates_dir, services)?;
|
||||
|
||||
// Generate helper templates
|
||||
generate_helpers_template(&templates_dir)?;
|
||||
|
||||
// Generate .helmignore
|
||||
generate_helmignore(chart_dir)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_chart_yaml(chart_dir: &Path, chart_name: &str) -> Result<()> {
|
||||
let chart_yaml = format!(
|
||||
r#"apiVersion: v2
|
||||
name: {}
|
||||
description: A Helm chart for the predict-otron-9000 AI platform
|
||||
type: application
|
||||
version: 0.1.0
|
||||
appVersion: "0.1.0"
|
||||
keywords:
|
||||
- ai
|
||||
- llm
|
||||
- inference
|
||||
- embeddings
|
||||
- chat
|
||||
maintainers:
|
||||
- name: predict-otron-9000-team
|
||||
"#,
|
||||
chart_name
|
||||
);
|
||||
|
||||
fs::write(chart_dir.join("Chart.yaml"), chart_yaml)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_values_yaml(chart_dir: &Path, services: &[ServiceInfo]) -> Result<()> {
|
||||
let mut values = String::from(
|
||||
r#"# Default values for predict-otron-9000
|
||||
# This is a YAML-formatted file.
|
||||
|
||||
global:
|
||||
imagePullPolicy: IfNotPresent
|
||||
serviceType: ClusterIP
|
||||
|
||||
# Ingress configuration
|
||||
ingress:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations: {}
|
||||
hosts:
|
||||
- host: predict-otron-9000.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: predict-otron-9000
|
||||
port:
|
||||
number: 8080
|
||||
tls: []
|
||||
|
||||
"#,
|
||||
);
|
||||
|
||||
for service in services {
|
||||
let service_config = format!(
|
||||
r#"{}:
|
||||
image:
|
||||
repository: {}
|
||||
tag: "latest"
|
||||
pullPolicy: IfNotPresent
|
||||
replicas: {}
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: {}
|
||||
resources:
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "1000m"
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "250m"
|
||||
nodeSelector: {{}}
|
||||
tolerations: []
|
||||
affinity: {{}}
|
||||
|
||||
"#,
|
||||
service.name.replace("-", "_"),
|
||||
service.image.split(':').next().unwrap_or(&service.image),
|
||||
service.replicas,
|
||||
service.port
|
||||
);
|
||||
values.push_str(&service_config);
|
||||
}
|
||||
|
||||
fs::write(chart_dir.join("values.yaml"), values)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_deployment_template(templates_dir: &Path, service: &ServiceInfo) -> Result<()> {
|
||||
let service_name_underscore = service.name.replace("-", "_");
|
||||
let deployment_template = format!(
|
||||
r#"apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{{{ include "predict-otron-9000.fullname" . }}}}-{}
|
||||
labels:
|
||||
{{{{- include "predict-otron-9000.labels" . | nindent 4 }}}}
|
||||
app.kubernetes.io/component: {}
|
||||
spec:
|
||||
replicas: {{{{ .Values.{}.replicas }}}}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{{{- include "predict-otron-9000.selectorLabels" . | nindent 6 }}}}
|
||||
app.kubernetes.io/component: {}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{{{- include "predict-otron-9000.selectorLabels" . | nindent 8 }}}}
|
||||
app.kubernetes.io/component: {}
|
||||
spec:
|
||||
containers:
|
||||
- name: {}
|
||||
image: "{{{{ .Values.{}.image.repository }}}}:{{{{ .Values.{}.image.tag }}}}"
|
||||
imagePullPolicy: {{{{ .Values.{}.image.pullPolicy }}}}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {}
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: http
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
resources:
|
||||
{{{{- toYaml .Values.{}.resources | nindent 12 }}}}
|
||||
{{{{- with .Values.{}.nodeSelector }}}}
|
||||
nodeSelector:
|
||||
{{{{- toYaml . | nindent 8 }}}}
|
||||
{{{{- end }}}}
|
||||
{{{{- with .Values.{}.affinity }}}}
|
||||
affinity:
|
||||
{{{{- toYaml . | nindent 8 }}}}
|
||||
{{{{- end }}}}
|
||||
{{{{- with .Values.{}.tolerations }}}}
|
||||
tolerations:
|
||||
{{{{- toYaml . | nindent 8 }}}}
|
||||
{{{{- end }}}}
|
||||
"#,
|
||||
service.name,
|
||||
service.name,
|
||||
service_name_underscore,
|
||||
service.name,
|
||||
service.name,
|
||||
service.name,
|
||||
service_name_underscore,
|
||||
service_name_underscore,
|
||||
service_name_underscore,
|
||||
service.port,
|
||||
service_name_underscore,
|
||||
service_name_underscore,
|
||||
service_name_underscore,
|
||||
service_name_underscore
|
||||
);
|
||||
|
||||
let filename = format!("{}-deployment.yaml", service.name);
|
||||
fs::write(templates_dir.join(filename), deployment_template)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_service_template(templates_dir: &Path, service: &ServiceInfo) -> Result<()> {
|
||||
let service_template = format!(
|
||||
r#"apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{{{ include "predict-otron-9000.fullname" . }}}}-{}
|
||||
labels:
|
||||
{{{{- include "predict-otron-9000.labels" . | nindent 4 }}}}
|
||||
app.kubernetes.io/component: {}
|
||||
spec:
|
||||
type: {{{{ .Values.{}.service.type }}}}
|
||||
ports:
|
||||
- port: {{{{ .Values.{}.service.port }}}}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
{{{{- include "predict-otron-9000.selectorLabels" . | nindent 4 }}}}
|
||||
app.kubernetes.io/component: {}
|
||||
"#,
|
||||
service.name,
|
||||
service.name,
|
||||
service.name.replace("-", "_"),
|
||||
service.name.replace("-", "_"),
|
||||
service.name
|
||||
);
|
||||
|
||||
let filename = format!("{}-service.yaml", service.name);
|
||||
fs::write(templates_dir.join(filename), service_template)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_ingress_template(templates_dir: &Path, services: &[ServiceInfo]) -> Result<()> {
|
||||
let ingress_template = r#"{{- if .Values.ingress.enabled -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ include "predict-otron-9000.fullname" . }}
|
||||
labels:
|
||||
{{- include "predict-otron-9000.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.ingress.className }}
|
||||
ingressClassName: {{ .Values.ingress.className }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
{{- if .pathType }}
|
||||
pathType: {{ .pathType }}
|
||||
{{- end }}
|
||||
backend:
|
||||
service:
|
||||
name: {{ include "predict-otron-9000.fullname" $ }}-{{ .backend.service.name }}
|
||||
port:
|
||||
number: {{ .backend.service.port.number }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
"#;
|
||||
|
||||
fs::write(templates_dir.join("ingress.yaml"), ingress_template)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_helpers_template(templates_dir: &Path) -> Result<()> {
|
||||
let helpers_template = r#"{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "predict-otron-9000.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "predict-otron-9000.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "predict-otron-9000.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "predict-otron-9000.labels" -}}
|
||||
helm.sh/chart: {{ include "predict-otron-9000.chart" . }}
|
||||
{{ include "predict-otron-9000.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "predict-otron-9000.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "predict-otron-9000.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "predict-otron-9000.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "predict-otron-9000.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
"#;
|
||||
|
||||
fs::write(templates_dir.join("_helpers.tpl"), helpers_template)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_helmignore(chart_dir: &Path) -> Result<()> {
|
||||
let helmignore_content = r#"# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
"#;
|
||||
|
||||
fs::write(chart_dir.join(".helmignore"), helmignore_content)?;
|
||||
Ok(())
|
||||
}
|
Reference in New Issue
Block a user