Add KV store providers (dynamic configuration only)
Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
This commit is contained in:
parent
028683666d
commit
9b9f4be6a4
61 changed files with 5825 additions and 70 deletions
128
pkg/config/kv/kv_node.go
Normal file
128
pkg/config/kv/kv_node.go
Normal file
|
@ -0,0 +1,128 @@
|
|||
package kv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/abronan/valkeyrie/store"
|
||||
"github.com/containous/traefik/v2/pkg/config/parser"
|
||||
)
|
||||
|
||||
// DecodeToNode converts the labels to a tree of nodes.
|
||||
// If any filters are present, labels which do not match the filters are skipped.
|
||||
func DecodeToNode(pairs []*store.KVPair, rootName string, filters ...string) (*parser.Node, error) {
|
||||
sortedPairs := filterPairs(pairs, filters)
|
||||
|
||||
exp := regexp.MustCompile(`^\d+$`)
|
||||
|
||||
var node *parser.Node
|
||||
|
||||
for i, pair := range sortedPairs {
|
||||
split := strings.FieldsFunc(pair.Key, func(c rune) bool { return c == '/' })
|
||||
|
||||
if split[0] != rootName {
|
||||
return nil, fmt.Errorf("invalid label root %s", split[0])
|
||||
}
|
||||
|
||||
var parts []string
|
||||
for _, fragment := range split {
|
||||
if exp.MatchString(fragment) {
|
||||
parts = append(parts, "["+fragment+"]")
|
||||
} else {
|
||||
parts = append(parts, fragment)
|
||||
}
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
node = &parser.Node{}
|
||||
}
|
||||
decodeToNode(node, parts, string(pair.Value))
|
||||
}
|
||||
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func decodeToNode(root *parser.Node, path []string, value string) {
|
||||
if len(root.Name) == 0 {
|
||||
root.Name = path[0]
|
||||
}
|
||||
|
||||
// it's a leaf or not -> children
|
||||
if len(path) > 1 {
|
||||
if n := containsNode(root.Children, path[1]); n != nil {
|
||||
// the child already exists
|
||||
decodeToNode(n, path[1:], value)
|
||||
} else {
|
||||
// new child
|
||||
child := &parser.Node{Name: path[1]}
|
||||
decodeToNode(child, path[1:], value)
|
||||
root.Children = append(root.Children, child)
|
||||
}
|
||||
} else {
|
||||
root.Value = value
|
||||
}
|
||||
}
|
||||
|
||||
func containsNode(nodes []*parser.Node, name string) *parser.Node {
|
||||
for _, n := range nodes {
|
||||
if strings.EqualFold(name, n.Name) {
|
||||
return n
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func filterPairs(pairs []*store.KVPair, filters []string) []*store.KVPair {
|
||||
exp := regexp.MustCompile(`^(.+)/\d+$`)
|
||||
|
||||
sort.Slice(pairs, func(i, j int) bool {
|
||||
return pairs[i].Key < pairs[j].Key
|
||||
})
|
||||
|
||||
var simplePairs = map[string]*store.KVPair{}
|
||||
var slicePairs = map[string][]string{}
|
||||
|
||||
for _, pair := range pairs {
|
||||
if len(filters) == 0 {
|
||||
// Slice of simple type
|
||||
if exp.MatchString(pair.Key) {
|
||||
sanitizedKey := exp.FindStringSubmatch(pair.Key)[1]
|
||||
slicePairs[sanitizedKey] = append(slicePairs[sanitizedKey], string(pair.Value))
|
||||
} else {
|
||||
simplePairs[pair.Key] = pair
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
for _, filter := range filters {
|
||||
if len(pair.Key) >= len(filter) && strings.EqualFold(pair.Key[:len(filter)], filter) {
|
||||
// Slice of simple type
|
||||
if exp.MatchString(pair.Key) {
|
||||
sanitizedKey := exp.FindStringSubmatch(pair.Key)[1]
|
||||
slicePairs[sanitizedKey] = append(slicePairs[sanitizedKey], string(pair.Value))
|
||||
} else {
|
||||
simplePairs[pair.Key] = pair
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sortedPairs []*store.KVPair
|
||||
for k, v := range slicePairs {
|
||||
delete(simplePairs, k)
|
||||
sortedPairs = append(sortedPairs, &store.KVPair{Key: k, Value: []byte(strings.Join(v, ","))})
|
||||
}
|
||||
|
||||
for _, v := range simplePairs {
|
||||
sortedPairs = append(sortedPairs, v)
|
||||
}
|
||||
|
||||
sort.Slice(sortedPairs, func(i, j int) bool {
|
||||
return sortedPairs[i].Key < sortedPairs[j].Key
|
||||
})
|
||||
|
||||
return sortedPairs
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue