diff --git a/cmd/compose/compose.go b/cmd/compose/compose.go index 080d25f765d..8faf323e072 100644 --- a/cmd/compose/compose.go +++ b/cmd/compose/compose.go @@ -37,6 +37,7 @@ import ( dockercli "github.com/docker/cli/cli" "github.com/docker/cli/cli-plugins/manager" "github.com/docker/cli/cli/command" + cliopts "github.com/docker/cli/opts" "github.com/docker/compose/v2/cmd/formatter" "github.com/docker/compose/v2/internal/desktop" "github.com/docker/compose/v2/internal/experimental" @@ -70,6 +71,26 @@ const ( ComposeMenu = "COMPOSE_MENU" ) +// rawEnv load a dot env file using docker/cli key=value parser, without attempt to interpolate or evaluate values +func rawEnv(filename string, lookup func(key string) (string, bool)) (map[string]string, error) { + lines, err := cliopts.ParseEnvFileWithLookup(filename, lookup) + if err != nil { + return nil, err + } + vars := types.Mapping{} + for _, line := range lines { + key, value, _ := strings.Cut(line, "=") + vars[key] = value + } + return vars, nil +} + +func init() { + // compose evaluates env file values for interpolation + // `raw` format allows to load env_file with the same parser used by docker run --env-file + dotenv.RegisterFormat("raw", rawEnv) +} + type Backend interface { api.Service diff --git a/cmd/formatter/colors.go b/cmd/formatter/colors.go index 8b2ed5246dc..a2f57f438e7 100644 --- a/cmd/formatter/colors.go +++ b/cmd/formatter/colors.go @@ -21,7 +21,7 @@ import ( "strconv" "sync" - "github.com/docker/compose/v2/pkg/api" + "github.com/docker/cli/cli/command" ) var names = []string{ @@ -59,7 +59,7 @@ const ( ) // SetANSIMode configure formatter for colored output on ANSI-compliant console -func SetANSIMode(streams api.Streams, ansi string) { +func SetANSIMode(streams command.Streams, ansi string) { if !useAnsi(streams, ansi) { nextColor = func() colorFunc { return monochrome @@ -68,7 +68,7 @@ func SetANSIMode(streams api.Streams, ansi string) { } } -func useAnsi(streams api.Streams, ansi string) bool { +func useAnsi(streams command.Streams, ansi string) bool { switch ansi { case Always: return true diff --git a/go.mod b/go.mod index da8a67a3292..7cdac54a38d 100644 --- a/go.mod +++ b/go.mod @@ -193,4 +193,6 @@ require ( tags.cncf.io/container-device-interface v0.8.0 // indirect ) -replace github.com/compose-spec/compose-go/v2 => github.com/compose-spec/compose-go/v2 v2.2.1-0.20240926141145-d3fd7d94aa31 +replace github.com/compose-spec/compose-go/v2 => github.com/ndeloof/compose-go/v2 v2.0.1-0.20241002065538-2d728e7fdf2e + +replace github.com/docker/cli => github.com/ndeloof/cli v0.0.0-20241002062458-a9adc954e073 diff --git a/go.sum b/go.sum index c980ef2ce2e..ebcc48b3c38 100644 --- a/go.sum +++ b/go.sum @@ -85,8 +85,6 @@ github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/P github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= -github.com/compose-spec/compose-go/v2 v2.2.1-0.20240926141145-d3fd7d94aa31 h1:1LUnOD+HiecazmN9NDFE9mtwywIehxt/I4g0jc/syc0= -github.com/compose-spec/compose-go/v2 v2.2.1-0.20240926141145-d3fd7d94aa31/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= @@ -128,8 +126,6 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/buildx v0.17.1 h1:9ob2jGp4+W9PxWw68GsoNFp+eYFc7eUoRL9VljLCSM4= github.com/docker/buildx v0.17.1/go.mod h1:kJOhOhS47LRvrLFRulFiO5SE6VJf54yYMn7DzjgO5W0= -github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ= -github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli-docs-tool v0.8.0 h1:YcDWl7rQJC3lJ7WVZRwSs3bc9nka97QLWfyJQli8yJU= github.com/docker/cli-docs-tool v0.8.0/go.mod h1:8TQQ3E7mOXoYUs811LiPdUnAhXrcVsBIrW21a5pUbdk= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= @@ -357,6 +353,10 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/ndeloof/cli v0.0.0-20241002062458-a9adc954e073 h1:+D7DoyHrvA/GxnYFkZeG+qqx6ozsf4wyf57tkEhGapE= +github.com/ndeloof/cli v0.0.0-20241002062458-a9adc954e073/go.mod h1:wxmb4t3v3ZwISBr3B/B631+3VJe+erAxkl3vXQwXj2c= +github.com/ndeloof/compose-go/v2 v2.0.1-0.20241002065538-2d728e7fdf2e h1:NXonWgToLhvW6urgyxu2QWtXEgyahpcdlf9wxf2lPNE= +github.com/ndeloof/compose-go/v2 v2.0.1-0.20241002065538-2d728e7fdf2e/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= diff --git a/pkg/e2e/env_file_test.go b/pkg/e2e/env_file_test.go new file mode 100644 index 00000000000..f4982655da0 --- /dev/null +++ b/pkg/e2e/env_file_test.go @@ -0,0 +1,31 @@ +/* + Copyright 2020 Docker Compose CLI authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package e2e + +import ( + "strings" + "testing" + + "gotest.tools/v3/assert" +) + +func TestRawEnvFile(t *testing.T) { + c := NewParallelCLI(t) + + res := c.RunDockerComposeCmd(t, "-f", "./fixtures/dotenv/raw.yaml", "run", "test") + assert.Equal(t, strings.TrimSpace(res.Stdout()), "'{\"key\": \"value\"}'") +} diff --git a/pkg/e2e/fixtures/dotenv/.env.raw b/pkg/e2e/fixtures/dotenv/.env.raw new file mode 100644 index 00000000000..306900800fc --- /dev/null +++ b/pkg/e2e/fixtures/dotenv/.env.raw @@ -0,0 +1 @@ +TEST_VAR='{"key": "value"}' \ No newline at end of file diff --git a/pkg/e2e/fixtures/dotenv/raw.yaml b/pkg/e2e/fixtures/dotenv/raw.yaml new file mode 100644 index 00000000000..a65664273d3 --- /dev/null +++ b/pkg/e2e/fixtures/dotenv/raw.yaml @@ -0,0 +1,7 @@ +services: + test: + image: alpine + command: sh -c "echo $$TEST_VAR" + env_file: + - path: .env.raw + format: raw # parse without interpolation \ No newline at end of file