Skip to content

Commit bc34a5c

Browse files
committed
Extract common params into a base struct & use that as an argument
It's getting ridiculous that those fields have to be passed around everywhere into functions and methods. This becomes even more ridiculous with upcoming PR of mine, so I just bite the bullet and make a struct for it. This struct is typically embedded into other structs that need access to these common resources, and each function or method has just to take the `RuntimeConfig` as a parameter, and this will be populated from there.
1 parent 76dcdff commit bc34a5c

File tree

13 files changed

+167
-178
lines changed

13 files changed

+167
-178
lines changed

cmd/icinga-notifications/main.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ import (
1919
)
2020

2121
func main() {
22-
daemon.ParseFlagsAndConfig()
23-
conf := daemon.Config()
22+
conf := daemon.ParseFlagsAndConfig()
2423

2524
logs, err := logging.NewLoggingFromConfig("icinga-notifications", conf.Logging)
2625
if err != nil {
@@ -45,17 +44,19 @@ func main() {
4544
logger.Fatalf("Cannot connect to the database: %+v", err)
4645
}
4746

48-
channel.UpsertPlugins(ctx, conf.ChannelsDir, logs.GetChildLogger("channel"), db)
47+
channel.UpsertPlugins(ctx, conf, logs.GetChildLogger("channel"), db)
4948

50-
runtimeConfig := config.NewRuntimeConfig(logs, db)
49+
resources := config.MakeResources(nil, conf, db, logs)
50+
runtimeConfig := config.NewRuntimeConfig(resources)
51+
resources.RuntimeConfig = runtimeConfig
5152
if err := runtimeConfig.UpdateFromDatabase(ctx); err != nil {
5253
logger.Fatalf("Failed to load config from database %+v", err)
5354
}
5455

5556
go runtimeConfig.PeriodicUpdates(ctx, 1*time.Second)
5657

57-
err = incident.LoadOpenIncidents(ctx, db, logs.GetChildLogger("incident"), runtimeConfig)
58-
if err != nil {
58+
logger.Info("Loading all active incidents from database")
59+
if err = incident.LoadOpenIncidents(ctx, resources); err != nil {
5960
logger.Fatalf("Cannot load incidents from database: %+v", err)
6061
}
6162

@@ -68,7 +69,7 @@ func main() {
6869
// When Icinga Notifications is started by systemd, we've to notify systemd that we're ready.
6970
_ = sdnotify.Ready()
7071

71-
if err := listener.NewListener(db, runtimeConfig, logs).Run(ctx); err != nil {
72+
if err := listener.NewListener(resources).Run(ctx); err != nil {
7273
logger.Errorf("Listener has finished with an error: %+v", err)
7374
} else {
7475
logger.Info("Listener has finished")

internal/channel/channel.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/icinga/icinga-go-library/notifications/plugin"
88
"github.com/icinga/icinga-notifications/internal/config/baseconf"
99
"github.com/icinga/icinga-notifications/internal/contracts"
10+
"github.com/icinga/icinga-notifications/internal/daemon"
1011
"github.com/icinga/icinga-notifications/internal/event"
1112
"github.com/icinga/icinga-notifications/internal/recipient"
1213
"go.uber.org/zap"
@@ -23,8 +24,9 @@ type Channel struct {
2324

2425
Logger *zap.SugaredLogger `db:"-"`
2526

26-
restartCh chan newConfig
27-
pluginCh chan *Plugin
27+
daemonConfig *daemon.ConfigFile
28+
restartCh chan newConfig
29+
pluginCh chan *Plugin
2830

2931
pluginCtx context.Context
3032
pluginCtxCancel func()
@@ -50,8 +52,9 @@ type newConfig struct {
5052
}
5153

5254
// Start initializes the channel and starts the plugin in the background
53-
func (c *Channel) Start(ctx context.Context, logger *zap.SugaredLogger) {
55+
func (c *Channel) Start(ctx context.Context, conf *daemon.ConfigFile, logger *zap.SugaredLogger) {
5456
c.Logger = logger.With(zap.Object("channel", c))
57+
c.daemonConfig = conf
5558
c.restartCh = make(chan newConfig)
5659
c.pluginCh = make(chan *Plugin)
5760
c.pluginCtx, c.pluginCtxCancel = context.WithCancel(ctx)
@@ -63,7 +66,7 @@ func (c *Channel) Start(ctx context.Context, logger *zap.SugaredLogger) {
6366
func (c *Channel) initPlugin(cType string, config string) *Plugin {
6467
c.Logger.Debug("Initializing channel plugin")
6568

66-
p, err := NewPlugin(cType, c.Logger)
69+
p, err := NewPlugin(cType, c.daemonConfig.ChannelsDir, c.Logger)
6770
if err != nil {
6871
c.Logger.Errorw("Failed to initialize channel plugin", zap.Error(err))
6972
return nil

internal/channel/plugin.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ type Plugin struct {
3030
}
3131

3232
// NewPlugin starts and returns a new plugin instance. If the start of the plugin fails, an error is returned
33-
func NewPlugin(pluginType string, logger *zap.SugaredLogger) (*Plugin, error) {
34-
file := filepath.Join(daemon.Config().ChannelsDir, pluginType)
33+
func NewPlugin(pluginType, channelsDir string, logger *zap.SugaredLogger) (*Plugin, error) {
34+
file := filepath.Join(channelsDir, pluginType)
3535

3636
logger.Debugw("Starting new channel plugin process", zap.String("path", file))
3737

@@ -167,9 +167,9 @@ func forwardLogs(errPipe io.Reader, logger *zap.SugaredLogger) {
167167
}
168168

169169
// UpsertPlugins upsert the available_channel_type table with working plugins
170-
func UpsertPlugins(ctx context.Context, channelPluginDir string, logger *logging.Logger, db *database.DB) {
170+
func UpsertPlugins(ctx context.Context, conf *daemon.ConfigFile, logger *logging.Logger, db *database.DB) {
171171
logger.Debug("Updating available channel types")
172-
files, err := os.ReadDir(channelPluginDir)
172+
files, err := os.ReadDir(conf.ChannelsDir)
173173
if err != nil {
174174
logger.Errorw("Failed to read the channel plugin directory", zap.Error(err))
175175
}
@@ -185,7 +185,7 @@ func UpsertPlugins(ctx context.Context, channelPluginDir string, logger *logging
185185
continue
186186
}
187187

188-
p, err := NewPlugin(pluginType, pluginLogger)
188+
p, err := NewPlugin(pluginType, conf.ChannelsDir, pluginLogger)
189189
if err != nil {
190190
pluginLogger.Errorw("Failed to start plugin", zap.Error(err))
191191
continue

internal/config/channel.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ func (r *RuntimeConfig) applyPendingChannels() {
1111
r,
1212
&r.Channels, &r.configChange.Channels,
1313
func(newElement *channel.Channel) error {
14-
newElement.Start(context.TODO(), r.logs.GetChildLogger("channel").SugaredLogger)
14+
newElement.Start(context.TODO(), r.DaemonConfig, r.Logs.GetChildLogger("channel").SugaredLogger)
1515
return nil
1616
},
1717
func(curElement, update *channel.Channel) error {
1818
curElement.ChangedAt = update.ChangedAt
1919
curElement.Name = update.Name
2020
curElement.Type = update.Type
2121
curElement.Config = update.Config
22-
curElement.Restart(r.logs.GetChildLogger("channel").SugaredLogger)
22+
curElement.Restart(r.Logs.GetChildLogger("channel").SugaredLogger)
2323
return nil
2424
},
2525
func(delElement *channel.Channel) error {

internal/config/incremental_sync.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func incrementalFetch[
5858
stmtLogger := r.logger.With(zap.String("table", tableName))
5959

6060
var (
61-
stmt = r.db.BuildSelectStmt(typePtr, typePtr)
61+
stmt = r.DB.BuildSelectStmt(typePtr, typePtr)
6262
stmtArgs []any
6363
)
6464
if hasChangedAt {
@@ -67,7 +67,7 @@ func incrementalFetch[
6767
stmtArgs = []any{changedAt}
6868
}
6969

70-
stmt = r.db.Rebind(stmt + ` ORDER BY "changed_at"`)
70+
stmt = r.DB.Rebind(stmt + ` ORDER BY "changed_at"`)
7171
stmtLogger = stmtLogger.With(zap.String("query", stmt))
7272

7373
var ts []T

internal/config/runtime.go

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/icinga/icinga-go-library/logging"
99
"github.com/icinga/icinga-go-library/types"
1010
"github.com/icinga/icinga-notifications/internal/channel"
11+
"github.com/icinga/icinga-notifications/internal/daemon"
1112
"github.com/icinga/icinga-notifications/internal/recipient"
1213
"github.com/icinga/icinga-notifications/internal/rule"
1314
"github.com/icinga/icinga-notifications/internal/timeperiod"
@@ -19,12 +20,30 @@ import (
1920
"time"
2021
)
2122

23+
// Resources holds references to commonly used objects.
24+
type Resources struct {
25+
DaemonConfig *daemon.ConfigFile `db:"-" json:"-"`
26+
RuntimeConfig *RuntimeConfig `db:"-" json:"-"`
27+
DB *database.DB `db:"-" json:"-"`
28+
Logs *logging.Logging `db:"-" json:"-"`
29+
}
30+
31+
// MakeResources creates a new Resources instance with the provided components.
32+
//
33+
// This function initializes the Resources struct by assigning the given [RuntimeConfig],
34+
// database connection, and logging facilities.
35+
func MakeResources(rc *RuntimeConfig, file *daemon.ConfigFile, db *database.DB, logs *logging.Logging) *Resources {
36+
return &Resources{RuntimeConfig: rc, DaemonConfig: file, DB: db, Logs: logs}
37+
}
38+
2239
// RuntimeConfig stores the runtime representation of the configuration present in the database.
2340
type RuntimeConfig struct {
2441
// ConfigSet is the current live config. It is embedded to allow direct access to its members.
2542
// Accessing it requires a lock that is obtained with RLock() and released with RUnlock().
2643
ConfigSet
2744

45+
*Resources // Contains references to commonly used objects and to itself.
46+
2847
// configChange contains incremental changes to config objects to be merged into the live configuration.
2948
//
3049
// It will be both created and deleted within RuntimeConfig.UpdateFromDatabase. To keep track of the known state,
@@ -33,24 +52,18 @@ type RuntimeConfig struct {
3352
configChangeAvailable bool
3453
configChangeTimestamps map[string]types.UnixMilli
3554

36-
logs *logging.Logging
3755
logger *logging.Logger
38-
db *database.DB
3956

4057
// mu is used to synchronize access to the live ConfigSet.
4158
mu sync.RWMutex
4259
}
4360

44-
func NewRuntimeConfig(
45-
logs *logging.Logging,
46-
db *database.DB,
47-
) *RuntimeConfig {
61+
func NewRuntimeConfig(resouces *Resources) *RuntimeConfig {
4862
return &RuntimeConfig{
4963
configChangeTimestamps: make(map[string]types.UnixMilli),
5064

51-
logs: logs,
52-
logger: logs.GetChildLogger("runtime-updates"),
53-
db: db,
65+
Resources: resouces,
66+
logger: resouces.Logs.GetChildLogger("runtime-updates"),
5467
}
5568
}
5669

@@ -235,7 +248,7 @@ func (r *RuntimeConfig) GetSourceFromCredentials(user, pass string, logger *logg
235248
}
236249

237250
func (r *RuntimeConfig) fetchFromDatabase(ctx context.Context) error {
238-
tx, err := r.db.BeginTxx(ctx, &sql.TxOptions{
251+
tx, err := r.DB.BeginTxx(ctx, &sql.TxOptions{
239252
Isolation: sql.LevelRepeatableRead,
240253
ReadOnly: true,
241254
})

internal/daemon/config.go

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,23 +61,10 @@ type Flags struct {
6161
Config string `short:"c" long:"config" description:"path to config file"`
6262
}
6363

64-
// daemonConfig holds the configuration state as a singleton.
65-
// It is initialised by the ParseFlagsAndConfig func and exposed through the Config function.
66-
var daemonConfig *ConfigFile
67-
68-
// Config returns the config that was loaded while starting the daemon.
69-
// Panics when ParseFlagsAndConfig was not called earlier.
70-
func Config() *ConfigFile {
71-
if daemonConfig == nil {
72-
panic("ERROR: daemon.Config() called before daemon.ParseFlagsAndConfig()")
73-
}
74-
75-
return daemonConfig
76-
}
77-
7864
// ParseFlagsAndConfig parses the CLI flags provided to the executable and tries to load the config from the YAML file.
79-
// Prints any error during parsing or config loading to os.Stderr and exits.
80-
func ParseFlagsAndConfig() {
65+
//
66+
// Prints any error during parsing or config loading to os.Stderr and exits, otherwise returns the loaded ConfigFile.
67+
func ParseFlagsAndConfig() *ConfigFile {
8168
flags := Flags{Config: internal.SysConfDir + "/icinga-notifications/config.yml"}
8269
if err := config.ParseFlags(&flags); err != nil {
8370
if errors.Is(err, config.ErrInvalidArgument) {
@@ -92,12 +79,13 @@ func ParseFlagsAndConfig() {
9279
os.Exit(ExitSuccess)
9380
}
9481

95-
daemonConfig = new(ConfigFile)
82+
daemonConfig := new(ConfigFile)
9683
if err := config.FromYAMLFile(flags.Config, daemonConfig); err != nil {
9784
if errors.Is(err, config.ErrInvalidArgument) {
9885
panic(err)
9986
}
10087

10188
utils.PrintErrorThenExit(err, ExitFailure)
10289
}
90+
return daemonConfig
10391
}

0 commit comments

Comments
 (0)