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.oran-osc.org/r/ric-plt/appmgr/pkg/appmgr"
34 "gerrit.oran-osc.org/r/ric-plt/appmgr/pkg/cm"
35 "gerrit.oran-osc.org/r/ric-plt/appmgr/pkg/models"
36 "gerrit.oran-osc.org/r/ric-plt/appmgr/pkg/util"
44 func NewHelm() *Helm {
45 return &Helm{initDone: false, cm: cm.NewCM()}
48 func (h *Helm) Initialize() {
49 if h.initDone == true {
54 if _, err := h.Init(); err == nil {
55 appmgr.Logger.Info("Helm init done successfully!")
58 appmgr.Logger.Info("helm init failed, retyring ...")
59 time.Sleep(time.Duration(10) * time.Second)
63 if _, err := h.AddRepo(); err == nil {
64 appmgr.Logger.Info("Helm repo added successfully")
67 appmgr.Logger.Info("Helm repo addition failed, retyring ...")
68 time.Sleep(time.Duration(10) * time.Second)
73 func (h *Helm) Run(args string) (out []byte, err error) {
74 return util.HelmExec(args)
78 func (h *Helm) Init() (out []byte, err error) {
79 if err := h.AddTillerEnv(); err != nil {
83 return util.HelmExec(strings.Join([]string{"init -c --skip-refresh"}, ""))
86 func (h *Helm) AddRepo() (out []byte, err error) {
87 // Get helm repo user name and password from files mounted by secret object
88 credFile, err := ioutil.ReadFile(viper.GetString("helm.helm-username-file"))
90 appmgr.Logger.Info("helm_repo_username ReadFile failed: %v", err.Error())
93 username := " --username " + string(credFile)
95 credFile, err = ioutil.ReadFile(viper.GetString("helm.helm-password-file"))
97 appmgr.Logger.Info("helm_repo_password ReadFile failed: %v", err.Error())
100 pwd := " --password " + string(credFile)
102 rname := viper.GetString("helm.repo-name")
103 repo := viper.GetString("helm.repo")
105 return util.HelmExec(strings.Join([]string{"repo add ", rname, " ", repo, username, pwd}, ""))
108 func (h *Helm) Install(m models.XappDescriptor) (xapp models.Xapp, err error) {
110 m.Namespace = h.cm.GetNamespace(m.Namespace)
112 out, err := h.Run(strings.Join([]string{"repo update "}, ""))
117 if err = h.cm.GetConfigMap(m, &c); err != nil {
118 out, err = h.Run(h.GetInstallArgs(m, false))
122 return h.ParseStatus(*m.XappName, string(out))
125 // ConfigMap exists, try to override
126 out, err = h.Run(h.GetInstallArgs(m, true))
128 return h.ParseStatus(*m.XappName, string(out))
131 c, cmErr := h.cm.PurgeConfigMap(m)
132 out, err = h.Run(h.GetInstallArgs(m, false))
138 cmErr = h.cm.RestoreConfigMap(m, c)
140 return h.ParseStatus(*m.XappName, string(out))
143 func (h *Helm) Status(name string) (xapp models.Xapp, err error) {
144 out, err := h.Run(strings.Join([]string{"status ", name}, ""))
146 appmgr.Logger.Info("Getting xapps status: %v", err.Error())
150 return h.ParseStatus(name, string(out))
153 func (h *Helm) StatusAll() (xapps models.AllDeployedXapps, err error) {
154 xappNameList, err := h.List()
156 appmgr.Logger.Info("Helm list failed: %v", err.Error())
160 return h.parseAllStatus(xappNameList)
163 func (h *Helm) List() (names []string, err error) {
164 ns := h.cm.GetNamespace("")
165 out, err := h.Run(strings.Join([]string{"list --all --deployed --output yaml --namespace=", ns}, ""))
167 appmgr.Logger.Info("Listing deployed xapps failed: %v", err.Error())
171 return h.GetNames(string(out))
174 func (h *Helm) SearchAll() models.AllDeployableXapps {
175 return h.cm.GetNamesFromHelmRepo()
178 func (h *Helm) Delete(name string) (xapp models.Xapp, err error) {
179 xapp, err = h.Status(name)
181 appmgr.Logger.Info("Fetching xapp status failed: %v", err.Error())
185 _, err = h.Run(strings.Join([]string{"del --purge ", name}, ""))
189 func (h *Helm) Fetch(name, tarDir string) error {
190 if strings.HasSuffix(os.Args[0], ".test") {
194 rname := viper.GetString("helm.repo-name") + "/"
196 _, err := h.Run(strings.Join([]string{"fetch --untar --untardir ", tarDir, " ", rname, name}, ""))
201 func (h *Helm) GetVersion(name string) (version string) {
202 ns := h.cm.GetNamespace("")
203 out, err := h.Run(strings.Join([]string{"list --deployed --output yaml --namespace=", ns, " ", name}, ""))
208 var re = regexp.MustCompile(`AppVersion: .*`)
209 ver := re.FindStringSubmatch(string(out))
211 version = strings.Split(ver[0], ": ")[1]
212 version, _ = strconv.Unquote(version)
218 func (h *Helm) GetState(out string) (status string) {
219 re := regexp.MustCompile(`STATUS: .*`)
220 result := re.FindStringSubmatch(string(out))
222 status = strings.ToLower(strings.Split(result[0], ": ")[1])
228 func (h *Helm) GetAddress(out string) (ip, port string) {
230 re := regexp.MustCompile(`ClusterIP.*`)
231 addr := re.FindStringSubmatch(string(out))
233 fmt.Sscanf(addr[0], "%s %s %s %s", &tmp, &ip, &tmp, &port)
239 func (h *Helm) GetEndpointInfo(name string) (ip string, port int) {
240 ns := h.cm.GetNamespace("")
241 args := fmt.Sprintf(" get endpoints -o=jsonpath='{.subsets[*].addresses[*].ip}' service-%s-%s-rmr -n %s", ns, name, ns)
242 out, err := util.KubectlExec(args)
246 appmgr.Logger.Info("Endpoint IP address of %s: %s", name, string(out))
247 return fmt.Sprintf("service-%s-%s-rmr.%s", ns, name, ns), 4560
250 func (h *Helm) GetNames(out string) (names []string, err error) {
251 re := regexp.MustCompile(`Name: .*`)
252 result := re.FindAllStringSubmatch(out, -1)
257 for _, v := range result {
258 xappName := strings.Split(v[0], ": ")[1]
259 if strings.Contains(xappName, "appmgr") == false {
260 names = append(names, xappName)
266 func (h *Helm) FillInstanceData(name string, out string, xapp *models.Xapp, msgs appmgr.MessageTypes) {
267 ip, port := h.GetEndpointInfo(name)
269 appmgr.Logger.Info("Endpoint IP address not found, using CluserIP")
270 ip, _ = h.GetAddress(out)
274 r := regexp.MustCompile(`.*(?s)(Running|Pending|Succeeded|Failed|Unknown).*?\r?\n\r?\n`)
275 result := r.FindStringSubmatch(string(out))
280 re := regexp.MustCompile(name + "-(\\w+-\\w+).*")
281 resources := re.FindAllStringSubmatch(string(result[0]), -1)
282 if resources != nil {
283 for _, v := range resources {
284 var x models.XappInstance
286 fmt.Sscanf(v[0], "%s %s %s", &name, &tmp, &x.Status)
288 x.Status = strings.ToLower(x.Status)
291 x.TxMessages = msgs.TxMessages
292 x.RxMessages = msgs.RxMessages
293 xapp.Instances = append(xapp.Instances, &x)
298 func (h *Helm) ParseStatus(name string, out string) (xapp models.Xapp, err error) {
300 xapp.Version = h.GetVersion(name)
301 xapp.Status = h.GetState(out)
303 h.FillInstanceData(name, out, &xapp, h.cm.GetMessages(name))
307 func (h *Helm) parseAllStatus(names []string) (xapps models.AllDeployedXapps, err error) {
308 xapps = models.AllDeployedXapps{}
309 for _, name := range names {
310 err := h.cm.ReadSchema(name, &models.XAppConfig{})
315 x, err := h.Status(name)
317 xapps = append(xapps, &x)
323 func (h *Helm) AddTillerEnv() (err error) {
324 service := viper.GetString("helm.tiller-service")
325 namespace := viper.GetString("helm.tiller-namespace")
326 port := viper.GetString("helm.tiller-port")
328 if err = os.Setenv("HELM_HOST", service+"."+namespace+":"+port); err != nil {
329 appmgr.Logger.Info("Tiller Env Setting Failed: %v", err.Error())
334 func (h *Helm) GetInstallArgs(x models.XappDescriptor, cmOverride bool) (args string) {
335 args = args + " --namespace=" + x.Namespace
336 if x.HelmVersion != "" {
337 args = args + " --version=" + x.HelmVersion
340 if x.ReleaseName != "" {
341 args = args + " --name=" + x.ReleaseName
343 args = args + " --name=" + *x.XappName
346 if cmOverride == true {
347 args = args + " --set ricapp.appconfig.override=" + *x.XappName + "-appconfig"
350 if x.OverrideFile != nil {
351 if overrideYaml, err := yaml.JSONToYAML([]byte(x.OverrideFile.(string))); err == nil {
352 err = ioutil.WriteFile("/tmp/appmgr_override.yaml", overrideYaml, 0644)
354 appmgr.Logger.Info("ioutil.WriteFile(/tmp/appmgr_override.yaml) failed: %v", err)
356 args = args + " -f=/tmp/appmgr_override.yaml"
359 appmgr.Logger.Info("yaml.JSONToYAML failed: %v", err)
363 repoName := viper.GetString("helm.repo-name")
365 repoName = "helm-repo"
367 return fmt.Sprintf("install %s/%s %s", repoName, *x.XappName, args)