package helmhelper import ( "fmt" "os" "strings" "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" "helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/cli" "helm.sh/helm/v3/pkg/getter" "helm.sh/helm/v3/pkg/registry" "helm.sh/helm/v3/pkg/repo" ) type Helm struct{} func NewHelm() Helmhelper { return &Helm{} } func getDownloadDirPath(workdirPath string) string { return fmt.Sprintf("%s/.charts", workdirPath) } func getChartDirPath(downloadDirPath string, release *ChartData) string { return fmt.Sprintf("%s/%s-%s-%s", downloadDirPath, release.RepositoryName, release.Name, release.Version) } func (h *Helm) PullChart(workdirPath string, release *ChartData) (path string, err error) { downloadDirPath := getDownloadDirPath(workdirPath) if err := os.MkdirAll(downloadDirPath, 0777); err != nil { return "", err } config := new(action.Configuration) cl := cli.New() chartDir := getChartDirPath(downloadDirPath, release) _, err = os.Stat(chartDir) if err != nil && !os.IsNotExist(err) { return "", nil } else if os.IsNotExist(err) { if err := os.Mkdir(chartDir, 0777); err != nil { return "", err } registry, err := registry.NewClient() if err != nil { return "", err } var path string // Download the chart to the workdir if release.RepositoryKind != "oci" { r, err := repo.NewChartRepository(&repo.Entry{ Name: release.RepositoryName, URL: release.RepositoryURL, }, getter.All(cl)) if err != nil { return "", err } path = r.Config.Name } else { path = release.RepositoryURL } client := action.NewPullWithOpts(action.WithConfig(config)) client.SetRegistryClient(registry) client.Untar = true client.DestDir = chartDir client.Settings = cl chartRemote := fmt.Sprintf("%s/%s", path, release.Name) logrus.Infof("trying to pull: %s", chartRemote) if _, err = client.Run(chartRemote); err != nil { return "", err } } path, err = getChartPathFromDir(chartDir) if err != nil { return "", err } return path, nil } func (h *Helm) FindLatestVersion(workdirPath string, release *ChartData) (version string, err error) { downloadDirPath := getDownloadDirPath(workdirPath) if err := os.MkdirAll(downloadDirPath, 0777); err != nil { return "", err } config := new(action.Configuration) cl := cli.New() chartDir := getChartDirPath(downloadDirPath, release) chartPath, err := h.PullChart(workdirPath, release) if err != nil { return "", err } showAction := action.NewShowWithConfig(action.ShowChart, config) res, err := showAction.LocateChart(fmt.Sprintf("%s/%s", chartDir, chartPath), cl) if err != nil { return "", err } res, err = showAction.Run(res) if err != nil { return "", nil } chartData, err := chartFromString(res) if err != nil { return "", err } logrus.Infof("the latest version of %s is %s", release.Name, chartData.Version) release.Version = chartData.Version versionedChartDir := getChartDirPath(downloadDirPath, release) if err := os.Rename(chartDir, versionedChartDir); err != nil { return "", err } return chartData.Version, err } func (h *Helm) PushChart(workdirPath string, server, prefix, username, password string, chartdata *ChartData) (err error) { downloadDirPath := getDownloadDirPath(workdirPath) chartDir := getChartDirPath(downloadDirPath, chartdata) _, err = os.Stat(chartDir) if err != nil && !os.IsNotExist(err) { return err } else if os.IsNotExist(err) { if err := os.Mkdir(chartDir, 0777); err != nil { return err } } regclient, err := registry.NewClient() options := registry.LoginOptBasicAuth("allanger", "") tls := registry.LoginOptInsecure(true) serverClean := strings.ReplaceAll(server, "oci://", "") if err :=regclient.Login(serverClean, options, tls); err != nil { return err } if err != nil { return err } versionedChartDir := fmt.Sprintf("%s/%s", getChartDirPath(downloadDirPath, chartdata), chartdata.Name) tar := action.NewPackage() tar.Destination = downloadDirPath logrus.Info(versionedChartDir) logrus.Info(chartDir) tarname, err := tar.Run(versionedChartDir, nil) // tarpath := fmt.Sprintf("%s/%s", versionedChartDir, tarname) if err != nil { return err } client := action.NewPushWithOpts(action.WithPushConfig(&action.Configuration{})) logrus.Infof("trying to push: %s", tarname) client.Settings = &cli.EnvSettings{} smth, err := client.Run(tarname, fmt.Sprintf("%s/%s", server, prefix)) if err != nil { return err } logrus.Info(smth) return nil } func (h *Helm) RenderChart(workdirPath string, release *ReleaseData) error { return nil // downloadDirPath := getDownloadDirPath(workdirPath) // chartDirPath := getChartDirPath(downloadDirPath, release) // chartPath, err := getChartPathFromDir(chartDirPath) // if err != nil { // return err // } // logrus.Info(fmt.Sprintf("%s/%s", chartDirPath, chartPath)) // chartObj, err := loader.Load(fmt.Sprintf("%s/%s", chartDirPath, chartPath)) // if err != nil { // return err // } // values := chartutil.Values{} // values["Values"] = chartObj.Values // values["Release"] = map[string]string{ // "Name": release.Name, // "Namespace": release.Namespace, // } // values["Capabilities"] = map[string]map[string]string{ // "KubeVersion": { // "Version": "v1.27.9", // "GitVersion": "v1.27.9", // }, // } // files, err := engine.Engine{Strict: false}.Render(chartObj, values) // if err != nil { // return err // } // logrus.Info(files) // for file, data := range files { // logrus.Infof("%s - %s", file, data) // } // logrus.Info("I'm here") // return nil } func getChartPathFromDir(downloadDir string) (file string, err error) { files, err := os.ReadDir(downloadDir) if err != nil { return "", err } else if len(files) == 0 { return "", fmt.Errorf("expected to have one file, got zero in a dir %s", downloadDir) } else if len(files) > 1 { return "", fmt.Errorf("expected to have only one file in a dir %s", downloadDir) } return files[0].Name(), nil } func chartFromString(info string) (*ChartData, error) { releaseData := new(ChartData) if err := yaml.Unmarshal([]byte(info), &releaseData); err != nil { return nil, err } return releaseData, nil }