registry: refuse duplicate registrations with a warning
RegisterChecker and RegisterObservationProvider previously overwrote existing entries silently, which lets a misconfigured plugin shadow a built-in (or another plugin) without any signal. Refuse the duplicate and keep the existing entry instead. RegisterExternalizableChecker now performs the dedup check before appending the "endpoint" AdminOpt, so a rejected re-registration no longer mutates the live definition.
This commit is contained in:
parent
8160adcdca
commit
8e2ba83a0d
2 changed files with 152 additions and 2 deletions
|
|
@ -27,8 +27,16 @@ var checkerRegistry = map[string]*CheckerDefinition{}
|
|||
// keyed by ObservationKey.
|
||||
var observationProviderRegistry = map[ObservationKey]ObservationProvider{}
|
||||
|
||||
// RegisterChecker registers a checker definition globally.
|
||||
// RegisterChecker registers a checker definition globally. A second
|
||||
// registration under the same ID is refused with a warning rather than
|
||||
// silently overwriting the previous entry: in production this almost
|
||||
// always indicates a deployment mistake (two plugins shipping the same
|
||||
// checker, or a plugin shadowing a built-in).
|
||||
func RegisterChecker(c *CheckerDefinition) {
|
||||
if _, exists := checkerRegistry[c.ID]; exists {
|
||||
log.Printf("Warning: checker %q is already registered; ignoring duplicate registration", c.ID)
|
||||
return
|
||||
}
|
||||
log.Println("Registering new checker:", c.ID)
|
||||
c.BuildRulesInfo()
|
||||
checkerRegistry[c.ID] = c
|
||||
|
|
@ -38,7 +46,16 @@ func RegisterChecker(c *CheckerDefinition) {
|
|||
// delegated to a remote HTTP endpoint. It appends an "endpoint" AdminOpt
|
||||
// so the administrator can optionally configure a remote URL.
|
||||
// When the endpoint is left empty, the checker runs locally as usual.
|
||||
//
|
||||
// The duplicate check happens before the AdminOpt append so that a
|
||||
// rejected second registration does not mutate the in-memory definition
|
||||
// of the already-registered checker (which a caller might still hold a
|
||||
// pointer to).
|
||||
func RegisterExternalizableChecker(c *CheckerDefinition) {
|
||||
if _, exists := checkerRegistry[c.ID]; exists {
|
||||
log.Printf("Warning: checker %q is already registered; ignoring duplicate registration", c.ID)
|
||||
return
|
||||
}
|
||||
c.Options.AdminOpts = append(c.Options.AdminOpts,
|
||||
CheckerOptionDocumentation{
|
||||
Id: "endpoint",
|
||||
|
|
@ -53,8 +70,15 @@ func RegisterExternalizableChecker(c *CheckerDefinition) {
|
|||
}
|
||||
|
||||
// RegisterObservationProvider registers an observation provider globally.
|
||||
// A second registration under the same key is refused with a warning for
|
||||
// the same reason as RegisterChecker.
|
||||
func RegisterObservationProvider(p ObservationProvider) {
|
||||
observationProviderRegistry[p.Key()] = p
|
||||
key := p.Key()
|
||||
if _, exists := observationProviderRegistry[key]; exists {
|
||||
log.Printf("Warning: observation provider %q is already registered; ignoring duplicate registration", key)
|
||||
return
|
||||
}
|
||||
observationProviderRegistry[key] = p
|
||||
}
|
||||
|
||||
// GetCheckers returns all registered checker definitions.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue