Skip to content

Commit dcb644b

Browse files
committed
feat: add hooks output runtime variable
1 parent cf5e5ad commit dcb644b

File tree

9 files changed

+72
-34
lines changed

9 files changed

+72
-34
lines changed

e2e/kube/kube.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ package kube
33
import (
44
"context"
55
"fmt"
6+
"github.com/loft-sh/devspace/pkg/devspace/imageselector"
67
"strings"
78
"time"
89

910
"github.com/loft-sh/devspace/pkg/devspace/kubectl"
1011
"github.com/loft-sh/devspace/pkg/devspace/services/targetselector"
11-
"github.com/loft-sh/devspace/pkg/util/imageselector"
1212
"github.com/loft-sh/devspace/pkg/util/log"
1313
"github.com/loft-sh/devspace/pkg/util/randutil"
1414
corev1 "k8s.io/api/core/v1"

pkg/devspace/config/loader/loader_test.go

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,13 +1291,12 @@ deployments:
12911291
- name: deployment
12921292
helm:
12931293
componentChart: true
1294-
values:
1295-
containers:
1296-
- image: nginx
1294+
valuesFiles:
1295+
- test.yaml
12971296
profiles:
12981297
- name: testprofile
12991298
patches:
1300-
- path: deployments..image
1299+
- path: deployments..valuesFiles[0]
13011300
op: replace
13021301
value: $(echo ubuntu)
13031302
`,
@@ -1314,12 +1313,8 @@ profiles:
13141313
Name: "deployment",
13151314
Helm: &latest.HelmConfig{
13161315
ComponentChart: ptr.Bool(true),
1317-
Values: map[interface{}]interface{}{
1318-
"containers": []interface{}{
1319-
map[interface{}]interface{}{
1320-
"image": "ubuntu",
1321-
},
1322-
},
1316+
ValuesFiles: []string{
1317+
"ubuntu",
13231318
},
13241319
},
13251320
},
@@ -1420,7 +1415,7 @@ profiles:
14201415
Values: map[interface{}]interface{}{
14211416
"containers": []interface{}{
14221417
map[interface{}]interface{}{
1423-
"image": "ubuntu",
1418+
"image": "${IMAGE_B}",
14241419
},
14251420
},
14261421
},
@@ -1440,18 +1435,17 @@ deployments:
14401435
- name: deployment
14411436
helm:
14421437
componentChart: true
1443-
values:
1444-
containers:
1445-
- image: nginx
1438+
valuesFiles:
1439+
- test.yaml
14461440
profiles:
14471441
- name: A
14481442
patches:
1449-
- path: deployments..image
1443+
- path: deployments..valuesFiles[0]
14501444
op: replace
14511445
value: $(echo ${IMAGE_A})
14521446
- name: B
14531447
patches:
1454-
- path: deployments..image
1448+
- path: deployments..valuesFiles[0]
14551449
op: replace
14561450
value: $(echo ${IMAGE_B})
14571451
`,
@@ -1466,12 +1460,8 @@ profiles:
14661460
Name: "deployment",
14671461
Helm: &latest.HelmConfig{
14681462
ComponentChart: ptr.Bool(true),
1469-
Values: map[interface{}]interface{}{
1470-
"containers": []interface{}{
1471-
map[interface{}]interface{}{
1472-
"image": "ubuntu",
1473-
},
1474-
},
1463+
ValuesFiles: []string{
1464+
"ubuntu",
14751465
},
14761466
},
14771467
},
@@ -2052,7 +2042,7 @@ profiles:
20522042
- name: A
20532043
activation:
20542044
- vars:
2055-
USE_A: true
2045+
USE_A: "true"
20562046
patches:
20572047
- path: deployments..image
20582048
op: replace
@@ -2104,7 +2094,7 @@ profiles:
21042094
- name: A
21052095
activation:
21062096
- vars:
2107-
USE_A: true
2097+
USE_A: "true"
21082098
patches:
21092099
- path: deployments..image
21102100
op: replace

pkg/devspace/config/loader/parser.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,14 @@ func (p *profilesParser) Parse(originalRawConfig map[interface{}]interface{}, ra
9797
func fillVariablesAndParse(resolver variable.Resolver, preparedConfig map[interface{}]interface{}, log log.Logger) (*latest.Config, error) {
9898
// fill in variables and expressions (leave out
9999
preparedConfigInterface, err := resolver.FillVariablesExclude(preparedConfig, []string{
100-
//"/deployments/*/helm/values",
100+
"/deployments/*/helm/values/**",
101+
"/hooks/*/command",
102+
"/hooks/*/args/*",
103+
"/hooks/*/container/imageSelector",
104+
"/dev/ports/*/imageSelector",
105+
"/dev/sync/*/imageSelector",
106+
"/dev/logs/*/selectors/*/imageSelector",
107+
"/dev/terminal/imageSelector",
101108
})
102109
if err != nil {
103110
return nil, err

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,20 @@ func ResolveAllExpressions(preparedConfig interface{}, dir string, exclude []*re
4646
return nil, err
4747
}
4848

49+
return t, nil
50+
case []interface{}:
51+
for i := range t {
52+
var err error
53+
t[i], err = ResolveAllExpressions(t[i], dir, exclude)
54+
if err != nil {
55+
return nil, err
56+
}
57+
}
58+
4959
return t, nil
5060
}
5161

52-
return nil, fmt.Errorf("unrecognized haystack type: %#v", preparedConfig)
62+
return preparedConfig, nil
5363
}
5464

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

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,19 @@ func (r *resolver) fillVariables(haystack interface{}, exclude []*regexp.Regexp)
5858
return r.replaceString(value)
5959
})
6060
return t, err
61+
case []interface{}:
62+
for i := range t {
63+
var err error
64+
t[i], err = r.fillVariables(t[i], exclude)
65+
if err != nil {
66+
return nil, err
67+
}
68+
}
69+
70+
return t, nil
6171
}
6272

63-
return nil, fmt.Errorf("unrecognized haystack type: %#v", haystack)
73+
return haystack, nil
6474
}
6575

6676
func (r *resolver) ResolvedVariables() map[string]interface{} {
@@ -117,6 +127,7 @@ func (r *resolver) FillVariablesExclude(haystack interface{}, excludedPaths []st
117127
paths := []*regexp.Regexp{}
118128
for _, path := range excludedPaths {
119129
path = strings.Replace(path, "*", "[^/]+", -1)
130+
path = strings.Replace(path, "**", ".+", -1)
120131
path = "^" + path
121132
expr, err := regexp.Compile(path)
122133
if err != nil {

pkg/devspace/config/loader/variable/runtime/runtime_resolver.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,5 +133,5 @@ func (r *runtimeResolver) fillRuntimeVariable(name string, config config.Config,
133133
return NewRuntimeVariable(name, config, dependencies, builtImages).Load()
134134
}
135135

136-
return false, nil, fmt.Errorf("cannot resolve variable %s as it is not a runtime variable and apparently wasn't resolved earlier")
136+
return false, nil, fmt.Errorf("cannot resolve variable %s as it is not a runtime variable and apparently wasn't resolved earlier", name)
137137
}

pkg/devspace/deploy/deployer/kubectl/walk/walk_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ test2:
3030
match := MatchFn(func(key, value string) bool {
3131
return key == "image" && value != "dontreplaceme"
3232
})
33-
replace := ReplaceFn(func(value string) (interface{}, error) {
33+
replace := ReplaceFn(func(_, value string) (interface{}, error) {
3434
if value == "appendtag" {
3535
return "appendtag:test", nil
3636
}

pkg/devspace/hook/local_command.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package hook
22

33
import (
4+
"bytes"
45
"encoding/json"
56
runtimevar "github.com/loft-sh/devspace/pkg/devspace/config/loader/variable/runtime"
67
"io"
@@ -55,12 +56,21 @@ func (l *localCommandHook) Execute(hook *latest.HookConfig, client kubectl.Clien
5556
}
5657

5758
// if args are nil we execute the command in a shell
59+
stdout := &bytes.Buffer{}
60+
stderr := &bytes.Buffer{}
61+
defer func() {
62+
if hook.Name != "" {
63+
config.SetRuntimeVariable("hooks."+hook.Name+".stdout", stdout.String())
64+
config.SetRuntimeVariable("hooks."+hook.Name+".stderr", stderr.String())
65+
}
66+
}()
67+
5868
if hook.Args == nil {
59-
return shell.ExecuteShellCommand(hookCommand, nil, dir, l.Stdout, l.Stderr, extraEnv)
69+
return shell.ExecuteShellCommand(hookCommand, nil, dir, io.MultiWriter(l.Stdout, stdout), io.MultiWriter(l.Stderr, stderr), extraEnv)
6070
}
6171

6272
// else we execute it directly
63-
return command.ExecuteCommandWithEnv(hookCommand, hookArgs, dir, l.Stdout, l.Stderr, extraEnv)
73+
return command.ExecuteCommandWithEnv(hookCommand, hookArgs, dir, io.MultiWriter(l.Stdout, stdout), io.MultiWriter(l.Stderr, stderr), extraEnv)
6474
}
6575

6676
func ResolveCommand(command string, args []string, config config.Config, dependencies []types.Dependency) (string, []string, error) {

pkg/devspace/hook/remote_command.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,23 @@ func (r *remoteCommandHook) ExecuteRemotely(hook *latest.HookConfig, podContaine
5757
}
5858
}
5959

60+
// if args are nil we execute the command in a shell
61+
stdout := &bytes.Buffer{}
62+
stderr := &bytes.Buffer{}
63+
defer func() {
64+
if hook.Name != "" {
65+
config.SetRuntimeVariable("hooks."+hook.Name+".stdout", stdout.String())
66+
config.SetRuntimeVariable("hooks."+hook.Name+".stderr", stderr.String())
67+
}
68+
}()
69+
6070
log.Infof("Execute hook '%s' in container '%s/%s/%s'", ansi.Color(hookName(hook), "white+b"), podContainer.Pod.Namespace, podContainer.Pod.Name, podContainer.Container.Name)
6171
err = client.ExecStream(&kubectl.ExecStreamOptions{
6272
Pod: podContainer.Pod,
6373
Container: podContainer.Container.Name,
6474
Command: cmd,
65-
Stdout: r.Stdout,
66-
Stderr: r.Stderr,
75+
Stdout: io.MultiWriter(r.Stdout, stdout),
76+
Stderr: io.MultiWriter(r.Stderr, stderr),
6777
})
6878
if err != nil {
6979
return errors.Errorf("error in container '%s/%s/%s': %v", podContainer.Pod.Namespace, podContainer.Pod.Name, podContainer.Container.Name, err)

0 commit comments

Comments
 (0)