Skip to content

Commit 0798f0c

Browse files
committed
fix: fix variable loading
1 parent 2846221 commit 0798f0c

16 files changed

Lines changed: 182 additions & 80 deletions

File tree

cmd/deploy.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package cmd
33
import (
44
"context"
55
"fmt"
6-
76
"github.com/loft-sh/devspace/cmd/flags"
87
"github.com/loft-sh/devspace/pkg/devspace/analyze"
98
"github.com/loft-sh/devspace/pkg/devspace/build"

cmd/root.go

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
package cmd
22

33
import (
4+
"context"
45
"flag"
6+
"fmt"
7+
"github.com/loft-sh/devspace/pkg/devspace/config/loader"
8+
"github.com/loft-sh/devspace/pkg/devspace/config/versions/latest"
9+
"github.com/loft-sh/devspace/pkg/devspace/env"
10+
"github.com/loft-sh/devspace/pkg/util/log"
11+
"github.com/loft-sh/devspace/pkg/util/message"
512
"io/ioutil"
613
"os"
714
"strings"
15+
"sync"
816
"time"
917

1018
"github.com/loft-sh/devspace/pkg/devspace/hook"
@@ -157,6 +165,14 @@ func BuildRoot(f factory.Factory, excludePlugins bool) *cobra.Command {
157165
plugin.SetPlugins(plugins)
158166
}
159167

168+
// try to parse the raw config
169+
rawConfig, err := parseConfig(f)
170+
if err != nil {
171+
f.GetLog().Debugf("error parsing raw config: %v", err)
172+
} else {
173+
env.GlobalGetEnv = rawConfig.GetEnv
174+
}
175+
160176
// build the root cmd
161177
rootCmd := NewRootCmd(f)
162178
rootCmd.SetHelpCommand(&cobra.Command{
@@ -232,7 +248,7 @@ Additional run commands:
232248
rootCmd.AddCommand(NewLogsCmd(f, globalFlags))
233249
rootCmd.AddCommand(NewOpenCmd(f, globalFlags))
234250
rootCmd.AddCommand(NewUICmd(f, globalFlags))
235-
rootCmd.AddCommand(NewRunCmd(f, globalFlags))
251+
rootCmd.AddCommand(NewRunCmd(f, globalFlags, rawConfig))
236252
rootCmd.AddCommand(NewAttachCmd(f, globalFlags))
237253
rootCmd.AddCommand(NewPrintCmd(f, globalFlags))
238254
rootCmd.AddCommand(NewCompletionCmd())
@@ -254,3 +270,96 @@ func disableKlog() {
254270
_ = flagSet.Set("logtostderr", "false")
255271
klogv2.SetOutput(ioutil.Discard)
256272
}
273+
274+
func parseConfig(f factory.Factory) (*RawConfig, error) {
275+
// get current working dir
276+
cwd, err := os.Getwd()
277+
if err != nil {
278+
return nil, err
279+
}
280+
281+
// set working dir back to original
282+
defer func() { _ = os.Chdir(cwd) }()
283+
284+
// Set config root
285+
configLoader, err := f.NewConfigLoader("")
286+
if err != nil {
287+
return nil, err
288+
}
289+
configExists, err := configLoader.SetDevSpaceRoot(log.Discard)
290+
if err != nil {
291+
return nil, err
292+
} else if !configExists {
293+
return nil, errors.New(message.ConfigNotFound)
294+
}
295+
296+
// Parse commands
297+
timeoutCtx, cancel := context.WithTimeout(context.Background(), time.Second*10)
298+
defer cancel()
299+
300+
r := &RawConfig{}
301+
_, err = configLoader.LoadWithParser(timeoutCtx, nil, nil, r, &loader.ConfigOptions{Dry: true}, log.Discard)
302+
if err != nil {
303+
return nil, err
304+
}
305+
306+
return r, nil
307+
}
308+
309+
type RawConfig struct {
310+
Ctx context.Context
311+
OriginalRawConfig map[string]interface{}
312+
RawConfig map[string]interface{}
313+
Resolver variable.Resolver
314+
315+
resolvedMutex sync.Mutex
316+
resolved map[string]string
317+
}
318+
319+
func (r *RawConfig) Parse(
320+
ctx context.Context,
321+
originalRawConfig map[string]interface{},
322+
rawConfig map[string]interface{},
323+
resolver variable.Resolver,
324+
log log.Logger,
325+
) (*latest.Config, map[string]interface{}, error) {
326+
r.Ctx = ctx
327+
r.OriginalRawConfig = originalRawConfig
328+
r.RawConfig = rawConfig
329+
r.Resolver = resolver
330+
return nil, nil, fmt.Errorf("error parsing")
331+
}
332+
333+
func (r *RawConfig) GetEnv(name string) string {
334+
// try to get from environment
335+
value := os.Getenv(name)
336+
if value != "" {
337+
return value
338+
}
339+
340+
// try to find devspace variable
341+
if r.Resolver != nil {
342+
r.resolvedMutex.Lock()
343+
defer r.resolvedMutex.Unlock()
344+
345+
// cache which ones were tried
346+
value, ok := r.resolved[name]
347+
if ok {
348+
return value
349+
}
350+
351+
varName := "${" + name + "}"
352+
out, err := r.Resolver.FillVariables(r.Ctx, varName)
353+
if err == nil {
354+
value := fmt.Sprintf("%v", out)
355+
if value != varName && value != "" {
356+
r.resolved[name] = value
357+
return value
358+
}
359+
}
360+
361+
r.resolved[name] = ""
362+
}
363+
364+
return ""
365+
}

cmd/run.go

Lines changed: 26 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,23 @@ import (
55
"fmt"
66
"github.com/loft-sh/devspace/pkg/devspace/config"
77
devspacecontext "github.com/loft-sh/devspace/pkg/devspace/context"
8+
"github.com/loft-sh/devspace/pkg/devspace/hook"
89
"github.com/loft-sh/devspace/pkg/devspace/pipeline/engine"
910
"github.com/loft-sh/devspace/pkg/util/command"
1011
"github.com/loft-sh/devspace/pkg/util/exit"
12+
"github.com/loft-sh/devspace/pkg/util/log"
1113
"io"
1214
"mvdan.cc/sh/v3/interp"
1315
"os"
1416
"strings"
1517

16-
"github.com/loft-sh/devspace/pkg/devspace/hook"
17-
1818
"github.com/loft-sh/devspace/pkg/devspace/config/loader"
19-
"github.com/loft-sh/devspace/pkg/devspace/config/versions/latest"
2019
"github.com/loft-sh/devspace/pkg/devspace/plugin"
2120

2221
"github.com/loft-sh/devspace/cmd/flags"
2322
"github.com/loft-sh/devspace/pkg/devspace/dependency"
2423
"github.com/loft-sh/devspace/pkg/util/factory"
2524
flagspkg "github.com/loft-sh/devspace/pkg/util/flags"
26-
"github.com/loft-sh/devspace/pkg/util/log"
2725
"github.com/loft-sh/devspace/pkg/util/message"
2826
"github.com/sirupsen/logrus"
2927

@@ -41,7 +39,7 @@ type RunCmd struct {
4139
}
4240

4341
// NewRunCmd creates a new run command
44-
func NewRunCmd(f factory.Factory, globalFlags *flags.GlobalFlags) *cobra.Command {
42+
func NewRunCmd(f factory.Factory, globalFlags *flags.GlobalFlags, rawConfig *RawConfig) *cobra.Command {
4543
cmd := &RunCmd{
4644
GlobalFlags: globalFlags,
4745
Stdout: os.Stdout,
@@ -103,29 +101,32 @@ devspace --dependency my-dependency run any-command --any-command-flag
103101
},
104102
}
105103

106-
commands, _ := getCommands(f)
107-
for _, command := range commands {
108-
description := command.Description
109-
if description == "" {
110-
description = "Runs command: " + command.Command
111-
}
112-
if len(description) > 64 {
113-
if len(description) > 64 {
114-
description = description[:61] + "..."
104+
if rawConfig != nil {
105+
latest, _, _ := loader.NewCommandsParser().Parse(rawConfig.Ctx, rawConfig.OriginalRawConfig, rawConfig.RawConfig, rawConfig.Resolver, log.Discard)
106+
if latest != nil {
107+
for _, cmd := range latest.Commands {
108+
description := cmd.Description
109+
if description == "" {
110+
description = "Runs command: " + cmd.Command
111+
}
112+
if len(description) > 64 {
113+
if len(description) > 64 {
114+
description = description[:61] + "..."
115+
}
116+
}
117+
runCmd.AddCommand(&cobra.Command{
118+
Use: cmd.Name,
119+
Short: description,
120+
Long: description,
121+
Args: cobra.ArbitraryArgs,
122+
DisableFlagParsing: true,
123+
RunE: func(cobraCmd *cobra.Command, args []string) error {
124+
return cobraCmd.Parent().RunE(cobraCmd, args)
125+
},
126+
})
115127
}
116128
}
117-
runCmd.AddCommand(&cobra.Command{
118-
Use: command.Name,
119-
Short: description,
120-
Long: description,
121-
Args: cobra.ArbitraryArgs,
122-
DisableFlagParsing: true,
123-
RunE: func(cobraCmd *cobra.Command, args []string) error {
124-
return cobraCmd.Parent().RunE(cobraCmd, args)
125-
},
126-
})
127129
}
128-
129130
runCmd.Flags().StringVar(&cmd.Dependency, "dependency", "", "Run a command from a specific dependency")
130131
return runCmd
131132
}
@@ -256,34 +257,3 @@ func ExecuteConfigCommand(ctx context.Context, config config.Config, name string
256257
shellArgs = append(shellArgs, args...)
257258
return command.CommandWithEnv(ctx, dir, stdout, stderr, stdin, extraEnv, shellCommand, shellArgs...)
258259
}
259-
260-
func getCommands(f factory.Factory) (map[string]*latest.CommandConfig, error) {
261-
// get current working dir
262-
cwd, err := os.Getwd()
263-
if err != nil {
264-
return nil, err
265-
}
266-
267-
// set working dir back to original
268-
defer func() { _ = os.Chdir(cwd) }()
269-
270-
// Set config root
271-
configLoader, err := f.NewConfigLoader("")
272-
if err != nil {
273-
return nil, err
274-
}
275-
configExists, err := configLoader.SetDevSpaceRoot(log.Discard)
276-
if err != nil {
277-
return nil, err
278-
}
279-
if !configExists {
280-
return nil, errors.New(message.ConfigNotFound)
281-
}
282-
283-
// Parse commands
284-
commandsInterface, err := configLoader.LoadWithParser(context.Background(), nil, nil, loader.NewCommandsParser(), &loader.ConfigOptions{Dry: true}, log.Discard)
285-
if err != nil {
286-
return nil, err
287-
}
288-
return commandsInterface.Config().Commands, nil
289-
}

cmd/sync.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ devspace sync --container-path=/my-path
7878
RunE: func(cobraCmd *cobra.Command, args []string) error {
7979
// Print upgrade message if new version available
8080
upgrade.PrintUpgradeMessage()
81-
8281
plugin.SetPluginCommand(cobraCmd, args)
8382
return cmd.Run(f)
8483
},

examples/pipelines/devspace.yaml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ version: v2beta1
22
name: pipelines
33

44
vars:
5-
MELLO: $(echo ${DELLO})
6-
DELLO: ${MELLO}-${CHELLO}
7-
HELLO: ${devspace.namespace}-${DELLO}
5+
HELLO: ${devspace.namespace}
86

97
pipelines:
108
dev:
119
steps:
1210
- run: |-
13-
echo "Hello World!"
11+
echo "${HELLO} ${DEVSPACE_NAMESPACE}"

pkg/devspace/config/loader/loader.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ func (l *configLoader) LoadWithParser(ctx context.Context, localCache localcache
144144
if !ok {
145145
return nil, fmt.Errorf("name is missing in " + filepath.Base(l.absConfigPath))
146146
}
147+
} else {
148+
data["name"] = options.OverrideName
147149
}
148150

149151
// create remote cache

pkg/devspace/config/loader/parser.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@ import (
1212
)
1313

1414
type Parser interface {
15-
Parse(ctx context.Context, originalRawConfig map[string]interface{}, rawConfig map[string]interface{}, resolver variable.Resolver, log log.Logger) (*latest.Config, map[string]interface{}, error)
15+
Parse(
16+
ctx context.Context,
17+
originalRawConfig map[string]interface{},
18+
rawConfig map[string]interface{},
19+
resolver variable.Resolver,
20+
log log.Logger,
21+
) (*latest.Config, map[string]interface{}, error)
1622
}
1723

1824
func NewDefaultParser() Parser {

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

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func (r *resolver) FindVariables(haystack interface{}) ([]*latest.Variable, erro
129129

130130
// filter out runtime environment variables
131131
for k := range varsUsed {
132-
if r.vars[k] == nil || IsPredefinedVariable(k) || strings.HasPrefix(k, "runtime.") {
132+
if !strings.HasPrefix(k, "runtime.") && !IsPredefinedVariable(k) && r.vars[k] == nil {
133133
delete(varsUsed, k)
134134
}
135135
}
@@ -141,10 +141,17 @@ func (r *resolver) orderVariables(vars map[string]bool) ([]*latest.Variable, err
141141
root := graph.NewNode("root", nil)
142142
g := graph.NewGraphOf(root, "variable")
143143
for name := range vars {
144-
// check if has definition
145-
definition, ok := r.vars[name]
146-
if !ok {
147-
continue
144+
// check if predefined variable
145+
var definition *latest.Variable
146+
if IsPredefinedVariable(name) {
147+
definition = &latest.Variable{Name: name}
148+
} else {
149+
// check if has definition
150+
var ok bool
151+
definition, ok = r.vars[name]
152+
if !ok {
153+
continue
154+
}
148155
}
149156

150157
err := r.insertVariableGraph(g, definition)
@@ -381,7 +388,7 @@ func (r *resolver) findVariablesInDefinition(definition *latest.Variable) map[st
381388

382389
// filter out runtime environment variables and non existing ones
383390
for k := range varsUsed {
384-
if r.vars[k] == nil || IsPredefinedVariable(k) || strings.HasPrefix(k, "runtime.") {
391+
if !strings.HasPrefix(k, "runtime.") && !IsPredefinedVariable(k) && r.vars[k] == nil {
385392
delete(varsUsed, k)
386393
}
387394
}

pkg/devspace/config/localcache/schema.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package localcache
33
import (
44
"encoding/base64"
55
"fmt"
6+
"github.com/loft-sh/devspace/pkg/devspace/env"
67
"github.com/loft-sh/devspace/pkg/util/encryption"
78
"gopkg.in/yaml.v3"
89
"io/ioutil"
@@ -191,7 +192,7 @@ func (l *LocalCache) Save() error {
191192
}
192193

193194
// encrypt variables
194-
if os.Getenv(DevSpaceDisableVarsEncryptionEnv) != "true" && EncryptionKey != "" {
195+
if env.GlobalGetEnv(DevSpaceDisableVarsEncryptionEnv) != "true" && EncryptionKey != "" {
195196
for k, v := range copiedConfig.Vars {
196197
if len(v) == 0 {
197198
continue

0 commit comments

Comments
 (0)