Skip to content

Commit 6970ad9

Browse files
authored
Merge pull request #187 from snasovich/fix-rancher-35656
Fixed distinct namespaces resolution in Apply
2 parents a8647af + e7a1862 commit 6970ad9

File tree

2 files changed

+84
-6
lines changed

2 files changed

+84
-6
lines changed

pkg/apply/desiredset_process.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ func (o *desiredSet) process(debugID string, set labels.Selector, gvk schema.Gro
251251

252252
reconciler := o.reconcilers[gvk]
253253

254-
existing, err := o.list(nsed, controller, client, set)
254+
existing, err := o.list(nsed, controller, client, set, objs)
255255
if err != nil {
256256
o.err(errors.Wrapf(err, "failed to list %s for %s", gvk, debugID))
257257
return
@@ -338,19 +338,22 @@ func (o *desiredSet) process(debugID string, set labels.Selector, gvk schema.Gro
338338
}
339339
}
340340

341-
func (o *desiredSet) list(namespaced bool, informer cache.SharedIndexInformer, client dynamic.NamespaceableResourceInterface, selector labels.Selector) (map[objectset.ObjectKey]runtime.Object, error) {
341+
func (o *desiredSet) list(namespaced bool, informer cache.SharedIndexInformer, client dynamic.NamespaceableResourceInterface,
342+
selector labels.Selector, desiredObjects map[objectset.ObjectKey]runtime.Object) (map[objectset.ObjectKey]runtime.Object, error) {
342343
var (
343344
errs []error
344345
objs = map[objectset.ObjectKey]runtime.Object{}
345346
)
346347

347348
if informer == nil {
348-
// if a lister namespace is set assume all objects will belong to the listerNamespace
349+
// if a lister namespace is set assume all objects belong to the listerNamespace
350+
// otherwise use distinct namespaces from the desired objects
351+
// (even if not namespaced as we'll get a single empty namespace in this case which is working OK)
349352
var namespaces []string
350353
if o.listerNamespace != "" {
351354
namespaces = append(namespaces, o.listerNamespace)
352355
} else {
353-
namespaces = o.objs.Namespaces()
356+
namespaces = getDistinctNamespaces(desiredObjects)
354357
}
355358

356359
err := multiNamespaceList(o.ctx, namespaces, client, selector, func(obj unstructured.Unstructured) {
@@ -462,3 +465,23 @@ func multiNamespaceList(ctx context.Context, namespaces []string, baseClient dyn
462465

463466
return wg.Wait()
464467
}
468+
469+
func getDistinctNamespaces(objs map[objectset.ObjectKey]runtime.Object) (namespaces []string) {
470+
for objKey, _ := range objs {
471+
var duplicate bool
472+
for i := range namespaces {
473+
if namespaces[i] == objKey.Namespace {
474+
duplicate = true
475+
break
476+
}
477+
}
478+
479+
if duplicate {
480+
continue
481+
}
482+
483+
namespaces = append(namespaces, objKey.Namespace)
484+
}
485+
486+
return
487+
}

pkg/apply/desiredset_process_test.go

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@ package apply
33
import (
44
"context"
55
"errors"
6+
"strings"
7+
"testing"
8+
9+
"github.com/rancher/wrangler/pkg/objectset"
610
"github.com/stretchr/testify/assert"
711
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
812
"k8s.io/apimachinery/pkg/labels"
913
"k8s.io/apimachinery/pkg/runtime"
1014
"k8s.io/apimachinery/pkg/runtime/schema"
1115
"k8s.io/client-go/dynamic/fake"
1216
k8stesting "k8s.io/client-go/testing"
13-
"strings"
14-
"testing"
1517
)
1618

1719
func Test_multiNamespaceList(t *testing.T) {
@@ -106,3 +108,56 @@ func Test_multiNamespaceList(t *testing.T) {
106108
})
107109
}
108110
}
111+
112+
func TestObjectSet_getDistinctNamespaces(t *testing.T) {
113+
tests := []struct {
114+
name string
115+
objects map[objectset.ObjectKey]runtime.Object
116+
wantNamespaces []string
117+
}{
118+
{
119+
name: "empty",
120+
objects: map[objectset.ObjectKey]runtime.Object{},
121+
wantNamespaces: nil,
122+
},
123+
{
124+
name: "1 namespace",
125+
objects: map[objectset.ObjectKey]runtime.Object{
126+
objectset.ObjectKey{Namespace: "ns1", Name: "a"}: nil,
127+
objectset.ObjectKey{Namespace: "ns1", Name: "b"}: nil,
128+
},
129+
wantNamespaces: []string{"ns1"},
130+
},
131+
{
132+
name: "many namespaces",
133+
objects: map[objectset.ObjectKey]runtime.Object{
134+
objectset.ObjectKey{Namespace: "ns1", Name: "a"}: nil,
135+
objectset.ObjectKey{Namespace: "ns2", Name: "b"}: nil,
136+
},
137+
wantNamespaces: []string{"ns1", "ns2"},
138+
},
139+
{
140+
name: "many namespaces with duplicates",
141+
objects: map[objectset.ObjectKey]runtime.Object{
142+
objectset.ObjectKey{Namespace: "ns1", Name: "a"}: nil,
143+
objectset.ObjectKey{Namespace: "ns2", Name: "b"}: nil,
144+
objectset.ObjectKey{Namespace: "ns1", Name: "c"}: nil,
145+
},
146+
wantNamespaces: []string{"ns1", "ns2"},
147+
},
148+
{
149+
name: "missing namespace",
150+
objects: map[objectset.ObjectKey]runtime.Object{
151+
objectset.ObjectKey{Namespace: "ns1", Name: "a"}: nil,
152+
objectset.ObjectKey{Name: "b"}: nil,
153+
},
154+
wantNamespaces: []string{"", "ns1"},
155+
},
156+
}
157+
for _, tt := range tests {
158+
t.Run(tt.name, func(t *testing.T) {
159+
gotNamespaces := getDistinctNamespaces(tt.objects)
160+
assert.ElementsMatchf(t, tt.wantNamespaces, gotNamespaces, "getDistinctNamespaces() = %v, want %v", gotNamespaces, tt.wantNamespaces)
161+
})
162+
}
163+
}

0 commit comments

Comments
 (0)