Skip to content

Commit 4150928

Browse files
committed
Rewrite panic to log.Panicf
1 parent 8052904 commit 4150928

File tree

5 files changed

+99
-37
lines changed

5 files changed

+99
-37
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ vite.config.ts.timestamp-*
1515
!config.yaml.example
1616
protobuf/*
1717
install.yml
18+
.gitlab-ci.yml

main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"embed"
66
"io/fs"
7+
"log"
78

89
"gitlab.as203038.net/AS203038/looking-glass/server"
910
)
@@ -14,7 +15,7 @@ var webemned embed.FS
1415
func main() {
1516
web, err := fs.Sub(webemned, "dist")
1617
if err != nil {
17-
panic(err)
18+
log.Panicln(err)
1819
}
1920
server.Start(context.Background(), web)
2021
}

server/routers/frrouting.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: frrouting
22

3-
ping:
3+
ping:
44
# any:
55
# - ping -n -c5 {{.IP.IP}}
66
ipv4:
@@ -17,7 +17,7 @@ traceroute:
1717
- traceroute -6 -w 1 -q1 -I --back --mtu -e -s {{.Cfg.Source6.IP}} {{.IP.IP}}
1818

1919
bgp:
20-
route:
20+
route:
2121
- vtysh -c 'show bgp vrf {{.Cfg.VRF}} {{.IP.Family}} unicast {{.IP.IP}}'
2222
community:
2323
- vtysh -c 'show bgp vrf {{.Cfg.VRF}} ipv4 unicast community {{.Community}}'

server/routers/routers.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ var (
1111
)
1212

1313
func register(name string, rt utils.Router) bool {
14+
if name == "" {
15+
log.Panicln("Router name cannot be empty")
16+
}
1417
if _, ok := _routers[name]; ok {
15-
panic("Router already registered")
18+
log.Panicf("Router %s already registered", name)
1619
}
1720
_routers[name] = rt
1821
return true

server/routers/yaml.go

Lines changed: 90 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,84 +3,132 @@ package routers
33
import (
44
"bytes"
55
"embed"
6-
"fmt"
6+
"log"
7+
"os"
8+
"strings"
79
"text/template"
810

911
"gitlab.as203038.net/AS203038/looking-glass/server/errs"
1012
"gitlab.as203038.net/AS203038/looking-glass/server/utils"
1113
yaml "gopkg.in/yaml.v2"
1214
)
1315

16+
// _tpl_data represents the template data used in the router YAML file.
1417
type _tpl_data struct {
15-
Cfg *utils.RouterConfig
16-
IP *utils.IPNet
17-
Community string
18-
ASPath string
18+
Cfg *utils.RouterConfig // Cfg holds the router configuration.
19+
IP *utils.IPNet // IP holds the IP network information.
20+
Community string // Community holds the community string.
21+
ASPath string // ASPath holds the AS path information.
1922
}
2023

24+
// Yaml represents the structure of a YAML file.
2125
type Yaml struct {
22-
Path string
26+
Path string // Path represents the file path.
2327
Template struct {
24-
Name string `yaml:"name"`
28+
Name string `yaml:"name"` // Name represents the template name.
2529
Ping struct {
26-
Any []string `yaml:"any"`
27-
IPv4 []string `yaml:"ipv4"`
28-
IPv6 []string `yaml:"ipv6"`
29-
} `yaml:"ping"`
30+
Any []string `yaml:"any"` // Any represents the list of ping targets for any IP address.
31+
IPv4 []string `yaml:"ipv4"` // IPv4 represents the list of ping targets for IPv4 addresses.
32+
IPv6 []string `yaml:"ipv6"` // IPv6 represents the list of ping targets for IPv6 addresses.
33+
} `yaml:"ping"` // Ping represents the ping section in the template.
3034
Traceroute struct {
31-
Any []string `yaml:"any"`
32-
IPv4 []string `yaml:"ipv4"`
33-
IPv6 []string `yaml:"ipv6"`
34-
} `yaml:"traceroute"`
35+
Any []string `yaml:"any"` // Any represents the list of traceroute targets for any IP address.
36+
IPv4 []string `yaml:"ipv4"` // IPv4 represents the list of traceroute targets for IPv4 addresses.
37+
IPv6 []string `yaml:"ipv6"` // IPv6 represents the list of traceroute targets for IPv6 addresses.
38+
} `yaml:"traceroute"` // Traceroute represents the traceroute section in the template.
3539
BGP struct {
36-
Route []string `yaml:"route"`
37-
Community []string `yaml:"community"`
38-
ASPath []string `yaml:"aspath"`
39-
} `yaml:"bgp"`
40+
Route []string `yaml:"route"` // Route represents the list of BGP routes.
41+
Community []string `yaml:"community"` // Community represents the list of BGP communities.
42+
ASPath []string `yaml:"aspath"` // ASPath represents the list of BGP AS paths.
43+
} `yaml:"bgp"` // BGP represents the BGP section in the template.
4044
}
4145
}
4246

4347
//go:embed all:*.yml
4448
var compiledRouters embed.FS
4549

50+
// init is a function that is automatically called before the program starts.
51+
// It initializes the routers by loading them from the specified directory and bundled routers.
52+
// It reads YAML files, unmarshals them into router templates, and registers the routers.
53+
// If the ROUTER_DIR environment variable is set, it loads routers from the specified directory.
54+
// If the bundled routers exist, it loads them as well.
55+
// The function logs the registration status of each router.
4656
func init() {
47-
// Load all routers
57+
// Check for ROUTER_DIR environment variable
58+
rd := os.Getenv("ROUTER_DIR")
59+
if rd != "" {
60+
// Load all routers from ROUTER_DIR
61+
files, err := os.ReadDir(rd)
62+
if err != nil {
63+
log.Panicf("Could not Read directory %s: %+v", rd, err)
64+
}
65+
log.Printf("Loading routers from %s\n", rd)
66+
for _, file := range files {
67+
if file.IsDir() || (!strings.HasSuffix(file.Name(), ".yml") && !strings.HasSuffix(file.Name(), ".yaml")) {
68+
continue
69+
}
70+
// Rest of the code for processing the file
71+
y := &Yaml{Path: file.Name()}
72+
yamlFile, err := os.ReadFile(rd + "/" + y.Path)
73+
if err != nil {
74+
log.Panicf("Could not Read file %s/%s: %+v", rd, y.Path, err)
75+
}
76+
err = yaml.Unmarshal(yamlFile, &y.Template)
77+
if err != nil {
78+
log.Panicf("Could not Unmarshal file %s/%s: %+v", rd, y.Path, err)
79+
}
80+
if y.Template.Name == "" {
81+
log.Printf("Router name cannot be empty (%s/%s)", rd, y.Path)
82+
continue
83+
}
84+
register(y.Template.Name, y)
85+
log.Printf("Router %s (%s/%s) registered\n", y.Template.Name, rd, y.Path)
86+
}
87+
}
88+
89+
// Load all bundled routers
4890
files, err := compiledRouters.ReadDir(".")
4991
if err != nil {
50-
panic(err)
92+
log.Panicf("Could not Read builtin directory: %+v", err)
5193
}
5294
for _, file := range files {
53-
y := &Yaml{}
54-
y.Path = file.Name()
95+
y := &Yaml{Path: file.Name()}
5596
yamlFile, err := compiledRouters.ReadFile(y.Path)
5697
if err != nil {
57-
panic(err)
98+
log.Panicf("Could not Read file builtin:%s: %+v", y.Path, err)
5899
}
59100
err = yaml.Unmarshal(yamlFile, &y.Template)
60101
if err != nil {
61-
panic(err)
102+
log.Panicf("Could not Unmarshal file builtin:%s: %+v", y.Path, err)
103+
}
104+
if _, ok := _routers[y.Template.Name]; !ok {
105+
register(y.Template.Name, y)
106+
log.Printf("Router %s (builtin:%s) registered\n", y.Template.Name, y.Path)
107+
} else {
108+
log.Printf("Router %s already registered\n", y.Template.Name)
62109
}
63-
register(y.Template.Name, y)
64-
fmt.Printf("Router %s registered\n", y.Template.Name)
65110
}
66111
}
67112

113+
// _tpl is a helper function used to generate a list of strings based on the provided template name and data.
114+
// It takes a template name and data as input and returns a list of strings generated from the template.
115+
// The function first determines the appropriate template to use based on the template name and the IP version in the data.
116+
// It then iterates over the selected template(s), executes them with the provided data, and appends the generated strings to the result list.
117+
// If no template is found for the given name, the function returns nil and an error of type `errs.OperationUnknown`.
68118
func (rt *Yaml) _tpl(name string, data _tpl_data) ([]string, error) {
69119
var tpl []string
70120
var ret []string
71121
switch name {
72122
case "ping":
73-
if rt.Template.Ping.Any != nil {
74-
tpl = rt.Template.Ping.Any
75-
} else if data.IP.IsIPv4() {
123+
tpl = rt.Template.Ping.Any
124+
if data.IP.IsIPv4() {
76125
tpl = rt.Template.Ping.IPv4
77126
} else if data.IP.IsIPv6() {
78127
tpl = rt.Template.Ping.IPv6
79128
}
80129
case "traceroute":
81-
if rt.Template.Traceroute.Any != nil {
82-
tpl = rt.Template.Traceroute.Any
83-
} else if data.IP.IsIPv4() {
130+
tpl = rt.Template.Traceroute.Any
131+
if data.IP.IsIPv4() {
84132
tpl = rt.Template.Traceroute.IPv4
85133
} else if data.IP.IsIPv6() {
86134
tpl = rt.Template.Traceroute.IPv6
@@ -110,22 +158,31 @@ func (rt *Yaml) _tpl(name string, data _tpl_data) ([]string, error) {
110158
return ret, nil
111159
}
112160

161+
// Ping sends a ping request to the specified IP address using the provided router configuration.
162+
// It returns a slice of strings representing the ping response and an error if any.
113163
func (rt *Yaml) Ping(cfg *utils.RouterConfig, ip *utils.IPNet) ([]string, error) {
114164
return rt._tpl("ping", _tpl_data{Cfg: cfg, IP: ip})
115165
}
116166

167+
// Traceroute performs a traceroute operation using the provided router configuration and IP address.
168+
// It returns a slice of strings representing the traceroute results and an error if any.
117169
func (rt *Yaml) Traceroute(cfg *utils.RouterConfig, ip *utils.IPNet) ([]string, error) {
118170
return rt._tpl("traceroute", _tpl_data{Cfg: cfg, IP: ip})
119171
}
120172

173+
// BGPRoute generates BGP route configuration based on the provided RouterConfig and IPNet.
174+
// It returns a slice of strings representing the generated configuration and an error if any.
121175
func (rt *Yaml) BGPRoute(cfg *utils.RouterConfig, ip *utils.IPNet) ([]string, error) {
122176
return rt._tpl("bgp.route", _tpl_data{Cfg: cfg, IP: ip})
123177
}
124178

179+
// BGPCommunity returns a list of strings representing the BGP community values for the given router configuration and community.
125180
func (rt *Yaml) BGPCommunity(cfg *utils.RouterConfig, community string) ([]string, error) {
126181
return rt._tpl("bgp.community", _tpl_data{Cfg: cfg, Community: community})
127182
}
128183

184+
// BGPASPath returns a slice of strings representing the BGP AS path for the given router configuration and AS path string.
185+
// It uses the "_tpl" method to render the "bgp.aspath" template with the provided configuration and AS path.
129186
func (rt *Yaml) BGPASPath(cfg *utils.RouterConfig, aspath string) ([]string, error) {
130187
return rt._tpl("bgp.aspath", _tpl_data{Cfg: cfg, ASPath: aspath})
131188
}

0 commit comments

Comments
 (0)