Skip to content

Commit 515c591

Browse files
authored
Merge pull request #2614 from 89luca89/main
fix: ensure namespaces during dependencies resolution
2 parents 0e19ee2 + f929ced commit 515c591

File tree

6 files changed

+103
-41
lines changed

6 files changed

+103
-41
lines changed

e2e/framework/helper.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,21 @@ func ExpectEmpty(actual interface{}, explain ...interface{}) {
6262
gomega.ExpectWithOffset(1, actual).To(gomega.BeEmpty(), explain...)
6363
}
6464

65+
func ExpectNamespace(namespace string) {
66+
kubeClient, err := kube.NewKubeHelper()
67+
ExpectNoErrorWithOffset(1, err)
68+
69+
err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) {
70+
ns, err := kubeClient.Client().KubeClient().CoreV1().Namespaces().Get(context.TODO(), namespace, metav1.GetOptions{})
71+
if err != nil {
72+
return false, nil
73+
}
74+
75+
return ns.Name == namespace, nil
76+
})
77+
ExpectNoErrorWithOffset(1, err)
78+
}
79+
6580
func ExpectRemoteFileContents(imageSelector string, namespace string, filePath string, contents string) {
6681
kubeClient, err := kube.NewKubeHelper()
6782
ExpectNoErrorWithOffset(1, err)

e2e/tests/dependencies/dependencies.go

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ package dependencies
33
import (
44
"bytes"
55
"context"
6-
ginkgo "github.com/onsi/ginkgo/v2"
7-
"github.com/onsi/gomega"
8-
"github.com/sirupsen/logrus"
96
"os"
107
"path/filepath"
118
"time"
129

10+
ginkgo "github.com/onsi/ginkgo/v2"
11+
"github.com/onsi/gomega"
12+
"github.com/sirupsen/logrus"
13+
1314
"github.com/loft-sh/devspace/pkg/devspace/config/versions/latest"
1415
dependencyutil "github.com/loft-sh/devspace/pkg/devspace/dependency/util"
1516
"github.com/loft-sh/devspace/pkg/devspace/kubectl/selector"
@@ -208,6 +209,47 @@ dep2dep2wait
208209
framework.ExpectEqual(len(list.Items), 0)
209210
})
210211

212+
ginkgo.It("should deploy dependency in custom namespace", func() {
213+
tempDir, err := framework.CopyToTempDir("tests/dependencies/testdata/namespace")
214+
framework.ExpectNoError(err)
215+
defer framework.CleanupTempDir(initialDir, tempDir)
216+
217+
depNamespace := "custon"
218+
219+
ns, err := kubeClient.CreateNamespace("dependencies")
220+
framework.ExpectNoError(err)
221+
defer func() {
222+
err := kubeClient.DeleteNamespace(ns)
223+
framework.ExpectNoError(err)
224+
err = kubeClient.DeleteNamespace(depNamespace)
225+
framework.ExpectNoError(err)
226+
}()
227+
228+
// create a new dev command and start it
229+
cancelCtx, cancel := context.WithCancel(context.Background())
230+
defer cancel()
231+
232+
os.Setenv("DEP1_NAMESPACE", depNamespace)
233+
defer os.Unsetenv("DEP1_NAMESPACE")
234+
devCmd := &cmd.RunPipelineCmd{
235+
GlobalFlags: &flags.GlobalFlags{
236+
NoWarn: true,
237+
Namespace: ns,
238+
},
239+
Pipeline: "dev",
240+
Ctx: cancelCtx,
241+
}
242+
err = devCmd.RunDefault(f)
243+
framework.ExpectNoError(err)
244+
cancel()
245+
246+
// now check if nonExistentNs got created
247+
framework.ExpectNamespace(depNamespace)
248+
249+
framework.ExpectNoError(err)
250+
251+
})
252+
211253
ginkgo.It("should deploy git dependency", func() {
212254
tempDir, err := framework.CopyToTempDir("tests/dependencies/testdata/git")
213255
framework.ExpectNoError(err)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
version: v1beta10
2+
deployments:
3+
- name: nginx
4+
helm:
5+
componentChart: true
6+
values:
7+
containers:
8+
- image: nginx
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
version: v2beta1
2+
vars:
3+
DEP1_NAMESPACE:
4+
source: env
5+
default: false
6+
deployments:
7+
nginx:
8+
helm:
9+
values:
10+
containers:
11+
- image: nginx
12+
13+
dependencies:
14+
test-dependency:
15+
path: ./dep1.yaml
16+
namespace: ${DEP1_NAMESPACE}

pkg/devspace/build/localregistry/local_registry.go

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ import (
1414
corev1 "k8s.io/api/core/v1"
1515
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1616
"k8s.io/apimachinery/pkg/util/wait"
17-
applyv1 "k8s.io/client-go/applyconfigurations/core/v1"
18-
19-
kerrors "k8s.io/apimachinery/pkg/api/errors"
2017

2118
"github.com/google/go-containerregistry/pkg/v1/remote"
2219
"github.com/loft-sh/devspace/pkg/devspace/kubectl"
@@ -176,41 +173,7 @@ func (r *LocalRegistry) ensureNamespace(ctx devspacecontext.Context) error {
176173
return nil
177174
}
178175

179-
// Try to get the namespace we need
180-
_, err := ctx.KubeClient().
181-
KubeClient().
182-
CoreV1().
183-
Namespaces().
184-
Get(ctx.Context(), r.Namespace, metav1.GetOptions{})
185-
// Ignore not found errors, but if we have any other type or error, report it
186-
if err != nil && !kerrors.IsNotFound(err) {
187-
return err
188-
}
189-
// And if we don't have errors, it means the namespace already exists.
190-
if err == nil {
191-
ctx.Log().Debugf("Namespace %s already exists, skipping creation", r.Namespace)
192-
return nil
193-
}
194-
195-
ctx.Log().Debugf("Namespace %s doesn't exist, attempting creation", r.Namespace)
196-
applyConfiguration, err := applyv1.ExtractNamespace(&corev1.Namespace{
197-
ObjectMeta: metav1.ObjectMeta{
198-
Name: r.Namespace,
199-
},
200-
}, ApplyFieldManager)
201-
if err != nil {
202-
return err
203-
}
204-
205-
_, err = ctx.KubeClient().KubeClient().CoreV1().Namespaces().Apply(
206-
ctx.Context(),
207-
applyConfiguration,
208-
metav1.ApplyOptions{
209-
FieldManager: ApplyFieldManager,
210-
Force: true,
211-
},
212-
)
213-
return err
176+
return kubectl.EnsureNamespace(ctx.Context(), ctx.KubeClient(), r.Namespace, ctx.Log())
214177
}
215178

216179
func (r *LocalRegistry) SelectRegistryPod(ctx devspacecontext.Context) (*corev1.Pod, error) {

pkg/devspace/pipeline/pipeline.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,17 @@ func (p *pipeline) StartNewDependencies(ctx devspacecontext.Context, dependencie
257257
return t.Wait()
258258
}
259259

260+
func ensureNamespace(ctx devspacecontext.Context, namespace string) error {
261+
// If localregistry namespace is the same as devspace, we don't have
262+
// anything to do.
263+
if namespace == ctx.KubeClient().Namespace() || namespace == "" {
264+
ctx.Log().Debugf("Namespace %s is the default Devspace namespace", namespace)
265+
return nil
266+
}
267+
268+
return kubectl.EnsureNamespace(ctx.Context(), ctx.KubeClient(), namespace, ctx.Log())
269+
}
270+
260271
func waitForDependency(ctx context.Context, start types.Pipeline, dependencyName string, log log.Logger) {
261272
// get top level pipeline
262273
for start.Parent() != nil {
@@ -373,6 +384,13 @@ func (p *pipeline) startNewDependency(ctx devspacecontext.Context, dependency ty
373384
pipelineConfig *latest.Pipeline
374385
err error
375386
)
387+
388+
// Ensure dependency namespace exists
389+
err = ensureNamespace(ctx, dependency.DependencyConfig().Namespace)
390+
if err != nil {
391+
return errors.Wrapf(err, "cannot run dependency %s", dependency.Name())
392+
}
393+
376394
if dependency.Config().Config().Pipelines == nil || dependency.Config().Config().Pipelines[executePipeline] == nil {
377395
pipelineConfig, err = types.GetDefaultPipeline(executePipeline)
378396
if err != nil {

0 commit comments

Comments
 (0)