A framework for building Kubernetes installers with Helm
Helmet provides a reusable, batteries-included framework for creating intelligent Kubernetes installers that understand dependency relationships, manage configuration, and orchestrate complex deployments.
Helmet is designed to be imported as a Go library to build custom installers for Kubernetes-based product suites. It handles the complexity of dependency resolution, configuration management, and deployment orchestration, allowing you to focus on defining your products and their relationships.
- Automatic Dependency Resolution: Declares dependencies via Helm chart annotations and automatically determines installation order
- Configuration Management: YAML-based configuration with Kubernetes ConfigMap persistence
- Template Engine: Go templates for dynamic Helm values with cluster introspection
- Integration System: Pluggable integrations for external services (Git providers, registries, etc.)
- Hook Scripts: Execute custom logic before and after chart installations
- CLI Generation: Automatically generates a complete CLI with config, deploy, and integration commands
- MCP Support: Built-in Model Context Protocol server for AI assistant integration
- Monitoring: Resource readiness checks and Helm test execution
package main
import (
_ "embed"
"os"
"github.com/redhat-appstudio/helmet/api"
"github.com/redhat-appstudio/helmet/framework"
)
//go:embed installer.tar
var installerTarball []byte
func main() {
// Create application context with metadata
appCtx := &api.AppContext{
Name: "myapp",
Version: "1.0.0",
}
// Create and run the installer from embedded tarball
app, _ := framework.NewAppFromTarball(
appCtx,
installerTarball,
os.Getwd(),
framework.WithInstallerTarball(installerTarball),
)
app.Run()
}This generates a complete CLI with commands for configuration, deployment, topology inspection, and more.
Helmet uses a convention-based approach where your installer assets are organized in a predictable structure:
installer/
├── config.yaml # Configuration schema
├── values.yaml.tpl # Go template for Helm values
├── charts/ # Helm charts directory
│ ├── database/
│ ├── api-server/
│ └── frontend/
└── instructions.md # MCP server instructions (optional)
Charts declare dependencies and metadata via annotations:
# charts/api-server/Chart.yaml
annotations:
helmet.redhat-appstudio.github.com/product-name: "api"
helmet.redhat-appstudio.github.com/depends-on: "database"
helmet.redhat-appstudio.github.com/weight: "100"The framework resolves dependencies, builds an installation topology, and orchestrates deployment in the correct order.
Automatically resolves and orders chart installations based on:
- Declared dependencies (
depends-onannotation) - Weight-based prioritization (
weightannotation) - Product associations (
product-nameannotation) - Integration requirements (
integrations-requiredCEL expressions)
See Topology Documentation for details.
Product-based configuration with dynamic updates:
myapp:
settings:
crc: false
products:
- name: test-product-name
enabled: true
namespace: test-product-namespace
properties:
manageSubscription: trueConfiguration is stored as Kubernetes ConfigMaps and can be updated programmatically.
Render Helm values dynamically based on configuration and cluster state:
{{- $db := .Installer.Products.Database -}}
{{- if $db.Enabled }}
database:
replicas: {{ $db.Properties.replicas | default 1 }}
host: db.{{ .OpenShift.Ingress.Domain }}
{{- end }}The framework automatically generates a complete CLI:
myapp config --create # Create configuration
myapp integration github --token=<token> # Configure integrations
myapp topology # View installation order
myapp deploy # Deploy all products
myapp mcp # Start MCP serverExtend the framework with custom integrations, commands, and MCP tools:
app := framework.NewApp("myapp", filesystem,
framework.WithInstallerTarball(InstallerTarball),
framework.WithIntegrations(customIntegrations...),
framework.WithMCPToolsBuilder(customMCPTools),
)
// Add custom commands
rootCmd := app.Command()
rootCmd.AddCommand(myCustomCommand)
app.Run()Import Helmet into your Go project:
go get github.com/redhat-appstudio/helmet/framework- Dependency Topology - Chart dependency resolution and installation ordering
- MCP Server - AI assistant integration via Model Context Protocol
- Contributing Guide - Development guidelines and best practices
See example/helmet-ex/ for a comprehensive example demonstrating all framework features.
package main
import (
_ "embed"
"os"
"github.com/redhat-appstudio/helmet/api"
"github.com/redhat-appstudio/helmet/framework"
)
//go:embed installer.tar
var installerTarball []byte
func main() {
appCtx := &api.AppContext{Name: "myinstaller"}
cwd, _ := os.Getwd()
app, _ := framework.NewAppFromTarball(
appCtx,
installerTarball,
cwd,
framework.WithInstallerTarball(installerTarball),
)
app.Run()
}import (
_ "embed"
"os"
"github.com/redhat-appstudio/helmet/api"
"github.com/redhat-appstudio/helmet/framework"
)
//go:embed installer.tar
var installerTarball []byte
type CustomIntegration struct{}
func (i *CustomIntegration) Name() string { return "custom" }
func (i *CustomIntegration) Init(ctx context.Context, logger logr.Logger, k8s *kubernetes.Clientset) (api.Integration, error) {
// Implementation
return &CustomIntegrationImpl{}, nil
}
func (i *CustomIntegration) Command(logger logr.Logger) (*cobra.Command, error) {
// CLI command definition
return &cobra.Command{Use: "custom"}, nil
}
func main() {
appCtx := &api.AppContext{Name: "myinstaller"}
cwd, _ := os.Getwd()
// Combine standard integrations with custom ones
integrations := append(
framework.StandardIntegrations(),
&CustomIntegration{},
)
app, _ := framework.NewAppFromTarball(
appCtx,
installerTarball,
cwd,
framework.WithInstallerTarball(installerTarball),
framework.WithIntegrations(integrations...),
)
app.Run()
}import (
_ "embed"
"os"
"github.com/redhat-appstudio/helmet/api"
"github.com/redhat-appstudio/helmet/framework"
"github.com/redhat-appstudio/helmet/framework/mcpserver"
)
//go:embed installer.tar
var installerTarball []byte
func customTools(ctx api.AppContext, s *mcpserver.Server) error {
s.AddTool(mcpserver.Tool{
Name: "myapp_status",
Description: "Get deployment status",
Handler: func(args map[string]interface{}) (interface{}, error) {
// Implementation
return map[string]string{"status": "healthy"}, nil
},
})
return nil
}
func main() {
appCtx := &api.AppContext{Name: "myinstaller"}
cwd, _ := os.Getwd()
app, _ := framework.NewAppFromTarball(
appCtx,
installerTarball,
cwd,
framework.WithInstallerTarball(installerTarball),
framework.WithMCPToolsBuilder(customTools),
)
app.Run()
}- Convention over Configuration: Predictable structure with sensible defaults
- Interface-Driven: Extensibility through well-defined interfaces
- API Stability: Functional options pattern for backward compatibility
- Kubernetes-Native: First-class support for namespaces, RBAC, and cluster introspection
- Helm-Centric: Leverages Helm's ecosystem and tooling
Contributions are welcome! Please see CONTRIBUTING.md for:
- Development environment setup
- Code style guidelines
- Testing requirements
- Pull request process
When contributing, please consider:
- API stability and backward compatibility
- Documentation for framework consumers
- Test coverage for new features
- Impact on existing consumers
Note: This is a framework for building installers. For specific product installers built with Helmet, please refer to their respective repositories.