1
2
3
4
5
6
7 package remote
8
9 import (
10 "bytes"
11 "io"
12 "os"
13 "strings"
14
15 crypt "github.com/sagikazarmark/crypt/config"
16
17 "github.com/spf13/viper"
18 )
19
20 type remoteConfigProvider struct{}
21
22 func (rc remoteConfigProvider) Get(rp viper.RemoteProvider) (io.Reader, error) {
23 cm, err := getConfigManager(rp)
24 if err != nil {
25 return nil, err
26 }
27 b, err := cm.Get(rp.Path())
28 if err != nil {
29 return nil, err
30 }
31 return bytes.NewReader(b), nil
32 }
33
34 func (rc remoteConfigProvider) Watch(rp viper.RemoteProvider) (io.Reader, error) {
35 cm, err := getConfigManager(rp)
36 if err != nil {
37 return nil, err
38 }
39 resp, err := cm.Get(rp.Path())
40 if err != nil {
41 return nil, err
42 }
43
44 return bytes.NewReader(resp), nil
45 }
46
47 func (rc remoteConfigProvider) WatchChannel(rp viper.RemoteProvider) (<-chan *viper.RemoteResponse, chan bool) {
48 cm, err := getConfigManager(rp)
49 if err != nil {
50 return nil, nil
51 }
52 quit := make(chan bool)
53 quitwc := make(chan bool)
54 viperResponsCh := make(chan *viper.RemoteResponse)
55 cryptoResponseCh := cm.Watch(rp.Path(), quit)
56
57 go func(cr <-chan *crypt.Response, vr chan<- *viper.RemoteResponse, quitwc <-chan bool, quit chan<- bool) {
58 for {
59 select {
60 case <-quitwc:
61 quit <- true
62 return
63 case resp := <-cr:
64 vr <- &viper.RemoteResponse{
65 Error: resp.Error,
66 Value: resp.Value,
67 }
68 }
69 }
70 }(cryptoResponseCh, viperResponsCh, quitwc, quit)
71
72 return viperResponsCh, quitwc
73 }
74
75 func getConfigManager(rp viper.RemoteProvider) (crypt.ConfigManager, error) {
76 var cm crypt.ConfigManager
77 var err error
78
79 endpoints := strings.Split(rp.Endpoint(), ";")
80 if rp.SecretKeyring() != "" {
81 var kr *os.File
82 kr, err = os.Open(rp.SecretKeyring())
83 if err != nil {
84 return nil, err
85 }
86 defer kr.Close()
87 switch rp.Provider() {
88 case "etcd":
89 cm, err = crypt.NewEtcdConfigManager(endpoints, kr)
90 case "etcd3":
91 cm, err = crypt.NewEtcdV3ConfigManager(endpoints, kr)
92 case "firestore":
93 cm, err = crypt.NewFirestoreConfigManager(endpoints, kr)
94 case "nats":
95 cm, err = crypt.NewNatsConfigManager(endpoints, kr)
96 default:
97 cm, err = crypt.NewConsulConfigManager(endpoints, kr)
98 }
99 } else {
100 switch rp.Provider() {
101 case "etcd":
102 cm, err = crypt.NewStandardEtcdConfigManager(endpoints)
103 case "etcd3":
104 cm, err = crypt.NewStandardEtcdV3ConfigManager(endpoints)
105 case "firestore":
106 cm, err = crypt.NewStandardFirestoreConfigManager(endpoints)
107 case "nats":
108 cm, err = crypt.NewStandardNatsConfigManager(endpoints)
109 default:
110 cm, err = crypt.NewStandardConsulConfigManager(endpoints)
111 }
112 }
113 if err != nil {
114 return nil, err
115 }
116 return cm, nil
117 }
118
119 func init() {
120 viper.RemoteConfig = &remoteConfigProvider{}
121 }
122
View as plain text