Skip to content

Commit dbcd74e

Browse files
committed
refactor: make variable resolver easier to reuse
1 parent f2be037 commit dbcd74e

File tree

5 files changed

+85
-85
lines changed

5 files changed

+85
-85
lines changed

pkg/devspace/config/loader/expression/expression.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,22 @@ func expressionMatchFn(key, value string) bool {
2020
return ExpressionMatchRegex.MatchString(value)
2121
}
2222

23-
func ResolveAllExpressions(preparedConfig map[interface{}]interface{}, dir string) error {
24-
err := walk.Walk(preparedConfig, expressionMatchFn, func(value string) (interface{}, error) {
25-
return ResolveExpressions(value, dir)
26-
})
27-
if err != nil {
28-
return err
23+
func ResolveAllExpressions(preparedConfig interface{}, dir string) (interface{}, error) {
24+
switch t := preparedConfig.(type) {
25+
case string:
26+
return ResolveExpressions(t, dir)
27+
case map[interface{}]interface{}:
28+
err := walk.Walk(t, expressionMatchFn, func(value string) (interface{}, error) {
29+
return ResolveExpressions(value, dir)
30+
})
31+
if err != nil {
32+
return nil, err
33+
}
34+
35+
return t, nil
2936
}
3037

31-
return nil
38+
return nil, fmt.Errorf("unrecognized haystack type: %#v", preparedConfig)
3239
}
3340

3441
func ResolveExpressions(value, dir string) (interface{}, error) {

pkg/devspace/config/loader/loader.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,12 @@ func (l *configLoader) parseConfig(absPath string, rawConfig map[interface{}]int
280280
return nil, nil, nil, err
281281
}
282282

283+
// parse cli --var's, the resolver will cache them for us
284+
_, err = resolver.ConvertFlags(options.Vars)
285+
if err != nil {
286+
return nil, nil, nil, err
287+
}
288+
283289
// apply the profiles
284290
copiedRawConfig, err = l.applyProfiles(copiedRawConfig, options, log)
285291
if err != nil {

pkg/devspace/config/loader/parser.go

Lines changed: 5 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
package loader
22

33
import (
4-
"path/filepath"
5-
"strings"
6-
74
"github.com/loft-sh/devspace/pkg/devspace/config/loader/expression"
85
"github.com/loft-sh/devspace/pkg/devspace/config/loader/variable"
96
"github.com/loft-sh/devspace/pkg/devspace/config/versions"
107
"github.com/loft-sh/devspace/pkg/devspace/config/versions/latest"
118
"github.com/loft-sh/devspace/pkg/util/log"
129
"github.com/pkg/errors"
1310
"gopkg.in/yaml.v2"
11+
"path/filepath"
1412
)
1513

1614
type Parser interface {
@@ -100,82 +98,28 @@ func (p *profilesParser) Parse(configPath string, originalRawConfig map[interfac
10098

10199
func fillVariablesAndParse(configPath string, preparedConfig map[interface{}]interface{}, vars []*latest.Variable, resolver variable.Resolver, options *ConfigOptions, log log.Logger) (*latest.Config, error) {
102100
// fill in variables
103-
err := fillVariables(resolver, preparedConfig, vars, options)
101+
preparedConfigInterface, err := resolver.FindAndFillVariables(preparedConfig, vars)
104102
if err != nil {
105103
return nil, err
106104
}
107105

108106
// execute expressions
109-
err = expression.ResolveAllExpressions(preparedConfig, filepath.Dir(configPath))
107+
preparedConfigInterface, err = expression.ResolveAllExpressions(preparedConfigInterface, filepath.Dir(configPath))
110108
if err != nil {
111109
return nil, err
112110
}
113111

114112
// fill in variables again
115-
err = fillVariables(resolver, preparedConfig, vars, options)
113+
preparedConfigInterface, err = resolver.FindAndFillVariables(preparedConfigInterface, vars)
116114
if err != nil {
117115
return nil, err
118116
}
119117

120118
// Now convert the whole config to latest
121-
latestConfig, err := versions.Parse(preparedConfig, log)
119+
latestConfig, err := versions.Parse(preparedConfigInterface.(map[interface{}]interface{}), log)
122120
if err != nil {
123121
return nil, errors.Wrap(err, "convert config")
124122
}
125123

126124
return latestConfig, nil
127125
}
128-
129-
// fillVariables fills in the given vars into the prepared config
130-
func fillVariables(resolver variable.Resolver, preparedConfig map[interface{}]interface{}, vars []*latest.Variable, options *ConfigOptions) error {
131-
// Find out what vars are really used
132-
varsUsed, err := resolver.FindVariables(preparedConfig, vars)
133-
if err != nil {
134-
return err
135-
}
136-
137-
// parse cli --var's, the resolver will cache them for us
138-
_, err = resolver.ConvertFlags(options.Vars)
139-
if err != nil {
140-
return err
141-
}
142-
143-
// Fill used defined variables
144-
if len(vars) > 0 {
145-
newVars := []*latest.Variable{}
146-
for _, v := range vars {
147-
if varsUsed[strings.TrimSpace(v.Name)] {
148-
newVars = append(newVars, v)
149-
}
150-
}
151-
152-
if len(newVars) > 0 {
153-
err = askQuestions(resolver, newVars)
154-
if err != nil {
155-
return err
156-
}
157-
}
158-
}
159-
160-
// Walk over data and fill in variables
161-
err = resolver.FillVariables(preparedConfig)
162-
if err != nil {
163-
return err
164-
}
165-
166-
return nil
167-
}
168-
169-
func askQuestions(resolver variable.Resolver, vars []*latest.Variable) error {
170-
for _, definition := range vars {
171-
name := strings.TrimSpace(definition.Name)
172-
173-
// fill the variable with definition
174-
_, err := resolver.Resolve(name, definition)
175-
if err != nil {
176-
return err
177-
}
178-
}
179-
180-
return nil
181-
}

pkg/devspace/config/loader/variable/resolver.go

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,18 @@ func varMatchFn(key, value string) bool {
3232
return varspkg.VarMatchRegex.MatchString(value)
3333
}
3434

35-
func (r *resolver) FillVariables(haystack map[interface{}]interface{}) error {
36-
err := walk.Walk(haystack, varMatchFn, func(value string) (interface{}, error) {
37-
return r.ReplaceString(value)
38-
})
39-
if err != nil {
40-
return err
35+
func (r *resolver) FillVariables(haystack interface{}) (interface{}, error) {
36+
switch t := haystack.(type) {
37+
case string:
38+
return r.ReplaceString(t)
39+
case map[interface{}]interface{}:
40+
err := walk.Walk(t, varMatchFn, func(value string) (interface{}, error) {
41+
return r.ReplaceString(value)
42+
})
43+
return t, err
4144
}
4245

43-
return nil
46+
return nil, fmt.Errorf("unrecognized haystack type: %#v", haystack)
4447
}
4548

4649
func (r *resolver) ResolvedVariables() map[string]interface{} {
@@ -58,19 +61,28 @@ func (r *resolver) ReplaceString(str string) (interface{}, error) {
5861
})
5962
}
6063

61-
func (r *resolver) FindVariables(haystack map[interface{}]interface{}, vars []*latest.Variable) (map[string]bool, error) {
64+
func (r *resolver) FindVariables(haystack interface{}, vars []*latest.Variable) (map[string]bool, error) {
6265
// find out what vars are really used
6366
varsUsed := map[string]bool{}
64-
err := walk.Walk(haystack, varMatchFn, func(value string) (interface{}, error) {
65-
_, _ = varspkg.ParseString(value, func(v string) (interface{}, error) {
67+
68+
switch t := haystack.(type) {
69+
case string:
70+
_, _ = varspkg.ParseString(t, func(v string) (interface{}, error) {
6671
varsUsed[v] = true
6772
return "", nil
6873
})
74+
case map[interface{}]interface{}:
75+
err := walk.Walk(t, varMatchFn, func(value string) (interface{}, error) {
76+
_, _ = varspkg.ParseString(value, func(v string) (interface{}, error) {
77+
varsUsed[v] = true
78+
return "", nil
79+
})
6980

70-
return value, nil
71-
})
72-
if err != nil {
73-
return nil, err
81+
return value, nil
82+
})
83+
if err != nil {
84+
return nil, err
85+
}
7486
}
7587

7688
// find out what vars are used within other vars definition
@@ -84,6 +96,37 @@ func (r *resolver) FindVariables(haystack map[interface{}]interface{}, vars []*l
8496
return varsUsed, nil
8597
}
8698

99+
func (r *resolver) FindAndFillVariables(haystack interface{}, vars []*latest.Variable) (interface{}, error) {
100+
varsUsed, err := r.FindVariables(haystack, vars)
101+
if err != nil {
102+
return nil, err
103+
}
104+
105+
// resolve used defined variables
106+
if len(vars) > 0 {
107+
newVars := []*latest.Variable{}
108+
for _, v := range vars {
109+
if varsUsed[strings.TrimSpace(v.Name)] {
110+
newVars = append(newVars, v)
111+
}
112+
}
113+
114+
if len(newVars) > 0 {
115+
for _, definition := range newVars {
116+
name := strings.TrimSpace(definition.Name)
117+
118+
// resolve the variable with definition
119+
_, err := r.Resolve(name, definition)
120+
if err != nil {
121+
return nil, err
122+
}
123+
}
124+
}
125+
}
126+
127+
return r.FillVariables(haystack)
128+
}
129+
87130
func (r *resolver) ConvertFlags(flags []string) (map[string]interface{}, error) {
88131
retVariables := map[string]interface{}{}
89132
for _, cmdVar := range flags {

pkg/devspace/config/loader/variable/types.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ type Resolver interface {
1616
ConvertFlags(flags []string) (map[string]interface{}, error)
1717

1818
// FindVariables returns all variable names that were found in the given map
19-
FindVariables(haystack map[interface{}]interface{}, vars []*latest.Variable) (map[string]bool, error)
19+
FindVariables(haystack interface{}, vars []*latest.Variable) (map[string]bool, error)
2020

21-
// FillVariables walks over the haystack and replaces all encountered variables
22-
FillVariables(haystack map[interface{}]interface{}) error
21+
// FindAndFillVariables finds the used variables first and then fills in those in the haystack
22+
FindAndFillVariables(haystack interface{}, vars []*latest.Variable) (interface{}, error)
2323

2424
// Replaces all variables in a string and returns either a string, integer or boolean
2525
ReplaceString(str string) (interface{}, error)

0 commit comments

Comments
 (0)