Remove system information from logs
[ealt-edge.git] / mecm / mepm / applcm / k8shelm / pkg / plugin / helmclient.go
1 /*
2  * Copyright 2020 Huawei Technologies Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package plugin
18
19 import (
20         "bytes"
21         "fmt"
22         "github.com/sirupsen/logrus"
23         "helm.sh/helm/v3/pkg/action"
24         "helm.sh/helm/v3/pkg/chart/loader"
25         "helm.sh/helm/v3/pkg/kube"
26         "os"
27 )
28
29 // Constants to be taken from deployment file
30 const (
31         releaseNamespace  = "default"
32         chartPath  = "/go/release/charts/"
33         kubeconfigPath  = "/go/release/kubeconfig/"
34 )
35
36 // Helm client
37 type HelmClient struct {
38         hostIP string
39         kubeconfig string
40         logger *logrus.Logger
41 }
42
43 // Constructor of helm client for a given host IP
44 func NewHelmClient(hostIP string, logger *logrus.Logger) (*HelmClient, error) {
45         // Kubeconfig file will be picked based on host IP and will be check for existence
46         exists, err := fileExists(kubeconfigPath + hostIP)
47         if exists {
48                 return &HelmClient{hostIP: hostIP, kubeconfig: kubeconfigPath + hostIP, logger: logger}, nil
49         } else {
50                 logger.Errorf("No file exist with name: %s. Err: %s", kubeconfigPath + hostIP)
51                 return nil, err
52         }
53 }
54
55 // Install a given helm chart
56 func (hc *HelmClient) installChart(helmPkg bytes.Buffer) (string, error) {
57         hc.logger.Debug("Inside helm client")
58
59         // Create temporary file to hold helm chart
60         file, err := os.Create(chartPath + "temp.tar.gz")
61         if err != nil {
62                 hc.logger.Errorf("Unable to create file: %s. Err: %s", chartPath + "temp.tar.gz", err)
63                 return "", err
64         }
65         defer os.Remove(chartPath + "temp.tar.gz")
66
67         // Write input bytes to temp file
68         _, err = helmPkg.WriteTo(file)
69         if err != nil {
70                 hc.logger.Errorf("Unable to write to file: %s. Err: %s", chartPath + "temp.tar.gz", err)
71                 return "", err
72         }
73
74         // Load the file to chart
75         chart, err := loader.Load(chartPath + "temp.tar.gz")
76         if err != nil {
77                 hc.logger.Errorf("Unable to load chart from file: %s. Err: %s", chartPath + "temp.tar.gz", err)
78                 return "", err
79         }
80
81         // Release name will be taken from the name in chart's metadata
82         relName := chart.Metadata.Name
83
84         // Initialize action config
85         actionConfig := new(action.Configuration)
86         if err := actionConfig.Init(kube.GetConfig(hc.kubeconfig, "", releaseNamespace), releaseNamespace,
87                 os.Getenv("HELM_DRIVER"), func(format string, v ...interface{}) {
88                         fmt.Sprintf(format, v)
89                 }); err != nil {
90                 hc.logger.Errorf("Unable to initialize action config Err: %s", err)
91                 return "", err
92         }
93
94         // Prepare chart install action and install chart
95         installer := action.NewInstall(actionConfig)
96         installer.Namespace = releaseNamespace
97         installer.ReleaseName = relName
98         rel, err := installer.Run(chart, nil)
99         if err != nil {
100                 hc.logger.Errorf("Unable to install chart with release name: %s. Err: %s", relName, err)
101                 return "", err
102         }
103         hc.logger.Info("Successfully create chart with release name: %s", relName)
104         return rel.Name, err
105 }
106
107 // Un-Install a given helm chart
108 func (hc *HelmClient) uninstallChart(relName string) (error) {
109         // Prepare action config and uninstall chart
110         actionConfig := new(action.Configuration)
111         if err := actionConfig.Init(kube.GetConfig(hc.kubeconfig, "", releaseNamespace), releaseNamespace,
112                 os.Getenv("HELM_DRIVER"), func(format string, v ...interface{}) {
113                         fmt.Sprintf(format, v)
114                 }); err != nil {
115                 hc.logger.Errorf("Unable to initialize action config Err: %s", err)
116                 return err
117         }
118
119         ui := action.NewUninstall(actionConfig)
120         res, err := ui.Run(relName);
121         if err != nil {
122                 hc.logger.Errorf("Unable to uninstall chart with release name: %s. Err: %s", relName, err)
123                 return err
124         }
125         hc.logger.Info("Successfully uninstalled chart with release name: %s. Response Info: %s", res.Release.Name, res.Info)
126         return nil
127 }
128
129 // Query a given chart
130 func (hc *HelmClient) queryChart(relName string) (string, error)  {
131         actionConfig := new(action.Configuration)
132         if err := actionConfig.Init(kube.GetConfig(hc.kubeconfig, "", releaseNamespace), releaseNamespace,
133                 os.Getenv("HELM_DRIVER"), func(format string, v ...interface{}) {
134                         fmt.Sprintf(format, v)
135                 }); err != nil {
136                 hc.logger.Errorf("Unable to initialize action config Err: %s", err)
137                 return "", err
138         }
139         s := action.NewStatus(actionConfig)
140         res, err := s.Run(relName)
141         if err != nil {
142                 hc.logger.Errorf("Unable to query chart with release name: %s. Err: %s", relName, err)
143                 return "", err
144         }
145         return res.Info.Status.String(), nil
146 }
147
148 // fileExists checks if a file exists and is not a directory before we
149 // try using it to prevent further errors.
150 func fileExists(filename string) (bool, error) {
151         info, err := os.Stat(filename)
152         if os.IsNotExist(err) {
153                 return false, err
154         }
155         return !info.IsDir(), nil
156 }