Skip to content

Commit c0897a4

Browse files
committed
pkg/kube: require namespace in Ctl.List
`client.Client` and `kube.Ctl` treated `namespace` (`client.InNamespace`) as an optional parameter. If not provided, it default to `"default"`. This parameter has been missed multiple times across various places in our codebase and resulted in latent errors, often because tests utilised the default namespace. This commit changes the signature of `Ctl.List` to require a `namespace string` parameter to make it impossible to forget. It additionally adds it to a few places (lifecycle client) that it was previously forgotten.
1 parent 5619ffb commit c0897a4

File tree

11 files changed

+70
-29
lines changed

11 files changed

+70
-29
lines changed

charts/console/chart/client_test.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,7 @@ func NewClient(ctx context.Context, kubeCtl *kube.Ctl, dot *helmette.Dot) (*Clie
7272
}
7373

7474
func (c *Client) getConsolePod(ctx context.Context) (*corev1.Pod, error) {
75-
deploys, err := kube.List[appsv1.DeploymentList](ctx, c.Ctl,
76-
k8sclient.InNamespace(c.Release.Namespace),
77-
)
75+
deploys, err := kube.List[appsv1.DeploymentList](ctx, c.Ctl, c.Release.Namespace)
7876
if err != nil {
7977
return nil, err
8078
}
@@ -92,7 +90,7 @@ func (c *Client) getConsolePod(ctx context.Context) (*corev1.Pod, error) {
9290
}
9391

9492
pods, err := kube.List[corev1.PodList](ctx, c.Ctl,
95-
k8sclient.InNamespace(deployment.Namespace),
93+
deployment.Namespace,
9694
k8sclient.MatchingLabels(deployment.Spec.Selector.MatchLabels))
9795
if err != nil {
9896
return nil, err

charts/redpanda/chart_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ func TestIntegrationChart(t *testing.T) {
168168
}),
169169
})
170170

171-
pods, err := kube.List[corev1.PodList](ctx, env.Ctl(), client.MatchingLabels{
171+
pods, err := kube.List[corev1.PodList](ctx, env.Ctl(), release.Namespace, client.MatchingLabels{
172172
"app.kubernetes.io/instance": release.Name,
173173
"app.kubernetes.io/component": release.Chart + "-statefulset",
174174
})
@@ -433,7 +433,7 @@ func TestIntegrationChart(t *testing.T) {
433433
}),
434434
})
435435

436-
pods, err := kube.List[corev1.PodList](ctx, env.Ctl(), client.MatchingLabels{
436+
pods, err := kube.List[corev1.PodList](ctx, env.Ctl(), release.Namespace, client.MatchingLabels{
437437
"app.kubernetes.io/instance": release.Name,
438438
"app.kubernetes.io/component": release.Chart + "-statefulset",
439439
})
@@ -473,7 +473,7 @@ func TestIntegrationChart(t *testing.T) {
473473
}),
474474
})
475475

476-
pods, err := kube.List[corev1.PodList](ctx, env.Ctl(), client.MatchingLabels{
476+
pods, err := kube.List[corev1.PodList](ctx, env.Ctl(), release.Namespace, client.MatchingLabels{
477477
"app.kubernetes.io/instance": release.Name,
478478
"app.kubernetes.io/name": "console",
479479
})

charts/redpanda/client/client.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"github.com/twmb/franz-go/pkg/sasl/scram"
2525
"github.com/twmb/franz-go/pkg/sr"
2626
corev1 "k8s.io/api/core/v1"
27-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2827
"sigs.k8s.io/controller-runtime/pkg/client"
2928

3029
"github.com/redpanda-data/redpanda-operator/charts/redpanda/v25"
@@ -328,9 +327,9 @@ func srvLookup(state *redpanda.RenderState, dialer DialContextFunc, service stri
328327
// Querying for k8s-app=kube-dns is a generally accepted / safe
329328
// way of finding the kube DNS. We could alternatively find the
330329
// kube-dns service and use its label selector.
331-
pods, err := kube.List[corev1.PodList](ctx, ctl, client.MatchingLabels{
330+
pods, err := kube.List[corev1.PodList](ctx, ctl, kube.NamespaceSystem, client.MatchingLabels{
332331
"k8s-app": "kube-dns",
333-
}, client.InNamespace(metav1.NamespaceSystem))
332+
})
334333
if err != nil {
335334
return nil, err
336335
}

go.work.sum

Lines changed: 41 additions & 7 deletions
Large diffs are not rendered by default.

operator/internal/controller/vectorized/cluster_controller_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ func normalizeClusterResources(ctx context.Context, testScheme *runtime.Scheme,
275275

276276
clusterSelector := labels.ForCluster(cluster).AsClientSelector()
277277
for _, l := range lists {
278-
err := ctl.List(ctx, l)
278+
err := ctl.List(ctx, cluster.Namespace, l)
279279
if errors.Is(err, &meta.NoKindMatchError{}) {
280280
continue
281281
}

operator/internal/lifecycle/client.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ func (r *ResourceClient[T, U]) DeleteAll(ctx context.Context, owner U) (bool, er
259259

260260
// fetchExistingPools fetches the existing pools (StatefulSets) for a given cluster.
261261
func (r *ResourceClient[T, U]) fetchExistingPools(ctx context.Context, cluster U) ([]*poolWithOrdinals, error) {
262-
sets, err := kube.List[appsv1.StatefulSetList](ctx, r.ctl, client.InNamespace(cluster.GetNamespace()), client.MatchingLabels(r.ownershipResolver.GetOwnerLabels(cluster)))
262+
sets, err := kube.List[appsv1.StatefulSetList](ctx, r.ctl, cluster.GetNamespace(), client.MatchingLabels(r.ownershipResolver.GetOwnerLabels(cluster)))
263263
if err != nil {
264264
return nil, errors.Wrapf(err, "listing StatefulSets")
265265
}
@@ -288,7 +288,7 @@ func (r *ResourceClient[T, U]) fetchExistingPools(ctx context.Context, cluster U
288288
}
289289

290290
// based on https://github.com/kubernetes/kubernetes/blob/c90a4b16b6aa849ed362ee40997327db09e3a62d/pkg/controller/history/controller_history.go#L222
291-
revisions, err := kube.List[appsv1.ControllerRevisionList](ctx, r.ctl, client.MatchingLabelsSelector{
291+
revisions, err := kube.List[appsv1.ControllerRevisionList](ctx, r.ctl, cluster.GetNamespace(), client.MatchingLabelsSelector{
292292
Selector: selector,
293293
})
294294
if err != nil {
@@ -303,7 +303,7 @@ func (r *ResourceClient[T, U]) fetchExistingPools(ctx context.Context, cluster U
303303
}
304304
}
305305

306-
pods, err := kube.List[corev1.PodList](ctx, r.ctl, client.MatchingLabelsSelector{
306+
pods, err := kube.List[corev1.PodList](ctx, r.ctl, cluster.GetNamespace(), client.MatchingLabelsSelector{
307307
Selector: selector,
308308
})
309309
if err != nil {

pkg/kube/ctl.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
corev1 "k8s.io/api/core/v1"
2121
k8serrors "k8s.io/apimachinery/pkg/api/errors"
2222
"k8s.io/apimachinery/pkg/api/meta"
23+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2324
"k8s.io/apimachinery/pkg/runtime"
2425
"k8s.io/apimachinery/pkg/runtime/schema"
2526
"k8s.io/client-go/kubernetes/scheme"
@@ -37,8 +38,11 @@ type (
3738
Object = client.Object
3839
ObjectList = client.ObjectList
3940
ObjectKey = client.ObjectKey
41+
)
4042

41-
InNamespace = client.InNamespace
43+
const (
44+
NamespaceAll = metav1.NamespaceAll
45+
NamespaceSystem = metav1.NamespaceSystem
4246
)
4347

4448
type Option interface {
@@ -164,11 +168,17 @@ func (c *Ctl) GetAndWait(ctx context.Context, key ObjectKey, obj Object, cond Co
164168
}
165169

166170
// List fetches a list of objects into `objs` from Kubernetes.
171+
//
172+
// Cluster scoped resources should pass `""` as namespace.
173+
//
167174
// Usage:
168175
//
169176
// var pods corev1.PodList
170177
// ctl.List(ctx, &pods)
171-
func (c *Ctl) List(ctx context.Context, objs ObjectList, opts ...client.ListOption) error {
178+
func (c *Ctl) List(ctx context.Context, namespace string, objs ObjectList, opts ...client.ListOption) error {
179+
// Top level namespace parameter takes precedence over anything specified
180+
// in opts. The other way around is less straightforward.
181+
opts = append(opts, client.InNamespace(namespace))
172182
if err := c.client.List(ctx, objs, opts...); err != nil {
173183
return errors.WithStack(err)
174184
}

pkg/kube/ctl_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func TestCtl(t *testing.T) {
5050
))
5151
require.Equal(t, []string{"cm-0", "cm-1", "cm-2"}, seen)
5252

53-
cms, err := kube.List[corev1.ConfigMapList](ctx, ctl, kube.InNamespace("hello-world"))
53+
cms, err := kube.List[corev1.ConfigMapList](ctx, ctl, "hello-world")
5454
require.NoError(t, err)
5555
require.Len(t, cms.Items, 3)
5656

pkg/kube/generics.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ func ApplyAndWait[T any, PT AddrOfObject[T]](ctx context.Context, ctl *Ctl, obj
5555
}
5656

5757
// List is a generic equivalent of [Ctl.List].
58-
func List[T any, L AddrOfObjectList[T]](ctx context.Context, ctl *Ctl, opts ...client.ListOption) (*T, error) {
58+
func List[T any, L AddrOfObjectList[T]](ctx context.Context, ctl *Ctl, namespace string, opts ...client.ListOption) (*T, error) {
5959
var list T
60-
if err := ctl.List(ctx, L(&list), opts...); err != nil {
60+
if err := ctl.List(ctx, namespace, L(&list), opts...); err != nil {
6161
return nil, err
6262
}
6363
return &list, nil

pkg/kube/syncer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ func (s *Syncer) listInPurview(ctx context.Context) ([]Object, error) {
170170
return nil, err
171171
}
172172

173-
if err := s.Ctl.List(ctx, list, client.InNamespace(s.Namespace), client.MatchingLabels(s.OwnershipLabels)); err != nil {
173+
if err := s.Ctl.List(ctx, s.Namespace, list, client.MatchingLabels(s.OwnershipLabels)); err != nil {
174174
return nil, err
175175
}
176176

0 commit comments

Comments
 (0)