diff --git a/plugins/config/environment.go b/plugins/config/environment.go index 0f6131250..bb4f6166f 100644 --- a/plugins/config/environment.go +++ b/plugins/config/environment.go @@ -396,20 +396,28 @@ func prettyPrintEnvEntries(prefix string, entries map[string]string) string { func loadFromFile(name string, filename string) (env *Env, err error) { envMap := make(map[string]string) + dirty := false if filename == "-" { envMap, err = godotenv.Parse(os.Stdin) if err != nil { return nil, err } } - if _, err := os.Stat(filename); err == nil { - envMap, err = godotenv.Read(filename) - if err != nil { - return nil, err + if _, statErr := os.Stat(filename); statErr == nil { + contents, readErr := os.ReadFile(filename) + if readErr != nil { + return nil, readErr } + + parsed, parseErr := godotenv.Unmarshal(string(contents)) + if parseErr != nil { + common.LogInfo1(fmt.Sprintf("Discarding unparseable entries from config for %s: %s", name, parseErr)) + parsed = parseLineByLine(string(contents)) + dirty = true + } + envMap = parsed } - dirty := false for k := range envMap { if err := validateKey(k); err != nil { common.LogInfo1(fmt.Sprintf("Deleting invalid key %s from config for %s", k, name)) @@ -431,6 +439,23 @@ func loadFromFile(name string, filename string) (env *Env, err error) { return } +// parseLineByLine parses ENVFILE contents a line at a time, discarding the +// lines the parser rejects, so that a single malformed entry does not make the +// rest of the environment unreadable +func parseLineByLine(contents string) map[string]string { + envMap := make(map[string]string) + for _, line := range strings.Split(contents, "\n") { + lineMap, err := godotenv.Unmarshal(line) + if err != nil { + continue + } + for key, value := range lineMap { + envMap[key] = value + } + } + return envMap +} + func loadFromFileJSON(name string, filename string) (env *Env, err error) { envMap := make(map[string]string) if filename == "-" { diff --git a/plugins/config/environment_test.go b/plugins/config/environment_test.go index 61f55bf85..fd1dd2a22 100644 --- a/plugins/config/environment_test.go +++ b/plugins/config/environment_test.go @@ -46,14 +46,16 @@ func TestMerge(t *testing.T) { e.Merge(e2) Expect(e.Map()).To(Equal(pairs("BAR", "baz", "FOO", "bar"))) - e3, _ := newEnvFromString("FOO='ba \\nz'") + e3, err := newEnvFromString("FOO=\"ba \\nz\"") + Expect(err).NotTo(HaveOccurred()) e.Merge(e3) Expect(e.Map()).To(Equal(pairs("BAR", "baz", "FOO", "ba \nz"))) } func TestExport(t *testing.T) { RegisterTestingT(t) - e, _ := newEnvFromString("BAR='BAZ'\nFOO='b'ar '\nBAZ='a\\nb'") + e, err := newEnvFromString("BAR='BAZ'\nFOO=\"b'ar \"\nBAZ=\"a\\nb\"") + Expect(err).NotTo(HaveOccurred()) Expect(e.Export(ExportFormatEnvfile)).To(Equal("BAR=\"BAZ\"\nBAZ=\"a\\nb\"\nFOO=\"b'ar \"")) Expect(e.Export(ExportFormatDockerArgs)).To(Equal("--env=BAR='BAZ' --env=BAZ='a\nb' --env=FOO='b'\\''ar '")) Expect(e.Export(ExportFormatDockerArgsKeys)).To(Equal("--env=BAR --env=BAZ --env=FOO"))