Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit c7927e1

Browse files
authored
Merge pull request #610 from ulyssessouza/add-env_file-warning
Add warnings for env_file entries not copied
2 parents 080e680 + d2c567b commit c7927e1

File tree

7 files changed

+140
-22
lines changed

7 files changed

+140
-22
lines changed

e2e/commands_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,64 @@ func TestRenderFormatters(t *testing.T) {
108108
})
109109
}
110110

111+
func checkFileWarning(t *testing.T, goldenFile, composeData string) {
112+
cmd, cleanup := dockerCli.createTestCmd()
113+
defer cleanup()
114+
115+
tmpDir := fs.NewDir(t, "app_input",
116+
fs.WithFile(internal.ComposeFileName, composeData),
117+
)
118+
defer tmpDir.Remove()
119+
120+
cmd.Dir = tmpDir.Path()
121+
cmd.Command = dockerCli.Command("app", "init", "app-test",
122+
"--compose-file", tmpDir.Join(internal.ComposeFileName))
123+
stdErr := icmd.RunCmd(cmd).Assert(t, icmd.Success).Stderr()
124+
golden.Assert(t, stdErr, goldenFile)
125+
}
126+
127+
func TestInitWarningEnvFiles(t *testing.T) {
128+
testCases := []struct {
129+
name string
130+
golden string
131+
compose string
132+
}{
133+
{
134+
name: "initWarningSingleEnvFileTest",
135+
golden: "init-output-warning-single-envfile.golden",
136+
compose: `version: "3.2"
137+
services:
138+
nginx:
139+
image: nginx:latest
140+
env_file: myenv1.env`,
141+
},
142+
{
143+
name: "initWarningMultipleEnvFilesTest",
144+
golden: "init-output-warning-multiple-envfiles.golden",
145+
compose: `version: "3.2"
146+
services:
147+
nginx:
148+
image: nginx:latest
149+
env_file:
150+
- myenv1.env
151+
- myenv2.env`,
152+
},
153+
{
154+
name: "initNoEnvFilesTest",
155+
golden: "init-output-no-envfile.golden",
156+
compose: `version: "3.2"
157+
services:
158+
nginx:
159+
image: nginx:latest`,
160+
},
161+
}
162+
for _, test := range testCases {
163+
t.Run(test.name, func(t *testing.T) {
164+
checkFileWarning(t, test.golden, test.compose)
165+
})
166+
}
167+
}
168+
111169
func TestInit(t *testing.T) {
112170
cmd, cleanup := dockerCli.createTestCmd()
113171
defer cleanup()

e2e/testdata/init-output-no-envfile.golden

Whitespace-only changes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
nginx.env_file "myenv1.env" will not be copied into app-test.dockerapp. Please copy it manually and update the path accordingly in the compose file.
2+
nginx.env_file "myenv2.env" will not be copied into app-test.dockerapp. Please copy it manually and update the path accordingly in the compose file.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nginx.env_file "myenv1.env" will not be copied into app-test.dockerapp. Please copy it manually and update the path accordingly in the compose file.

internal/commands/init.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func initCmd(dockerCli command.Cli) *cobra.Command {
2121
$ docker app init myapp --compose-file docker-compose.yml`,
2222
Args: cli.ExactArgs(1),
2323
RunE: func(cmd *cobra.Command, args []string) error {
24-
created, err := packager.Init(args[0], initComposeFile)
24+
created, err := packager.Init(dockerCli.Err(), args[0], initComposeFile)
2525
if err != nil {
2626
return err
2727
}

internal/packager/init.go

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package packager
33
import (
44
"bytes"
55
"fmt"
6+
"io"
67
"io/ioutil"
78
"os"
89
"os/user"
@@ -27,7 +28,7 @@ import (
2728
// Init is the entrypoint initialization function.
2829
// It generates a new application definition based on the provided parameters
2930
// and returns the path to the created application definition.
30-
func Init(name string, composeFile string) (string, error) {
31+
func Init(errWriter io.Writer, name string, composeFile string) (string, error) {
3132
if err := internal.ValidateAppName(name); err != nil {
3233
return "", err
3334
}
@@ -48,7 +49,7 @@ func Init(name string, composeFile string) (string, error) {
4849
if composeFile == "" {
4950
err = initFromScratch(name)
5051
} else {
51-
err = initFromComposeFile(name, composeFile)
52+
err = initFromComposeFile(errWriter, name, composeFile)
5253
}
5354
if err != nil {
5455
return "", err
@@ -79,22 +80,52 @@ func checkComposeFileVersion(compose map[string]interface{}) error {
7980
return schema.Validate(compose, fmt.Sprintf("%v", version))
8081
}
8182

82-
func initFromComposeFile(name string, composeFile string) error {
83-
logrus.Debugf("Initializing from compose file %s", composeFile)
84-
85-
dirName := internal.DirNameFromAppName(name)
86-
87-
composeRaw, err := ioutil.ReadFile(composeFile)
88-
if err != nil {
89-
return errors.Wrap(err, "failed to read compose file")
83+
func getEnvFiles(svcName string, envFileEntry interface{}) ([]string, error) {
84+
var envFiles []string
85+
switch envFileEntry.(type) {
86+
case string:
87+
envFiles = append(envFiles, envFileEntry.(string))
88+
case []interface{}:
89+
for _, env := range envFileEntry.([]interface{}) {
90+
envFiles = append(envFiles, env.(string))
91+
}
92+
default:
93+
return nil, fmt.Errorf("unknown entries in 'env_file' for service %s -> %v",
94+
svcName, envFileEntry)
9095
}
91-
cfgMap, err := composeloader.ParseYAML(composeRaw)
92-
if err != nil {
93-
return errors.Wrap(err, "failed to parse compose file")
96+
return envFiles, nil
97+
}
98+
99+
func checkEnvFiles(errWriter io.Writer, appName string, cfgMap map[string]interface{}) error {
100+
services := cfgMap["services"]
101+
servicesMap, ok := services.(map[string]interface{})
102+
if !ok {
103+
return fmt.Errorf("invalid Compose file")
94104
}
95-
if err := checkComposeFileVersion(cfgMap); err != nil {
96-
return err
105+
for svcName, svc := range servicesMap {
106+
svcContent, ok := svc.(map[string]interface{})
107+
if !ok {
108+
return fmt.Errorf("invalid service %q", svcName)
109+
}
110+
envFileEntry, ok := svcContent["env_file"]
111+
if !ok {
112+
continue
113+
}
114+
envFiles, err := getEnvFiles(svcName, envFileEntry)
115+
if err != nil {
116+
return errors.Wrap(err, "invalid Compose file")
117+
}
118+
for _, envFilePath := range envFiles {
119+
fmt.Fprintf(errWriter,
120+
"%s.env_file %q will not be copied into %s.dockerapp. "+
121+
"Please copy it manually and update the path accordingly in the compose file.\n",
122+
svcName, envFilePath, appName)
123+
}
97124
}
125+
return nil
126+
}
127+
128+
func getParamsFromDefaultEnvFile(composeFile string, composeRaw []byte) (map[string]string, bool, error) {
98129
params := make(map[string]string)
99130
envs, err := opts.ParseEnvFile(filepath.Join(filepath.Dir(composeFile), ".env"))
100131
if err == nil {
@@ -107,7 +138,7 @@ func initFromComposeFile(name string, composeFile string) error {
107138
}
108139
vars, err := compose.ExtractVariables(composeRaw, compose.ExtrapolationPattern)
109140
if err != nil {
110-
return errors.Wrap(err, "failed to parse compose file")
141+
return nil, false, errors.Wrap(err, "failed to parse compose file")
111142
}
112143
needsFilling := false
113144
for k, v := range vars {
@@ -120,6 +151,32 @@ func initFromComposeFile(name string, composeFile string) error {
120151
}
121152
}
122153
}
154+
return params, needsFilling, nil
155+
}
156+
157+
func initFromComposeFile(errWriter io.Writer, name string, composeFile string) error {
158+
logrus.Debugf("Initializing from compose file %s", composeFile)
159+
160+
dirName := internal.DirNameFromAppName(name)
161+
162+
composeRaw, err := ioutil.ReadFile(composeFile)
163+
if err != nil {
164+
return errors.Wrapf(err, "failed to read compose file %q", composeFile)
165+
}
166+
cfgMap, err := composeloader.ParseYAML(composeRaw)
167+
if err != nil {
168+
return errors.Wrap(err, "failed to parse compose file")
169+
}
170+
if err := checkComposeFileVersion(cfgMap); err != nil {
171+
return err
172+
}
173+
if err := checkEnvFiles(errWriter, name, cfgMap); err != nil {
174+
return err
175+
}
176+
params, needsFilling, err := getParamsFromDefaultEnvFile(composeFile, composeRaw)
177+
if err != nil {
178+
return err
179+
}
123180
expandedParams, err := parameters.FromFlatten(params)
124181
if err != nil {
125182
return errors.Wrap(err, "failed to expand parameters")

internal/packager/init_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ services:
3232
)
3333
defer dir.Remove()
3434

35-
err := initFromComposeFile(dir.Join(appName), inputDir.Join(internal.ComposeFileName))
35+
err := initFromComposeFile(nil, dir.Join(appName), inputDir.Join(internal.ComposeFileName))
3636
assert.NilError(t, err)
3737

3838
manifest := fs.Expected(
@@ -73,7 +73,7 @@ services:
7373
)
7474
defer dir.Remove()
7575

76-
err := initFromComposeFile(dir.Join(appName), inputDir.Join(internal.ComposeFileName))
76+
err := initFromComposeFile(nil, dir.Join(appName), inputDir.Join(internal.ComposeFileName))
7777
assert.NilError(t, err)
7878

7979
const expectedParameters = `ports:
@@ -108,7 +108,7 @@ services:
108108
}
109109

110110
func TestInitFromInvalidComposeFile(t *testing.T) {
111-
err := initFromComposeFile("my.dockerapp", "doesnotexist")
111+
err := initFromComposeFile(nil, "my.dockerapp", "doesnotexist")
112112
assert.ErrorContains(t, err, "failed to read")
113113
}
114114

@@ -131,7 +131,7 @@ services:
131131
)
132132
defer dir.Remove()
133133

134-
err := initFromComposeFile(dir.Join(appName), inputDir.Join(internal.ComposeFileName))
134+
err := initFromComposeFile(nil, dir.Join(appName), inputDir.Join(internal.ComposeFileName))
135135
assert.ErrorContains(t, err, "unsupported Compose file version")
136136
}
137137

@@ -151,7 +151,7 @@ nginx:
151151
)
152152
defer dir.Remove()
153153

154-
err := initFromComposeFile(dir.Join(appName), inputDir.Join(internal.ComposeFileName))
154+
err := initFromComposeFile(nil, dir.Join(appName), inputDir.Join(internal.ComposeFileName))
155155
assert.ErrorContains(t, err, "unsupported Compose file version")
156156
}
157157

0 commit comments

Comments
 (0)