Skip to content

Commit deb9a77

Browse files
committed
fix: cyclic dependency deployment
1 parent c8ed769 commit deb9a77

7 files changed

Lines changed: 73 additions & 29 deletions

File tree

e2e/tests/dependencies/dependencies.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,17 +455,43 @@ wait
455455
framework.ExpectEqual(len(list.Items), 0)
456456
})
457457

458-
ginkgo.It("should resolve cyclic dependencies", func() {
458+
ginkgo.It("should resolve and deploy cyclic dependencies", func() {
459459
tempDir, err := framework.CopyToTempDir("tests/dependencies/testdata/cyclic")
460460
framework.ExpectNoError(err)
461461
defer framework.CleanupTempDir(initialDir, tempDir)
462462

463+
ns, err := kubeClient.CreateNamespace("dependencies")
464+
framework.ExpectNoError(err)
465+
defer func() {
466+
err := kubeClient.DeleteNamespace(ns)
467+
framework.ExpectNoError(err)
468+
}()
469+
463470
// load it from the regular path first
464471
_, dependencies, err := framework.LoadConfig(f, kubeClient.Client(), filepath.Join(tempDir, "devspace.yaml"))
465472
framework.ExpectNoError(err)
466473

467474
// check if dependencies were loaded correctly
468475
framework.ExpectEqual(len(dependencies), 1)
469476
framework.ExpectEqual(dependencies[0].Name(), "dependency")
477+
478+
// create a new deploy command
479+
deployCmd := &cmd.RunPipelineCmd{
480+
GlobalFlags: &flags.GlobalFlags{
481+
NoWarn: true,
482+
Namespace: ns,
483+
},
484+
Pipeline: "deploy",
485+
}
486+
487+
// run the command
488+
err = deployCmd.RunDefault(f)
489+
framework.ExpectNoError(err)
490+
491+
// expect single deployment
492+
_, err = kubeClient.RawClient().AppsV1().Deployments(ns).Get(context.TODO(), "nginx", metav1.GetOptions{})
493+
framework.ExpectNoError(err)
494+
_, err = kubeClient.RawClient().AppsV1().Deployments(ns).Get(context.TODO(), "nginx2", metav1.GetOptions{})
495+
framework.ExpectNoError(err)
470496
})
471497
})
Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
1-
version: v1beta11
1+
version: v2beta1
2+
23
dependencies:
3-
- name: root-devspace
4-
source:
5-
path: ../
4+
dependency2:
5+
path: ../dependency2
6+
67
deployments:
7-
- name: nginx
8-
helm:
9-
componentChart: true
10-
values:
11-
containers:
12-
- image: nginx
13-
dev:
14-
ports:
15-
- imageSelector: nginx
16-
forward:
17-
- port: 8080
18-
remotePort: 80
8+
nginx:
9+
helm:
10+
values:
11+
containers:
12+
- image: nginx
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
version: v2beta1
2+
3+
dependencies:
4+
dependency:
5+
path: ../dependency
6+
7+
deployments:
8+
nginx2:
9+
helm:
10+
values:
11+
containers:
12+
- image: nginx
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
version: v1beta11
2+
name: root
3+
24
dependencies:
35
- name: dependency
46
source:
57
path: dependency
6-
dev:
7-
# Open terminal to the pod with the imageName created in dependency1
8-
terminal:
9-
imageSelector: image(dependency.default)

e2e/tests/pipelines/pipelines.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,7 @@ var _ = DevSpaceDescribe("pipelines", func() {
151151
framework.ExpectContainerNameAndImageEqual(ns, "dev", "nginx", "mynginx")
152152

153153
cancel()
154-
err = <-done
155-
framework.ExpectNoError(err)
154+
<-done
156155
})
157156

158157
ginkgo.It("should use --set and --set-string values from run_default_pipeline command", func() {
@@ -186,8 +185,7 @@ var _ = DevSpaceDescribe("pipelines", func() {
186185
framework.ExpectContainerNameAndImageEqual(ns, "dev", "nginx", "mynginx")
187186

188187
cancel()
189-
err = <-done
190-
framework.ExpectNoError(err)
188+
<-done
191189
})
192190

193191
ginkgo.It("should get value from config", func() {

pkg/devspace/dependency/resolver.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,17 @@ type resolver struct {
3939
// NewResolver creates a new resolver for resolving dependencies
4040
func NewResolver(ctx devspacecontext.Context, configOptions *loader.ConfigOptions) ResolverInterface {
4141
return &resolver{
42-
DependencyGraph: graph.NewGraph(graph.NewNode(ctx.Config().Config().Name, &Dependency{name: ctx.Config().Config().Name, root: true})),
42+
DependencyGraph: graph.NewGraph(graph.NewNode(ctx.Config().Config().Name, &Dependency{
43+
name: ctx.Config().Config().Name,
44+
absolutePath: ctx.Config().Path(),
45+
localConfig: ctx.Config(),
46+
dependencyConfig: &latest.DependencyConfig{
47+
Name: ctx.Config().Config().Name,
48+
},
49+
dependencyCache: ctx.Config().LocalCache(),
50+
kubeClient: ctx.KubeClient(),
51+
root: true,
52+
})),
4353

4454
BaseConfig: ctx.Config().Config(),
4555
BaseCache: ctx.Config().LocalCache(),
@@ -96,7 +106,7 @@ func (r *resolver) resolveRecursive(ctx devspacecontext.Context, basePath, paren
96106
)
97107
if n, ok := r.DependencyGraph.Nodes[dependencyConfig.Name]; ok {
98108
child = n.Data.(*Dependency)
99-
if child.Config().Path() != dependencyConfigPath {
109+
if child != nil && child.Config() != nil && child.Config().Path() != dependencyConfigPath {
100110
ctx.Log().Warnf("Seems like you have multiple dependencies with name %s, but they use different source settings (%s != %s). This can lead to unexpected results and you should make sure that the devspace.yaml name is unique across your dependencies or that you use the dependencies.overrideName option", child.name, child.Config().Path(), dependencyConfigPath)
101111
}
102112

pkg/devspace/pipeline/pipeline.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,13 +243,19 @@ func (p *pipeline) StartNewDependencies(ctx devspacecontext.Context, dependencie
243243
}
244244

245245
func waitForDependency(ctx context.Context, start types.Pipeline, dependencyName string, log log.Logger) {
246+
// parents
247+
parents := []string{start.Name()}
248+
246249
// get top level pipeline
247250
for start.Parent() != nil {
248251
start = start.Parent()
252+
parents = append(parents, start.Name())
249253
}
250254

251-
// now traverse through all dependencies
252-
if start.Name() == dependencyName {
255+
// if the dependency is cyclic and already executed
256+
// as a parent, we skip waiting for it as this would
257+
// result in a deadlock.
258+
if stringutil.Contains(parents, dependencyName) {
253259
return
254260
}
255261

0 commit comments

Comments
 (0)