daemon/logger/factory.go
3a8728b4
 package logger
 
 import (
 	"fmt"
17abacb8
 	"sort"
3a8728b4
 	"sync"
054abff3
 
 	containertypes "github.com/docker/docker/api/types/container"
27bd6842
 	"github.com/docker/docker/pkg/plugingetter"
054abff3
 	units "github.com/docker/go-units"
 	"github.com/pkg/errors"
3a8728b4
 )
 
ccbe539e
 // Creator builds a logging driver instance with given context.
17ec911d
 type Creator func(Info) (Logger, error)
3a8728b4
 
ccbe539e
 // LogOptValidator checks the options specific to the underlying
 // logging implementation.
9b782d3a
 type LogOptValidator func(cfg map[string]string) error
 
3a8728b4
 type logdriverFactory struct {
9b782d3a
 	registry     map[string]Creator
 	optValidator map[string]LogOptValidator
 	m            sync.Mutex
3a8728b4
 }
 
17abacb8
 func (lf *logdriverFactory) list() []string {
 	ls := make([]string, 0, len(lf.registry))
 	lf.m.Lock()
 	for name := range lf.registry {
 		ls = append(ls, name)
 	}
 	lf.m.Unlock()
 	sort.Strings(ls)
 	return ls
 }
 
 // ListDrivers gets the list of registered log driver names
 func ListDrivers() []string {
 	return factory.list()
 }
 
3a8728b4
 func (lf *logdriverFactory) register(name string, c Creator) error {
1790980e
 	if lf.driverRegistered(name) {
3a8728b4
 		return fmt.Errorf("logger: log driver named '%s' is already registered", name)
 	}
1790980e
 
 	lf.m.Lock()
3a8728b4
 	lf.registry[name] = c
1790980e
 	lf.m.Unlock()
3a8728b4
 	return nil
 }
 
1790980e
 func (lf *logdriverFactory) driverRegistered(name string) bool {
 	lf.m.Lock()
 	_, ok := lf.registry[name]
 	lf.m.Unlock()
27bd6842
 	if !ok {
 		if pluginGetter != nil { // this can be nil when the init functions are running
 			if l, _ := getPlugin(name, plugingetter.Lookup); l != nil {
 				return true
 			}
 		}
 	}
1790980e
 	return ok
 }
 
9b782d3a
 func (lf *logdriverFactory) registerLogOptValidator(name string, l LogOptValidator) error {
 	lf.m.Lock()
 	defer lf.m.Unlock()
 
 	if _, ok := lf.optValidator[name]; ok {
ccbe539e
 		return fmt.Errorf("logger: log validator named '%s' is already registered", name)
9b782d3a
 	}
 	lf.optValidator[name] = l
 	return nil
 }
 
3a8728b4
 func (lf *logdriverFactory) get(name string) (Creator, error) {
 	lf.m.Lock()
 	defer lf.m.Unlock()
 
 	c, ok := lf.registry[name]
27bd6842
 	if ok {
 		return c, nil
3a8728b4
 	}
27bd6842
 
 	c, err := getPlugin(name, plugingetter.Acquire)
 	return c, errors.Wrapf(err, "logger: no log driver named '%s' is registered", name)
3a8728b4
 }
 
9b782d3a
 func (lf *logdriverFactory) getLogOptValidator(name string) LogOptValidator {
 	lf.m.Lock()
 	defer lf.m.Unlock()
 
f7f101d5
 	c := lf.optValidator[name]
9b782d3a
 	return c
 }
 
 var factory = &logdriverFactory{registry: make(map[string]Creator), optValidator: make(map[string]LogOptValidator)} // global factory instance
3a8728b4
 
 // RegisterLogDriver registers the given logging driver builder with given logging
 // driver name.
 func RegisterLogDriver(name string, c Creator) error {
 	return factory.register(name, c)
 }
 
ccbe539e
 // RegisterLogOptValidator registers the logging option validator with
 // the given logging driver name.
9b782d3a
 func RegisterLogOptValidator(name string, l LogOptValidator) error {
 	return factory.registerLogOptValidator(name, l)
 }
 
3a8728b4
 // GetLogDriver provides the logging driver builder for a logging driver name.
 func GetLogDriver(name string) (Creator, error) {
 	return factory.get(name)
 }
9b782d3a
 
054abff3
 var builtInLogOpts = map[string]bool{
 	"mode":            true,
 	"max-buffer-size": true,
 }
 
ccbe539e
 // ValidateLogOpts checks the options for the given log driver. The
 // options supported are specific to the LogDriver implementation.
9b782d3a
 func ValidateLogOpts(name string, cfg map[string]string) error {
1790980e
 	if name == "none" {
 		return nil
 	}
 
054abff3
 	switch containertypes.LogMode(cfg["mode"]) {
 	case containertypes.LogModeBlocking, containertypes.LogModeNonBlock, containertypes.LogModeUnset:
 	default:
 		return fmt.Errorf("logger: logging mode not supported: %s", cfg["mode"])
 	}
 
 	if s, ok := cfg["max-buffer-size"]; ok {
 		if containertypes.LogMode(cfg["mode"]) != containertypes.LogModeNonBlock {
 			return fmt.Errorf("logger: max-buffer-size option is only supported with 'mode=%s'", containertypes.LogModeNonBlock)
 		}
 		if _, err := units.RAMInBytes(s); err != nil {
 			return errors.Wrap(err, "error parsing option max-buffer-size")
 		}
 	}
 
1790980e
 	if !factory.driverRegistered(name) {
 		return fmt.Errorf("logger: no log driver named '%s' is registered", name)
 	}
 
054abff3
 	filteredOpts := make(map[string]string, len(builtInLogOpts))
 	for k, v := range cfg {
 		if !builtInLogOpts[k] {
 			filteredOpts[k] = v
 		}
 	}
 
1790980e
 	validator := factory.getLogOptValidator(name)
 	if validator != nil {
054abff3
 		return validator(filteredOpts)
9b782d3a
 	}
d68c55bc
 	return nil
9b782d3a
 }