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/xeipuuv/gojsonschema"
37 type ConfigMetadata struct {
38 Name string `json:"name"`
39 ConfigName string `json:"configName, omitempty"`
40 Namespace string `json:"namespace, omitempty"`
43 type XAppConfig struct {
44 Metadata ConfigMetadata `json:"metadata"`
45 Descriptor interface{} `json:"descriptor, omitempty"`
46 Configuration interface{} `json:"config, omitempty"`
49 type ConfigMap struct {
50 Kind string `json:"kind"`
51 ApiVersion string `json:"apiVersion"`
52 Data interface{} `json:"data"`
53 Metadata CMMetadata `json:"metadata"`
56 type CMMetadata struct {
57 Name string `json:"name"`
58 Namespace string `json:"namespace"`
61 func UploadConfig() (cfg []XAppConfig) {
62 for _, name := range GetNamesFromHelmRepo() {
68 Metadata: ConfigMetadata{Name: name, Namespace: "ricxapp", ConfigName: name + "-appconfig"},
71 err := ReadSchema(name, &c)
76 err = ReadConfigMap(name, "ricxapp", &c.Configuration)
78 log.Println("No active configMap found, using default!")
86 func ReadSchema(name string, c *XAppConfig) (err error) {
87 if err = FetchChart(name); err != nil {
91 tarDir := viper.GetString("xapp.tarDir")
92 err = ReadFile(path.Join(tarDir, name, viper.GetString("xapp.schema")), &c.Descriptor)
97 err = ReadFile(path.Join(tarDir, name, viper.GetString("xapp.config")), &c.Configuration)
102 if err = os.RemoveAll(path.Join(tarDir, name)); err != nil {
103 log.Println("RemoveAll failed", err)
109 func ReadConfigMap(name string, ns string, c *interface{}) (err error) {
110 args := fmt.Sprintf("get configmap -o jsonpath='{.data.config-file\\.json}' -n %s %s-appconfig", ns, name)
111 configMapJson, err := KubectlExec(args)
116 err = json.Unmarshal([]byte(configMapJson), &c)
124 func ApplyConfigMap(r XAppConfig) (err error) {
128 Metadata: CMMetadata{Name: r.Metadata.Name, Namespace: r.Metadata.Namespace},
129 Data: r.Configuration,
132 cmJson, err := json.Marshal(cm)
134 log.Println("Config marshalling failed: ", err)
138 cmFile := viper.GetString("xapp.tmpConfig")
139 err = ioutil.WriteFile(cmFile, cmJson, 0644)
141 log.Println("WriteFile failed: ", err)
145 cmd := " create configmap -n %s %s --from-file=%s -o json --dry-run | kubectl apply -f -"
146 args := fmt.Sprintf(cmd, r.Metadata.Namespace, r.Metadata.ConfigName, cmFile)
147 _, err = KubectlExec(args)
151 log.Println("Configmap changes created!")
156 func CreateConfigMap(r XAppConfig) (err error) {
157 if err = Validate(r); err != nil {
160 return ApplyConfigMap(r)
163 func DeleteConfigMap(r XAppConfig) (cm interface{}, err error) {
164 err = ReadConfigMap(r.Metadata.Name, r.Metadata.Namespace, &cm)
166 args := fmt.Sprintf(" delete configmap --namespace=%s %s", r.Metadata.Namespace, r.Metadata.ConfigName)
167 _, err = KubectlExec(args)
172 func PurgeConfigMap(m ConfigMetadata) (cm interface{}, err error) {
173 if m.ConfigName == "" {
174 m.ConfigName = m.Name + "-appconfig"
176 return DeleteConfigMap(XAppConfig{Metadata: m})
179 func RestoreConfigMap(m ConfigMetadata, cm interface{}) (err error) {
180 if m.ConfigName == "" {
181 m.ConfigName = m.Name + "-appconfig"
183 time.Sleep(time.Duration(10 * time.Second))
185 return ApplyConfigMap(XAppConfig{Metadata: m, Configuration: cm})
188 func GetNamesFromHelmRepo() (names []string) {
189 rname := viper.GetString("helm.repo-name")
191 cmdArgs := strings.Join([]string{"search ", rname}, "")
192 out, err := 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 Validate(req XAppConfig) (err error) {
211 err = ReadSchema(req.Metadata.Name, &c)
213 log.Printf("No schema file found for '%s', aborting ...", req.Metadata.Name)
217 schemaLoader := gojsonschema.NewGoLoader(c.Descriptor)
218 documentLoader := gojsonschema.NewGoLoader(req.Configuration)
220 log.Println("Starting validation ...")
221 result, err := gojsonschema.Validate(schemaLoader, documentLoader)
223 log.Println("Validation failed: ", err)
227 log.Println("validation done ...", err, result.Valid())
228 if result.Valid() == false {
229 log.Println("The document is not valid, Errors: ", result.Errors())
230 s := make([]string, 3)
231 for i, desc := range result.Errors() {
232 s = append(s, fmt.Sprintf(" (%d): %s.\n", i, desc.String()))
234 return errors.New(strings.Join(s, " "))
239 func ReadFile(name string, data interface{}) (err error) {
240 f, err := ioutil.ReadFile(name)
242 log.Printf("Reading '%s' file failed: %v", name, err)
246 err = json.Unmarshal(f, &data)
248 log.Printf("Unmarshalling '%s' file failed: %v", name, err)
255 func FetchChart(name string) (err error) {
256 tarDir := viper.GetString("xapp.tarDir")
257 repo := viper.GetString("helm.repo-name")
258 fetchArgs := fmt.Sprintf("--untar --untardir %s %s/%s", tarDir, repo, name)
260 _, err = HelmExec(strings.Join([]string{"fetch ", fetchArgs}, ""))
264 func GetMessages(name string) (msgs MessageTypes, err error) {
265 log.Println("Fetching tx/rx messages for: ", name)