Skip to content

Commit dbc22c4

Browse files
author
root
committed
yaml parser refactor
1 parent 84cc1d0 commit dbc22c4

8 files changed

Lines changed: 1041 additions & 519 deletions

File tree

cmd/vxlan-controller/main.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func runController(configPath string, defaultConfig, mockMode bool, logLevel str
9292
configPath = "controller.yaml"
9393
}
9494

95-
cfg, err := config.LoadControllerConfig(configPath)
95+
cfg, defaults, err := config.LoadControllerConfig(configPath)
9696
if err != nil {
9797
log.Fatalf("Failed to load config: %v", err)
9898
}
@@ -103,6 +103,10 @@ func runController(configPath string, defaultConfig, mockMode bool, logLevel str
103103
vlog.SetLevel(vlog.ParseLevel(cfg.LogLevel))
104104
}
105105

106+
for _, d := range defaults {
107+
vlog.Warnf("[Config] %s applied default value %s", d.Path, d.Value)
108+
}
109+
106110
sigCh := make(chan os.Signal, 1)
107111
signal.Notify(sigCh, syscall.SIGTERM, syscall.SIGINT)
108112

@@ -145,7 +149,7 @@ func runClient(configPath string, defaultConfig bool, logLevel string) {
145149
configPath = "client.yaml"
146150
}
147151

148-
cfg, err := config.LoadClientConfig(configPath)
152+
cfg, defaults, err := config.LoadClientConfig(configPath)
149153
if err != nil {
150154
log.Fatalf("Failed to load config: %v", err)
151155
}
@@ -156,6 +160,10 @@ func runClient(configPath string, defaultConfig bool, logLevel string) {
156160
vlog.SetLevel(vlog.ParseLevel(cfg.LogLevel))
157161
}
158162

163+
for _, d := range defaults {
164+
vlog.Warnf("[Config] %s applied default value %s", d.Path, d.Value)
165+
}
166+
159167
cl := client.New(cfg)
160168

161169
sigCh := make(chan os.Signal, 1)

pkg/config/autogen.go

Lines changed: 60 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package config
22

33
import (
4-
"encoding/base64"
54
"fmt"
65
"net/netip"
76
"os"
@@ -27,7 +26,7 @@ type AutogenConfig struct {
2726
VxlanMTU int `yaml:"vxlan_mtu"`
2827
ProbePort uint16 `yaml:"probe_port"`
2928
Priority int `yaml:"priority"`
30-
ForwardCost float64 `yaml:"forward_cost"`
29+
ForwardCost float64 `yaml:"forward_cost"`
3130

3231
Nodes map[string]map[string]AutogenAF `yaml:"nodes"`
3332
Controllers []string `yaml:"controllers"`
@@ -36,10 +35,10 @@ type AutogenConfig struct {
3635
}
3736

3837
type AutogenWebUI struct {
39-
BindAddr string `yaml:"bind_addr"`
40-
Title string `yaml:"title"`
41-
URL string `yaml:"url"`
42-
Nodes map[string]*WebUINodeFile `yaml:"nodes"`
38+
BindAddr string `yaml:"bind_addr"`
39+
Title string `yaml:"title"`
40+
URL string `yaml:"url"`
41+
Nodes map[string]*WebUINode `yaml:"nodes"`
4342
}
4443

4544
// AutogenAF represents a per-AF bind config.
@@ -82,6 +81,20 @@ type autogenNodeKeys struct {
8281
Pub [32]byte
8382
}
8483

84+
var DefaultAutogenConfig = AutogenConfig{
85+
BridgeName: "br-vxlan",
86+
VxlanNamePrefix: "vxlan-",
87+
VxlanDstPort: 4789,
88+
VxlanSrcPortStart: 4789,
89+
VxlanSrcPortEnd: 4789,
90+
CommunicationPort: 5000,
91+
VxlanVNI: 100,
92+
VxlanMTU: 1400,
93+
ProbePort: 5010,
94+
Priority: 10,
95+
ForwardCost: 20,
96+
}
97+
8598
// Autogen loads a topology file and generates controller+client configs.
8699
// Output files are written to the same directory as the input file.
87100
func Autogen(path string) error {
@@ -90,46 +103,11 @@ func Autogen(path string) error {
90103
return fmt.Errorf("read topology: %w", err)
91104
}
92105

93-
var ag AutogenConfig
106+
ag := DefaultAutogenConfig
94107
if err := yaml.Unmarshal(data, &ag); err != nil {
95108
return fmt.Errorf("parse topology: %w", err)
96109
}
97110

98-
// Apply defaults
99-
if ag.BridgeName == "" {
100-
ag.BridgeName = "br-vxlan"
101-
}
102-
if ag.VxlanNamePrefix == "" {
103-
ag.VxlanNamePrefix = "vxlan-"
104-
}
105-
if ag.VxlanDstPort == 0 {
106-
ag.VxlanDstPort = 4789
107-
}
108-
if ag.VxlanSrcPortStart == 0 {
109-
ag.VxlanSrcPortStart = 4789
110-
}
111-
if ag.VxlanSrcPortEnd == 0 {
112-
ag.VxlanSrcPortEnd = 4789
113-
}
114-
if ag.CommunicationPort == 0 {
115-
ag.CommunicationPort = 5000
116-
}
117-
if ag.VxlanVNI == 0 {
118-
ag.VxlanVNI = 100
119-
}
120-
if ag.VxlanMTU == 0 {
121-
ag.VxlanMTU = 1400
122-
}
123-
if ag.ProbePort == 0 {
124-
ag.ProbePort = 5010
125-
}
126-
if ag.Priority == 0 {
127-
ag.Priority = 10
128-
}
129-
if ag.ForwardCost == 0 {
130-
ag.ForwardCost = 20
131-
}
132-
133111
// Validate node references
134112
allRoles := map[string]bool{}
135113
for _, name := range ag.Controllers {
@@ -166,7 +144,11 @@ func Autogen(path string) error {
166144
// Generate controller configs
167145
for _, name := range ag.Controllers {
168146
cfg := ag.buildControllerConfig(name, keys)
169-
if err := writeYAML(filepath.Join(outDir, name+".controller.yaml"), cfg); err != nil {
147+
data, err := MarshalControllerConfig(cfg)
148+
if err != nil {
149+
return fmt.Errorf("marshal controller config for %s: %w", name, err)
150+
}
151+
if err := os.WriteFile(filepath.Join(outDir, name+".controller.yaml"), data, 0644); err != nil {
170152
return fmt.Errorf("write controller config for %s: %w", name, err)
171153
}
172154
fmt.Printf(" %s.controller.yaml\n", name)
@@ -175,7 +157,11 @@ func Autogen(path string) error {
175157
// Generate client configs
176158
for _, name := range ag.Clients {
177159
cfg := ag.buildClientConfig(name, keys)
178-
if err := writeYAML(filepath.Join(outDir, name+".client.yaml"), cfg); err != nil {
160+
data, err := MarshalClientConfig(cfg)
161+
if err != nil {
162+
return fmt.Errorf("marshal client config for %s: %w", name, err)
163+
}
164+
if err := os.WriteFile(filepath.Join(outDir, name+".client.yaml"), data, 0644); err != nil {
179165
return fmt.Errorf("write client config for %s: %w", name, err)
180166
}
181167
fmt.Printf(" %s.client.yaml\n", name)
@@ -184,17 +170,17 @@ func Autogen(path string) error {
184170
return nil
185171
}
186172

187-
func (ag *AutogenConfig) buildControllerConfig(name string, keys map[string]*autogenNodeKeys) *ControllerConfigFile {
173+
func (ag *AutogenConfig) buildControllerConfig(name string, keys map[string]*autogenNodeKeys) *ControllerConfig {
188174
k := keys[name]
189-
cfg := DefaultControllerConfig
175+
cfg := cloneControllerConfig(&DefaultControllerConfig)
190176

191-
cfg.PrivateKey = base64.StdEncoding.EncodeToString(k.Priv[:])
192-
cfg.PublicKey = base64.StdEncoding.EncodeToString(k.Pub[:])
177+
cfg.PrivateKey = k.Priv
193178

194179
// AF settings from this node's AFs
195-
cfg.AFSettings = make(map[string]*ControllerAFConfigFile)
180+
cfg.AFSettings = make(map[types.AFName]*ControllerAFConfig)
196181
for afName, af := range ag.Nodes[name] {
197-
afCfg := &ControllerAFConfigFile{
182+
afCfg := &ControllerAFConfig{
183+
Name: types.AFName(afName),
198184
Enable: true,
199185
CommunicationPort: ag.CommunicationPort,
200186
VxlanVNI: ag.VxlanVNI,
@@ -205,9 +191,9 @@ func (ag *AutogenConfig) buildControllerConfig(name string, keys map[string]*aut
205191
if af.IsAutoIP() {
206192
afCfg.AutoIPInterface = af.Bind
207193
} else {
208-
afCfg.BindAddr = af.Bind
194+
afCfg.BindAddr = netip.MustParseAddr(af.Bind)
209195
}
210-
cfg.AFSettings[afName] = afCfg
196+
cfg.AFSettings[types.AFName(afName)] = afCfg
211197
}
212198

213199
// WebUI config
@@ -216,15 +202,15 @@ func (ag *AutogenConfig) buildControllerConfig(name string, keys map[string]*aut
216202
if bindAddr == "" {
217203
bindAddr = ":8080"
218204
}
219-
cfg.WebUI = &WebUIConfigFile{
205+
cfg.WebUI = &WebUIConfig{
220206
BindAddr: bindAddr,
221207
Title: ag.WebUI.Title,
222208
URL: ag.WebUI.URL,
223209
}
224210
if len(ag.WebUI.Nodes) > 0 {
225-
cfg.WebUI.Nodes = make(map[string]*WebUINodeFile, len(ag.WebUI.Nodes))
211+
cfg.WebUI.Nodes = make(map[string]*WebUINode, len(ag.WebUI.Nodes))
226212
for nodeName, n := range ag.WebUI.Nodes {
227-
cfg.WebUI.Nodes[nodeName] = &WebUINodeFile{
213+
cfg.WebUI.Nodes[nodeName] = &WebUINode{
228214
Label: n.Label,
229215
Pos: n.Pos,
230216
}
@@ -236,37 +222,34 @@ func (ag *AutogenConfig) buildControllerConfig(name string, keys map[string]*aut
236222
cfg.AllowedClients = nil
237223
for _, clientName := range ag.Clients {
238224
ck := keys[clientName]
239-
pc := PerClientConfigFile{
240-
ClientID: base64.StdEncoding.EncodeToString(ck.Pub[:]),
225+
pc := types.PerClientConfig{
226+
ClientID: types.ClientID(ck.Pub),
241227
ClientName: clientName,
242228
}
243-
// Same-node client: connects via LAN IP, but controller should distribute
244-
// the public IP/hostname to other clients. Only needed when client == controller node.
245229
if clientName == name {
246230
for afName, af := range ag.Nodes[clientName] {
247231
if af.DDNS == "" {
248232
continue
249233
}
250234
if pc.AFSettings == nil {
251-
pc.AFSettings = make(map[string]*types.PerClientAFConfig)
235+
pc.AFSettings = make(map[types.AFName]*types.PerClientAFConfig)
252236
}
253-
pc.AFSettings[afName] = &types.PerClientAFConfig{
237+
pc.AFSettings[types.AFName(afName)] = &types.PerClientAFConfig{
254238
EndpointOverride: af.DDNS,
255239
}
256240
}
257241
}
258242
cfg.AllowedClients = append(cfg.AllowedClients, pc)
259243
}
260244

261-
return &cfg
245+
return cfg
262246
}
263247

264-
func (ag *AutogenConfig) buildClientConfig(name string, keys map[string]*autogenNodeKeys) *ClientConfigFile {
248+
func (ag *AutogenConfig) buildClientConfig(name string, keys map[string]*autogenNodeKeys) *ClientConfig {
265249
k := keys[name]
266-
cfg := DefaultClientConfig
250+
cfg := cloneClientConfig(&DefaultClientConfig)
267251

268-
cfg.PrivateKey = base64.StdEncoding.EncodeToString(k.Priv[:])
269-
cfg.PublicKey = base64.StdEncoding.EncodeToString(k.Pub[:])
252+
cfg.PrivateKey = k.Priv
270253
cfg.BridgeName = ag.BridgeName
271254
if ag.ClampMSSToMTU != nil {
272255
cfg.ClampMSSToMTU = *ag.ClampMSSToMTU
@@ -276,9 +259,10 @@ func (ag *AutogenConfig) buildClientConfig(name string, keys map[string]*autogen
276259
}
277260

278261
// AF settings from this node's AFs
279-
cfg.AFSettings = make(map[string]*ClientAFConfigFile)
262+
cfg.AFSettings = make(map[types.AFName]*ClientAFConfig)
280263
for afName, af := range ag.Nodes[name] {
281-
afCfg := &ClientAFConfigFile{
264+
afCfg := &ClientAFConfig{
265+
Name: types.AFName(afName),
282266
Enable: true,
283267
ProbePort: ag.ProbePort,
284268
VxlanName: ag.VxlanNamePrefix + afName,
@@ -288,12 +272,12 @@ func (ag *AutogenConfig) buildClientConfig(name string, keys map[string]*autogen
288272
VxlanSrcPortStart: ag.VxlanSrcPortStart,
289273
VxlanSrcPortEnd: ag.VxlanSrcPortEnd,
290274
Priority: ag.Priority,
291-
ForwardCost: ag.ForwardCost,
275+
ForwardCost: ag.ForwardCost,
292276
}
293277
if af.IsAutoIP() {
294278
afCfg.AutoIPInterface = af.Bind
295279
} else {
296-
afCfg.BindAddr = af.Bind
280+
afCfg.BindAddr = netip.MustParseAddr(af.Bind)
297281
}
298282

299283
// Add controllers that have this AF
@@ -302,38 +286,29 @@ func (ag *AutogenConfig) buildClientConfig(name string, keys map[string]*autogen
302286
if !ok {
303287
continue
304288
}
305-
// Same node: connect via bind addr (LAN); different node: use ddns/endpoint
306289
var addr string
307290
if ctrlName == name {
308291
addr = ctrlAF.Bind
309292
} else {
310293
addr, _ = ctrlAF.Endpoint() // already validated
311294
}
312295
ck := keys[ctrlName]
313-
afCfg.Controllers = append(afCfg.Controllers, ControllerEndpointFile{
314-
PubKey: base64.StdEncoding.EncodeToString(ck.Pub[:]),
315-
Addr: formatAddrPort(addr, ag.CommunicationPort),
296+
ap, _ := netip.ParseAddrPort(formatAddrPort(addr, ag.CommunicationPort))
297+
afCfg.Controllers = append(afCfg.Controllers, ControllerEndpoint{
298+
PubKey: ck.Pub,
299+
Addr: ap,
316300
})
317301
}
318302

319-
cfg.AFSettings[afName] = afCfg
303+
cfg.AFSettings[types.AFName(afName)] = afCfg
320304
}
321305

322-
return &cfg
306+
return cfg
323307
}
324308

325309
func formatAddrPort(host string, port uint16) string {
326-
// If it's an IPv6 address, wrap in brackets
327310
if addr, err := netip.ParseAddr(host); err == nil && addr.Is6() {
328311
return fmt.Sprintf("[%s]:%d", host, port)
329312
}
330313
return fmt.Sprintf("%s:%d", host, port)
331314
}
332-
333-
func writeYAML(path string, v interface{}) error {
334-
data, err := yaml.Marshal(v)
335-
if err != nil {
336-
return err
337-
}
338-
return os.WriteFile(path, data, 0644)
339-
}

0 commit comments

Comments
 (0)