2 ==================================================================================
3 Copyright (c) 2019 AT&T Intellectual Property.
4 Copyright (c) 2019 Nokia
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 ==================================================================================
24 "github.com/ghodss/yaml"
25 "github.com/spf13/viper"
33 "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/appmgr"
34 "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/cm"
35 "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/models"
36 "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/util"
39 var kubeExec = util.KubectlExec
40 var helmExec = util.HelmExec
47 func GetHelmVersion() {
49 temp = os.Getenv("HELMVERSION")
53 appmgr.Logger.Info("Inside new Helm")
54 temp = strings.TrimLeft(temp,"v")
55 cm.EnvHelmVersion = string(temp[0:1]) //s.TrimRight(temp, ".")
56 appmgr.Logger.Info(cm.EnvHelmVersion)
60 func NewHelm() *Helm {
62 return &Helm{initDone: false, cm: cm.NewCM()}
65 func (h *Helm) Initialize() {
66 if h.initDone == true {
69 appmgr.Logger.Info("START")
71 if _, err := h.Init(); err == nil {
72 appmgr.Logger.Info("Helm init done successfully!")
75 appmgr.Logger.Info("helm init failed, retyring ...")
76 time.Sleep(time.Duration(10) * time.Second)
78 if cm.EnvHelmVersion == cm.HELM_VERSION_3 {
79 appmgr.Logger.Info("Codintion met for HELM3")
80 util.HelmExec(strings.Join([]string{"repo add stable https://kubernetes-charts.storage.googleapis.com/ "}, ""))
84 if _, err := h.AddRepo(); err == nil {
85 appmgr.Logger.Info("Helm repo added successfully")
88 appmgr.Logger.Info("Helm repo addition failed, retyring ...")
89 time.Sleep(time.Duration(10) * time.Second)
94 func (h *Helm) Run(args string) (out []byte, err error) {
99 func (h *Helm) Init() (out []byte, err error) {
100 if err := h.AddTillerEnv(); err != nil {
103 if cm.EnvHelmVersion == cm.HELM_VERSION_2{
104 appmgr.Logger.Info("Init for Version 2")
105 return helmExec(strings.Join([]string{"init -c --skip-refresh"}, ""))
111 func (h *Helm) AddRepo() (out []byte, err error) {
112 // Get helm repo user name and password from files mounted by secret object
113 username, err := ioutil.ReadFile(viper.GetString("helm.helm-username-file"))
115 appmgr.Logger.Info("helm_repo_username ReadFile failed: %v", err.Error())
119 password, err := ioutil.ReadFile(viper.GetString("helm.helm-password-file"))
121 appmgr.Logger.Info("helm_repo_password ReadFile failed: %v", err.Error())
125 repoArgs := fmt.Sprintf(" %s %s ", viper.GetString("helm.repo-name"), viper.GetString("helm.repo"))
126 credentials := fmt.Sprintf(" --username %s --password %s", string(username), string(password))
128 return helmExec(strings.Join([]string{"repo add ", repoArgs, credentials}, ""))
131 func (h *Helm) Install(m models.XappDescriptor) (xapp models.Xapp, err error) {
132 m.Namespace = h.cm.GetNamespace(m.Namespace)
134 out, err := h.Run(strings.Join([]string{"repo update "}, ""))
139 out, err = h.Run(h.GetInstallArgs(m, false))
143 return h.ParseStatus(*m.XappName, string(out))
146 func (h *Helm) Status(name string) (xapp models.Xapp, err error) {
148 if cm.EnvHelmVersion == cm.HELM_VERSION_3 {
149 names := h.cm.GetNamespace("")
150 command = strings.Join([]string{"status ", name," --namespace ", names}, "")
151 appmgr.Logger.Info ("Status: Version 3")
153 command = strings.Join([]string{"status ", name}, "")
154 appmgr.Logger.Info ("Status: Version 2")
156 out, err := h.Run(command)
159 appmgr.Logger.Info("Getting xapps status: %v", err.Error())
162 return h.ParseStatus(name, string(out))
165 func (h *Helm) StatusAll() (xapps models.AllDeployedXapps, err error) {
166 xappNameList, err := h.List()
168 appmgr.Logger.Info("Helm list failed: %v", err.Error())
172 return h.parseAllStatus(xappNameList)
175 func (h *Helm) List() (names []string, err error) {
176 ns := h.cm.GetNamespace("")
177 out, err := h.Run(strings.Join([]string{"list --all --deployed --output yaml --namespace=", ns}, ""))
179 appmgr.Logger.Info("Listing deployed xapps failed: %v", err.Error())
183 return h.GetNames(string(out))
186 func (h *Helm) SearchAll() models.AllDeployableXapps {
187 return h.cm.GetNamesFromHelmRepo()
190 func (h *Helm) Delete(name string) (xapp models.Xapp, err error) {
191 xapp, err = h.Status(name)
192 var command string = ""
193 ns := h.cm.GetNamespace("")
196 appmgr.Logger.Info("Fetching xapp status failed: %v", err.Error())
199 if cm.EnvHelmVersion == cm.HELM_VERSION_3 {
200 command = strings.Join([]string{"uninstall ", name," -n ", ns}, "")
201 appmgr.Logger.Info ("DELETE: Version 3")
203 command = strings.Join([]string{"del --purge ", name}, "")
204 appmgr.Logger.Info ("DELETE: Version 2")
206 _, err = h.Run (command)
211 func (h *Helm) Fetch(name, tarDir string) error {
212 if strings.HasSuffix(os.Args[0], ".test") {
216 rname := viper.GetString("helm.repo-name") + "/"
218 _, err := h.Run(strings.Join([]string{"fetch --untar --untardir ", tarDir, " ", rname, name}, ""))
223 func (h *Helm) GetVersion(name string) (version string) {
224 ns := h.cm.GetNamespace("")
225 var command string = ""
226 if cm.EnvHelmVersion == cm.HELM_VERSION_3 {
227 command = strings.Join([]string{"list --deployed --output yaml --namespace=", ns, " ","-f ",name}, "")
228 appmgr.Logger.Info ("GetVersion: Version 3")
230 command = strings.Join([]string{"list --deployed --output yaml --namespace=", ns, " ", name}, "")
231 appmgr.Logger.Info ("GetVersion: Version 2")
233 out, err := h.Run(command)
239 var re = regexp.MustCompile(`AppVersion: .*`)
240 ver := re.FindStringSubmatch(string(out))
242 version = strings.Split(ver[0], ": ")[1]
243 version, _ = strconv.Unquote(version)
249 func (h *Helm) GetState(out string) (status string) {
250 re := regexp.MustCompile(`STATUS: .*`)
251 result := re.FindStringSubmatch(string(out))
253 status = strings.ToLower(strings.Split(result[0], ": ")[1])
259 func (h *Helm) GetAddress(out string) (ip, port string) {
261 re := regexp.MustCompile(`ClusterIP.*`)
262 addr := re.FindStringSubmatch(string(out))
264 fmt.Sscanf(addr[0], "%s %s %s %s", &tmp, &ip, &tmp, &port)
270 func (h *Helm) GetEndpointInfo(name string) (svc string, port int) {
271 port = 4560 // Default
272 ns := h.cm.GetNamespace("")
273 args := fmt.Sprintf(" get service -n %s service-%s-%s-rmr -o json", ns, ns, name)
274 out, err := kubeExec(args)
276 return fmt.Sprintf("service-%s-%s-rmr.%s", ns, name, ns), 4560
278 appmgr.Logger.Debug("Endpoint IP address of %s: %s", name, string(out))
280 v, err := h.cm.ParseJson(string(out))
282 return fmt.Sprintf("service-%s-%s-rmr.%s", ns, name, ns), 4560
285 for _, p := range v.GetArray("spec", "ports") {
286 if string(p.GetStringBytes("name")) == "rmrdata" {
287 port = int(p.GetInt("port"))
291 appmgr.Logger.Info("service-%s-%s-rmr.%s %d", ns, name, ns, port)
293 return fmt.Sprintf("service-%s-%s-rmr.%s", ns, name, ns), port
296 func (h *Helm) GetNames(out string) (names []string, err error) {
297 re := regexp.MustCompile(`Name: .*`)
298 result := re.FindAllStringSubmatch(out, -1)
303 for _, v := range result {
304 xappName := strings.Split(v[0], ": ")[1]
305 if strings.Contains(xappName, "appmgr") == false {
306 names = append(names, xappName)
312 func (h *Helm) FillInstanceData(name string, out string, xapp *models.Xapp, rtData appmgr.RtmData) {
313 ip, port := h.GetEndpointInfo(name)
315 appmgr.Logger.Info("Endpoint IP address not found, using CluserIP")
316 ip, _ = h.GetAddress(out)
320 r := regexp.MustCompile(`.*(?s)(Running|Pending|Succeeded|Failed|Unknown).*?\r?\n\r?\n`)
321 result := r.FindStringSubmatch(string(out))
326 re := regexp.MustCompile(name + "-(\\w+-\\w+).*")
327 resources := re.FindAllStringSubmatch(string(result[0]), -1)
328 if resources != nil {
329 for _, v := range resources {
330 var x models.XappInstance
332 fmt.Sscanf(v[0], "%s %s %s", &name, &tmp, &x.Status)
334 x.Status = strings.ToLower(x.Status)
337 x.TxMessages = rtData.TxMessages
338 x.RxMessages = rtData.RxMessages
339 x.Policies = rtData.Policies
340 xapp.Instances = append(xapp.Instances, &x)
345 func (h *Helm) ParseStatus(name string, out string) (xapp models.Xapp, err error) {
347 xapp.Version = h.GetVersion(name)
348 xapp.Status = h.GetState(out)
350 h.FillInstanceData(name, out, &xapp, h.cm.GetRtmData(name))
354 func (h *Helm) parseAllStatus(names []string) (xapps models.AllDeployedXapps, err error) {
355 xapps = models.AllDeployedXapps{}
356 for _, name := range names {
358 err := h.cm.ReadSchema(name, &desc)
363 x, err := h.Status(name)
365 xapps = append(xapps, &x)
371 func (h *Helm) AddTillerEnv() (err error) {
372 service := viper.GetString("helm.tiller-service")
373 namespace := viper.GetString("helm.tiller-namespace")
374 port := viper.GetString("helm.tiller-port")
376 if err = os.Setenv("HELM_HOST", service+"."+namespace+":"+port); err != nil {
377 appmgr.Logger.Info("Tiller Env Setting Failed: %v", err.Error())
382 func (h *Helm) GetInstallArgs(x models.XappDescriptor, cmOverride bool) (args string) {
383 args = fmt.Sprintf("%s--namespace=%s", args, x.Namespace)
384 if x.HelmVersion != "" {
385 args = fmt.Sprintf("%s --version=%s", args, x.HelmVersion)
388 if cm.EnvHelmVersion == cm.HELM_VERSION_2 {
389 if x.ReleaseName != "" {
390 args = fmt.Sprintf("%s --name=%s", args, x.ReleaseName)
392 args = fmt.Sprintf("%s --name=%s", args, *x.XappName)
393 appmgr.Logger.Info("")
395 appmgr.Logger.Info ("GetInstallArgs: Version 2")
398 if cmOverride == true {
399 args = fmt.Sprintf("%s --set ricapp.appconfig.override=%s-appconfig", args, *x.XappName)
402 if x.OverrideFile != nil {
403 if overrideYaml, err := yaml.JSONToYAML([]byte(x.OverrideFile.(string))); err == nil {
404 err = ioutil.WriteFile("/tmp/appmgr_override.yaml", overrideYaml, 0644)
406 appmgr.Logger.Info("ioutil.WriteFile(/tmp/appmgr_override.yaml) failed: %v", err)
408 args = args + " -f=/tmp/appmgr_override.yaml"
411 appmgr.Logger.Info("yaml.JSONToYAML failed: %v", err)
415 repoName := viper.GetString("helm.repo-name")
417 repoName = "helm-repo"
420 if cm.EnvHelmVersion == cm.HELM_VERSION_3 {
421 appmgr.Logger.Info ("GetInstallArgs last: Version 3")
422 return fmt.Sprintf("install %s %s/%s %s",*x.XappName, repoName, *x.XappName, args)
424 appmgr.Logger.Info ("GetInstallArgs last: Version 2")
425 return fmt.Sprintf("install %s/%s %s", repoName, *x.XappName, args)