mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Use a regex to match environment variables #27565
Signed-off-by: Joseph Rothrock <rothrock@rothrock.org>
This commit is contained in:
parent
e1c5e72902
commit
9758a2a724
11 changed files with 89 additions and 34 deletions
|
|
@ -78,7 +78,10 @@ func New(info logger.Info) (logger.Logger, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
extra := info.ExtraAttributes(nil)
|
extra, err := info.ExtraAttributes(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
bufferLimit := defaultBufferLimit
|
bufferLimit := defaultBufferLimit
|
||||||
if info.Config[bufferLimitKey] != "" {
|
if info.Config[bufferLimitKey] != "" {
|
||||||
|
|
@ -169,6 +172,7 @@ func ValidateLogOpt(cfg map[string]string) error {
|
||||||
for key := range cfg {
|
for key := range cfg {
|
||||||
switch key {
|
switch key {
|
||||||
case "env":
|
case "env":
|
||||||
|
case "env-regex":
|
||||||
case "labels":
|
case "labels":
|
||||||
case "tag":
|
case "tag":
|
||||||
case addressKey:
|
case addressKey:
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ const (
|
||||||
projectOptKey = "gcp-project"
|
projectOptKey = "gcp-project"
|
||||||
logLabelsKey = "labels"
|
logLabelsKey = "labels"
|
||||||
logEnvKey = "env"
|
logEnvKey = "env"
|
||||||
|
logEnvRegexKey = "env-regex"
|
||||||
logCmdKey = "gcp-log-cmd"
|
logCmdKey = "gcp-log-cmd"
|
||||||
logZoneKey = "gcp-meta-zone"
|
logZoneKey = "gcp-meta-zone"
|
||||||
logNameKey = "gcp-meta-name"
|
logNameKey = "gcp-meta-name"
|
||||||
|
|
@ -133,6 +134,11 @@ func New(info logger.Info) (logger.Logger, error) {
|
||||||
return nil, fmt.Errorf("unable to connect or authenticate with Google Cloud Logging: %v", err)
|
return nil, fmt.Errorf("unable to connect or authenticate with Google Cloud Logging: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extraAttributes, err := info.ExtraAttributes(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
l := &gcplogs{
|
l := &gcplogs{
|
||||||
logger: lg,
|
logger: lg,
|
||||||
container: &containerInfo{
|
container: &containerInfo{
|
||||||
|
|
@ -141,7 +147,7 @@ func New(info logger.Info) (logger.Logger, error) {
|
||||||
ImageName: info.ContainerImageName,
|
ImageName: info.ContainerImageName,
|
||||||
ImageID: info.ContainerImageID,
|
ImageID: info.ContainerImageID,
|
||||||
Created: info.ContainerCreated,
|
Created: info.ContainerCreated,
|
||||||
Metadata: info.ExtraAttributes(nil),
|
Metadata: extraAttributes,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -185,7 +191,7 @@ func New(info logger.Info) (logger.Logger, error) {
|
||||||
func ValidateLogOpts(cfg map[string]string) error {
|
func ValidateLogOpts(cfg map[string]string) error {
|
||||||
for k := range cfg {
|
for k := range cfg {
|
||||||
switch k {
|
switch k {
|
||||||
case projectOptKey, logLabelsKey, logEnvKey, logCmdKey, logZoneKey, logNameKey, logIDKey:
|
case projectOptKey, logLabelsKey, logEnvKey, logEnvRegexKey, logCmdKey, logZoneKey, logNameKey, logIDKey:
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("%q is not a valid option for the gcplogs driver", k)
|
return fmt.Errorf("%q is not a valid option for the gcplogs driver", k)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,12 +69,17 @@ func New(info logger.Info) (logger.Logger, error) {
|
||||||
"_created": info.ContainerCreated,
|
"_created": info.ContainerCreated,
|
||||||
}
|
}
|
||||||
|
|
||||||
extraAttrs := info.ExtraAttributes(func(key string) string {
|
extraAttrs, err := info.ExtraAttributes(func(key string) string {
|
||||||
if key[0] == '_' {
|
if key[0] == '_' {
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
return "_" + key
|
return "_" + key
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
for k, v := range extraAttrs {
|
for k, v := range extraAttrs {
|
||||||
extra[k] = v
|
extra[k] = v
|
||||||
}
|
}
|
||||||
|
|
@ -156,6 +161,7 @@ func ValidateLogOpt(cfg map[string]string) error {
|
||||||
case "tag":
|
case "tag":
|
||||||
case "labels":
|
case "labels":
|
||||||
case "env":
|
case "env":
|
||||||
|
case "env-regex":
|
||||||
case "gelf-compression-level":
|
case "gelf-compression-level":
|
||||||
i, err := strconv.Atoi(val)
|
i, err := strconv.Atoi(val)
|
||||||
if err != nil || i < flate.DefaultCompression || i > flate.BestCompression {
|
if err != nil || i < flate.DefaultCompression || i > flate.BestCompression {
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,10 @@ func New(info logger.Info) (logger.Logger, error) {
|
||||||
"CONTAINER_NAME": info.Name(),
|
"CONTAINER_NAME": info.Name(),
|
||||||
"CONTAINER_TAG": tag,
|
"CONTAINER_TAG": tag,
|
||||||
}
|
}
|
||||||
extraAttrs := info.ExtraAttributes(sanitizeKeyMod)
|
extraAttrs, err := info.ExtraAttributes(sanitizeKeyMod)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
for k, v := range extraAttrs {
|
for k, v := range extraAttrs {
|
||||||
vars[k] = v
|
vars[k] = v
|
||||||
}
|
}
|
||||||
|
|
@ -89,6 +92,7 @@ func validateLogOpt(cfg map[string]string) error {
|
||||||
switch key {
|
switch key {
|
||||||
case "labels":
|
case "labels":
|
||||||
case "env":
|
case "env":
|
||||||
|
case "env-regex":
|
||||||
case "tag":
|
case "tag":
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown log opt '%s' for journald log driver", key)
|
return fmt.Errorf("unknown log opt '%s' for journald log driver", key)
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,11 @@ func New(info logger.Info) (logger.Logger, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var extra []byte
|
var extra []byte
|
||||||
if attrs := info.ExtraAttributes(nil); len(attrs) > 0 {
|
attrs, err := info.ExtraAttributes(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(attrs) > 0 {
|
||||||
var err error
|
var err error
|
||||||
extra, err = json.Marshal(attrs)
|
extra, err = json.Marshal(attrs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -121,6 +125,7 @@ func ValidateLogOpt(cfg map[string]string) error {
|
||||||
case "max-size":
|
case "max-size":
|
||||||
case "labels":
|
case "labels":
|
||||||
case "env":
|
case "env":
|
||||||
|
case "env-regex":
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown log opt '%s' for json-file log driver", key)
|
return fmt.Errorf("unknown log opt '%s' for json-file log driver", key)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -160,13 +160,13 @@ func TestJSONFileLoggerWithLabelsEnv(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmp)
|
defer os.RemoveAll(tmp)
|
||||||
filename := filepath.Join(tmp, "container.log")
|
filename := filepath.Join(tmp, "container.log")
|
||||||
config := map[string]string{"labels": "rack,dc", "env": "environ,debug,ssl"}
|
config := map[string]string{"labels": "rack,dc", "env": "environ,debug,ssl", "env-regex": "^dc"}
|
||||||
l, err := New(logger.Info{
|
l, err := New(logger.Info{
|
||||||
ContainerID: cid,
|
ContainerID: cid,
|
||||||
LogPath: filename,
|
LogPath: filename,
|
||||||
Config: config,
|
Config: config,
|
||||||
ContainerLabels: map[string]string{"rack": "101", "dc": "lhr"},
|
ContainerLabels: map[string]string{"rack": "101", "dc": "lhr"},
|
||||||
ContainerEnv: []string{"environ=production", "debug=false", "port=10001", "ssl=true"},
|
ContainerEnv: []string{"environ=production", "debug=false", "port=10001", "ssl=true", "dc_region=west"},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -194,6 +194,7 @@ func TestJSONFileLoggerWithLabelsEnv(t *testing.T) {
|
||||||
"environ": "production",
|
"environ": "production",
|
||||||
"debug": "false",
|
"debug": "false",
|
||||||
"ssl": "true",
|
"ssl": "true",
|
||||||
|
"dc_region": "west",
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(extra, expected) {
|
if !reflect.DeepEqual(extra, expected) {
|
||||||
t.Fatalf("Wrong log attrs: %q, expected %q", extra, expected)
|
t.Fatalf("Wrong log attrs: %q, expected %q", extra, expected)
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@ func ValidateLogOpt(cfg map[string]string) error {
|
||||||
for key := range cfg {
|
for key := range cfg {
|
||||||
switch key {
|
switch key {
|
||||||
case "env":
|
case "env":
|
||||||
|
case "env-regex":
|
||||||
case "labels":
|
case "labels":
|
||||||
case "tag":
|
case "tag":
|
||||||
case key:
|
case key:
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package logger
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -26,7 +27,7 @@ type Info struct {
|
||||||
// ExtraAttributes returns the user-defined extra attributes (labels,
|
// ExtraAttributes returns the user-defined extra attributes (labels,
|
||||||
// environment variables) in key-value format. This can be used by log drivers
|
// environment variables) in key-value format. This can be used by log drivers
|
||||||
// that support metadata to add more context to a log.
|
// that support metadata to add more context to a log.
|
||||||
func (info *Info) ExtraAttributes(keyMod func(string) string) map[string]string {
|
func (info *Info) ExtraAttributes(keyMod func(string) string) (map[string]string, error) {
|
||||||
extra := make(map[string]string)
|
extra := make(map[string]string)
|
||||||
labels, ok := info.Config["labels"]
|
labels, ok := info.Config["labels"]
|
||||||
if ok && len(labels) > 0 {
|
if ok && len(labels) > 0 {
|
||||||
|
|
@ -40,14 +41,15 @@ func (info *Info) ExtraAttributes(keyMod func(string) string) map[string]string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
env, ok := info.Config["env"]
|
|
||||||
if ok && len(env) > 0 {
|
|
||||||
envMapping := make(map[string]string)
|
envMapping := make(map[string]string)
|
||||||
for _, e := range info.ContainerEnv {
|
for _, e := range info.ContainerEnv {
|
||||||
if kv := strings.SplitN(e, "=", 2); len(kv) == 2 {
|
if kv := strings.SplitN(e, "=", 2); len(kv) == 2 {
|
||||||
envMapping[kv[0]] = kv[1]
|
envMapping[kv[0]] = kv[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env, ok := info.Config["env"]
|
||||||
|
if ok && len(env) > 0 {
|
||||||
for _, l := range strings.Split(env, ",") {
|
for _, l := range strings.Split(env, ",") {
|
||||||
if v, ok := envMapping[l]; ok {
|
if v, ok := envMapping[l]; ok {
|
||||||
if keyMod != nil {
|
if keyMod != nil {
|
||||||
|
|
@ -58,7 +60,23 @@ func (info *Info) ExtraAttributes(keyMod func(string) string) map[string]string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return extra
|
envRegex, ok := info.Config["env-regex"]
|
||||||
|
if ok && len(envRegex) > 0 {
|
||||||
|
re, err := regexp.Compile(envRegex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for k, v := range envMapping {
|
||||||
|
if re.MatchString(k) {
|
||||||
|
if keyMod != nil {
|
||||||
|
k = keyMod(k)
|
||||||
|
}
|
||||||
|
extra[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return extra, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hostname returns the hostname from the underlying OS.
|
// Hostname returns the hostname from the underlying OS.
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ const (
|
||||||
splunkGzipCompressionKey = "splunk-gzip"
|
splunkGzipCompressionKey = "splunk-gzip"
|
||||||
splunkGzipCompressionLevelKey = "splunk-gzip-level"
|
splunkGzipCompressionLevelKey = "splunk-gzip-level"
|
||||||
envKey = "env"
|
envKey = "env"
|
||||||
|
envRegexKey = "env-regex"
|
||||||
labelsKey = "labels"
|
labelsKey = "labels"
|
||||||
tagKey = "tag"
|
tagKey = "tag"
|
||||||
)
|
)
|
||||||
|
|
@ -235,7 +236,10 @@ func New(info logger.Info) (logger.Logger, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attrs := info.ExtraAttributes(nil)
|
attrs, err := info.ExtraAttributes(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
postMessagesFrequency = getAdvancedOptionDuration(envVarPostMessagesFrequency, defaultPostMessagesFrequency)
|
postMessagesFrequency = getAdvancedOptionDuration(envVarPostMessagesFrequency, defaultPostMessagesFrequency)
|
||||||
|
|
@ -538,6 +542,7 @@ func ValidateLogOpt(cfg map[string]string) error {
|
||||||
case splunkGzipCompressionKey:
|
case splunkGzipCompressionKey:
|
||||||
case splunkGzipCompressionLevelKey:
|
case splunkGzipCompressionLevelKey:
|
||||||
case envKey:
|
case envKey:
|
||||||
|
case envRegexKey:
|
||||||
case labelsKey:
|
case labelsKey:
|
||||||
case tagKey:
|
case tagKey:
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ func TestValidateLogOpt(t *testing.T) {
|
||||||
splunkGzipCompressionKey: "true",
|
splunkGzipCompressionKey: "true",
|
||||||
splunkGzipCompressionLevelKey: "1",
|
splunkGzipCompressionLevelKey: "1",
|
||||||
envKey: "a",
|
envKey: "a",
|
||||||
|
envRegexKey: "^foo",
|
||||||
labelsKey: "b",
|
labelsKey: "b",
|
||||||
tagKey: "c",
|
tagKey: "c",
|
||||||
})
|
})
|
||||||
|
|
@ -217,6 +218,7 @@ func TestInlineFormatWithNonDefaultOptions(t *testing.T) {
|
||||||
splunkGzipCompressionKey: "true",
|
splunkGzipCompressionKey: "true",
|
||||||
tagKey: "{{.ImageName}}/{{.Name}}",
|
tagKey: "{{.ImageName}}/{{.Name}}",
|
||||||
labelsKey: "a",
|
labelsKey: "a",
|
||||||
|
envRegexKey: "^foo",
|
||||||
},
|
},
|
||||||
ContainerID: "containeriid",
|
ContainerID: "containeriid",
|
||||||
ContainerName: "/container_name",
|
ContainerName: "/container_name",
|
||||||
|
|
@ -225,6 +227,7 @@ func TestInlineFormatWithNonDefaultOptions(t *testing.T) {
|
||||||
ContainerLabels: map[string]string{
|
ContainerLabels: map[string]string{
|
||||||
"a": "b",
|
"a": "b",
|
||||||
},
|
},
|
||||||
|
ContainerEnv: []string{"foo_finder=bar"},
|
||||||
}
|
}
|
||||||
|
|
||||||
hostname, err := info.Hostname()
|
hostname, err := info.Hostname()
|
||||||
|
|
@ -295,6 +298,7 @@ func TestInlineFormatWithNonDefaultOptions(t *testing.T) {
|
||||||
event["source"] != "stdout" ||
|
event["source"] != "stdout" ||
|
||||||
event["tag"] != "container_image_name/container_name" ||
|
event["tag"] != "container_image_name/container_name" ||
|
||||||
event["attrs"].(map[string]interface{})["a"] != "b" ||
|
event["attrs"].(map[string]interface{})["a"] != "b" ||
|
||||||
|
event["attrs"].(map[string]interface{})["foo_finder"] != "bar" ||
|
||||||
len(event) != 4 {
|
len(event) != 4 {
|
||||||
t.Fatalf("Unexpected event in message %v", event)
|
t.Fatalf("Unexpected event in message %v", event)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,7 @@ func ValidateLogOpt(cfg map[string]string) error {
|
||||||
for key := range cfg {
|
for key := range cfg {
|
||||||
switch key {
|
switch key {
|
||||||
case "env":
|
case "env":
|
||||||
|
case "env-regex":
|
||||||
case "labels":
|
case "labels":
|
||||||
case "syslog-address":
|
case "syslog-address":
|
||||||
case "syslog-facility":
|
case "syslog-facility":
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue