Skip to content

Commit 72bde6f

Browse files
committed
add --with-env flag to publish command
this flag allow publishing env variables in the Compose OCI artifact Signed-off-by: Guillaume Lours <[email protected]>
1 parent 52578c0 commit 72bde6f

File tree

9 files changed

+115
-4
lines changed

9 files changed

+115
-4
lines changed

cmd/compose/publish.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type publishOptions struct {
2929
*ProjectOptions
3030
resolveImageDigests bool
3131
ociVersion string
32+
withEnvironment bool
3233
}
3334

3435
func publishCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
@@ -45,7 +46,9 @@ func publishCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Servic
4546
}
4647
flags := cmd.Flags()
4748
flags.BoolVar(&opts.resolveImageDigests, "resolve-image-digests", false, "Pin image tags to digests")
48-
flags.StringVar(&opts.ociVersion, "oci-version", "", "OCI Image/Artifact specification version (automatically determined by default)")
49+
flags.StringVar(&opts.ociVersion, "oci-version", "", "OCI image/artifact specification version (automatically determined by default)")
50+
flags.BoolVar(&opts.withEnvironment, "with-env", false, "Include environment variables in the published OCI artifact")
51+
4952
return cmd
5053
}
5154

@@ -58,5 +61,6 @@ func runPublish(ctx context.Context, dockerCli command.Cli, backend api.Service,
5861
return backend.Publish(ctx, project, repository, api.PublishOptions{
5962
ResolveImageDigests: opts.resolveImageDigests,
6063
OCIVersion: api.OCIVersion(opts.ociVersion),
64+
WithEnvironment: opts.withEnvironment,
6165
})
6266
}

docs/reference/compose_alpha_publish.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ Publish compose application
88
| Name | Type | Default | Description |
99
|:--------------------------|:---------|:--------|:-------------------------------------------------------------------------------|
1010
| `--dry-run` | `bool` | | Execute command in dry run mode |
11-
| `--oci-version` | `string` | | OCI Image/Artifact specification version (automatically determined by default) |
11+
| `--oci-version` | `string` | | OCI image/artifact specification version (automatically determined by default) |
1212
| `--resolve-image-digests` | `bool` | | Pin image tags to digests |
13+
| `--with-env` | `bool` | | Include environment variables in the published OCI artifact |
1314

1415

1516
<!---MARKER_GEN_END-->

docs/reference/docker_compose_alpha_publish.yaml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ options:
88
- option: oci-version
99
value_type: string
1010
description: |
11-
OCI Image/Artifact specification version (automatically determined by default)
11+
OCI image/artifact specification version (automatically determined by default)
1212
deprecated: false
1313
hidden: false
1414
experimental: false
@@ -25,6 +25,16 @@ options:
2525
experimentalcli: false
2626
kubernetes: false
2727
swarm: false
28+
- option: with-env
29+
value_type: bool
30+
default_value: "false"
31+
description: Include environment variables in the published OCI artifact
32+
deprecated: false
33+
hidden: false
34+
experimental: false
35+
experimentalcli: false
36+
kubernetes: false
37+
swarm: false
2838
inherited_options:
2939
- option: dry-run
3040
value_type: bool

pkg/api/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ const (
420420
// PublishOptions group options of the Publish API
421421
type PublishOptions struct {
422422
ResolveImageDigests bool
423+
WithEnvironment bool
423424

424425
OCIVersion OCIVersion
425426
}

pkg/compose/publish.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package compose
1818

1919
import (
2020
"context"
21+
"fmt"
2122
"os"
2223

2324
"github.com/compose-spec/compose-go/v2/types"
@@ -35,7 +36,11 @@ func (s *composeService) Publish(ctx context.Context, project *types.Project, re
3536
}
3637

3738
func (s *composeService) publish(ctx context.Context, project *types.Project, repository string, options api.PublishOptions) error {
38-
err := s.Push(ctx, project, api.PushOptions{IgnoreFailures: true, ImageMandatory: true})
39+
err := preChecks(project, options)
40+
if err != nil {
41+
return err
42+
}
43+
err = s.Push(ctx, project, api.PushOptions{IgnoreFailures: true, ImageMandatory: true})
3944
if err != nil {
4045
return err
4146
}
@@ -120,3 +125,22 @@ func (s *composeService) generateImageDigestsOverride(ctx context.Context, proje
120125
}
121126
return override.MarshalYAML()
122127
}
128+
129+
func preChecks(project *types.Project, options api.PublishOptions) error {
130+
if !options.WithEnvironment {
131+
for _, service := range project.Services {
132+
if len(service.EnvFiles) > 0 {
133+
return fmt.Errorf("service %q has env_file declared. To avoid leaking sensitive data, "+
134+
"you must either explicitly allow the sending of environment variables by using the --with-env flag,"+
135+
" or remove sensitive data from your Compose configuration", service.Name)
136+
}
137+
if len(service.Environment) > 0 {
138+
return fmt.Errorf("service %q has environment variable(s) declared. To avoid leaking sensitive data, "+
139+
"you must either explicitly allow the sending of environment variables by using the --with-env flag,"+
140+
" or remove sensitive data from your Compose configuration", service.Name)
141+
}
142+
}
143+
}
144+
145+
return nil
146+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
services:
2+
serviceA:
3+
image: "alpine:3.12"
4+
env_file:
5+
- publish.env
6+
serviceB:
7+
image: "alpine:3.12"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
services:
2+
serviceA:
3+
image: "alpine:3.12"
4+
environment:
5+
- "FOO=bar"
6+
serviceB:
7+
image: "alpine:3.12"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FOO=bar

pkg/e2e/publish_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
Copyright 2020 Docker Compose CLI authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package e2e
18+
19+
import (
20+
"strings"
21+
"testing"
22+
23+
"gotest.tools/v3/assert"
24+
"gotest.tools/v3/icmd"
25+
)
26+
27+
func TestPublishChecks(t *testing.T) {
28+
c := NewParallelCLI(t)
29+
const projectName = "compose-e2e-explicit-profiles"
30+
31+
t.Run("publish error environment", func(t *testing.T) {
32+
res := c.RunDockerComposeCmdNoCheck(t, "-f", "./fixtures/publish/compose-environment.yml",
33+
"-p", projectName, "alpha", "publish", "test/test")
34+
res.Assert(t, icmd.Expected{ExitCode: 1, Err: `service "serviceA" has environment variable(s) declared. To avoid leaking sensitive data,`})
35+
})
36+
37+
t.Run("publish error env_file", func(t *testing.T) {
38+
res := c.RunDockerComposeCmdNoCheck(t, "-f", "./fixtures/publish/compose-env-file.yml",
39+
"-p", projectName, "alpha", "publish", "test/test")
40+
res.Assert(t, icmd.Expected{ExitCode: 1, Err: `service "serviceA" has env_file declared. To avoid leaking sensitive data,`})
41+
})
42+
43+
t.Run("publish success environment", func(t *testing.T) {
44+
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/publish/compose-environment.yml",
45+
"-p", projectName, "alpha", "publish", "test/test", "--with-env", "--dry-run")
46+
assert.Assert(t, strings.Contains(res.Combined(), "test/test publishing"), res.Combined())
47+
assert.Assert(t, strings.Contains(res.Combined(), "test/test published"), res.Combined())
48+
})
49+
50+
t.Run("publish success env_file", func(t *testing.T) {
51+
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/publish/compose-env-file.yml",
52+
"-p", projectName, "alpha", "publish", "test/test", "--with-env", "--dry-run")
53+
assert.Assert(t, strings.Contains(res.Combined(), "test/test publishing"), res.Combined())
54+
assert.Assert(t, strings.Contains(res.Combined(), "test/test published"), res.Combined())
55+
})
56+
}

0 commit comments

Comments
 (0)