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

Commit d4f38e4

Browse files
author
Vincent Demeester
authored
Merge pull request #328 from vdemeester/clean-extract-variables
Use docker/cli template.ExtractVariables instead of own impl.
2 parents fc7798d + e73acc6 commit d4f38e4

5 files changed

Lines changed: 118 additions & 129 deletions

File tree

Gopkg.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/helm/helm.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ import (
1414
"github.com/docker/app/internal/helm/templateconversion"
1515
"github.com/docker/app/internal/helm/templateloader"
1616
"github.com/docker/app/internal/helm/templatev1beta2"
17-
"github.com/docker/app/internal/packager"
1817
"github.com/docker/app/internal/render"
1918
"github.com/docker/app/internal/settings"
2019
"github.com/docker/app/internal/slices"
2120
"github.com/docker/app/internal/types"
2221
"github.com/docker/cli/cli/command/stack/kubernetes"
2322
"github.com/docker/cli/cli/compose/loader"
23+
"github.com/docker/cli/cli/compose/template"
2424
"github.com/docker/cli/kubernetes/compose/v1beta1"
2525
"github.com/docker/cli/kubernetes/compose/v1beta2"
2626
"github.com/pkg/errors"
@@ -60,9 +60,15 @@ func Helm(appname string, composeFiles []string, settingsFile []string, env map[
6060
if err != nil {
6161
return errors.Wrap(err, "failed to read application Compose file")
6262
}
63-
variables, err := packager.ExtractVariables(string(data))
63+
cfgMap, err := loader.ParseYAML(data)
6464
if err != nil {
65-
return errors.Wrap(err, "failed to parse docker-compose.yml, maybe because it is a template")
65+
return errors.Wrap(err, "failed to parse compose file")
66+
}
67+
vars := template.ExtractVariables(cfgMap)
68+
// FIXME(vdemeester): remove the need to create this slice
69+
variables := []string{}
70+
for k := range vars {
71+
variables = append(variables, k)
6672
}
6773
err = makeStack(appname, targetDir, data, stackVersion)
6874
if err != nil {

internal/packager/init.go

Lines changed: 23 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
195108
func 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)

internal/packager/init_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"testing"
1010

1111
"github.com/docker/app/internal"
12-
1312
"gotest.tools/assert"
1413
"gotest.tools/fs"
1514
)

vendor/github.com/docker/cli/cli/compose/template/template.go

Lines changed: 85 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)