feat: enhance evobgp with new command-line tools for bundle management, including pull, verify, and apply functionalities. Update go.mod to include necessary dependencies and complete todos in architecture plan for improved observability and deployment practices.
CI / changes (push) Successful in 4s
CI / go (push) Failing after 6s
CI / bird2 (push) Has been skipped
CI / openapi (push) Has been skipped

This commit is contained in:
Denozordec
2026-04-05 14:07:45 +07:00
parent 272542b92a
commit bf52b21150
131 changed files with 9222 additions and 17 deletions
+114
View File
@@ -0,0 +1,114 @@
package birdfmt
import (
"fmt"
"strings"
)
// BGPPeerIPv4Options describes a single BGP session (BIRD 2, IPv4 AF).
type BGPPeerIPv4Options struct {
ProtocolName string // e.g. evobgp_peer_uplink
LocalIP string // e.g. 192.0.2.1
LocalASN uint32
NeighborIP string
NeighborASN uint32
// ExportFilter is a filter name, or empty for "export all".
ExportFilter string
// ImportFilter is a filter name, or empty for "import all".
ImportFilter string
}
// RenderProtocolBGPIPv4 renders a protocol bgp { … ipv4 { … } } block.
func RenderProtocolBGPIPv4(opts BGPPeerIPv4Options) (string, error) {
if strings.TrimSpace(opts.ProtocolName) == "" {
return "", fmt.Errorf("birdfmt: protocol name is required")
}
if strings.TrimSpace(opts.LocalIP) == "" || strings.TrimSpace(opts.NeighborIP) == "" {
return "", fmt.Errorf("birdfmt: local and neighbor addresses are required")
}
if opts.LocalASN == 0 || opts.NeighborASN == 0 {
return "", fmt.Errorf("birdfmt: AS numbers must be non-zero")
}
imp := "all"
if strings.TrimSpace(opts.ImportFilter) != "" {
imp = "filter " + strings.TrimSpace(opts.ImportFilter)
}
exp := "all"
if strings.TrimSpace(opts.ExportFilter) != "" {
exp = "filter " + strings.TrimSpace(opts.ExportFilter)
}
var b strings.Builder
b.WriteString("protocol bgp ")
b.WriteString(strings.TrimSpace(opts.ProtocolName))
b.WriteString(" {\n")
b.WriteString(" local ")
b.WriteString(strings.TrimSpace(opts.LocalIP))
fmt.Fprintf(&b, " as %d;\n", opts.LocalASN)
b.WriteString(" neighbor ")
b.WriteString(strings.TrimSpace(opts.NeighborIP))
fmt.Fprintf(&b, " as %d;\n", opts.NeighborASN)
b.WriteString(" ipv4 {\n")
b.WriteString(" import ")
b.WriteString(imp)
b.WriteString(";\n")
b.WriteString(" export ")
b.WriteString(exp)
b.WriteString(";\n")
b.WriteString(" };\n")
b.WriteString("}\n")
return b.String(), nil
}
// BGPPeerIPv6Options describes a BGP session for the IPv6 AF.
type BGPPeerIPv6Options struct {
ProtocolName string
LocalIP string
LocalASN uint32
NeighborIP string
NeighborASN uint32
ExportFilter string
ImportFilter string
}
// RenderProtocolBGPIPv6 renders a protocol bgp block with ipv6 { import/export }.
func RenderProtocolBGPIPv6(opts BGPPeerIPv6Options) (string, error) {
if strings.TrimSpace(opts.ProtocolName) == "" {
return "", fmt.Errorf("birdfmt: protocol name is required")
}
if strings.TrimSpace(opts.LocalIP) == "" || strings.TrimSpace(opts.NeighborIP) == "" {
return "", fmt.Errorf("birdfmt: local and neighbor addresses are required")
}
if opts.LocalASN == 0 || opts.NeighborASN == 0 {
return "", fmt.Errorf("birdfmt: AS numbers must be non-zero")
}
imp := "all"
if strings.TrimSpace(opts.ImportFilter) != "" {
imp = "filter " + strings.TrimSpace(opts.ImportFilter)
}
exp := "all"
if strings.TrimSpace(opts.ExportFilter) != "" {
exp = "filter " + strings.TrimSpace(opts.ExportFilter)
}
var b strings.Builder
b.WriteString("protocol bgp ")
b.WriteString(strings.TrimSpace(opts.ProtocolName))
b.WriteString(" {\n")
b.WriteString(" local ")
b.WriteString(strings.TrimSpace(opts.LocalIP))
fmt.Fprintf(&b, " as %d;\n", opts.LocalASN)
b.WriteString(" neighbor ")
b.WriteString(strings.TrimSpace(opts.NeighborIP))
fmt.Fprintf(&b, " as %d;\n", opts.NeighborASN)
b.WriteString(" ipv6 {\n")
b.WriteString(" import ")
b.WriteString(imp)
b.WriteString(";\n")
b.WriteString(" export ")
b.WriteString(exp)
b.WriteString(";\n")
b.WriteString(" };\n")
b.WriteString("}\n")
return b.String(), nil
}