ext: lock all drivers
This commit is contained in:
parent
78cef02fda
commit
f9b319089d
@ -21,6 +21,8 @@
|
|||||||
package notification
|
package notification
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/coreos/pkg/capnslog"
|
"github.com/coreos/pkg/capnslog"
|
||||||
|
|
||||||
"github.com/coreos/clair/config"
|
"github.com/coreos/clair/config"
|
||||||
@ -30,8 +32,8 @@ import (
|
|||||||
var (
|
var (
|
||||||
log = capnslog.NewPackageLogger("github.com/coreos/clair", "ext/notification")
|
log = capnslog.NewPackageLogger("github.com/coreos/clair", "ext/notification")
|
||||||
|
|
||||||
// Senders is the list of registered Senders.
|
sendersM sync.RWMutex
|
||||||
Senders = make(map[string]Sender)
|
senders = make(map[string]Sender)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Sender represents anything that can transmit notifications.
|
// Sender represents anything that can transmit notifications.
|
||||||
@ -46,8 +48,8 @@ type Sender interface {
|
|||||||
|
|
||||||
// RegisterSender makes a Sender available by the provided name.
|
// RegisterSender makes a Sender available by the provided name.
|
||||||
//
|
//
|
||||||
// If RegisterSender is called twice with the same name, the name is blank, or
|
// If called twice with the same name, the name is blank, or if the provided
|
||||||
// if the provided Sender is nil, this function panics.
|
// Sender is nil, this function panics.
|
||||||
func RegisterSender(name string, s Sender) {
|
func RegisterSender(name string, s Sender) {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
panic("notification: could not register a Sender with an empty name")
|
panic("notification: could not register a Sender with an empty name")
|
||||||
@ -57,9 +59,33 @@ func RegisterSender(name string, s Sender) {
|
|||||||
panic("notification: could not register a nil Sender")
|
panic("notification: could not register a nil Sender")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, dup := Senders[name]; dup {
|
sendersM.Lock()
|
||||||
|
defer sendersM.Unlock()
|
||||||
|
|
||||||
|
if _, dup := senders[name]; dup {
|
||||||
panic("notification: RegisterSender called twice for " + name)
|
panic("notification: RegisterSender called twice for " + name)
|
||||||
}
|
}
|
||||||
|
|
||||||
Senders[name] = s
|
senders[name] = s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Senders returns the list of the registered Senders.
|
||||||
|
func Senders() map[string]Sender {
|
||||||
|
sendersM.RLock()
|
||||||
|
defer sendersM.RUnlock()
|
||||||
|
|
||||||
|
ret := make(map[string]Sender)
|
||||||
|
for k, v := range senders {
|
||||||
|
ret[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnregisterSender removes a Sender with a particular name from the list.
|
||||||
|
func UnregisterSender(name string) {
|
||||||
|
sendersM.Lock()
|
||||||
|
defer sendersM.Unlock()
|
||||||
|
|
||||||
|
delete(senders, name)
|
||||||
}
|
}
|
||||||
|
@ -63,18 +63,20 @@ type Parser interface {
|
|||||||
// if the provided Parser is nil, this function panics.
|
// if the provided Parser is nil, this function panics.
|
||||||
func RegisterParser(name string, p Parser) {
|
func RegisterParser(name string, p Parser) {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
panic("Could not register a Parser with an empty name")
|
panic("versionfmt: could not register a Parser with an empty name")
|
||||||
}
|
}
|
||||||
|
|
||||||
if p == nil {
|
if p == nil {
|
||||||
panic("Could not register a nil Parser")
|
panic("versionfmt: could not register a nil Parser")
|
||||||
}
|
}
|
||||||
|
|
||||||
parsersM.Lock()
|
parsersM.Lock()
|
||||||
defer parsersM.Unlock()
|
defer parsersM.Unlock()
|
||||||
|
|
||||||
if _, alreadyExists := parsers[name]; alreadyExists {
|
if _, dup := parsers[name]; dup {
|
||||||
panic("Parser '" + name + "' is already registered")
|
panic("versionfmt: RegisterParser called twice for " + name)
|
||||||
}
|
}
|
||||||
|
|
||||||
parsers[name] = p
|
parsers[name] = p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,12 +17,16 @@
|
|||||||
package vulnmdsrc
|
package vulnmdsrc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/utils/types"
|
"github.com/coreos/clair/utils/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Appenders is the list of registered Appenders.
|
var (
|
||||||
var Appenders = make(map[string]Appender)
|
appendersM sync.RWMutex
|
||||||
|
appenders = make(map[string]Appender)
|
||||||
|
)
|
||||||
|
|
||||||
// AppendFunc is the type of a callback provided to an Appender.
|
// AppendFunc is the type of a callback provided to an Appender.
|
||||||
type AppendFunc func(metadataKey string, metadata interface{}, severity types.Priority)
|
type AppendFunc func(metadataKey string, metadata interface{}, severity types.Priority)
|
||||||
@ -49,20 +53,37 @@ type Appender interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RegisterAppender makes an Appender available by the provided name.
|
// RegisterAppender makes an Appender available by the provided name.
|
||||||
// If Register is called twice with the same name or if driver is nil,
|
//
|
||||||
// it panics.
|
// If called twice with the same name, the name is blank, or if the provided
|
||||||
|
// Appender is nil, this function panics.
|
||||||
func RegisterAppender(name string, a Appender) {
|
func RegisterAppender(name string, a Appender) {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
panic("updater: could not register an Appender with an empty name")
|
panic("vulnmdsrc: could not register an Appender with an empty name")
|
||||||
}
|
}
|
||||||
|
|
||||||
if a == nil {
|
if a == nil {
|
||||||
panic("vulnmdsrc: could not register a nil Appender")
|
panic("vulnmdsrc: could not register a nil Appender")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, dup := Appenders[name]; dup {
|
appendersM.Lock()
|
||||||
|
defer appendersM.Unlock()
|
||||||
|
|
||||||
|
if _, dup := appenders[name]; dup {
|
||||||
panic("vulnmdsrc: RegisterAppender called twice for " + name)
|
panic("vulnmdsrc: RegisterAppender called twice for " + name)
|
||||||
}
|
}
|
||||||
|
|
||||||
Appenders[name] = a
|
appenders[name] = a
|
||||||
|
}
|
||||||
|
|
||||||
|
// Appenders returns the list of the registered Appenders.
|
||||||
|
func Appenders() map[string]Appender {
|
||||||
|
appendersM.RLock()
|
||||||
|
defer appendersM.RUnlock()
|
||||||
|
|
||||||
|
ret := make(map[string]Appender)
|
||||||
|
for k, v := range appenders {
|
||||||
|
ret[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
@ -18,21 +18,30 @@ package vulnsrc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Updaters is the list of registered Updaters.
|
|
||||||
Updaters = make(map[string]Updater)
|
|
||||||
|
|
||||||
// ErrFilesystem is returned when a fetcher fails to interact with the local filesystem.
|
// ErrFilesystem is returned when a fetcher fails to interact with the local filesystem.
|
||||||
ErrFilesystem = errors.New("vulnsrc: something went wrong when interacting with the fs")
|
ErrFilesystem = errors.New("vulnsrc: something went wrong when interacting with the fs")
|
||||||
|
|
||||||
// ErrGitFailure is returned when a fetcher fails to interact with git.
|
// ErrGitFailure is returned when a fetcher fails to interact with git.
|
||||||
ErrGitFailure = errors.New("vulnsrc: something went wrong when interacting with git")
|
ErrGitFailure = errors.New("vulnsrc: something went wrong when interacting with git")
|
||||||
|
|
||||||
|
updatersM sync.RWMutex
|
||||||
|
updaters = make(map[string]Updater)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// UpdateResponse represents the sum of results of an update.
|
||||||
|
type UpdateResponse struct {
|
||||||
|
FlagName string
|
||||||
|
FlagValue string
|
||||||
|
Notes []string
|
||||||
|
Vulnerabilities []database.Vulnerability
|
||||||
|
}
|
||||||
|
|
||||||
// Updater represents anything that can fetch vulnerabilities and insert them
|
// Updater represents anything that can fetch vulnerabilities and insert them
|
||||||
// into a Clair datastore.
|
// into a Clair datastore.
|
||||||
type Updater interface {
|
type Updater interface {
|
||||||
@ -44,18 +53,10 @@ type Updater interface {
|
|||||||
Clean()
|
Clean()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateResponse represents the sum of results of an update.
|
|
||||||
type UpdateResponse struct {
|
|
||||||
FlagName string
|
|
||||||
FlagValue string
|
|
||||||
Notes []string
|
|
||||||
Vulnerabilities []database.Vulnerability
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegisterUpdater makes an Updater available by the provided name.
|
// RegisterUpdater makes an Updater available by the provided name.
|
||||||
//
|
//
|
||||||
// If RegisterUpdater is called twice with the same name, the name is blank, or
|
// If called twice with the same name, the name is blank, or if the provided
|
||||||
// if the provided Updater is nil, this function panics.
|
// Updater is nil, this function panics.
|
||||||
func RegisterUpdater(name string, u Updater) {
|
func RegisterUpdater(name string, u Updater) {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
panic("vulnsrc: could not register an Updater with an empty name")
|
panic("vulnsrc: could not register an Updater with an empty name")
|
||||||
@ -65,9 +66,25 @@ func RegisterUpdater(name string, u Updater) {
|
|||||||
panic("vulnsrc: could not register a nil Updater")
|
panic("vulnsrc: could not register a nil Updater")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, dup := Updaters[name]; dup {
|
updatersM.Lock()
|
||||||
|
defer updatersM.Unlock()
|
||||||
|
|
||||||
|
if _, dup := updaters[name]; dup {
|
||||||
panic("vulnsrc: RegisterUpdater called twice for " + name)
|
panic("vulnsrc: RegisterUpdater called twice for " + name)
|
||||||
}
|
}
|
||||||
|
|
||||||
Updaters[name] = u
|
updaters[name] = u
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updaters returns the list of the registered Updaters.
|
||||||
|
func Updaters() map[string]Updater {
|
||||||
|
updatersM.RLock()
|
||||||
|
defer updatersM.RUnlock()
|
||||||
|
|
||||||
|
ret := make(map[string]Updater)
|
||||||
|
for k, v := range updaters {
|
||||||
|
ret[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
@ -63,11 +63,11 @@ func Run(config *config.NotifierConfig, datastore database.Datastore, stopper *u
|
|||||||
defer stopper.End()
|
defer stopper.End()
|
||||||
|
|
||||||
// Configure registered notifiers.
|
// Configure registered notifiers.
|
||||||
for senderName, sender := range notification.Senders {
|
for senderName, sender := range notification.Senders() {
|
||||||
if configured, err := sender.Configure(config); configured {
|
if configured, err := sender.Configure(config); configured {
|
||||||
log.Infof("sender '%s' configured\n", senderName)
|
log.Infof("sender '%s' configured\n", senderName)
|
||||||
} else {
|
} else {
|
||||||
delete(notification.Senders, senderName)
|
notification.UnregisterSender(senderName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("could not configure notifier '%s': %s", senderName, err)
|
log.Errorf("could not configure notifier '%s': %s", senderName, err)
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ func Run(config *config.NotifierConfig, datastore database.Datastore, stopper *u
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Do not run the updater if there is no notifier enabled.
|
// Do not run the updater if there is no notifier enabled.
|
||||||
if len(notification.Senders) == 0 {
|
if len(notification.Senders()) == 0 {
|
||||||
log.Infof("notifier service is disabled")
|
log.Infof("notifier service is disabled")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -149,7 +149,7 @@ func findTask(datastore database.Datastore, renotifyInterval time.Duration, whoA
|
|||||||
|
|
||||||
func handleTask(n database.VulnerabilityNotification, st *utils.Stopper, maxAttempts int) (bool, bool) {
|
func handleTask(n database.VulnerabilityNotification, st *utils.Stopper, maxAttempts int) (bool, bool) {
|
||||||
// Send notification.
|
// Send notification.
|
||||||
for senderName, sender := range notification.Senders {
|
for senderName, sender := range notification.Senders() {
|
||||||
var attempts int
|
var attempts int
|
||||||
var backOff time.Duration
|
var backOff time.Duration
|
||||||
for {
|
for {
|
||||||
|
@ -152,10 +152,10 @@ func Run(config *config.UpdaterConfig, datastore database.Datastore, st *utils.S
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clean resources.
|
// Clean resources.
|
||||||
for _, appenders := range vulnmdsrc.Appenders {
|
for _, appenders := range vulnmdsrc.Appenders() {
|
||||||
appenders.Clean()
|
appenders.Clean()
|
||||||
}
|
}
|
||||||
for _, updaters := range vulnsrc.Updaters {
|
for _, updaters := range vulnsrc.Updaters() {
|
||||||
updaters.Clean()
|
updaters.Clean()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,7 +215,7 @@ func fetch(datastore database.Datastore) (bool, []database.Vulnerability, map[st
|
|||||||
// Fetch updates in parallel.
|
// Fetch updates in parallel.
|
||||||
log.Info("fetching vulnerability updates")
|
log.Info("fetching vulnerability updates")
|
||||||
var responseC = make(chan *vulnsrc.UpdateResponse, 0)
|
var responseC = make(chan *vulnsrc.UpdateResponse, 0)
|
||||||
for n, u := range vulnsrc.Updaters {
|
for n, u := range vulnsrc.Updaters() {
|
||||||
go func(name string, u vulnsrc.Updater) {
|
go func(name string, u vulnsrc.Updater) {
|
||||||
response, err := u.Update(datastore)
|
response, err := u.Update(datastore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -231,7 +231,7 @@ func fetch(datastore database.Datastore) (bool, []database.Vulnerability, map[st
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Collect results of updates.
|
// Collect results of updates.
|
||||||
for i := 0; i < len(vulnsrc.Updaters); i++ {
|
for i := 0; i < len(vulnsrc.Updaters()); i++ {
|
||||||
resp := <-responseC
|
resp := <-responseC
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
vulnerabilities = append(vulnerabilities, doVulnerabilitiesNamespacing(resp.Vulnerabilities)...)
|
vulnerabilities = append(vulnerabilities, doVulnerabilitiesNamespacing(resp.Vulnerabilities)...)
|
||||||
@ -248,7 +248,7 @@ func fetch(datastore database.Datastore) (bool, []database.Vulnerability, map[st
|
|||||||
|
|
||||||
// Add metadata to the specified vulnerabilities using the registered MetadataFetchers, in parallel.
|
// Add metadata to the specified vulnerabilities using the registered MetadataFetchers, in parallel.
|
||||||
func addMetadata(datastore database.Datastore, vulnerabilities []database.Vulnerability) []database.Vulnerability {
|
func addMetadata(datastore database.Datastore, vulnerabilities []database.Vulnerability) []database.Vulnerability {
|
||||||
if len(vulnmdsrc.Appenders) == 0 {
|
if len(vulnmdsrc.Appenders()) == 0 {
|
||||||
return vulnerabilities
|
return vulnerabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,9 +264,9 @@ func addMetadata(datastore database.Datastore, vulnerabilities []database.Vulner
|
|||||||
}
|
}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(len(vulnmdsrc.Appenders))
|
wg.Add(len(vulnmdsrc.Appenders()))
|
||||||
|
|
||||||
for n, a := range vulnmdsrc.Appenders {
|
for n, a := range vulnmdsrc.Appenders() {
|
||||||
go func(name string, appender vulnmdsrc.Appender) {
|
go func(name string, appender vulnmdsrc.Appender) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user