forked from bacongobbler/confd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.go
96 lines (81 loc) · 1.92 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package file
import (
"fmt"
"io/ioutil"
"strings"
"github.com/fsnotify/fsnotify"
"github.com/kelseyhightower/confd/log"
"gopkg.in/yaml.v2"
)
var replacer = strings.NewReplacer("/", "_")
// Client provides a shell for the yaml client
type Client struct {
filepath string
}
func NewFileClient(filepath string) (*Client, error) {
return &Client{filepath}, nil
}
func (c *Client) GetValues(keys []string) (map[string]string, error) {
yamlMap := make(map[interface{}]interface{})
vars := make(map[string]string)
data, err := ioutil.ReadFile(c.filepath)
if err != nil {
return vars, err
}
err = yaml.Unmarshal(data, &yamlMap)
if err != nil {
return vars, err
}
nodeWalk(yamlMap, "", vars)
log.Debug(fmt.Sprintf("Key Map: %#v", vars))
return vars, nil
}
// nodeWalk recursively descends nodes, updating vars.
func nodeWalk(node map[interface{}]interface{}, key string, vars map[string]string) error {
for k, v := range node {
key := key + "/" + k.(string)
switch v.(type) {
case map[interface{}]interface{}:
nodeWalk(v.(map[interface{}]interface{}), key, vars)
case []interface{}:
for _, j := range v.([]interface{}) {
switch j.(type) {
case map[interface{}]interface{}:
nodeWalk(j.(map[interface{}]interface{}), key, vars)
case string:
vars[key+"/"+j.(string)] = ""
}
}
case string:
vars[key] = v.(string)
}
}
return nil
}
func (c *Client) WatchPrefix(prefix string, keys []string, waitIndex uint64, stopChan chan bool) (uint64, error) {
if waitIndex == 0 {
return 1, nil
}
watcher, err := fsnotify.NewWatcher()
if err != nil {
return 0, err
}
defer watcher.Close()
err = watcher.Add(c.filepath)
if err != nil {
return 0, err
}
for {
select {
case event := <-watcher.Events:
if event.Op&fsnotify.Write == fsnotify.Write {
return 1, nil
}
case err := <-watcher.Errors:
return 0, err
case <-stopChan:
return 0, nil
}
}
return waitIndex, nil
}