@@ -13,6 +13,9 @@ import (
1313
1414 "github.com/docker/app/internal"
1515 "github.com/docker/app/internal/types"
16+ "github.com/docker/cli/cli/compose/loader"
17+ dtemplate "github.com/docker/cli/cli/compose/template"
18+ "github.com/docker/cli/opts"
1619 "github.com/pkg/errors"
1720 log "github.com/sirupsen/logrus"
1821 "gopkg.in/yaml.v2"
@@ -102,118 +105,39 @@ func initFromScratch(name string) error {
102105 return ioutil .WriteFile (filepath .Join (dirName , internal .SettingsFileName ), []byte {'\n' }, 0644 )
103106}
104107
105- func parseEnv (env string , target map [string ]string ) {
106- envlines := strings .Split (env , "\n " )
107- for _ , l := range envlines {
108- l = strings .Trim (l , "\r " )
109- if l == "" || l [0 ] == '#' {
110- continue
111- }
112- kv := strings .SplitN (l , "=" , 2 )
113- if len (kv ) != 2 {
114- continue
115- }
116- target [kv [0 ]] = kv [1 ]
117- }
118- }
119-
120- func isAlNum (b byte ) bool {
121- return (b >= 'A' && b <= 'Z' ) || (b >= 'a' && b <= 'z' ) || (b >= '0' && b <= '9' ) || b == '_' || b == '.'
122- }
123-
124- func extractString (data string , res * []string ) {
125- for {
126- dollar := strings .Index (data , "$" )
127- if dollar == - 1 || len (data ) == dollar + 1 {
128- break
129- }
130- if data [dollar + 1 ] == '$' {
131- data = data [dollar + 2 :]
132- continue
133- }
134- dollar ++
135- if data [dollar ] == '{' {
136- dollar ++
137- }
138- start := dollar
139- for dollar < len (data ) && isAlNum (data [dollar ]) {
140- dollar ++
141- }
142- * res = append (* res , data [start :dollar ])
143- data = data [dollar :]
144- }
145- }
146-
147- func extractRecurseList (node []interface {}, res * []string ) error {
148- for _ , v := range node {
149- switch vv := v .(type ) {
150- case string :
151- extractString (vv , res )
152- case []interface {}:
153- if err := extractRecurseList (vv , res ); err != nil {
154- return err
155- }
156- case map [interface {}]interface {}:
157- if err := extractRecurse (vv , res ); err != nil {
158- return err
159- }
160- }
161- }
162- return nil
163- }
164-
165- func extractRecurse (node map [interface {}]interface {}, res * []string ) error {
166- for _ , v := range node {
167- switch vv := v .(type ) {
168- case string :
169- extractString (vv , res )
170- case []interface {}:
171- if err := extractRecurseList (vv , res ); err != nil {
172- return err
173- }
174- case map [interface {}]interface {}:
175- if err := extractRecurse (vv , res ); err != nil {
176- return err
177- }
178- }
179- }
180- return nil
181- }
182-
183- // ExtractVariables returns the list of variables used by given compose raw data
184- func ExtractVariables (composeRaw string ) ([]string , error ) {
185- compose := make (map [interface {}]interface {})
186- err := yaml .Unmarshal ([]byte (composeRaw ), compose )
187- if err != nil {
188- return nil , err
189- }
190- var res []string
191- err = extractRecurse (compose , & res )
192- return res , err
193- }
194-
195108func initFromComposeFile (name string , composeFile string ) error {
196109 log .Debug ("init from compose" )
197110
198111 dirName := internal .DirNameFromAppName (name )
112+
199113 composeRaw , err := ioutil .ReadFile (composeFile )
200114 if err != nil {
201115 return errors .Wrap (err , "failed to read compose file" )
202116 }
203- settings := make (map [string ]string )
204- envRaw , err := ioutil .ReadFile (filepath .Join (filepath .Dir (composeFile ), ".env" ))
205- if err == nil {
206- parseEnv (string (envRaw ), settings )
207- }
208- keys , err := ExtractVariables (string (composeRaw ))
117+ cfgMap , err := loader .ParseYAML (composeRaw )
209118 if err != nil {
210119 return errors .Wrap (err , "failed to parse compose file" )
211120 }
121+ settings := make (map [string ]string )
122+ envs , err := opts .ParseEnvFile (filepath .Join (filepath .Dir (composeFile ), ".env" ))
123+ if err == nil {
124+ for _ , v := range envs {
125+ kv := strings .SplitN (v , "=" , 2 )
126+ if len (kv ) == 2 {
127+ settings [kv [0 ]] = kv [1 ]
128+ }
129+ }
130+ }
131+ vars := dtemplate .ExtractVariables (cfgMap )
212132 needsFilling := false
213- for _ , k := range keys {
133+ for k , v := range vars {
214134 if _ , ok := settings [k ]; ! ok {
215- settings [k ] = "FILL ME"
216- needsFilling = true
135+ if v != "" {
136+ settings [k ] = v
137+ } else {
138+ settings [k ] = "FILL ME"
139+ needsFilling = true
140+ }
217141 }
218142 }
219143 settingsYAML , err := yaml .Marshal (settings )
0 commit comments