127 lines
3.6 KiB
Go
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
|
|
}
|