==================================================================================
*/
-package main
+package helm
import (
- "bytes"
- "errors"
"fmt"
+ "github.com/ghodss/yaml"
"github.com/spf13/viper"
"io/ioutil"
- "log"
"os"
- "os/exec"
"regexp"
"strconv"
"strings"
"time"
-)
-
-var execCommand = exec.Command
-
-func Exec(args string) (out []byte, err error) {
- cmd := execCommand("/bin/sh", "-c", args)
-
- var stdout bytes.Buffer
- var stderr bytes.Buffer
- cmd.Stdout = &stdout
- cmd.Stderr = &stderr
-
- log.Println("Running command: ", cmd)
- for i := 0; i < viper.GetInt("helm.retry"); i++ {
- err = cmd.Run()
- if err != nil {
- Logger.Error("Command '%s' failed with error: %v, retrying", args, err.Error()+stderr.String())
- time.Sleep(time.Duration(2) * time.Second)
- continue
- }
- break
- }
- if err == nil && !strings.HasSuffix(os.Args[0], ".test") {
- Logger.Info("command success: %s", stdout.String())
- return stdout.Bytes(), nil
- }
-
- return stdout.Bytes(), errors.New(stderr.String())
-}
-
-var HelmExec = func(args string) (out []byte, err error) {
- return Exec(strings.Join([]string{"helm", args}, " "))
-}
+ "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"
+)
-var KubectlExec = func(args string) (out []byte, err error) {
- return Exec(strings.Join([]string{"kubectl", args}, " "))
+type Helm struct {
+ initDone bool
+ cm *cm.CM
}
-func (h *Helm) SetCM(cm ConfigMapper) {
- h.cm = cm
+func NewHelm() *Helm {
+ return &Helm{initDone: false, cm: cm.NewCM()}
}
func (h *Helm) Initialize() {
for {
if _, err := h.Init(); err == nil {
- Logger.Info("Helm init done successfully!")
+ appmgr.Logger.Info("Helm init done successfully!")
break
}
- Logger.Error("helm init failed, retyring ...")
+ appmgr.Logger.Info("helm init failed, retyring ...")
time.Sleep(time.Duration(10) * time.Second)
}
for {
if _, err := h.AddRepo(); err == nil {
- Logger.Info("Helm repo added successfully")
+ appmgr.Logger.Info("Helm repo added successfully")
break
}
- Logger.Error("Helm repo addition failed, retyring ...")
+ 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 HelmExec(args)
+ return util.HelmExec(args)
}
// API functions
func (h *Helm) Init() (out []byte, err error) {
- // Add Tiller address as environment variable
- if err := addTillerEnv(); err != nil {
+ if err := h.AddTillerEnv(); err != nil {
return out, err
}
- return HelmExec(strings.Join([]string{"init -c --skip-refresh"}, ""))
+ return util.HelmExec(strings.Join([]string{"init -c --skip-refresh"}, ""))
}
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 {
- Logger.Error("helm_repo_username ReadFile failed: %v", err.Error())
+ 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 {
- Logger.Error("helm_repo_password ReadFile failed: %v", err.Error())
+ appmgr.Logger.Info("helm_repo_password ReadFile failed: %v", err.Error())
return
}
-
pwd := " --password " + string(credFile)
- // Get internal helm repo name
rname := viper.GetString("helm.repo-name")
-
- // Get helm repo address from values.yaml
repo := viper.GetString("helm.repo")
- return HelmExec(strings.Join([]string{"repo add ", rname, " ", repo, username, pwd}, ""))
+ return util.HelmExec(strings.Join([]string{"repo add ", rname, " ", repo, username, pwd}, ""))
}
-func (h *Helm) Install(m XappDeploy) (xapp Xapp, err error) {
+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
}
- var cm interface{}
- m.Namespace = h.cm.GetNamespace(m.Namespace)
-
- if err = h.cm.GetConfigMap(m, &cm); err != nil {
- out, err = h.Run(getInstallArgs(m, false))
+ 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.Name, string(out))
+ return h.ParseStatus(*m.XappName, string(out))
}
// ConfigMap exists, try to override
- out, err = h.Run(getInstallArgs(m, true))
+ out, err = h.Run(h.GetInstallArgs(m, true))
if err == nil {
- return h.ParseStatus(m.Name, string(out))
+ return h.ParseStatus(*m.XappName, string(out))
}
- cm, cmErr := h.cm.PurgeConfigMap(m)
- out, err = h.Run(getInstallArgs(m, false))
+ 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, cm)
+ cmErr = h.cm.RestoreConfigMap(m, c)
}
- return h.ParseStatus(m.Name, string(out))
+ return h.ParseStatus(*m.XappName, string(out))
}
-func (h *Helm) Status(name string) (xapp Xapp, err error) {
+func (h *Helm) Status(name string) (xapp models.Xapp, err error) {
out, err := h.Run(strings.Join([]string{"status ", name}, ""))
if err != nil {
- Logger.Error("Getting xapps status: %v", err.Error())
+ appmgr.Logger.Info("Getting xapps status: %v", err.Error())
return
}
return h.ParseStatus(name, string(out))
}
-func (h *Helm) StatusAll() (xapps []Xapp, err error) {
+func (h *Helm) StatusAll() (xapps models.AllDeployedXapps, err error) {
xappNameList, err := h.List()
if err != nil {
- Logger.Error("Helm list failed: %v", err.Error())
+ appmgr.Logger.Info("Helm list failed: %v", err.Error())
return
}
func (h *Helm) List() (names []string, err error) {
ns := h.cm.GetNamespace("")
- out, err := h.Run(strings.Join([]string{"list --all --output yaml --namespace=", ns}, ""))
+ out, err := h.Run(strings.Join([]string{"list --all --deployed --output yaml --namespace=", ns}, ""))
if err != nil {
- Logger.Error("Listing deployed xapps failed: %v", err.Error())
+ appmgr.Logger.Info("Listing deployed xapps failed: %v", err.Error())
return
}
return h.GetNames(string(out))
}
-func (h *Helm) SearchAll() (names []string) {
+func (h *Helm) SearchAll() models.AllDeployableXapps {
return h.cm.GetNamesFromHelmRepo()
}
-func (h *Helm) Delete(name string) (xapp Xapp, err error) {
+func (h *Helm) Delete(name string) (xapp models.Xapp, err error) {
xapp, err = h.Status(name)
if err != nil {
- Logger.Error("Fetching xapp status failed: %v", err.Error())
+ appmgr.Logger.Info("Fetching xapp status failed: %v", err.Error())
return
}
// Helper functions
func (h *Helm) GetVersion(name string) (version string) {
ns := h.cm.GetNamespace("")
- out, err := h.Run(strings.Join([]string{"list --output yaml --namespace=", ns, " ", name}, ""))
+ out, err := h.Run(strings.Join([]string{"list --deployed --output yaml --namespace=", ns, " ", name}, ""))
if err != nil {
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 := KubectlExec(args)
+ out, err := util.KubectlExec(args)
if err != nil {
return
}
- Logger.Info("Endpoint IP address of %s: %s", name, string(out))
-
- // "service-<namespace>-<chartname>-rmr.<namespace>"
- return "service-" + ns + "-" + name + "-rmr." + ns, 4560
+ 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) GetNames(out string) (names []string, err error) {
return names, nil
}
-func (h *Helm) FillInstanceData(name string, out string, xapp *Xapp, msgs MessageTypes) {
+func (h *Helm) FillInstanceData(name string, out string, xapp *models.Xapp, msgs appmgr.MessageTypes) {
ip, port := h.GetEndpointInfo(name)
if ip == "" {
- Logger.Info("Endpoint IP address not found, using CluserIP")
+ appmgr.Logger.Info("Endpoint IP address not found, using CluserIP")
ip, _ = h.GetAddress(out)
}
resources := re.FindAllStringSubmatch(string(result[0]), -1)
if resources != nil {
for _, v := range resources {
- var x XappInstance
- fmt.Sscanf(v[0], "%s %s %s", &x.Name, &tmp, &x.Status)
+ 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 = port
+ x.IP = ip
+ x.Port = int64(port)
x.TxMessages = msgs.TxMessages
x.RxMessages = msgs.RxMessages
- xapp.Instances = append(xapp.Instances, x)
+ xapp.Instances = append(xapp.Instances, &x)
}
}
}
-func (h *Helm) ParseStatus(name string, out string) (xapp Xapp, err error) {
- xapp.Name = name
+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)
h.FillInstanceData(name, out, &xapp, h.cm.GetMessages(name))
-
return
}
-func (h *Helm) parseAllStatus(names []string) (xapps []Xapp, err error) {
- xapps = []Xapp{}
-
+func (h *Helm) parseAllStatus(names []string) (xapps models.AllDeployedXapps, err error) {
+ xapps = models.AllDeployedXapps{}
for _, name := range names {
- err := h.cm.ReadSchema(name, &XAppConfig{})
+ err := h.cm.ReadSchema(name, &models.XAppConfig{})
if err != nil {
continue
}
x, err := h.Status(name)
if err == nil {
- xapps = append(xapps, x)
+ xapps = append(xapps, &x)
}
}
-
return
}
-func addTillerEnv() (err error) {
+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 {
- Logger.Error("Tiller Env Setting Failed: %v", err.Error())
+ appmgr.Logger.Info("Tiller Env Setting Failed: %v", err.Error())
}
-
return err
}
-func getInstallArgs(x XappDeploy, cmOverride bool) (args string) {
+func (h *Helm) GetInstallArgs(x models.XappDescriptor, cmOverride bool) (args string) {
args = args + " --namespace=" + x.Namespace
-
- if x.ImageRepo != "" {
- args = args + " --set global.repository=" + x.ImageRepo
- }
-
- if x.ServiceName != "" {
- args = args + " --set ricapp.service.name=" + x.ServiceName
+ if x.HelmVersion != "" {
+ args = args + " --version=" + x.HelmVersion
}
- if x.Hostname != "" {
- args = args + " --set ricapp.hostname=" + x.Hostname
+ if x.ReleaseName != "" {
+ args = args + " --name=" + x.ReleaseName
+ } else {
+ args = args + " --name=" + *x.XappName
}
if cmOverride == true {
- args = args + " --set ricapp.appconfig.override=" + x.Name + "-appconfig"
+ 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)
+ }
}
- rname := viper.GetString("helm.repo-name")
- return fmt.Sprintf("install %s/%s --name=%s %s", rname, x.Name, x.Name, args)
+ repoName := viper.GetString("helm.repo-name")
+ if repoName == "" {
+ repoName = "helm-repo"
+ }
+ return fmt.Sprintf("install %s/%s %s", repoName, *x.XappName, args)
}