From dca9e02b15a3757272c90ec4cf0cc2b052a25fe3 Mon Sep 17 00:00:00 2001 From: wlan0 Date: Mon, 4 May 2015 14:39:48 -0700 Subject: [PATCH] Add log opts flag to pass in logging options Signed-off-by: wlan0 --- daemon/config.go | 1 + docker/daemon.go | 3 +++ docs/sources/reference/run.md | 4 +++ opts/opts.go | 51 +++++++++++++++++++++++++++++++++++ opts/opts_test.go | 35 ++++++++++++++++++++++++ runconfig/parse.go | 18 ++++++++++++- 6 files changed, 111 insertions(+), 1 deletion(-) diff --git a/daemon/config.go b/daemon/config.go index 5fe01e5c7c..cd555cfc88 100644 --- a/daemon/config.go +++ b/daemon/config.go @@ -80,6 +80,7 @@ func (config *Config) InstallFlags() { opts.UlimitMapVar(config.Ulimits, []string{"-default-ulimit"}, "Set default ulimits for containers") flag.StringVar(&config.LogConfig.Type, []string{"-log-driver"}, "json-file", "Default driver for container logs") flag.BoolVar(&config.Bridge.EnableUserlandProxy, []string{"-userland-proxy"}, true, "Use userland proxy for loopback traffic") + opts.LogOptsVar(config.LogConfig.Config, []string{"-log-opt"}, "Set log driver options") } func getDefaultNetworkMtu() int { diff --git a/docker/daemon.go b/docker/daemon.go index 55cb090d67..06bdbc0fc6 100644 --- a/docker/daemon.go +++ b/docker/daemon.go @@ -32,6 +32,9 @@ var ( ) func init() { + if daemonCfg.LogConfig.Config == nil { + daemonCfg.LogConfig.Config = make(map[string]string) + } daemonCfg.InstallFlags() registryCfg.InstallFlags() } diff --git a/docs/sources/reference/run.md b/docs/sources/reference/run.md index 0145828024..ff6cfa80ba 100644 --- a/docs/sources/reference/run.md +++ b/docs/sources/reference/run.md @@ -849,6 +849,10 @@ command is not available for this logging driver Journald logging driver for Docker. Writes log messages to journald; the container id will be stored in the journal's `CONTAINER_ID` field. `docker logs` command is not available for this logging driver. For detailed information on working with this logging driver, see [the journald logging driver](reference/logging/journald) reference documentation. +#### Log Opts : + +Logging options for configuring a log driver. The following log options are supported: [none] + ## Overriding Dockerfile image defaults When a developer builds an image from a [*Dockerfile*](/reference/builder) diff --git a/opts/opts.go b/opts/opts.go index 1db454736e..3801596631 100644 --- a/opts/opts.go +++ b/opts/opts.go @@ -28,6 +28,14 @@ func ListVar(values *[]string, names []string, usage string) { flag.Var(newListOptsRef(values, nil), names, usage) } +func MapVar(values map[string]string, names []string, usage string) { + flag.Var(newMapOpt(values, nil), names, usage) +} + +func LogOptsVar(values map[string]string, names []string, usage string) { + flag.Var(newMapOpt(values, ValidateLogOpts), names, usage) +} + func HostListVar(values *[]string, names []string, usage string) { flag.Var(newListOptsRef(values, ValidateHost), names, usage) } @@ -130,10 +138,53 @@ func (opts *ListOpts) Len() int { return len((*opts.values)) } +//MapOpts type +type MapOpts struct { + values map[string]string + validator ValidatorFctType +} + +func (opts *MapOpts) Set(value string) error { + if opts.validator != nil { + v, err := opts.validator(value) + if err != nil { + return err + } + value = v + } + vals := strings.SplitN(value, "=", 2) + if len(vals) == 1 { + (opts.values)[vals[0]] = "" + } else { + (opts.values)[vals[0]] = vals[1] + } + return nil +} + +func (opts *MapOpts) String() string { + return fmt.Sprintf("%v", map[string]string((opts.values))) +} + +func newMapOpt(values map[string]string, validator ValidatorFctType) *MapOpts { + return &MapOpts{ + values: values, + validator: validator, + } +} + // Validators type ValidatorFctType func(val string) (string, error) type ValidatorFctListType func(val string) ([]string, error) +func ValidateLogOpts(val string) (string, error) { + allowedKeys := map[string]string{} + vals := strings.Split(val, "=") + if allowedKeys[vals[0]] != "" { + return val, nil + } + return "", fmt.Errorf("%s is not a valid log opt", vals[0]) +} + func ValidateAttach(val string) (string, error) { s := strings.ToLower(val) for _, str := range []string{"stdin", "stdout", "stderr"} { diff --git a/opts/opts_test.go b/opts/opts_test.go index 8370926da5..dfad430ac4 100644 --- a/opts/opts_test.go +++ b/opts/opts_test.go @@ -1,6 +1,7 @@ package opts import ( + "fmt" "strings" "testing" ) @@ -28,6 +29,31 @@ func TestValidateIPAddress(t *testing.T) { } +func TestMapOpts(t *testing.T) { + tmpMap := make(map[string]string) + o := newMapOpt(tmpMap, logOptsValidator) + o.Set("max-size=1") + if o.String() != "map[max-size:1]" { + t.Errorf("%s != [map[max-size:1]", o.String()) + } + + o.Set("max-file=2") + if len(tmpMap) != 2 { + t.Errorf("map length %d != 2", len(tmpMap)) + } + + if tmpMap["max-file"] != "2" { + t.Errorf("max-file = %s != 2", tmpMap["max-file"]) + } + + if tmpMap["max-size"] != "1" { + t.Errorf("max-size = %s != 1", tmpMap["max-size"]) + } + if o.Set("dummy-val=3") == nil { + t.Errorf("validator is not being called") + } +} + func TestValidateMACAddress(t *testing.T) { if _, err := ValidateMACAddress(`92:d0:c6:0a:29:33`); err != nil { t.Fatalf("ValidateMACAddress(`92:d0:c6:0a:29:33`) got %s", err) @@ -152,3 +178,12 @@ func TestValidateExtraHosts(t *testing.T) { } } } + +func logOptsValidator(val string) (string, error) { + allowedKeys := map[string]string{"max-size": "1", "max-file": "2"} + vals := strings.Split(val, "=") + if allowedKeys[vals[0]] != "" { + return val, nil + } + return "", fmt.Errorf("invalid key %s", vals[0]) +} diff --git a/runconfig/parse.go b/runconfig/parse.go index ac5cdbf61a..e944a644e3 100644 --- a/runconfig/parse.go +++ b/runconfig/parse.go @@ -47,6 +47,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe flCapDrop = opts.NewListOpts(nil) flSecurityOpt = opts.NewListOpts(nil) flLabelsFile = opts.NewListOpts(nil) + flLoggingOpts = opts.NewListOpts(nil) flNetwork = cmd.Bool([]string{"#n", "#-networking"}, true, "Enable networking for this container") flPrivileged = cmd.Bool([]string{"#privileged", "-privileged"}, false, "Give extended privileges to this container") @@ -95,6 +96,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe cmd.Var(&flCapDrop, []string{"-cap-drop"}, "Drop Linux capabilities") cmd.Var(&flSecurityOpt, []string{"-security-opt"}, "Security Options") cmd.Var(flUlimits, []string{"-ulimit"}, "Ulimit options") + cmd.Var(&flLoggingOpts, []string{"-log-opt"}, "Log driver options") cmd.Require(flag.Min, 1) @@ -283,6 +285,11 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe return nil, nil, cmd, err } + loggingOpts, err := parseLoggingOpts(*flLoggingDriver, flLoggingOpts.GetAll()) + if err != nil { + return nil, nil, cmd, err + } + config := &Config{ Hostname: hostname, Domainname: domainname, @@ -335,7 +342,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe SecurityOpt: flSecurityOpt.GetAll(), ReadonlyRootfs: *flReadonlyRootfs, Ulimits: flUlimits.GetList(), - LogConfig: LogConfig{Type: *flLoggingDriver}, + LogConfig: LogConfig{Type: *flLoggingDriver, Config: loggingOpts}, CgroupParent: *flCgroupParent, } @@ -377,6 +384,15 @@ func convertKVStringsToMap(values []string) map[string]string { return result } +func parseLoggingOpts(loggingDriver string, loggingOpts []string) (map[string]string, error) { + loggingOptsMap := convertKVStringsToMap(loggingOpts) + if loggingDriver == "none" && len(loggingOpts) > 0 { + return map[string]string{}, fmt.Errorf("Invalid logging opts for driver %s", loggingDriver) + } + //TODO - validation step + return loggingOptsMap, nil +} + // ParseRestartPolicy returns the parsed policy or an error indicating what is incorrect func ParseRestartPolicy(policy string) (RestartPolicy, error) { p := RestartPolicy{}