@@ -17,6 +17,7 @@ import (
1717 "fmt"
1818 "os"
1919 "path/filepath"
20+ "regexp"
2021 "strings"
2122
2223 "github.com/alecthomas/kingpin/v2"
@@ -29,6 +30,10 @@ import (
2930 "github.com/prometheus/snmp_exporter/config"
3031)
3132
33+ var (
34+ cannotFindModuleRE = regexp .MustCompile (`Cannot find module \((.+)\): (.+)` )
35+ )
36+
3237// Generate a snmp_exporter config and write it out.
3338func generateConfig (nodes * Node , nameToNode map [string ]* Node , logger log.Logger ) error {
3439 outputPath , err := filepath .Abs (* outputPath )
@@ -95,8 +100,8 @@ func generateConfig(nodes *Node, nameToNode map[string]*Node, logger log.Logger)
95100}
96101
97102var (
98- failOnParseErrors = kingpin .Flag ("fail-on-parse-errors" , "Exit with a non-zero status if there are MIB parsing errors" ).Default ("false " ).Bool ()
99- snmpMIBOpts = kingpin .Flag ("snmp.mibopts" , "Toggle various defaults controlling MIB parsing, see snmpwalk --help" ).String ()
103+ failOnParseErrors = kingpin .Flag ("fail-on-parse-errors" , "Exit with a non-zero status if there are MIB parsing errors" ).Default ("true " ).Bool ()
104+ snmpMIBOpts = kingpin .Flag ("snmp.mibopts" , "Toggle various defaults controlling MIB parsing, see snmpwalk --help" ).Default ( "e" ). String ()
100105 generateCommand = kingpin .Command ("generate" , "Generate snmp.yml from generator.yml" )
101106 userMibsDir = kingpin .Flag ("mibs-dir" , "Paths to mibs directory" ).Default ("" ).Short ('m' ).Strings ()
102107 generatorYmlPath = generateCommand .Flag ("generator-path" , "Path to the input generator.yml file" ).Default ("generator.yml" ).Short ('g' ).String ()
@@ -112,30 +117,35 @@ func main() {
112117 command := kingpin .Parse ()
113118 logger := promlog .New (promlogConfig )
114119
115- parseOutput , err := initSNMP (logger )
120+ output , err := initSNMP (logger )
116121 if err != nil {
117122 level .Error (logger ).Log ("msg" , "Error initializing netsnmp" , "err" , err )
118123 os .Exit (1 )
119124 }
120125
121- parseOutput = strings .TrimSpace (parseOutput )
122- parseErrors := len (parseOutput ) != 0
123- if parseErrors {
124- level .Warn (logger ).Log ("msg" , "NetSNMP reported parse error(s)" , "errors" , len (strings .Split (parseOutput , "\n " )))
125- }
126+ parseOutput := scanParseOutput (logger , output )
127+ parseErrors := len (parseOutput )
126128
127129 nodes := getMIBTree ()
128130 nameToNode := prepareTree (nodes , logger )
129131
130132 switch command {
131133 case generateCommand .FullCommand ():
132- err := generateConfig (nodes , nameToNode , logger )
133- if err != nil {
134- level .Error (logger ).Log ("msg" , "Error generating config netsnmp" , "err" , err )
135- os .Exit (1 )
134+ if * failOnParseErrors && parseErrors > 0 {
135+ level .Error (logger ).Log ("msg" , "Failing on reported parse error(s)" , "help" , "Use 'generator parse_errors' command to see errors, --no-fail-on-parse-errors to ignore" )
136+ } else {
137+ err := generateConfig (nodes , nameToNode , logger )
138+ if err != nil {
139+ level .Error (logger ).Log ("msg" , "Error generating config netsnmp" , "err" , err )
140+ os .Exit (1 )
141+ }
136142 }
137143 case parseErrorsCommand .FullCommand ():
138- fmt .Println (parseOutput )
144+ if parseErrors > 0 {
145+ fmt .Printf ("%s\n " , strings .Join (parseOutput , "\n " ))
146+ } else {
147+ level .Info (logger ).Log ("msg" , "No parse errors" )
148+ }
139149 case dumpCommand .FullCommand ():
140150 walkNode (nodes , func (n * Node ) {
141151 t := n .Type
@@ -150,7 +160,28 @@ func main() {
150160 n .Oid , n .Label , t , n .TextualConvention , n .Hint , n .Indexes , implied , n .EnumValues , n .Description )
151161 })
152162 }
153- if * failOnParseErrors && parseErrors {
163+ if * failOnParseErrors && parseErrors > 0 {
154164 os .Exit (1 )
155165 }
156166}
167+
168+ func scanParseOutput (logger log.Logger , output string ) []string {
169+ var parseOutput []string
170+ output = strings .TrimSpace (strings .ToValidUTF8 (output , "�" ))
171+ if len (output ) > 0 {
172+ parseOutput = strings .Split (output , "\n " )
173+ }
174+ parseErrors := len (parseOutput )
175+
176+ if parseErrors > 0 {
177+ level .Warn (logger ).Log ("msg" , "NetSNMP reported parse error(s)" , "errors" , parseErrors )
178+ }
179+
180+ for _ , line := range parseOutput {
181+ if strings .HasPrefix (line , "Cannot find module" ) {
182+ missing := cannotFindModuleRE .FindStringSubmatch (line )
183+ level .Error (logger ).Log ("msg" , "Missing MIB" , "mib" , missing [1 ], "from" , missing [2 ])
184+ }
185+ }
186+ return parseOutput
187+ }
0 commit comments