Skip to content

Commit eb08b66

Browse files
committed
chore: fix env var mapping
1 parent 529c538 commit eb08b66

File tree

1 file changed

+82
-39
lines changed

1 file changed

+82
-39
lines changed

cmd/crowdsec-exporter/main.go

Lines changed: 82 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net/http"
88
"os"
99
"os/signal"
10+
"strings"
1011
"syscall"
1112
"time"
1213

@@ -18,48 +19,97 @@ import (
1819
)
1920

2021
var (
21-
cfg *config.Config
22+
version = "dev"
23+
commit = "unknown"
24+
date = "unknown"
2225
)
2326

24-
var rootCmd = &cobra.Command{
25-
Use: "crowdsec-exporter",
26-
Short: "Prometheus exporter for CrowdSec decisions",
27-
Long: `A Prometheus exporter that exposes CrowdSec decisions with rich geographical
28-
and ASN information as metrics, compatible with Grafana dashboards.`,
29-
RunE: runExporter,
27+
func main() {
28+
if err := newRootCmd().Execute(); err != nil {
29+
slog.Error("Command execution failed", "error", err)
30+
os.Exit(1)
31+
}
3032
}
3133

32-
func init() {
33-
// Global flags
34-
rootCmd.PersistentFlags().String("crowdsec-url", "http://localhost:8080", "CrowdSec Local API URL")
35-
rootCmd.PersistentFlags().String("crowdsec-login", "", "CrowdSec machine login")
36-
rootCmd.PersistentFlags().String("crowdsec-password", "", "CrowdSec machine password")
37-
rootCmd.PersistentFlags().String("crowdsec-registration-token", "", "CrowdSec auto-registration token")
38-
rootCmd.PersistentFlags().String("crowdsec-machine-name", "", "Machine name for auto-registration (defaults to hostname)")
39-
rootCmd.PersistentFlags().String("listen-address", ":9090", "Address to listen on for web interface and metrics")
40-
rootCmd.PersistentFlags().String("metrics-path", "/metrics", "Path under which to expose metrics")
41-
rootCmd.PersistentFlags().String("instance-name", "crowdsec", "Instance name to use in metrics labels")
42-
rootCmd.PersistentFlags().String("log-level", "info", "Log level (debug, info, warn, error)")
34+
func newRootCmd() *cobra.Command {
35+
cmd := &cobra.Command{
36+
Use: "crowdsec-exporter",
37+
Short: "Prometheus exporter for CrowdSec decisions",
38+
Long: `A Prometheus exporter that exposes CrowdSec decisions with rich geographical
39+
and ASN information as metrics, compatible with Grafana dashboards.`,
4340

44-
// Bind flags to viper
45-
viper.BindPFlag("crowdsec.url", rootCmd.PersistentFlags().Lookup("crowdsec-url"))
46-
viper.BindPFlag("crowdsec.login", rootCmd.PersistentFlags().Lookup("crowdsec-login"))
47-
viper.BindPFlag("crowdsec.password", rootCmd.PersistentFlags().Lookup("crowdsec-password"))
48-
viper.BindPFlag("crowdsec.registration_token", rootCmd.PersistentFlags().Lookup("crowdsec-registration-token"))
49-
viper.BindPFlag("crowdsec.machine_name", rootCmd.PersistentFlags().Lookup("crowdsec-machine-name"))
50-
viper.BindPFlag("server.listen_address", rootCmd.PersistentFlags().Lookup("listen-address"))
51-
viper.BindPFlag("server.metrics_path", rootCmd.PersistentFlags().Lookup("metrics-path"))
52-
viper.BindPFlag("exporter.instance_name", rootCmd.PersistentFlags().Lookup("instance-name"))
53-
viper.BindPFlag("log_level", rootCmd.PersistentFlags().Lookup("log-level"))
54-
}
41+
SilenceUsage: true, // Don't show usage on errors
42+
SilenceErrors: true, // We handle errors manually
43+
RunE: func(cmd *cobra.Command, args []string) error {
44+
return runExporter()
45+
},
46+
}
5547

56-
func runExporter(cmd *cobra.Command, args []string) error {
57-
// Set up viper to read from environment variables and flags
48+
// Setup Viper for automatic env binding
5849
viper.SetEnvPrefix("CROWDSEC_EXPORTER")
5950
viper.AutomaticEnv()
51+
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_", ".", "_"))
52+
53+
flags := cmd.Flags()
54+
flags.String("crowdsec-url", "http://localhost:8080", "CrowdSec Local API URL")
55+
flags.String("crowdsec-login", "", "CrowdSec machine login")
56+
flags.String("crowdsec-password", "", "CrowdSec machine password")
57+
flags.String("crowdsec-registration-token", "", "CrowdSec auto-registration token")
58+
flags.String("crowdsec-machine-name", "", "Machine name for auto-registration (defaults to hostname)")
59+
flags.String("listen-address", ":9090", "Address to listen on for web interface and metrics")
60+
flags.String("metrics-path", "/metrics", "Path under which to expose metrics")
61+
flags.String("instance-name", "crowdsec", "Instance name to use in metrics labels")
62+
flags.String("log-level", "info", "Log level (debug, info, warn, error)")
63+
64+
// Bind flags to viper
65+
if err := viper.BindPFlag("crowdsec.url", flags.Lookup("crowdsec-url")); err != nil {
66+
panic(fmt.Sprintf("failed to bind crowdsec-url flag: %v", err))
67+
}
68+
if err := viper.BindPFlag("crowdsec.login", flags.Lookup("crowdsec-login")); err != nil {
69+
panic(fmt.Sprintf("failed to bind crowdsec-login flag: %v", err))
70+
}
71+
if err := viper.BindPFlag("crowdsec.password", flags.Lookup("crowdsec-password")); err != nil {
72+
panic(fmt.Sprintf("failed to bind crowdsec-password flag: %v", err))
73+
}
74+
if err := viper.BindPFlag("crowdsec.registration_token", flags.Lookup("crowdsec-registration-token")); err != nil {
75+
panic(fmt.Sprintf("failed to bind crowdsec-registration-token flag: %v", err))
76+
}
77+
if err := viper.BindPFlag("crowdsec.machine_name", flags.Lookup("crowdsec-machine-name")); err != nil {
78+
panic(fmt.Sprintf("failed to bind crowdsec-machine-name flag: %v", err))
79+
}
80+
if err := viper.BindPFlag("server.listen_address", flags.Lookup("listen-address")); err != nil {
81+
panic(fmt.Sprintf("failed to bind listen-address flag: %v", err))
82+
}
83+
if err := viper.BindPFlag("server.metrics_path", flags.Lookup("metrics-path")); err != nil {
84+
panic(fmt.Sprintf("failed to bind metrics-path flag: %v", err))
85+
}
86+
if err := viper.BindPFlag("exporter.instance_name", flags.Lookup("instance-name")); err != nil {
87+
panic(fmt.Sprintf("failed to bind instance-name flag: %v", err))
88+
}
89+
if err := viper.BindPFlag("log_level", flags.Lookup("log-level")); err != nil {
90+
panic(fmt.Sprintf("failed to bind log-level flag: %v", err))
91+
}
6092

93+
cmd.AddCommand(newVersionCmd())
94+
95+
return cmd
96+
}
97+
98+
func newVersionCmd() *cobra.Command {
99+
return &cobra.Command{
100+
Use: "version",
101+
Short: "Show version information",
102+
Run: func(cmd *cobra.Command, args []string) {
103+
fmt.Printf("crowdsec-exporter %s\n", version)
104+
fmt.Printf("commit: %s\n", commit)
105+
fmt.Printf("built: %s\n", date)
106+
},
107+
}
108+
}
109+
110+
func runExporter() error {
61111
// Load config from flags and env vars
62-
cfg = &config.Config{}
112+
cfg := &config.Config{}
63113
if err := viper.Unmarshal(cfg); err != nil {
64114
return fmt.Errorf("unable to decode config: %w", err)
65115
}
@@ -127,10 +177,3 @@ func runExporter(cmd *cobra.Command, args []string) error {
127177
slog.Info("Server exited")
128178
return nil
129179
}
130-
131-
func main() {
132-
if err := rootCmd.Execute(); err != nil {
133-
fmt.Println(err)
134-
os.Exit(1)
135-
}
136-
}

0 commit comments

Comments
 (0)