Skip to content

Commit

Permalink
Use CLI flags parser from Icinga Go Library
Browse files Browse the repository at this point in the history
  • Loading branch information
yhabteab committed Jul 19, 2024
1 parent f3ad7bd commit a5ad434
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 78 deletions.
33 changes: 2 additions & 31 deletions cmd/icinga-notifications/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package main

import (
"context"
"flag"
"fmt"
"github.com/icinga/icinga-go-library/database"
"github.com/icinga/icinga-go-library/logging"
"github.com/icinga/icinga-go-library/utils"
Expand All @@ -16,45 +14,18 @@ import (
"github.com/icinga/icinga-notifications/internal/listener"
"github.com/icinga/icinga-notifications/internal/object"
"github.com/okzk/sdnotify"
"os"
"os/signal"
"runtime"
"syscall"
"time"
)

func main() {
var configPath string
var showVersion bool

flag.StringVar(&configPath, "config", internal.SysConfDir+"/icinga-notifications/config.yml", "path to config file")
flag.BoolVar(&showVersion, "version", false, "print version")
flag.Parse()

if showVersion {
// reuse internal.Version.print() once the project name is configurable
fmt.Println("Icinga Notifications version:", internal.Version.Version)
fmt.Println()

fmt.Println("Build information:")
fmt.Printf(" Go version: %s (%s, %s)\n", runtime.Version(), runtime.GOOS, runtime.GOARCH)
if internal.Version.Commit != "" {
fmt.Println(" Git commit:", internal.Version.Commit)
}
return
}

err := daemon.LoadConfig(configPath)
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, "cannot load config:", err)
os.Exit(1)
}

daemon.ParseFlagsAndConfig()
conf := daemon.Config()

logs, err := logging.NewLoggingFromConfig("icinga-notifications", conf.Logging)
if err != nil {
utils.PrintErrorThenExit(err, 1)
utils.PrintErrorThenExit(err, daemon.ExitFailure)
}

logger := logs.GetLogger()
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ require (
github.com/creasty/defaults v1.7.0
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43
github.com/emersion/go-smtp v0.21.3
github.com/goccy/go-yaml v1.11.3
github.com/google/uuid v1.6.0
github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/icinga/icinga-go-library v0.2.0
github.com/icinga/icinga-go-library v0.3.0
github.com/jhillyerd/enmime v1.2.0
github.com/jmoiron/sqlx v1.4.0
github.com/okzk/sdnotify v0.0.0-20180710141335-d9becc38acbd
Expand All @@ -27,6 +26,7 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/goccy/go-yaml v1.11.3 // indirect
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f // indirect
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 // indirect
github.com/jessevdk/go-flags v1.5.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/icinga/icinga-go-library v0.2.0 h1:1or5s3KMEJGdhFbMzlN8NPw1NCd/3ntsKLw5et4/9XI=
github.com/icinga/icinga-go-library v0.2.0/go.mod h1:YN7XJN3W0FodD+j4kirO89zk2tgvanXWt1RMV8UgOLo=
github.com/icinga/icinga-go-library v0.3.0 h1:BeoomAiQC5RTRWCNqNkgbdTGxQ7ZFfkruR4HCSn5e0k=
github.com/icinga/icinga-go-library v0.3.0/go.mod h1:YN7XJN3W0FodD+j4kirO89zk2tgvanXWt1RMV8UgOLo=
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 h1:iCHtR9CQyktQ5+f3dMVZfwD2KWJUgm7M0gdL9NGr8KA=
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
Expand Down
97 changes: 54 additions & 43 deletions internal/daemon/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ package daemon
import (
"errors"
"github.com/creasty/defaults"
"github.com/goccy/go-yaml"
"github.com/icinga/icinga-go-library/config"
"github.com/icinga/icinga-go-library/database"
"github.com/icinga/icinga-go-library/logging"
"github.com/icinga/icinga-go-library/utils"
"github.com/icinga/icinga-notifications/internal"
"os"
"time"
)

const (
ExitSuccess = 0
ExitFailure = 1
)

type ConfigFile struct {
Listen string `yaml:"listen" default:"localhost:5680"`
DebugPassword string `yaml:"debug-password"`
Expand All @@ -28,65 +34,70 @@ func (c *ConfigFile) SetDefaults() {
}
}

// Assert interface compliance.
var _ defaults.Setter = (*ConfigFile)(nil)

// config holds the configuration state as a singleton. It is used from LoadConfig and Config
var config *ConfigFile

// LoadConfig loads the daemon config from given path. Call it only once when starting the daemon.
func LoadConfig(path string) error {
if config != nil {
return errors.New("config already set")
// Validate implements the config.Validator interface.
// Validates the entire daemon configuration on daemon startup.
func (c *ConfigFile) Validate() error {
if err := c.Database.Validate(); err != nil {
return err
}

cfg, err := fromFile(path)
if err != nil {
if err := c.Logging.Validate(); err != nil {
return err
}

config = cfg

return nil
}

// Config returns the config that was loaded while starting the daemon
func Config() *ConfigFile {
return config
// Assert interface compliance.
var (
_ defaults.Setter = (*ConfigFile)(nil)
_ config.Validator = (*ConfigFile)(nil)
)

// Flags defines the CLI flags supported by Icinga Notifications.
type Flags struct {
// Version decides whether to just print the version and exit.
Version bool `long:"version" description:"print version and exit"`
// Config is the path to the config file
Config string `short:"c" long:"config" description:"path to config file"`
}

func fromFile(path string) (*ConfigFile, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
// daemonConfig holds the configuration state as a singleton.
// It is initialised by the ParseFlagsAndConfig func and exposed through the Config function.
var daemonConfig *ConfigFile

// Config returns the config that was loaded while starting the daemon.
// Panics when ParseFlagsAndConfig was not called earlier.
func Config() *ConfigFile {
if daemonConfig == nil {
panic("ERROR: daemon.config not initialized")
}
defer func() { _ = f.Close() }()

var c ConfigFile
return daemonConfig
}

if err := defaults.Set(&c); err != nil {
return nil, err
}
// ParseFlagsAndConfig parses the CLI flags provided to the executable and tries to load the config from the YAML file.
// Prints any error during parsing or config loading to os.Stderr and exits.
func ParseFlagsAndConfig() {
flags := Flags{Config: internal.SysConfDir + "/icinga-notifications/config.yml"}
if err := config.ParseFlags(&flags); err != nil {
if errors.Is(err, config.ErrInvalidArgument) {
panic(err)
}

d := yaml.NewDecoder(f)
if err := d.Decode(&c); err != nil {
return nil, err
utils.PrintErrorThenExit(err, ExitFailure)
}

if err := c.Validate(); err != nil {
return nil, err
if flags.Version {
internal.Version.Print("Icinga Notifications")
os.Exit(ExitSuccess)
}

return &c, nil
}
daemonConfig = new(ConfigFile)
if err := config.FromYAMLFile(flags.Config, daemonConfig); err != nil {
if errors.Is(err, config.ErrInvalidArgument) {
panic(err)
}

func (c *ConfigFile) Validate() error {
if err := c.Database.Validate(); err != nil {
return err
utils.PrintErrorThenExit(err, ExitFailure)
}
if err := c.Logging.Validate(); err != nil {
return err
}

return nil
}

0 comments on commit a5ad434

Please sign in to comment.