X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=capifcore%2Finternal%2Fhelmmanagement%2Fhelm.go;fp=capifcore%2Finternal%2Fhelmmanagement%2Fhelm.go;h=cfed6eb0dc2b0949efaaff73d5c93383d228089f;hb=c9e08b2a2f647f9f870040570c5e71305f0fb5d2;hp=0000000000000000000000000000000000000000;hpb=8fcfa4ecde6d95ead33c34b0e7efc4933ad44444;p=nonrtric%2Fplt%2Fsme.git diff --git a/capifcore/internal/helmmanagement/helm.go b/capifcore/internal/helmmanagement/helm.go new file mode 100644 index 0000000..cfed6eb --- /dev/null +++ b/capifcore/internal/helmmanagement/helm.go @@ -0,0 +1,187 @@ +// - +// ========================LICENSE_START================================= +// O-RAN-SC +// %% +// Copyright (C) 2022: Nordix Foundation +// %% +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ========================LICENSE_END=================================== +// + +package helmmanagement + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" + "gopkg.in/yaml.v2" + "helm.sh/helm/v3/pkg/action" + "helm.sh/helm/v3/pkg/chart/loader" + "helm.sh/helm/v3/pkg/cli" + "helm.sh/helm/v3/pkg/getter" + "helm.sh/helm/v3/pkg/kube" + "helm.sh/helm/v3/pkg/repo" + "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/client-go/rest" +) + +//go:generate mockery --name HelmManager +type HelmManager interface { + AddToRepo(repoName, url string) error + InstallHelmChart(namespace, repoName, chartName, releaseName string) error + UninstallHelmChart(namespace, chartName string) +} + +type helmManagerImpl struct { + settings *cli.EnvSettings +} + +func NewHelmManager() *helmManagerImpl { + return &helmManagerImpl{ + settings: cli.New(), + } +} + +func (hm *helmManagerImpl) AddToRepo(repoName, url string) error { + repoFile := hm.settings.RepositoryConfig + + //Ensure the file directory exists as it is required for file locking + err := os.MkdirAll(filepath.Dir(repoFile), os.ModePerm) + if err != nil && !os.IsExist(err) { + return err + } + + b, err := ioutil.ReadFile(repoFile) + if err != nil && !os.IsNotExist(err) { + return err + } + + var f repo.File + if err := yaml.Unmarshal(b, &f); err != nil { + return err + } + + if f.Has(repoName) { + fmt.Printf("repository name (%s) already exists\n", repoName) + return nil + } + + c := repo.Entry{ + Name: repoName, + URL: url, + } + + r, err := repo.NewChartRepository(&c, getter.All(hm.settings)) + if err != nil { + return err + } + + if _, err := r.DownloadIndexFile(); err != nil { + err := errors.Wrapf(err, "looks like %q is not a valid chart repository or cannot be reached", url) + return err + } + + f.Update(&c) + + if err := f.WriteFile(repoFile, 0644); err != nil { + return err + } + fmt.Printf("%q has been added to your repositories\n", repoName) + return nil +} + +func (hm *helmManagerImpl) InstallHelmChart(namespace, repoName, chartName, releaseName string) error { + actionConfig, err := getActionConfig(namespace) + if err != nil { + return err + } + + install := action.NewInstall(actionConfig) + + cp, err := install.ChartPathOptions.LocateChart(fmt.Sprintf("%s/%s", repoName, chartName), hm.settings) + if err != nil { + log.Error("Unable to locate chart!") + return err + } + + chartRequested, err := loader.Load(cp) + if err != nil { + log.Error("Unable to load chart path!") + return err + } + + install.Namespace = namespace + install.ReleaseName = releaseName + _, err = install.Run(chartRequested, nil) + if err != nil { + log.Error("Unable to run chart!") + return err + } + log.Debug("Successfully onboarded ", namespace, repoName, chartName, releaseName) + return nil +} + +func (hm *helmManagerImpl) UninstallHelmChart(namespace, chartName string) { + actionConfig, err := getActionConfig(namespace) + if err != nil { + fmt.Println(err) + } + + iCli := action.NewUninstall(actionConfig) + + resp, err := iCli.Run(chartName) + if err != nil { + fmt.Println(err) + } + log.Debug("Successfully uninstalled chart: ", resp.Release.Name) +} + +func getActionConfig(namespace string) (*action.Configuration, error) { + actionConfig := new(action.Configuration) + // Create the rest config instance with ServiceAccount values loaded in them + config, err := rest.InClusterConfig() + if err != nil { + // fallback to kubeconfig + home, exists := os.LookupEnv("HOME") + if !exists { + home = "/root" + } + kubeconfigPath := filepath.Join(home, ".kube", "config") + if envvar := os.Getenv("KUBECONFIG"); len(envvar) > 0 { + kubeconfigPath = envvar + } + if err := actionConfig.Init(kube.GetConfig(kubeconfigPath, "", namespace), namespace, os.Getenv("HELM_DRIVER"), + func(format string, v ...interface{}) { + fmt.Sprintf(format, v) + }); err != nil { + fmt.Println(err) + } + } else { + // Create the ConfigFlags struct instance with initialized values from ServiceAccount + kubeConfig := genericclioptions.NewConfigFlags(false) + kubeConfig.APIServer = &config.Host + kubeConfig.BearerToken = &config.BearerToken + kubeConfig.CAFile = &config.CAFile + kubeConfig.Namespace = &namespace + if err := actionConfig.Init(kubeConfig, namespace, os.Getenv("HELM_DRIVER"), func(format string, v ...interface{}) { + fmt.Sprintf(format, v) + }); err != nil { + fmt.Println(err) + } + } + return actionConfig, err +}