Skip to content

Commit c8ed769

Browse files
authored
Merge pull request #2051 from tukobadnyanoba/add-set-flag
Added --set and --set-string flags to run_pipelines and run_default_pipeline commands along with e2e tests
2 parents 21f818f + 1e702e3 commit c8ed769

7 files changed

Lines changed: 192 additions & 1 deletion

File tree

e2e/framework/helper.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package framework
22

33
import (
4+
"context"
45
"fmt"
56
"github.com/go-resty/resty/v2"
67
"github.com/loft-sh/devspace/e2e/kube"
78
"github.com/onsi/gomega"
89
"github.com/pkg/errors"
910
"io/ioutil"
11+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1012
"k8s.io/apimachinery/pkg/util/wait"
1113
"os"
1214
"strings"
@@ -86,6 +88,21 @@ func ExpectLocalCurlContents(urlString string, contents string) {
8688
ExpectNoErrorWithOffset(1, err)
8789
}
8890

91+
func ExpectContainerNameAndImageEqual(namespace, deploymentName, containerImage, containerName string) {
92+
kubeClient, err := kube.NewKubeHelper()
93+
ExpectNoErrorWithOffset(1, err)
94+
err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) {
95+
deploy, err := kubeClient.RawClient().AppsV1().Deployments(namespace).Get(context.TODO(),
96+
deploymentName, metav1.GetOptions{})
97+
if err != nil {
98+
return false, nil
99+
}
100+
return deploy.Spec.Template.Spec.Containers[0].Name == containerName &&
101+
deploy.Spec.Template.Spec.Containers[0].Image == containerImage, nil
102+
})
103+
ExpectNoErrorWithOffset(1, err)
104+
}
105+
89106
func ExpectRemoteCurlContents(imageSelector string, namespace string, urlString string, contents string) {
90107
kubeClient, err := kube.NewKubeHelper()
91108
ExpectNoErrorWithOffset(1, err)

e2e/tests/pipelines/pipelines.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,76 @@ var _ = DevSpaceDescribe("pipelines", func() {
120120
}
121121
})
122122

123+
ginkgo.It("should use --set and --set-string values from run_pipelines command", func() {
124+
tempDir, err := framework.CopyToTempDir("tests/pipelines/testdata/run_pipelines")
125+
framework.ExpectNoError(err)
126+
defer framework.CleanupTempDir(initialDir, tempDir)
127+
128+
ns, err := kubeClient.CreateNamespace("pipelines")
129+
framework.ExpectNoError(err)
130+
defer framework.ExpectDeleteNamespace(kubeClient, ns)
131+
132+
done := make(chan error)
133+
cancelCtx, cancel := context.WithCancel(context.Background())
134+
defer cancel()
135+
136+
go func() {
137+
defer ginkgo.GinkgoRecover()
138+
devCmd := &cmd.RunPipelineCmd{
139+
GlobalFlags: &flags.GlobalFlags{
140+
NoWarn: true,
141+
Namespace: ns,
142+
ConfigPath: "devspace.yaml",
143+
},
144+
Pipeline: "dev",
145+
Ctx: cancelCtx,
146+
}
147+
done <- devCmd.RunDefault(f)
148+
}()
149+
150+
// check if deployments are there
151+
framework.ExpectContainerNameAndImageEqual(ns, "dev", "nginx", "mynginx")
152+
153+
cancel()
154+
err = <-done
155+
framework.ExpectNoError(err)
156+
})
157+
158+
ginkgo.It("should use --set and --set-string values from run_default_pipeline command", func() {
159+
tempDir, err := framework.CopyToTempDir("tests/pipelines/testdata/run_default_pipeline")
160+
framework.ExpectNoError(err)
161+
defer framework.CleanupTempDir(initialDir, tempDir)
162+
163+
ns, err := kubeClient.CreateNamespace("pipelines")
164+
framework.ExpectNoError(err)
165+
defer framework.ExpectDeleteNamespace(kubeClient, ns)
166+
167+
done := make(chan error)
168+
cancelCtx, cancel := context.WithCancel(context.Background())
169+
defer cancel()
170+
171+
go func() {
172+
defer ginkgo.GinkgoRecover()
173+
devCmd := &cmd.RunPipelineCmd{
174+
GlobalFlags: &flags.GlobalFlags{
175+
NoWarn: true,
176+
Namespace: ns,
177+
ConfigPath: "devspace.yaml",
178+
},
179+
Pipeline: "dev",
180+
Ctx: cancelCtx,
181+
}
182+
done <- devCmd.RunDefault(f)
183+
}()
184+
185+
// check if deployments are there
186+
framework.ExpectContainerNameAndImageEqual(ns, "dev", "nginx", "mynginx")
187+
188+
cancel()
189+
err = <-done
190+
framework.ExpectNoError(err)
191+
})
192+
123193
ginkgo.It("should get value from config", func() {
124194
tempDir, err := framework.CopyToTempDir("tests/pipelines/testdata/getconfigvalue")
125195
framework.ExpectNoError(err)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
version: v2beta1
2+
name: run-pipelines-demo
3+
4+
pipelines:
5+
dev: |-
6+
run_default_pipeline deploy --set deployments.dev.helm.values.containers[0].image=nginx --set-string deployments.dev.helm.values.containers[0].name=mynginx
7+
8+
deployments:
9+
dev:
10+
helm:
11+
values:
12+
containers:
13+
- image: alpine
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
version: v2beta1
2+
name: run-pipelines-demo
3+
4+
pipelines:
5+
dev: |-
6+
run_pipelines deploy --set deployments.dev.helm.values.containers[0].image=nginx --set-string deployments.dev.helm.values.containers[0].name=mynginx
7+
deploy: |-
8+
create_deployments --all
9+
10+
deployments:
11+
dev:
12+
helm:
13+
values:
14+
containers:
15+
- image: alpine

pkg/devspace/pipeline/engine/pipelinehandler/commands/create_deployments.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ func applySetValues(ctx devspacecontext.Context, name, objName string, set, setS
147147
continue
148148
}
149149

150-
err = strvals.ParseInto(s, mapObj)
150+
err = strvals.ParseIntoString(s, mapObj)
151151
if err != nil {
152152
return nil, errors.Wrap(err, "parsing --set-string flag")
153153
}

pkg/devspace/pipeline/engine/pipelinehandler/commands/run_default_pipeline.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,25 @@ package commands
22

33
import (
44
"fmt"
5+
"github.com/jessevdk/go-flags"
6+
"github.com/loft-sh/devspace/pkg/devspace/config"
7+
"github.com/loft-sh/devspace/pkg/devspace/config/versions"
8+
"github.com/loft-sh/devspace/pkg/devspace/config/versions/util"
59
devspacecontext "github.com/loft-sh/devspace/pkg/devspace/context"
610
"github.com/loft-sh/devspace/pkg/devspace/pipeline/engine"
711
enginetypes "github.com/loft-sh/devspace/pkg/devspace/pipeline/engine/types"
812
"github.com/loft-sh/devspace/pkg/devspace/pipeline/types"
13+
"github.com/loft-sh/devspace/pkg/util/strvals"
14+
"github.com/pkg/errors"
915
"io"
1016
"mvdan.cc/sh/v3/interp"
1117
)
1218

19+
type RunDefaultPipelineOptions struct {
20+
Set []string `long:"set" description:"Set configuration"`
21+
SetString []string `long:"set-string" description:"Set configuration as string"`
22+
}
23+
1324
type NewHandlerFn func(ctx devspacecontext.Context, stdout, stderr io.Writer, pipeline types.Pipeline) enginetypes.ExecHandler
1425

1526
func RunDefaultPipeline(ctx devspacecontext.Context, pipeline types.Pipeline, args []string, newHandler NewHandlerFn) error {
@@ -19,10 +30,24 @@ func RunDefaultPipeline(ctx devspacecontext.Context, pipeline types.Pipeline, ar
1930
}
2031

2132
hc := interp.HandlerCtx(ctx.Context())
33+
34+
options := &RunDefaultPipelineOptions{}
35+
args, err = flags.ParseArgs(options, args)
36+
if err != nil {
37+
return errors.Wrap(err, "parse args")
38+
}
39+
2240
if len(args) != 1 {
2341
return fmt.Errorf("usage: run_default_pipeline [pipeline]")
2442
}
2543

44+
if len(args) > 0 {
45+
ctx, err = applyPipelineSetValue(ctx, options.Set, options.SetString)
46+
if err != nil {
47+
return err
48+
}
49+
}
50+
2651
defaultPipeline, err := types.GetDefaultPipeline(args[0])
2752
if err != nil {
2853
return err
@@ -31,3 +56,45 @@ func RunDefaultPipeline(ctx devspacecontext.Context, pipeline types.Pipeline, ar
3156
_, err = engine.ExecutePipelineShellCommand(ctx.Context(), defaultPipeline.Run, nil, hc.Dir, false, hc.Stdout, hc.Stderr, hc.Stdin, hc.Env, newHandler(ctx, hc.Stdout, hc.Stderr, pipeline))
3257
return err
3358
}
59+
60+
func applyPipelineSetValue(ctx devspacecontext.Context, set, setString []string) (devspacecontext.Context, error) {
61+
if len(set) == 0 && len(setString) == 0 {
62+
return ctx, nil
63+
}
64+
65+
rawConfigOriginal := ctx.Config().RawBeforeConversion()
66+
rawConfig := map[string]interface{}{}
67+
err := util.Convert(rawConfigOriginal, &rawConfig)
68+
if err != nil {
69+
return nil, err
70+
}
71+
72+
for _, s := range set {
73+
err = strvals.ParseInto(s, rawConfig)
74+
if err != nil {
75+
return nil, errors.Wrap(err, "parsing --set flag")
76+
}
77+
}
78+
79+
for _, s := range setString {
80+
err = strvals.ParseIntoString(s, rawConfig)
81+
if err != nil {
82+
return nil, errors.Wrap(err, "parsing --set-string flag")
83+
}
84+
}
85+
86+
latestConfig, err := versions.Parse(rawConfig, ctx.Log())
87+
if err != nil {
88+
return nil, err
89+
}
90+
91+
return ctx.WithConfig(config.NewConfig(
92+
ctx.Config().Raw(),
93+
rawConfig,
94+
latestConfig,
95+
ctx.Config().LocalCache(),
96+
ctx.Config().RemoteCache(),
97+
ctx.Config().Variables(),
98+
ctx.Config().Path(),
99+
)), nil
100+
}

pkg/devspace/pipeline/engine/pipelinehandler/commands/run_pipelines.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313

1414
type RunPipelineOptions struct {
1515
types.PipelineOptions
16+
Set []string `long:"set" description:"Set configuration"`
17+
SetString []string `long:"set-string" description:"Set configuration as string"`
1618
}
1719

1820
func RunPipelines(ctx devspacecontext.Context, pipeline types.Pipeline, args []string, environ expand.Environ) error {
@@ -23,6 +25,13 @@ func RunPipelines(ctx devspacecontext.Context, pipeline types.Pipeline, args []s
2325
return errors.Wrap(err, "parse args")
2426
}
2527

28+
if len(args) > 0 {
29+
ctx, err = applyPipelineSetValue(ctx, options.Set, options.SetString)
30+
if err != nil {
31+
return err
32+
}
33+
}
34+
2635
pipelines := []*latest.Pipeline{}
2736
for _, arg := range args {
2837
if arg == "" {

0 commit comments

Comments
 (0)