github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/daemon/logger/factory.go (about)

     1  package logger // import "github.com/docker/docker/daemon/logger"
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"sync"
     7  
     8  	containertypes "github.com/docker/docker/api/types/container"
     9  	"github.com/docker/docker/pkg/plugingetter"
    10  	units "github.com/docker/go-units"
    11  	"github.com/pkg/errors"
    12  )
    13  
    14  // Creator builds a logging driver instance with given context.
    15  type Creator func(Info) (Logger, error)
    16  
    17  // LogOptValidator checks the options specific to the underlying
    18  // logging implementation.
    19  type LogOptValidator func(cfg map[string]string) error
    20  
    21  type logdriverFactory struct {
    22  	registry     map[string]Creator
    23  	optValidator map[string]LogOptValidator
    24  	m            sync.Mutex
    25  }
    26  
    27  func (lf *logdriverFactory) list() []string {
    28  	ls := make([]string, 0, len(lf.registry))
    29  	lf.m.Lock()
    30  	for name := range lf.registry {
    31  		ls = append(ls, name)
    32  	}
    33  	lf.m.Unlock()
    34  	sort.Strings(ls)
    35  	return ls
    36  }
    37  
    38  // ListDrivers gets the list of registered log driver names
    39  func ListDrivers() []string {
    40  	return factory.list()
    41  }
    42  
    43  func (lf *logdriverFactory) register(name string, c Creator) error {
    44  	registered, err := lf.driverRegistered(name)
    45  	if err != nil {
    46  		return err
    47  	}
    48  	if registered {
    49  		return fmt.Errorf("logger: log driver named '%s' is already registered", name)
    50  	}
    51  
    52  	lf.m.Lock()
    53  	lf.registry[name] = c
    54  	lf.m.Unlock()
    55  	return nil
    56  }
    57  
    58  func (lf *logdriverFactory) driverRegistered(name string) (bool, error) {
    59  	lf.m.Lock()
    60  	_, ok := lf.registry[name]
    61  	lf.m.Unlock()
    62  	if !ok {
    63  		if pluginGetter != nil { // this can be nil when the init functions are running
    64  			l, err := getPlugin(name, plugingetter.Lookup)
    65  			if err != nil {
    66  				return false, err
    67  			}
    68  			if l != nil {
    69  				return true, nil
    70  			}
    71  		}
    72  	}
    73  	return ok, nil
    74  }
    75  
    76  func (lf *logdriverFactory) registerLogOptValidator(name string, l LogOptValidator) error {
    77  	lf.m.Lock()
    78  	defer lf.m.Unlock()
    79  
    80  	if _, ok := lf.optValidator[name]; ok {
    81  		return fmt.Errorf("logger: log validator named '%s' is already registered", name)
    82  	}
    83  	lf.optValidator[name] = l
    84  	return nil
    85  }
    86  
    87  func (lf *logdriverFactory) get(name string) (Creator, error) {
    88  	lf.m.Lock()
    89  	defer lf.m.Unlock()
    90  
    91  	c, ok := lf.registry[name]
    92  	if ok {
    93  		return c, nil
    94  	}
    95  
    96  	c, err := getPlugin(name, plugingetter.Acquire)
    97  	return c, errors.Wrapf(err, "logger: no log driver named '%s' is registered", name)
    98  }
    99  
   100  func (lf *logdriverFactory) getLogOptValidator(name string) LogOptValidator {
   101  	lf.m.Lock()
   102  	defer lf.m.Unlock()
   103  
   104  	c := lf.optValidator[name]
   105  	return c
   106  }
   107  
   108  var factory = &logdriverFactory{registry: make(map[string]Creator), optValidator: make(map[string]LogOptValidator)} // global factory instance
   109  
   110  // RegisterLogDriver registers the given logging driver builder with given logging
   111  // driver name.
   112  func RegisterLogDriver(name string, c Creator) error {
   113  	return factory.register(name, c)
   114  }
   115  
   116  // RegisterLogOptValidator registers the logging option validator with
   117  // the given logging driver name.
   118  func RegisterLogOptValidator(name string, l LogOptValidator) error {
   119  	return factory.registerLogOptValidator(name, l)
   120  }
   121  
   122  // GetLogDriver provides the logging driver builder for a logging driver name.
   123  func GetLogDriver(name string) (Creator, error) {
   124  	return factory.get(name)
   125  }
   126  
   127  var builtInLogOpts = map[string]bool{
   128  	"mode":            true,
   129  	"max-buffer-size": true,
   130  }
   131  
   132  // ValidateLogOpts checks the options for the given log driver. The
   133  // options supported are specific to the LogDriver implementation.
   134  func ValidateLogOpts(name string, cfg map[string]string) error {
   135  	if name == "none" {
   136  		return nil
   137  	}
   138  
   139  	switch containertypes.LogMode(cfg["mode"]) {
   140  	case containertypes.LogModeBlocking, containertypes.LogModeNonBlock, containertypes.LogModeUnset:
   141  	default:
   142  		return fmt.Errorf("logger: logging mode not supported: %s", cfg["mode"])
   143  	}
   144  
   145  	if s, ok := cfg["max-buffer-size"]; ok {
   146  		if containertypes.LogMode(cfg["mode"]) != containertypes.LogModeNonBlock {
   147  			return fmt.Errorf("logger: max-buffer-size option is only supported with 'mode=%s'", containertypes.LogModeNonBlock)
   148  		}
   149  		if _, err := units.RAMInBytes(s); err != nil {
   150  			return errors.Wrap(err, "error parsing option max-buffer-size")
   151  		}
   152  	}
   153  
   154  	if err := validateExternal(cfg); err != nil {
   155  		return err
   156  	}
   157  
   158  	registered, err := factory.driverRegistered(name)
   159  	if err != nil {
   160  		return err
   161  	}
   162  	if !registered {
   163  		return fmt.Errorf("logger: no log driver named '%s' is registered", name)
   164  	}
   165  
   166  	filteredOpts := make(map[string]string, len(builtInLogOpts))
   167  	for k, v := range cfg {
   168  		if !builtInLogOpts[k] {
   169  			filteredOpts[k] = v
   170  		}
   171  	}
   172  
   173  	validator := factory.getLogOptValidator(name)
   174  	if validator != nil {
   175  		return validator(filteredOpts)
   176  	}
   177  	return nil
   178  }