/
di.go
189 lines (159 loc) · 4.63 KB
/
di.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
package registry
import (
"bufio"
"bytes"
"fmt"
"github.com/google/wire"
"github.com/pkg/errors"
"jochum.dev/orb/orb/cli"
"jochum.dev/orb/orb/config"
"jochum.dev/orb/orb/di"
"jochum.dev/orb/orb/log"
)
type DiFlags struct{}
// DiConfig is marker that DiFlags has been parsed into Config
type DiConfig struct{}
const (
cliArgPlugin = "registry"
cliArgAddresses = "registry_address"
)
func ProvideFlags(
config Config,
cliConfig cli.Config,
c cli.Cli,
) (DiFlags, error) {
if *cliConfig.GetNoFlags() {
// Defined silently ignore that
return DiFlags{}, nil
}
if err := c.Add(
cli.Name(cli.PrefixName(cliConfig.GetArgPrefix(), cliArgPlugin)),
cli.Usage("Registry for discovery. etcd, mdns"),
cli.Default(config.GetPlugin()),
cli.EnvVars(cli.PrefixEnv(cliConfig.GetArgPrefix(), cliArgPlugin)),
); err != nil {
return DiFlags{}, err
}
if err := c.Add(
cli.Name(cli.PrefixName(cliConfig.GetArgPrefix(), cliArgAddresses)),
cli.Usage("List of registry addresses"),
cli.Default(config.GetAddresses()),
cli.EnvVars(cli.PrefixEnv(cliConfig.GetArgPrefix(), cliArgAddresses)),
); err != nil {
return DiFlags{}, err
}
return DiFlags{}, nil
}
func ProvideConfig(
_ di.DiConfig,
flags DiFlags,
cfg Config,
c cli.Cli,
cliConfig cli.Config,
configDatas []config.Data,
) (DiConfig, error) {
plugin, err := config.GetPluginFromConfigData(cliConfig.GetConfigSection(), Name, configDatas)
if err != nil {
return DiConfig{}, err
}
previousConfig := any(cfg)
for _, configData := range configDatas {
// Go own section deeper.
var err error
data := configData.Data
if cliConfig.GetConfigSection() != "" {
if data, err = config.Get(data, cliConfig.GetConfigSection(), map[string]any{}); err != nil {
// Ignore unknown configSection in config.
if errors.Is(err, config.ErrNotExistent) {
log.Warn().
Fields(map[string]string{"section": cliConfig.GetConfigSection(), "url": configData.URL.String()}).
Msg("unknown config section in config")
continue
}
return DiConfig{}, err
}
}
// Now fetch my own section.
if data, err = config.Get(data, Name, map[string]any{}); err != nil {
// Ignore unknown section in config.
if errors.Is(err, config.ErrNotExistent) {
log.Warn().
Fields(map[string]string{"section": Name, "url": configData.URL.String()}).
Msg("unknown config section in config")
continue
}
return DiConfig{}, err
}
// Create a new config.
aNew, err := NewConfig(plugin)
if err != nil {
return DiConfig{}, err
}
// Create a marshaler for this section.
buf := bytes.Buffer{}
if err := configData.Marshaler.Init(bufio.NewReader(&buf), bufio.NewWriter(&buf)); err != nil {
return DiConfig{}, err
}
// Encode this section into the bufr.
if err := configData.Marshaler.EncodeSocket(data); err != nil {
return DiConfig{}, err
}
// Decode this section from the bufr.
if err := configData.Marshaler.DecodeSocket(aNew); err != nil {
return DiConfig{}, err
}
merger, ok := aNew.(config.ConfigMerge)
if !ok {
return DiConfig{}, config.ErrUnknownConfig
}
// Merge previous config into this one.
if err := merger.MergePrevious(previousConfig); err != nil {
return DiConfig{}, err
}
// Update previousConfig for the next run
previousConfig = aNew
}
if cliConfig.GetNoFlags() != nil && *cliConfig.GetNoFlags() {
// Dont parse flags if NoFlags has been given.
return DiConfig{}, nil
}
// Read flags into config.
newCfg := NewComponentConfig()
if f, ok := c.Get(cli.PrefixName(cliConfig.GetArgPrefix(), cliArgPlugin)); ok {
newCfg.Plugin = cli.FlagValue(f, newCfg.GetPlugin())
}
if f, ok := c.Get(cli.PrefixName(cliConfig.GetArgPrefix(), cliArgAddresses)); ok {
newCfg.Addresses = cli.FlagValue(f, newCfg.GetAddresses())
}
if err := cfg.Merge(newCfg); err != nil {
return DiConfig{}, err
}
return DiConfig{}, nil
}
func Provide(
// Marker so cli has been merged into Config
_ DiConfig,
parentLogger log.Logger,
config Config,
) (Registry, error) {
if !*config.GetEnabled() {
// Not enabled silently ignore that
return nil, nil
}
pluginFunc, err := Plugins.Plugin(config.GetPlugin())
if err != nil {
return nil, fmt.Errorf("unknown plugin registry: '%s'", config.GetPlugin())
}
plugin := pluginFunc()
opts := []Option{}
logger, err := log.FromConfig(config.GetLogger(), parentLogger)
if err != nil {
return nil, fmt.Errorf("component '%s' is unable to setup its logger", config.GetPlugin())
}
opts = append(opts, WithLogger(logger))
if err := plugin.Init(config, opts...); err != nil {
return nil, err
}
return plugin, nil
}
var DiSet = wire.NewSet(ProvideFlags, ProvideConfig, Provide)