I use the following code which works and install helm chart (in the loop) in parallel,
it get a kubeconfig file (to access to k8s) create a helm client and install the charts from the defined location and waits (upgradeAction.Wait = true) that each chart installation will finished successfully.
At first I do it in sequence and now I added a wait.group to be able to reduce the installation time and install it in parallel, do I miss something? error handling etc?
package main
import (
"fmt"
"os"
"strings"
"sync"
)
func main() {
log.Info("tools Installation")
kcfgFilePath, err := kubeFile(cfg)
defer os.Remove(kcfgFilePath)
if err != nil {
return err
}
settings := cli.New()
actionConfig := new(action.Configuration)
clientGetter := genericclioptions.NewConfigFlags(false)
clientGetter.KubeConfig = &kcfgFilePath
// install all relevant components
var wg sync.WaitGroup
for _, chartInstallation := range charts {
wg.Add(1)
go installChart(&wg,chartInstallation, releaseName, actionConfig, clientGetter, settings, log)
}
return nil
}
func installChart(wg *sync.WaitGroup,chartInstallation Installation, releaseName string, actionConfig *action.Configuration, clientGetter *genericclioptions.ConfigFlags, settings *cli.EnvSettings, log logr.Logger) (error, bool) {
defer wg.Done()
chart, err := loader.Load(chartInstallation.Path)
if err != nil {
return err, true
}
releaseName = releaseName + "-" + chartInstallation.Name
if err := actionConfig.Init(clientGetter, settings.Namespace(), os.Getenv("HELM_DRIVER"), func(format string, v ...interface{}) {
r := fmt.Sprintf(format, v)
log.Info("Helm Installation", "deploy status", r)
}); err != nil {
return err, true
}
releasePresent := true
status, err := action.NewStatus(actionConfig).Run(releaseName)
if err != nil {
//if errors.Is(err, driver.ErrReleaseNotFound) {
if strings.Contains(err.Error(), driver.ErrReleaseNotFound.Error()) {
releasePresent = false
} else {
return err, true
}
}
if !releasePresent {
// install chart
installAction := action.NewInstall(actionConfig)
installAction.CreateNamespace = true
installAction.Namespace = chartInstallation.Namespace
installAction.ReleaseName = releaseName
installAction.Wait = true
// install new
_, err := installAction.Run(chart, nil)
if err != nil {
return err, true
}
log.Info("installed: ", "releaseName", releaseName)
}
if status != nil {
if releasePresent && status.Info.Status.String() == release.StatusFailed.String() { // upgrade if broken
upgradeAction := action.NewUpgrade(actionConfig)
upgradeAction.Atomic = false
upgradeAction.CleanupOnFail = true
upgradeAction.Wait = true
upgradeAction.ReuseValues = false
upgradeAction.Recreate = false
_, err := upgradeAction.Run(releaseName, chart, nil)
if err != nil {
return err, true
}
}
}
return nil, false
}