func (m Matcher) Process(tree *gabs.Container) error { return Repeat(5, func() error { return ProcessAll(tree, func(ktype string, output *gabs.Container, value interface{}, key interface{}) error { if ktype == "map" { skey, err := templater.MatchTemplate(key.(string), tree) if err != nil { return err } parts := strings.SplitN(skey, "?", 2) if valmap, ok := value.(map[string]interface{}); ok && len(parts) > 1 { matchValue := strings.Trim(strings.TrimSpace(parts[1]), "\"'") newKey := strings.TrimSpace(parts[0]) output.Delete(key.(string)) output.Delete(newKey) if v, ok := valmap[matchValue]; ok { output.Set(v, newKey) return nil } for k, v := range valmap { if k == "*" { continue } re, err := regexp.Compile("^" + strings.Trim(k, "^$") + "$") if err != nil { return err } matches := re.FindStringSubmatch(matchValue) groups := re.SubexpNames() if len(matches) > 0 { for i, group := range groups { if group != "" { tree.Set(matches[i], "match", group) } } output.Set(v, newKey) return nil } } if v, ok := valmap["*"]; ok { output.Set(v, newKey) } } } return nil }) }) }
func includeFile(file string, tree *gabs.Container) error { loaded, err := loader.LoadFile(file) if err != nil { return err } log.Println("include:", file) merged, err := mergemap.Merge(loaded.Data().(map[string]interface{}), tree.Data().(map[string]interface{})) if err != nil { return err } _, err = tree.Set(merged) return err }
func ProcessAll(tree *gabs.Container, visitor func(string, *gabs.Container, interface{}, interface{}) error) error { errors := make([]string, 0) if _, ok := tree.Data().(map[string]interface{}); ok { mmap, _ := tree.ChildrenMap() for k, v := range mmap { if err := ProcessAll(v, visitor); err != nil { errors = append(errors, err.Error()) continue } if err := visitor("map", tree, v.Data(), k); err != nil { errors = append(errors, err.Error()) } } } else if _, ok := tree.Data().([]interface{}); ok { marray, _ := tree.Children() for i, v := range marray { if err := ProcessAll(v, visitor); err != nil { errors = append(errors, err.Error()) continue } if err := visitor("array", tree, v.Data(), i); err != nil { errors = append(errors, err.Error()) } } } else { if err := visitor("other", tree, tree.Data(), nil); err != nil { errors = append(errors, err.Error()) } } if len(errors) == 0 { return nil } else { return fmt.Errorf(strings.Join(errors, "\n")) } }
func _template(s string, context *gabs.Container, modify bool) (string, error) { t, err := fasttemplate.NewTemplate(s, "{{", "}}") if err != nil { return "", err } w := bytesBufferPool.Get().(*bytes.Buffer) if _, err := t.ExecuteFunc(w, func(w io.Writer, tag string) (int, error) { tag = strings.TrimSpace(tag) if value := context.Path(tag).Data(); value != nil { if valueArr, ok := value.([]interface{}); ok && len(valueArr) > 0 { value = valueArr[0] } return w.Write([]byte(fmt.Sprintf("%v", value))) } else if modify && strings.Contains(tag, "|") { if v, err := ModifyExec(tag, context); err == nil { return w.Write([]byte(fmt.Sprintf("%v", v))) } } if strings.HasPrefix(tag, "vars.") || context.ExistsP(tag) { return 0, nil } return 0, fmt.Errorf("Undefined template variable: '%s'", tag) }); err != nil { return "", err } out := string(w.Bytes()) w.Reset() bytesBufferPool.Put(w) return out, nil }
func makePluginPair(plugin string, data *gabs.Container) PluginData { if s, ok := data.Data().(string); ok { obj := gabs.New() ns := strings.Split(plugin, ".") obj.Set(s, ns[len(ns)-1]) data = obj } else { var cpy interface{} bs, _ := json.Marshal(data.Data()) json.Unmarshal(bs, &cpy) data.Set(cpy) } return PluginData{plugin, PluginRegestry.Get(plugin), Manifest{data}} }
func (in Include) Process(tree *gabs.Container) error { path := ConfigPath if customPath, ok := tree.Path("vars.config-path").Data().(string); ok { path = customPath } if tree.ExistsP("include") { items, err := tree.Path("include").Children() if err != nil { return err } for i, _ := range items { inc := items[len(items)-i-1] // loop in reverse order for merge priority if file, ok := inc.Search("file").Data().(string); ok { if !strings.HasPrefix(file, "/") { file = path + "/" + file } if err := includeFile(file, tree); err != nil { return err } } } } // include all base configs if files, err := filepath.Glob(path + "/conf.d/*.yml"); err == nil { for _, file := range files { if err := includeFile(file, tree); err != nil { return err } } } return nil }