X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=pkg%2Fhelm%2Fhelm.go;h=3a3587736389feadb29206f4cd02b9e7d1a49714;hb=bc99f0bbf612db426f0805b0e1f70067b60ddbc7;hp=a3d7b1830ff0161dddca9424fd2f630c448b97a3;hpb=34e4383c438f87023bc411d9b0baa4a828a7e306;p=ric-plt%2Fappmgr.git diff --git a/pkg/helm/helm.go b/pkg/helm/helm.go index a3d7b18..3a35877 100755 --- a/pkg/helm/helm.go +++ b/pkg/helm/helm.go @@ -20,349 +20,408 @@ package helm import ( - "fmt" - "github.com/ghodss/yaml" - "github.com/spf13/viper" - "io/ioutil" - "os" - "regexp" - "strconv" - "strings" - "time" - - "gerrit.oran-osc.org/r/ric-plt/appmgr/pkg/appmgr" - "gerrit.oran-osc.org/r/ric-plt/appmgr/pkg/cm" - "gerrit.oran-osc.org/r/ric-plt/appmgr/pkg/models" - "gerrit.oran-osc.org/r/ric-plt/appmgr/pkg/util" + "fmt" + "github.com/ghodss/yaml" + "github.com/spf13/viper" + "io/ioutil" + "os" + "regexp" + "strconv" + "strings" + "time" + + "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/appmgr" + "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/cm" + "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/models" + "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/util" ) +var kubeExec = util.KubectlExec +var helmExec = util.HelmExec + type Helm struct { - initDone bool - cm *cm.CM + initDone bool + cm *cm.CM +} + +func GetHelmVersion() { + var temp string + temp = os.Getenv("HELMVERSION") + if temp == "" { + temp = "v2.12.3" + } + appmgr.Logger.Info("Inside new Helm") + temp = strings.TrimLeft(temp,"v") + cm.EnvHelmVersion = string(temp[0:1]) //s.TrimRight(temp, ".") + appmgr.Logger.Info(cm.EnvHelmVersion) } + func NewHelm() *Helm { - return &Helm{initDone: false, cm: cm.NewCM()} + GetHelmVersion() + return &Helm{initDone: false, cm: cm.NewCM()} } func (h *Helm) Initialize() { - if h.initDone == true { - return - } - - for { - if _, err := h.Init(); err == nil { - appmgr.Logger.Info("Helm init done successfully!") - break - } - appmgr.Logger.Info("helm init failed, retyring ...") - time.Sleep(time.Duration(10) * time.Second) - } - - for { - if _, err := h.AddRepo(); err == nil { - appmgr.Logger.Info("Helm repo added successfully") - break - } - appmgr.Logger.Info("Helm repo addition failed, retyring ...") - time.Sleep(time.Duration(10) * time.Second) - } - h.initDone = true + if h.initDone == true { + return + } + appmgr.Logger.Info("START") + for { + if _, err := h.Init(); err == nil { + appmgr.Logger.Info("Helm init done successfully!") + break + } + appmgr.Logger.Info("helm init failed, retyring ...") + time.Sleep(time.Duration(10) * time.Second) + } + if cm.EnvHelmVersion == cm.HELM_VERSION_3 { + appmgr.Logger.Info("Codintion met for HELM3") + util.HelmExec(strings.Join([]string{"repo add stable https://kubernetes-charts.storage.googleapis.com/ "}, "")) + } + + for { + if _, err := h.AddRepo(); err == nil { + appmgr.Logger.Info("Helm repo added successfully") + break + } + appmgr.Logger.Info("Helm repo addition failed, retyring ...") + time.Sleep(time.Duration(10) * time.Second) + } + h.initDone = true } func (h *Helm) Run(args string) (out []byte, err error) { - return util.HelmExec(args) + return helmExec(args) } // API functions func (h *Helm) Init() (out []byte, err error) { - if err := h.AddTillerEnv(); err != nil { - return out, err - } - - return util.HelmExec(strings.Join([]string{"init -c --skip-refresh"}, "")) + if err := h.AddTillerEnv(); err != nil { + return out, err + } + if cm.EnvHelmVersion == cm.HELM_VERSION_2{ + appmgr.Logger.Info("Init for Version 2") + return helmExec(strings.Join([]string{"init -c --skip-refresh"}, "")) + } + + return out, err } func (h *Helm) AddRepo() (out []byte, err error) { - // Get helm repo user name and password from files mounted by secret object - credFile, err := ioutil.ReadFile(viper.GetString("helm.helm-username-file")) - if err != nil { - appmgr.Logger.Info("helm_repo_username ReadFile failed: %v", err.Error()) - return - } - username := " --username " + string(credFile) - - credFile, err = ioutil.ReadFile(viper.GetString("helm.helm-password-file")) - if err != nil { - appmgr.Logger.Info("helm_repo_password ReadFile failed: %v", err.Error()) - return - } - pwd := " --password " + string(credFile) - - rname := viper.GetString("helm.repo-name") - repo := viper.GetString("helm.repo") - - return util.HelmExec(strings.Join([]string{"repo add ", rname, " ", repo, username, pwd}, "")) + // Get helm repo user name and password from files mounted by secret object + username, err := ioutil.ReadFile(viper.GetString("helm.helm-username-file")) + if err != nil { + appmgr.Logger.Info("helm_repo_username ReadFile failed: %v", err.Error()) + return + } + + password, err := ioutil.ReadFile(viper.GetString("helm.helm-password-file")) + if err != nil { + appmgr.Logger.Info("helm_repo_password ReadFile failed: %v", err.Error()) + return + } + + repoArgs := fmt.Sprintf(" %s %s ", viper.GetString("helm.repo-name"), viper.GetString("helm.repo")) + credentials := fmt.Sprintf(" --username %s --password %s", string(username), string(password)) + + return helmExec(strings.Join([]string{"repo add ", repoArgs, credentials}, "")) } func (h *Helm) Install(m models.XappDescriptor) (xapp models.Xapp, err error) { - var c interface{} - m.Namespace = h.cm.GetNamespace(m.Namespace) - - out, err := h.Run(strings.Join([]string{"repo update "}, "")) - if err != nil { - return - } - - if err = h.cm.GetConfigMap(m, &c); err != nil { - out, err = h.Run(h.GetInstallArgs(m, false)) - if err != nil { - return - } - return h.ParseStatus(*m.XappName, string(out)) - } - - // ConfigMap exists, try to override - out, err = h.Run(h.GetInstallArgs(m, true)) - if err == nil { - return h.ParseStatus(*m.XappName, string(out)) - } - - c, cmErr := h.cm.PurgeConfigMap(m) - out, err = h.Run(h.GetInstallArgs(m, false)) - if err != nil { - return - } - - if cmErr == nil { - cmErr = h.cm.RestoreConfigMap(m, c) - } - return h.ParseStatus(*m.XappName, string(out)) + m.Namespace = h.cm.GetNamespace(m.Namespace) + + out, err := h.Run(strings.Join([]string{"repo update "}, "")) + if err != nil { + return + } + + out, err = h.Run(h.GetInstallArgs(m, false)) + if err != nil { + return + } + return h.ParseStatus(*m.XappName, string(out)) } func (h *Helm) Status(name string) (xapp models.Xapp, err error) { - out, err := h.Run(strings.Join([]string{"status ", name}, "")) - if err != nil { - appmgr.Logger.Info("Getting xapps status: %v", err.Error()) - return - } - - return h.ParseStatus(name, string(out)) + var command string + if cm.EnvHelmVersion == cm.HELM_VERSION_3 { + names := h.cm.GetNamespace("") + command = strings.Join([]string{"status ", name," --namespace ", names}, "") + appmgr.Logger.Info ("Status: Version 3") + }else { + command = strings.Join([]string{"status ", name}, "") + appmgr.Logger.Info ("Status: Version 2") + } + out, err := h.Run(command) + + if err != nil { + appmgr.Logger.Info("Getting xapps status: %v", err.Error()) + return + } + return h.ParseStatus(name, string(out)) } func (h *Helm) StatusAll() (xapps models.AllDeployedXapps, err error) { - xappNameList, err := h.List() - if err != nil { - appmgr.Logger.Info("Helm list failed: %v", err.Error()) - return - } + xappNameList, err := h.List() + if err != nil { + appmgr.Logger.Info("Helm list failed: %v", err.Error()) + return + } - return h.parseAllStatus(xappNameList) + return h.parseAllStatus(xappNameList) } func (h *Helm) List() (names []string, err error) { - ns := h.cm.GetNamespace("") - out, err := h.Run(strings.Join([]string{"list --all --deployed --output yaml --namespace=", ns}, "")) - if err != nil { - appmgr.Logger.Info("Listing deployed xapps failed: %v", err.Error()) - return - } - - return h.GetNames(string(out)) + ns := h.cm.GetNamespace("") + out, err := h.Run(strings.Join([]string{"list --all --deployed --output yaml --namespace=", ns}, "")) + if err != nil { + appmgr.Logger.Info("Listing deployed xapps failed: %v", err.Error()) + return + } + + return h.GetNames(string(out)) } func (h *Helm) SearchAll() models.AllDeployableXapps { - return h.cm.GetNamesFromHelmRepo() + return h.cm.GetNamesFromHelmRepo() } func (h *Helm) Delete(name string) (xapp models.Xapp, err error) { - xapp, err = h.Status(name) - if err != nil { - appmgr.Logger.Info("Fetching xapp status failed: %v", err.Error()) - return - } - - _, err = h.Run(strings.Join([]string{"del --purge ", name}, "")) - return xapp, err + xapp, err = h.Status(name) + var command string = "" + ns := h.cm.GetNamespace("") + + if err != nil { + appmgr.Logger.Info("Fetching xapp status failed: %v", err.Error()) + return + } + if cm.EnvHelmVersion == cm.HELM_VERSION_3 { + command = strings.Join([]string{"uninstall ", name," -n ", ns}, "") + appmgr.Logger.Info ("DELETE: Version 3") + } else { + command = strings.Join([]string{"del --purge ", name}, "") + appmgr.Logger.Info ("DELETE: Version 2") + } + _, err = h.Run (command) + + return xapp, err } func (h *Helm) Fetch(name, tarDir string) error { - if strings.HasSuffix(os.Args[0], ".test") { - return nil - } + if strings.HasSuffix(os.Args[0], ".test") { + return nil + } - rname := viper.GetString("helm.repo-name") + "/" + rname := viper.GetString("helm.repo-name") + "/" - _, err := h.Run(strings.Join([]string{"fetch --untar --untardir ", tarDir, " ", rname, name}, "")) - return err + _, err := h.Run(strings.Join([]string{"fetch --untar --untardir ", tarDir, " ", rname, name}, "")) + return err } // Helper functions func (h *Helm) GetVersion(name string) (version string) { - ns := h.cm.GetNamespace("") - out, err := h.Run(strings.Join([]string{"list --deployed --output yaml --namespace=", ns, " ", name}, "")) - if err != nil { - return - } - - var re = regexp.MustCompile(`AppVersion: .*`) - ver := re.FindStringSubmatch(string(out)) - if ver != nil { - version = strings.Split(ver[0], ": ")[1] - version, _ = strconv.Unquote(version) - } - - return + ns := h.cm.GetNamespace("") + var command string = "" + if cm.EnvHelmVersion == cm.HELM_VERSION_3 { + command = strings.Join([]string{"list --deployed --output yaml --namespace=", ns, " ","-f ",name}, "") + appmgr.Logger.Info ("GetVersion: Version 3") + } else { + command = strings.Join([]string{"list --deployed --output yaml --namespace=", ns, " ", name}, "") + appmgr.Logger.Info ("GetVersion: Version 2") + } + out, err := h.Run(command) + + if err != nil { + return + } + + var re = regexp.MustCompile(`AppVersion: .*`) + ver := re.FindStringSubmatch(string(out)) + if ver != nil { + version = strings.Split(ver[0], ": ")[1] + version, _ = strconv.Unquote(version) + } + + return } func (h *Helm) GetState(out string) (status string) { - re := regexp.MustCompile(`STATUS: .*`) - result := re.FindStringSubmatch(string(out)) - if result != nil { - status = strings.ToLower(strings.Split(result[0], ": ")[1]) - } + re := regexp.MustCompile(`STATUS: .*`) + result := re.FindStringSubmatch(string(out)) + if result != nil { + status = strings.ToLower(strings.Split(result[0], ": ")[1]) + } - return + return } func (h *Helm) GetAddress(out string) (ip, port string) { - var tmp string - re := regexp.MustCompile(`ClusterIP.*`) - addr := re.FindStringSubmatch(string(out)) - if addr != nil { - fmt.Sscanf(addr[0], "%s %s %s %s", &tmp, &ip, &tmp, &port) - } - - return + var tmp string + re := regexp.MustCompile(`ClusterIP.*`) + addr := re.FindStringSubmatch(string(out)) + if addr != nil { + fmt.Sscanf(addr[0], "%s %s %s %s", &tmp, &ip, &tmp, &port) + } + + return } -func (h *Helm) GetEndpointInfo(name string) (ip string, port int) { - ns := h.cm.GetNamespace("") - args := fmt.Sprintf(" get endpoints -o=jsonpath='{.subsets[*].addresses[*].ip}' service-%s-%s-rmr -n %s", ns, name, ns) - out, err := util.KubectlExec(args) - if err != nil { - return - } - appmgr.Logger.Info("Endpoint IP address of %s: %s", name, string(out)) - return fmt.Sprintf("service-%s-%s-rmr.%s", ns, name, ns), 4560 +func (h *Helm) GetEndpointInfo(name string) (svc string, port int) { + port = 4560 // Default + ns := h.cm.GetNamespace("") + args := fmt.Sprintf(" get service -n %s service-%s-%s-rmr -o json", ns, ns, name) + out, err := kubeExec(args) + if err != nil { + return fmt.Sprintf("service-%s-%s-rmr.%s", ns, name, ns), 4560 + } + appmgr.Logger.Debug("Endpoint IP address of %s: %s", name, string(out)) + + v, err := h.cm.ParseJson(string(out)) + if err != nil { + return fmt.Sprintf("service-%s-%s-rmr.%s", ns, name, ns), 4560 + } + + for _, p := range v.GetArray("spec", "ports") { + if string(p.GetStringBytes("name")) == "rmrdata" { + port = int(p.GetInt("port")) + break + } + } + appmgr.Logger.Info("service-%s-%s-rmr.%s %d", ns, name, ns, port) + + return fmt.Sprintf("service-%s-%s-rmr.%s", ns, name, ns), port } func (h *Helm) GetNames(out string) (names []string, err error) { - re := regexp.MustCompile(`Name: .*`) - result := re.FindAllStringSubmatch(out, -1) - if result == nil { - return - } - - for _, v := range result { - xappName := strings.Split(v[0], ": ")[1] - if strings.Contains(xappName, "appmgr") == false { - names = append(names, xappName) - } - } - return names, nil + re := regexp.MustCompile(`Name: .*`) + result := re.FindAllStringSubmatch(out, -1) + if result == nil { + return + } + + for _, v := range result { + xappName := strings.Split(v[0], ": ")[1] + if strings.Contains(xappName, "appmgr") == false { + names = append(names, xappName) + } + } + return names, nil } -func (h *Helm) FillInstanceData(name string, out string, xapp *models.Xapp, msgs appmgr.MessageTypes) { - ip, port := h.GetEndpointInfo(name) - if ip == "" { - appmgr.Logger.Info("Endpoint IP address not found, using CluserIP") - ip, _ = h.GetAddress(out) - } - - var tmp string - r := regexp.MustCompile(`.*(?s)(Running|Pending|Succeeded|Failed|Unknown).*?\r?\n\r?\n`) - result := r.FindStringSubmatch(string(out)) - if result == nil { - return - } - - re := regexp.MustCompile(name + "-(\\w+-\\w+).*") - resources := re.FindAllStringSubmatch(string(result[0]), -1) - if resources != nil { - for _, v := range resources { - var x models.XappInstance - var name string - fmt.Sscanf(v[0], "%s %s %s", &name, &tmp, &x.Status) - x.Name = &name - x.Status = strings.ToLower(x.Status) - x.IP = ip - x.Port = int64(port) - x.TxMessages = msgs.TxMessages - x.RxMessages = msgs.RxMessages - xapp.Instances = append(xapp.Instances, &x) - } - } +func (h *Helm) FillInstanceData(name string, out string, xapp *models.Xapp, rtData appmgr.RtmData) { + ip, port := h.GetEndpointInfo(name) + if ip == "" { + appmgr.Logger.Info("Endpoint IP address not found, using CluserIP") + ip, _ = h.GetAddress(out) + } + + var tmp string + r := regexp.MustCompile(`.*(?s)(Running|Pending|Succeeded|Failed|Unknown).*?\r?\n\r?\n`) + result := r.FindStringSubmatch(string(out)) + if result == nil { + return + } + + re := regexp.MustCompile(name + "-(\\w+-\\w+).*") + resources := re.FindAllStringSubmatch(string(result[0]), -1) + if resources != nil { + for _, v := range resources { + var x models.XappInstance + var name string + fmt.Sscanf(v[0], "%s %s %s", &name, &tmp, &x.Status) + x.Name = &name + x.Status = strings.ToLower(x.Status) + x.IP = ip + x.Port = int64(port) + x.TxMessages = rtData.TxMessages + x.RxMessages = rtData.RxMessages + x.Policies = rtData.Policies + xapp.Instances = append(xapp.Instances, &x) + } + } } func (h *Helm) ParseStatus(name string, out string) (xapp models.Xapp, err error) { - xapp.Name = &name - xapp.Version = h.GetVersion(name) - xapp.Status = h.GetState(out) + xapp.Name = &name + xapp.Version = h.GetVersion(name) + xapp.Status = h.GetState(out) - h.FillInstanceData(name, out, &xapp, h.cm.GetMessages(name)) - return + h.FillInstanceData(name, out, &xapp, h.cm.GetRtmData(name)) + return } func (h *Helm) parseAllStatus(names []string) (xapps models.AllDeployedXapps, err error) { - xapps = models.AllDeployedXapps{} - for _, name := range names { - err := h.cm.ReadSchema(name, &models.XAppConfig{}) - if err != nil { - continue - } - - x, err := h.Status(name) - if err == nil { - xapps = append(xapps, &x) - } - } - return + xapps = models.AllDeployedXapps{} + for _, name := range names { + var desc interface{} + err := h.cm.ReadSchema(name, &desc) + if err != nil { + continue + } + + x, err := h.Status(name) + if err == nil { + xapps = append(xapps, &x) + } + } + return } func (h *Helm) AddTillerEnv() (err error) { - service := viper.GetString("helm.tiller-service") - namespace := viper.GetString("helm.tiller-namespace") - port := viper.GetString("helm.tiller-port") - - if err = os.Setenv("HELM_HOST", service+"."+namespace+":"+port); err != nil { - appmgr.Logger.Info("Tiller Env Setting Failed: %v", err.Error()) - } - return err + service := viper.GetString("helm.tiller-service") + namespace := viper.GetString("helm.tiller-namespace") + port := viper.GetString("helm.tiller-port") + + if err = os.Setenv("HELM_HOST", service+"."+namespace+":"+port); err != nil { + appmgr.Logger.Info("Tiller Env Setting Failed: %v", err.Error()) + } + return err } func (h *Helm) GetInstallArgs(x models.XappDescriptor, cmOverride bool) (args string) { - args = args + " --namespace=" + x.Namespace - if x.HelmVersion != "" { - args = args + " --version=" + x.HelmVersion - } - - if x.ReleaseName != "" { - args = args + " --name=" + x.ReleaseName - } else { - args = args + " --name=" + *x.XappName - } - - if cmOverride == true { - args = args + " --set ricapp.appconfig.override=" + *x.XappName + "-appconfig" - } - - if x.OverrideFile != nil { - if overrideYaml, err := yaml.JSONToYAML([]byte(x.OverrideFile.(string))); err == nil { - err = ioutil.WriteFile("/tmp/appmgr_override.yaml", overrideYaml, 0644) - if err != nil { - appmgr.Logger.Info("ioutil.WriteFile(/tmp/appmgr_override.yaml) failed: %v", err) - } else { - args = args + " -f=/tmp/appmgr_override.yaml" - } - } else { - appmgr.Logger.Info("yaml.JSONToYAML failed: %v", err) - } - } - - repoName := viper.GetString("helm.repo-name") - if repoName == "" { - repoName = "helm-repo" - } - return fmt.Sprintf("install %s/%s %s", repoName, *x.XappName, args) + args = fmt.Sprintf("%s--namespace=%s", args, x.Namespace) + if x.HelmVersion != "" { + args = fmt.Sprintf("%s --version=%s", args, x.HelmVersion) + } + + if cm.EnvHelmVersion == cm.HELM_VERSION_2 { + if x.ReleaseName != "" { + args = fmt.Sprintf("%s --name=%s", args, x.ReleaseName) + } else { + args = fmt.Sprintf("%s --name=%s", args, *x.XappName) + appmgr.Logger.Info("") + } + appmgr.Logger.Info ("GetInstallArgs: Version 2") + } + + if cmOverride == true { + args = fmt.Sprintf("%s --set ricapp.appconfig.override=%s-appconfig", args, *x.XappName) + } + + if x.OverrideFile != nil { + if overrideYaml, err := yaml.JSONToYAML([]byte(x.OverrideFile.(string))); err == nil { + err = ioutil.WriteFile("/tmp/appmgr_override.yaml", overrideYaml, 0644) + if err != nil { + appmgr.Logger.Info("ioutil.WriteFile(/tmp/appmgr_override.yaml) failed: %v", err) + } else { + args = args + " -f=/tmp/appmgr_override.yaml" + } + } else { + appmgr.Logger.Info("yaml.JSONToYAML failed: %v", err) + } + } + + repoName := viper.GetString("helm.repo-name") + if repoName == "" { + repoName = "helm-repo" + } + + if cm.EnvHelmVersion == cm.HELM_VERSION_3 { + appmgr.Logger.Info ("GetInstallArgs last: Version 3") + return fmt.Sprintf("install %s %s/%s %s",*x.XappName, repoName, *x.XappName, args) + } else { + appmgr.Logger.Info ("GetInstallArgs last: Version 2") + return fmt.Sprintf("install %s/%s %s", repoName, *x.XappName, args) + } }