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 ==================================================================================
26 "github.com/spf13/viper"
27 "github.com/valyala/fastjson"
28 "github.com/xeipuuv/gojsonschema"
36 "gerrit.oran-osc.org/r/ric-plt/appmgr/pkg/appmgr"
37 "gerrit.oran-osc.org/r/ric-plt/appmgr/pkg/models"
38 "gerrit.oran-osc.org/r/ric-plt/appmgr/pkg/util"
47 func (cm *CM) UploadConfig() (cfg models.AllXappConfig) {
48 ns := cm.GetNamespace("")
49 for _, name := range cm.GetNamesFromHelmRepo() {
54 c := models.XAppConfig{
55 Metadata: &models.ConfigMetadata{Name: &name, Namespace: ns, ConfigName: cm.GetConfigMapName(name, ns)},
58 err := cm.ReadSchema(name, &c)
63 err = cm.ReadConfigMap(c.Metadata.ConfigName, ns, &c.Config)
65 appmgr.Logger.Info("No active configMap found, using default!")
73 func (cm *CM) ReadSchema(name string, c *models.XAppConfig) (err error) {
74 if err = cm.FetchChart(name); err != nil {
78 tarDir := viper.GetString("xapp.tarDir")
79 err = cm.ReadFile(path.Join(tarDir, name, viper.GetString("xapp.schema")), &c.Descriptor)
84 err = cm.ReadFile(path.Join(tarDir, name, viper.GetString("xapp.config")), &c.Config)
89 if err = os.RemoveAll(path.Join(tarDir, name)); err != nil {
90 appmgr.Logger.Info("RemoveAll failed: %v", err)
96 func (cm *CM) ReadConfigMap(ConfigName string, ns string, c *interface{}) (err error) {
97 args := fmt.Sprintf("get configmap -o jsonpath='{.data.config-file\\.json}' -n %s %s", ns, ConfigName)
98 configMapJson, err := util.KubectlExec(args)
103 err = json.Unmarshal([]byte(configMapJson), &c)
111 func (cm *CM) ApplyConfigMap(r models.XAppConfig, action string) (err error) {
112 c := appmgr.ConfigMap{
115 Metadata: appmgr.CMMetadata{Name: *r.Metadata.Name, Namespace: r.Metadata.Namespace},
119 cmJson, err := json.Marshal(c.Data)
121 appmgr.Logger.Info("Config marshalling failed: %v", err)
125 cmFile := viper.GetString("xapp.tmpConfig")
126 err = ioutil.WriteFile(cmFile, cmJson, 0644)
128 appmgr.Logger.Info("WriteFile failed: %v", err)
132 cmd := " create configmap -n %s %s --from-file=%s -o json --dry-run | kubectl %s -f -"
133 args := fmt.Sprintf(cmd, r.Metadata.Namespace, r.Metadata.ConfigName, cmFile, action)
134 _, err = util.KubectlExec(args)
138 appmgr.Logger.Info("Configmap changes done!")
143 func (cm *CM) GetConfigMap(m models.XappDescriptor, c *interface{}) (err error) {
144 return cm.ReadConfigMap(cm.GetConfigMapName(*m.XappName, m.Namespace), m.Namespace, c)
147 func (cm *CM) CreateConfigMap(r models.XAppConfig) (errList models.ConfigValidationErrors, err error) {
148 if errList, err = cm.Validate(r); err != nil {
151 err = cm.ApplyConfigMap(r, "create")
155 func (cm *CM) UpdateConfigMap(r models.XAppConfig) (errList models.ConfigValidationErrors, err error) {
156 if errList, err = cm.Validate(r); err != nil {
160 // Re-create the configmap with the new parameters
161 err = cm.ApplyConfigMap(r, "apply")
165 func (cm *CM) DeleteConfigMap(r models.ConfigMetadata) (c interface{}, err error) {
166 err = cm.ReadConfigMap(r.ConfigName, r.Namespace, &c)
168 args := fmt.Sprintf(" delete configmap --namespace=%s %s", r.Namespace, r.ConfigName)
169 _, err = util.KubectlExec(args)
174 func (cm *CM) PurgeConfigMap(m models.XappDescriptor) (c interface{}, err error) {
175 md := models.ConfigMetadata{Name: m.XappName, Namespace: m.Namespace, ConfigName: cm.GetConfigMapName(*m.XappName, m.Namespace)}
177 return cm.DeleteConfigMap(md)
180 func (cm *CM) RestoreConfigMap(m models.XappDescriptor, c interface{}) (err error) {
181 md := &models.ConfigMetadata{Name: m.XappName, Namespace: m.Namespace, ConfigName: cm.GetConfigMapName(*m.XappName, m.Namespace)}
182 time.Sleep(time.Duration(10 * time.Second))
184 return cm.ApplyConfigMap(models.XAppConfig{Metadata: md, Config: c}, "create")
187 func (cm *CM) GetNamesFromHelmRepo() (names []string) {
188 rname := viper.GetString("helm.repo-name")
190 cmdArgs := strings.Join([]string{"search ", rname}, "")
191 out, err := util.HelmExec(cmdArgs)
196 re := regexp.MustCompile(rname + `/.*`)
197 result := re.FindAllStringSubmatch(string(out), -1)
200 for _, v := range result {
201 fmt.Sscanf(v[0], "%s", &tmp)
202 names = append(names, strings.Split(tmp, "/")[1])
208 func (cm *CM) Validate(req models.XAppConfig) (errList models.ConfigValidationErrors, err error) {
209 c := models.XAppConfig{}
210 err = cm.ReadSchema(*req.Metadata.Name, &c)
212 appmgr.Logger.Info("No schema file found for '%s', aborting ...", *req.Metadata.Name)
215 return cm.doValidate(c.Descriptor, req.Config)
218 func (cm *CM) doValidate(schema, cfg interface{}) (errList models.ConfigValidationErrors, err error) {
219 schemaLoader := gojsonschema.NewGoLoader(schema)
220 documentLoader := gojsonschema.NewGoLoader(cfg)
222 result, err := gojsonschema.Validate(schemaLoader, documentLoader)
224 appmgr.Logger.Info("Validation failed: %v", err)
228 if result.Valid() == false {
229 appmgr.Logger.Info("The document is not valid, Errors: %v", result.Errors())
230 for _, desc := range result.Errors() {
231 field := desc.Field()
232 validationError := desc.Description()
233 errList = append(errList, &models.ConfigValidationError{Field: &field, Error: &validationError})
235 return errList, errors.New("Validation failed!")
240 func (cm *CM) ReadFile(name string, data interface{}) (err error) {
241 f, err := ioutil.ReadFile(name)
243 appmgr.Logger.Info("Reading '%s' file failed: %v", name, err)
247 err = json.Unmarshal(f, &data)
249 appmgr.Logger.Info("Unmarshalling '%s' file failed: %v", name, err)
256 func (cm *CM) FetchChart(name string) (err error) {
257 tarDir := viper.GetString("xapp.tarDir")
258 repo := viper.GetString("helm.repo-name")
259 fetchArgs := fmt.Sprintf("--untar --untardir %s %s/%s", tarDir, repo, name)
261 _, err = util.HelmExec(strings.Join([]string{"fetch ", fetchArgs}, ""))
265 func (cm *CM) GetMessages(name string) (msgs appmgr.MessageTypes) {
266 appmgr.Logger.Info("Fetching tx/rx messages for: %s", name)
268 ns := cm.GetNamespace("")
269 args := fmt.Sprintf("get configmap -o jsonpath='{.data.config-file\\.json}' -n %s %s", ns, cm.GetConfigMapName(name, ns))
270 out, err := util.KubectlExec(args)
275 var p fastjson.Parser
276 v, err := p.Parse(string(out))
278 appmgr.Logger.Info("fastjson.Parser for '%s' failed: %v", name, err)
282 for _, m := range v.GetArray("rmr", "txMessages") {
283 msgs.TxMessages = append(msgs.TxMessages, strings.Trim(m.String(), `"`))
285 for _, m := range v.GetArray("rmr", "rxMessages") {
286 msgs.RxMessages = append(msgs.RxMessages, strings.Trim(m.String(), `"`))
292 func (cm *CM) GetConfigMapName(xappName, namespace string) string {
293 return " configmap-" + namespace + "-" + xappName + "-appconfig"
296 func (cm *CM) GetNamespace(ns string) string {
301 ns = viper.GetString("xapp.namespace")