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"
37 "gerrit.oran-osc.org/r/ric-plt/appmgr/pkg/appmgr"
38 "gerrit.oran-osc.org/r/ric-plt/appmgr/pkg/models"
39 "gerrit.oran-osc.org/r/ric-plt/appmgr/pkg/util"
48 func (cm *CM) UploadConfig() (cfg models.AllXappConfig) {
49 ns := cm.GetNamespace("")
50 for _, name := range cm.GetNamesFromHelmRepo() {
55 c := models.XAppConfig{
56 Metadata: &models.ConfigMetadata{Name: &name, Namespace: ns, ConfigName: cm.GetConfigMapName(name, ns)},
59 err := cm.ReadSchema(name, &c)
64 err = cm.ReadConfigMap(c.Metadata.ConfigName, ns, &c.Config)
66 appmgr.Logger.Info("No active configMap found, using default!")
74 func (cm *CM) ReadSchema(name string, c *models.XAppConfig) (err error) {
75 if err = cm.FetchChart(name); err != nil {
79 tarDir := viper.GetString("xapp.tarDir")
80 err = cm.ReadFile(path.Join(tarDir, name, viper.GetString("xapp.schema")), &c.Descriptor)
85 err = cm.ReadFile(path.Join(tarDir, name, viper.GetString("xapp.config")), &c.Config)
90 if err = os.RemoveAll(path.Join(tarDir, name)); err != nil {
91 appmgr.Logger.Info("RemoveAll failed: %v", err)
97 func (cm *CM) ReadConfigMap(ConfigName string, ns string, c *interface{}) (err error) {
98 args := fmt.Sprintf("get configmap -o jsonpath='{.data.config-file\\.json}' -n %s %s", ns, ConfigName)
99 configMapJson, err := util.KubectlExec(args)
104 err = json.Unmarshal([]byte(configMapJson), &c)
112 func (cm *CM) ApplyConfigMap(r models.XAppConfig, action string) (err error) {
113 c := appmgr.ConfigMap{
116 Metadata: appmgr.CMMetadata{Name: *r.Metadata.Name, Namespace: r.Metadata.Namespace},
120 cmJson, err := json.Marshal(c.Data)
122 appmgr.Logger.Info("Config marshalling failed: %v", err)
126 cmFile := viper.GetString("xapp.tmpConfig")
127 err = ioutil.WriteFile(cmFile, cmJson, 0644)
129 appmgr.Logger.Info("WriteFile failed: %v", err)
133 cmd := " create configmap -n %s %s --from-file=%s -o json --dry-run | kubectl %s -f -"
134 args := fmt.Sprintf(cmd, r.Metadata.Namespace, r.Metadata.ConfigName, cmFile, action)
135 _, err = util.KubectlExec(args)
139 appmgr.Logger.Info("Configmap changes done!")
144 func (cm *CM) GetConfigMap(m models.XappDescriptor, c *interface{}) (err error) {
145 return cm.ReadConfigMap(cm.GetConfigMapName(*m.XappName, m.Namespace), m.Namespace, c)
148 func (cm *CM) CreateConfigMap(r models.XAppConfig) (errList models.ConfigValidationErrors, err error) {
149 if errList, err = cm.Validate(r); err != nil {
152 err = cm.ApplyConfigMap(r, "create")
156 func (cm *CM) UpdateConfigMap(r models.XAppConfig) (errList models.ConfigValidationErrors, err error) {
157 if errList, err = cm.Validate(r); err != nil {
161 // Re-create the configmap with the new parameters
162 err = cm.ApplyConfigMap(r, "apply")
166 func (cm *CM) DeleteConfigMap(r models.ConfigMetadata) (c interface{}, err error) {
167 err = cm.ReadConfigMap(r.ConfigName, r.Namespace, &c)
169 args := fmt.Sprintf(" delete configmap --namespace=%s %s", r.Namespace, r.ConfigName)
170 _, err = util.KubectlExec(args)
175 func (cm *CM) PurgeConfigMap(m models.XappDescriptor) (c interface{}, err error) {
176 md := models.ConfigMetadata{Name: m.XappName, Namespace: m.Namespace, ConfigName: cm.GetConfigMapName(*m.XappName, m.Namespace)}
178 return cm.DeleteConfigMap(md)
181 func (cm *CM) RestoreConfigMap(m models.XappDescriptor, c interface{}) (err error) {
182 md := &models.ConfigMetadata{Name: m.XappName, Namespace: m.Namespace, ConfigName: cm.GetConfigMapName(*m.XappName, m.Namespace)}
183 time.Sleep(time.Duration(10 * time.Second))
185 return cm.ApplyConfigMap(models.XAppConfig{Metadata: md, Config: c}, "create")
188 func (cm *CM) GetNamesFromHelmRepo() (names []string) {
189 rname := viper.GetString("helm.repo-name")
191 cmdArgs := strings.Join([]string{"search ", rname}, "")
192 out, err := util.HelmExec(cmdArgs)
197 re := regexp.MustCompile(rname + `/.*`)
198 result := re.FindAllStringSubmatch(string(out), -1)
201 for _, v := range result {
202 fmt.Sscanf(v[0], "%s", &tmp)
203 names = append(names, strings.Split(tmp, "/")[1])
209 func (cm *CM) Validate(req models.XAppConfig) (errList models.ConfigValidationErrors, err error) {
210 c := models.XAppConfig{}
211 err = cm.ReadSchema(*req.Metadata.Name, &c)
213 appmgr.Logger.Info("No schema file found for '%s', aborting ...", *req.Metadata.Name)
216 return cm.doValidate(c.Descriptor, req.Config)
219 func (cm *CM) doValidate(schema, cfg interface{}) (errList models.ConfigValidationErrors, err error) {
220 schemaLoader := gojsonschema.NewGoLoader(schema)
221 documentLoader := gojsonschema.NewGoLoader(cfg)
223 result, err := gojsonschema.Validate(schemaLoader, documentLoader)
225 appmgr.Logger.Info("Validation failed: %v", err)
229 if result.Valid() == false {
230 appmgr.Logger.Info("The document is not valid, Errors: %v", result.Errors())
231 for _, desc := range result.Errors() {
232 field := desc.Field()
233 validationError := desc.Description()
234 errList = append(errList, &models.ConfigValidationError{Field: &field, Error: &validationError})
236 return errList, errors.New("Validation failed!")
241 func (cm *CM) ReadFile(name string, data interface{}) (err error) {
242 f, err := ioutil.ReadFile(name)
244 appmgr.Logger.Info("Reading '%s' file failed: %v", name, err)
248 err = json.Unmarshal(f, &data)
250 appmgr.Logger.Info("Unmarshalling '%s' file failed: %v", name, err)
257 func (cm *CM) FetchChart(name string) (err error) {
258 tarDir := viper.GetString("xapp.tarDir")
259 repo := viper.GetString("helm.repo-name")
260 fetchArgs := fmt.Sprintf("--untar --untardir %s %s/%s", tarDir, repo, name)
262 _, err = util.HelmExec(strings.Join([]string{"fetch ", fetchArgs}, ""))
266 func (cm *CM) GetRtmData(name string) (msgs appmgr.RtmData) {
267 appmgr.Logger.Info("Fetching RT data for xApp=%s", name)
269 ns := cm.GetNamespace("")
270 args := fmt.Sprintf("get configmap -o jsonpath='{.data.config-file\\.json}' -n %s %s", ns, cm.GetConfigMapName(name, ns))
271 out, err := util.KubectlExec(args)
276 var p fastjson.Parser
277 v, err := p.Parse(string(out))
279 appmgr.Logger.Info("fastjson.Parser for '%s' failed: %v", name, err)
283 for _, m := range v.GetArray("rmr", "txMessages") {
284 msgs.TxMessages = append(msgs.TxMessages, strings.Trim(m.String(), `"`))
286 for _, m := range v.GetArray("rmr", "rxMessages") {
287 msgs.RxMessages = append(msgs.RxMessages, strings.Trim(m.String(), `"`))
289 for _, m := range v.GetArray("rmr", "policies") {
290 if val, err := strconv.Atoi(strings.Trim(m.String(), `"`)); err == nil {
291 msgs.Policies = append(msgs.Policies, int64(val))
298 func (cm *CM) GetConfigMapName(xappName, namespace string) string {
299 return " configmap-" + namespace + "-" + xappName + "-appconfig"
302 func (cm *CM) GetNamespace(ns string) string {
307 ns = viper.GetString("xapp.namespace")