diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000000..13566b81b01
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/compose.iml b/.idea/compose.iml
new file mode 100644
index 00000000000..5e764c4f0b9
--- /dev/null
+++ b/.idea/compose.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/golinter.xml b/.idea/golinter.xml
new file mode 100644
index 00000000000..1ccf3ec6d93
--- /dev/null
+++ b/.idea/golinter.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000000..2efec7ef046
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000000..35eb1ddfbbc
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cmd/compose/ps.go b/cmd/compose/ps.go
index 2528fccacfb..e79a8bcef89 100644
--- a/cmd/compose/ps.go
+++ b/cmd/compose/ps.go
@@ -81,7 +81,7 @@ func psCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *Backend
ValidArgsFunction: completeServiceNames(dockerCli, p),
}
flags := psCmd.Flags()
- flags.StringVar(&opts.Format, "format", "table", cliflags.FormatHelp)
+ flags.StringVar(&opts.Format, "format", "", cliflags.FormatHelp)
flags.StringVar(&opts.Filter, "filter", "", "Filter services by a property (supported filters: status)")
flags.StringArrayVar(&opts.Status, "status", []string{}, "Filter services by status. Values: [paused | restarting | removing | running | dead | created | exited]")
flags.BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs")
@@ -152,9 +152,14 @@ func runPs(ctx context.Context, dockerCli command.Cli, backendOptions *BackendOp
return nil
}
- if opts.Format == "" {
+ if len(opts.Format) == 0 {
opts.Format = dockerCli.ConfigFile().PsFormat
}
+ if len(opts.Format) == 0 {
+ opts.Format = "table"
+ } else if opts.Quiet {
+ _, _ = dockerCli.Err().Write([]byte("WARNING: Ignoring custom format, because both --format and --quiet are set.\n"))
+ }
containerCtx := cliformatter.Context{
Output: dockerCli.Out(),
diff --git a/cmd/compose/ps_format_test.go b/cmd/compose/ps_format_test.go
new file mode 100644
index 00000000000..dd5f8b68b19
--- /dev/null
+++ b/cmd/compose/ps_format_test.go
@@ -0,0 +1,47 @@
+/*
+ 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 compose
+
+import (
+ "testing"
+
+ "github.com/docker/cli/cli/config/configfile"
+ "github.com/docker/cli/cli/streams"
+ "go.uber.org/mock/gomock"
+ "gotest.tools/v3/assert"
+
+ "github.com/docker/compose/v5/pkg/mocks"
+)
+
+func TestPsCommandDefaultFormat(t *testing.T) {
+ // Test that the format flag has empty string as default
+ projectOpts := &ProjectOptions{}
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+
+ cli := mocks.NewMockCli(mockCtrl)
+ cli.EXPECT().ConfigFile().Return(configfile.New("test")).AnyTimes()
+ cli.EXPECT().Out().Return(&streams.Out{}).AnyTimes()
+ cli.EXPECT().Err().Return(&streams.Out{}).AnyTimes()
+
+ backendOptions := &BackendOptions{}
+ cmd := psCommand(projectOpts, cli, backendOptions)
+
+ // Check default value of format flag
+ formatFlag := cmd.Flags().Lookup("format")
+ assert.Equal(t, formatFlag.DefValue, "")
+}
diff --git a/pkg/compose/publish.go b/pkg/compose/publish.go
index fb466607559..4ec67a63263 100644
--- a/pkg/compose/publish.go
+++ b/pkg/compose/publish.go
@@ -251,6 +251,9 @@ func processFile(ctx context.Context, file string, project *types.Project, extFi
}
for name, service := range base.Services {
for i, envFile := range service.EnvFiles {
+ if !envFile.Required {
+ continue
+ }
hash := fmt.Sprintf("%x.env", sha256.Sum256([]byte(envFile.Path)))
envFiles[envFile.Path] = hash
f, err = transform.ReplaceEnvFile(f, name, i, hash)
@@ -351,8 +354,11 @@ func (s *composeService) checkEnvironmentVariables(project *types.Project, optio
errorList := map[string][]string{}
for _, service := range project.Services {
- if len(service.EnvFiles) > 0 {
- errorList[service.Name] = append(errorList[service.Name], fmt.Sprintf("service %q has env_file declared.", service.Name))
+ for _, envFile := range service.EnvFiles {
+ if envFile.Required {
+ errorList[service.Name] = append(errorList[service.Name], fmt.Sprintf("service %q has env_file declared.", service.Name))
+ break
+ }
}
}
@@ -438,6 +444,9 @@ func (s *composeService) checkForSensitiveData(project *types.Project) ([]secret
for _, service := range project.Services {
// Check env files
for _, envFile := range service.EnvFiles {
+ if !envFile.Required {
+ continue
+ }
findings, err := scan.ScanFile(envFile.Path)
if err != nil {
return nil, fmt.Errorf("failed to scan env file %s: %w", envFile.Path, err)
diff --git a/pkg/compose/publish_test.go b/pkg/compose/publish_test.go
index 8f91f663e69..b3ba8c77875 100644
--- a/pkg/compose/publish_test.go
+++ b/pkg/compose/publish_test.go
@@ -18,6 +18,7 @@ package compose
import (
"slices"
+ "strings"
"testing"
"github.com/compose-spec/compose-go/v2/loader"
@@ -100,3 +101,69 @@ services:
return !slices.Contains([]string{".Data", ".Digest", ".Size"}, path.String())
}, cmp.Ignore()))
}
+
+func Test_createLayers_withRequiredFalse(t *testing.T) {
+ project, err := loader.LoadWithContext(t.Context(), types.ConfigDetails{
+ WorkingDir: "testdata/publish/",
+ Environment: types.Mapping{},
+ ConfigFiles: []types.ConfigFile{
+ {
+ Filename: "testdata/publish/compose-required-false.yaml",
+ },
+ },
+ })
+ assert.NilError(t, err)
+ project.ComposeFiles = []string{"testdata/publish/compose-required-false.yaml"}
+
+ service := &composeService{}
+ layers, err := service.createLayers(t.Context(), project, api.PublishOptions{
+ WithEnvironment: true,
+ })
+ assert.NilError(t, err)
+
+ assert.Equal(t, len(layers), 2)
+
+ assert.Equal(t, layers[0].Annotations["com.docker.compose.file"], "compose-required-false.yaml")
+
+ assert.Equal(t, layers[1].MediaType, "application/vnd.docker.compose.envfile")
+
+ envFileHash := layers[1].Annotations["com.docker.compose.envfile"]
+ assert.Assert(t, len(envFileHash) > 0)
+ assert.Assert(t, envFileHash != "missing.env")
+}
+
+func Test_checkEnvironmentVariables_withRequiredFalse(t *testing.T) {
+ project := &types.Project{
+ Services: types.Services{
+ "test": {
+ Name: "test",
+ EnvFiles: []types.EnvFile{
+ {
+ Path: "missing.env",
+ Required: false,
+ },
+ {
+ Path: "existing.env",
+ Required: true,
+ },
+ },
+ },
+ "test2": {
+ Name: "test2",
+ EnvFiles: []types.EnvFile{
+ {
+ Path: "optional.env",
+ Required: false,
+ },
+ },
+ },
+ },
+ }
+
+ service := &composeService{}
+
+ err := service.checkEnvironmentVariables(project, api.PublishOptions{})
+ assert.Assert(t, err != nil)
+ assert.Assert(t, strings.Contains(err.Error(), `service "test" has env_file declared.`))
+ assert.Assert(t, !strings.Contains(err.Error(), `service "test2"`))
+}
diff --git a/pkg/compose/testdata/publish/compose-required-false.yaml b/pkg/compose/testdata/publish/compose-required-false.yaml
new file mode 100644
index 00000000000..64b94e38942
--- /dev/null
+++ b/pkg/compose/testdata/publish/compose-required-false.yaml
@@ -0,0 +1,9 @@
+name: test-required-false
+services:
+ test:
+ image: test
+ env_file:
+ - path: missing.env
+ required: false
+ - path: existing.env
+ required: true
diff --git a/pkg/compose/testdata/publish/existing.env b/pkg/compose/testdata/publish/existing.env
new file mode 100644
index 00000000000..bda5e6e581f
--- /dev/null
+++ b/pkg/compose/testdata/publish/existing.env
@@ -0,0 +1 @@
+EXISTING_VAR=value