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, rtData appmgr.RtmData) {
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 = rtData.TxMessages
292 x.RxMessages = rtData.RxMessages
293 x.Policies = rtData.Policies
294 xapp.Instances = append(xapp.Instances, &x)
299 func (h *Helm) ParseStatus(name string, out string) (xapp models.Xapp, err error) {
301 xapp.Version = h.GetVersion(name)
302 xapp.Status = h.GetState(out)
304 h.FillInstanceData(name, out, &xapp, h.cm.GetRtmData(name))
308 func (h *Helm) parseAllStatus(names []string) (xapps models.AllDeployedXapps, err error) {
309 xapps = models.AllDeployedXapps{}
310 for _, name := range names {
311 err := h.cm.ReadSchema(name, &models.XAppConfig{})
316 x, err := h.Status(name)
318 xapps = append(xapps, &x)
324 func (h *Helm) AddTillerEnv() (err error) {
325 service := viper.GetString("helm.tiller-service")
326 namespace := viper.GetString("helm.tiller-namespace")
327 port := viper.GetString("helm.tiller-port")
329 if err = os.Setenv("HELM_HOST", service+"."+namespace+":"+port); err != nil {
330 appmgr.Logger.Info("Tiller Env Setting Failed: %v", err.Error())
335 func (h *Helm) GetInstallArgs(x models.XappDescriptor, cmOverride bool) (args string) {
336 args = args + " --namespace=" + x.Namespace
337 if x.HelmVersion != "" {
338 args = args + " --version=" + x.HelmVersion
341 if x.ReleaseName != "" {
342 args = args + " --name=" + x.ReleaseName
344 args = args + " --name=" + *x.XappName
347 if cmOverride == true {
348 args = args + " --set ricapp.appconfig.override=" + *x.XappName + "-appconfig"
351 if x.OverrideFile != nil {
352 if overrideYaml, err := yaml.JSONToYAML([]byte(x.OverrideFile.(string))); err == nil {
353 err = ioutil.WriteFile("/tmp/appmgr_override.yaml", overrideYaml, 0644)
355 appmgr.Logger.Info("ioutil.WriteFile(/tmp/appmgr_override.yaml) failed: %v", err)
357 args = args + " -f=/tmp/appmgr_override.yaml"
360 appmgr.Logger.Info("yaml.JSONToYAML failed: %v", err)
364 repoName := viper.GetString("helm.repo-name")
366 repoName = "helm-repo"
368 return fmt.Sprintf("install %s/%s %s", repoName, *x.XappName, args)