Files
Go.Rig-Operator/deploy/rig-operator/internal/helm/client.go
2026-01-15 09:58:01 +00:00

127 lines
3.6 KiB
Go

package helm
import (
"fmt"
"log"
"os"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/registry" // [NEW] Required for OCI
"helm.sh/helm/v3/pkg/storage/driver"
"k8s.io/cli-runtime/pkg/genericclioptions"
)
type Config struct {
Namespace string
ReleaseName string
RepoURL string
ChartName string
Version string
Values map[string]interface{}
}
func Apply(cfg Config) error {
settings := cli.New()
// 1. Initialize Action Config
actionConfig := new(action.Configuration)
getter := genericclioptions.NewConfigFlags(false)
if err := actionConfig.Init(getter, cfg.Namespace, os.Getenv("HELM_DRIVER"), log.Printf); err != nil {
return fmt.Errorf("failed to init helm config: %w", err)
}
// 2. [NEW] Initialize OCI Registry Client
// This tells Helm how to talk to ghcr.io, docker.io, etc.
registryClient, err := registry.NewClient(
registry.ClientOptDebug(true),
registry.ClientOptEnableCache(true),
registry.ClientOptCredentialsFile(settings.RegistryConfig), // Uses ~/.config/helm/registry/config.json
)
if err != nil {
return fmt.Errorf("failed to init registry client: %w", err)
}
actionConfig.RegistryClient = registryClient
// 3. Setup Install Action
client := action.NewInstall(actionConfig)
client.Version = cfg.Version
client.Namespace = cfg.Namespace
client.ReleaseName = cfg.ReleaseName
client.CreateNamespace = true
if cfg.RepoURL != "" {
client.RepoURL = cfg.RepoURL
}
// 4. Locate Chart (Now supports oci:// because RegistryClient is set)
cp, err := client.ChartPathOptions.LocateChart(cfg.ChartName, settings)
if err != nil {
return fmt.Errorf("failed to locate chart %s: %w", cfg.ChartName, err)
}
chart, err := loader.Load(cp)
if err != nil {
return fmt.Errorf("failed to load chart: %w", err)
}
// 5. Install or Upgrade
histClient := action.NewHistory(actionConfig)
histClient.Max = 1
if _, err := histClient.Run(cfg.ReleaseName); err == driver.ErrReleaseNotFound {
fmt.Printf("Installing OCI Release %s...\n", cfg.ReleaseName)
_, err := client.Run(chart, cfg.Values)
return err
} else if err != nil {
return err
}
fmt.Printf("Upgrading OCI Release %s...\n", cfg.ReleaseName)
upgrade := action.NewUpgrade(actionConfig)
upgrade.Version = cfg.Version
upgrade.Namespace = cfg.Namespace
// Important: Upgrade also needs the RegistryClient, but it shares 'actionConfig'
// so it is already set up.
if cfg.RepoURL != "" {
upgrade.RepoURL = cfg.RepoURL
}
_, err = upgrade.Run(cfg.ReleaseName, chart, cfg.Values)
return err
}
func Uninstall(cfg Config) error {
settings := cli.New()
// 1. Initialize Action Config (Same as Apply)
actionConfig := new(action.Configuration)
getter := genericclioptions.NewConfigFlags(false)
if err := actionConfig.Init(getter, cfg.Namespace, os.Getenv("HELM_DRIVER"), log.Printf); err != nil {
return fmt.Errorf("failed to init helm config: %w", err)
}
// 2. Initialize OCI Registry Client (Crucial for OCI charts)
registryClient, err := registry.NewClient(
registry.ClientOptDebug(true),
registry.ClientOptEnableCache(true),
registry.ClientOptCredentialsFile(settings.RegistryConfig),
)
if err != nil {
return fmt.Errorf("failed to init registry client: %w", err)
}
actionConfig.RegistryClient = registryClient
// 3. Run Uninstall
client := action.NewUninstall(actionConfig)
// Don't fail if it's already gone
_, err = client.Run(cfg.ReleaseName)
if err != nil && err != driver.ErrReleaseNotFound {
return fmt.Errorf("failed to uninstall release: %w", err)
}
fmt.Printf("✅ Uninstalled Release %s\n", cfg.ReleaseName)
return nil
}