Skip to content

Commit 3ac3267

Browse files
committed
pkg/k8s: make generic typed interface client namespace aware when dealing with input resources
1 parent 685940d commit 3ac3267

6 files changed

Lines changed: 39 additions & 28 deletions

File tree

cmd/atc/flight_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func TestFlightInstance(t *testing.T) {
3434
client, err := k8s.NewClientFromKubeConfig(home.Kubeconfig)
3535
require.NoError(t, err)
3636

37-
flightIntf := k8s.TypedInterface[v1alpha1.Flight](client.Dynamic, v1alpha1.FlightGVR()).Namespace("default")
37+
flightIntf := k8s.TypedInterface[v1alpha1.Flight](client, v1alpha1.FlightGVR()).Namespace("default")
3838

3939
toJSONString := func(t *testing.T, value any) string {
4040
var buffer bytes.Buffer
@@ -132,7 +132,7 @@ func TestFlightCrossNamespace(t *testing.T) {
132132
client, err := k8s.NewClientFromKubeConfig(home.Kubeconfig)
133133
require.NoError(t, err)
134134

135-
flightIntf := k8s.TypedInterface[v1alpha1.Flight](client.Dynamic, v1alpha1.FlightGVR()).Namespace("default")
135+
flightIntf := k8s.TypedInterface[v1alpha1.Flight](client, v1alpha1.FlightGVR()).Namespace("default")
136136

137137
_, err = flightIntf.Create(
138138
context.Background(),
@@ -144,7 +144,7 @@ func TestFlightCrossNamespace(t *testing.T) {
144144
)
145145
require.ErrorContains(t, err, "Multiple namespaces detected (if desired enable multinamespace releases)")
146146

147-
clusterFlightIntf := k8s.TypedInterface[v1alpha1.ClusterFlight](client.Dynamic, v1alpha1.ClusterFlightGVR())
147+
clusterFlightIntf := k8s.TypedInterface[v1alpha1.ClusterFlight](client, v1alpha1.ClusterFlightGVR())
148148

149149
// Crossnamespace depends on "foo" and "bar"
150150
for _, ns := range []string{"foo", "bar"} {
@@ -205,7 +205,7 @@ func TestFlightInputObject(t *testing.T) {
205205
client, err := k8s.NewClientFromKubeConfig(home.Kubeconfig)
206206
require.NoError(t, err)
207207

208-
flightIntf := k8s.TypedInterface[v1alpha1.Flight](client.Dynamic, v1alpha1.FlightGVR()).Namespace("default")
208+
flightIntf := k8s.TypedInterface[v1alpha1.Flight](client, v1alpha1.FlightGVR()).Namespace("default")
209209

210210
flight, err := flightIntf.Create(
211211
context.Background(),
@@ -261,7 +261,7 @@ func TestFlightValidationWebhook(t *testing.T) {
261261
client, err := k8s.NewClientFromKubeConfig(home.Kubeconfig)
262262
require.NoError(t, err)
263263

264-
flightIntf := k8s.TypedInterface[v1alpha1.Flight](client.Dynamic, v1alpha1.FlightGVR()).Namespace("default")
264+
flightIntf := k8s.TypedInterface[v1alpha1.Flight](client, v1alpha1.FlightGVR()).Namespace("default")
265265

266266
_, err = flightIntf.Create(
267267
context.Background(),
@@ -282,7 +282,7 @@ func TestNotAllowedFlightWasmURL(t *testing.T) {
282282
client, err := k8s.NewClientFromKubeConfig(home.Kubeconfig)
283283
require.NoError(t, err)
284284

285-
flightIntf := k8s.TypedInterface[v1alpha1.Flight](client.Dynamic, v1alpha1.FlightGVR()).Namespace("default")
285+
flightIntf := k8s.TypedInterface[v1alpha1.Flight](client, v1alpha1.FlightGVR()).Namespace("default")
286286

287287
_, err = flightIntf.Create(
288288
context.Background(),
@@ -299,7 +299,7 @@ func TestFlightInvalidChecksum(t *testing.T) {
299299
client, err := k8s.NewClientFromKubeConfig(home.Kubeconfig)
300300
require.NoError(t, err)
301301

302-
flightIntf := k8s.TypedInterface[v1alpha1.Flight](client.Dynamic, v1alpha1.FlightGVR()).Namespace("default")
302+
flightIntf := k8s.TypedInterface[v1alpha1.Flight](client, v1alpha1.FlightGVR()).Namespace("default")
303303

304304
// Create the flight initially so that we can warm the cache.
305305
// Otherwise it'll behave different when we run this test alone versus with the rest of the test suite.
@@ -405,7 +405,7 @@ func TestFlightCodeSigning(t *testing.T) {
405405
Insecure: true,
406406
}))
407407

408-
flightIntf := k8s.TypedInterface[v1alpha1.Flight](client.Dynamic, v1alpha1.FlightGVR()).Namespace("default")
408+
flightIntf := k8s.TypedInterface[v1alpha1.Flight](client, v1alpha1.FlightGVR()).Namespace("default")
409409

410410
_, err = flightIntf.Create(
411411
context.Background(),

cmd/atc/main_test.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,7 +1056,7 @@ func TestClusterScopeDynamicAirway(t *testing.T) {
10561056
require.NoError(t, client.EnsureNamespace(context.Background(), ns))
10571057
}
10581058

1059-
testIntf := k8s.TypedInterface[EmptyCRD](client.Dynamic, schema.GroupVersionResource{
1059+
testIntf := k8s.TypedInterface[EmptyCRD](client, schema.GroupVersionResource{
10601060
Group: "examples.com",
10611061
Version: "v1",
10621062
Resource: "tests",
@@ -2219,7 +2219,7 @@ func TestDynamicWithExternalResource(t *testing.T) {
22192219
configMapIntf := client.Clientset.CoreV1().ConfigMaps("default")
22202220

22212221
backendIntf := k8s.
2222-
TypedInterface[EmptyCRD](client.Dynamic, schema.GroupVersionResource{
2222+
TypedInterface[EmptyCRD](client, schema.GroupVersionResource{
22232223
Group: "examples.com",
22242224
Version: "v1",
22252225
Resource: "backends",
@@ -2383,7 +2383,7 @@ func TestExternalDynamicCreateEvent(t *testing.T) {
23832383
configmapIntf := client.Clientset.CoreV1().ConfigMaps("default")
23842384

23852385
cloneIntf := k8s.
2386-
TypedInterface[CopyJob](client.Dynamic, schema.GroupVersionResource{
2386+
TypedInterface[CopyJob](client, schema.GroupVersionResource{
23872387
Group: "examples.com",
23882388
Version: "v1",
23892389
Resource: "clones",
@@ -2544,7 +2544,7 @@ func TestStatusUpdates(t *testing.T) {
25442544
Resource: "backends",
25452545
}
25462546

2547-
backendIntf := k8s.TypedInterface[CR](client.Dynamic, backendGVR).Namespace("default")
2547+
backendIntf := k8s.TypedInterface[CR](client, backendGVR).Namespace("default")
25482548

25492549
cases := []struct {
25502550
Name string
@@ -2783,7 +2783,7 @@ func TestDeploymentStatus(t *testing.T) {
27832783
Resource: "backends",
27842784
}
27852785

2786-
backendIntf := k8s.TypedInterface[CR](client.Dynamic, backendGVR).Namespace("default")
2786+
backendIntf := k8s.TypedInterface[CR](client, backendGVR).Namespace("default")
27872787

27882788
be := &CR{
27892789
TypeMeta: metav1.TypeMeta{
@@ -3311,7 +3311,7 @@ func TestTimeout(t *testing.T) {
33113311
}()
33123312

33133313
timeoutIntf := k8s.
3314-
TypedInterface[EmptyCRD](client.Dynamic, schema.GroupVersionResource{
3314+
TypedInterface[EmptyCRD](client, schema.GroupVersionResource{
33153315
Group: "examples.com",
33163316
Version: "v1",
33173317
Resource: "timeouts",
@@ -3403,7 +3403,7 @@ func TestSubscriptionMode(t *testing.T) {
34033403
)
34043404
}()
34053405

3406-
subIntf := k8s.TypedInterface[EmptyCRD](client.Dynamic, schema.GroupVersionResource{
3406+
subIntf := k8s.TypedInterface[EmptyCRD](client, schema.GroupVersionResource{
34073407
Group: "example.com",
34083408
Version: "v1",
34093409
Resource: "subscriptions",
@@ -3568,7 +3568,7 @@ func TestValidationCycle(t *testing.T) {
35683568

35693569
require.NoError(t, client.EnsureNamespace(context.Background(), "foo"))
35703570

3571-
backendIntf := k8s.TypedInterface[backendv1.Backend](client.Dynamic, schema.GroupVersionResource{
3571+
backendIntf := k8s.TypedInterface[backendv1.Backend](client, schema.GroupVersionResource{
35723572
Resource: "backends",
35733573
Group: "examples.com",
35743574
Version: "v1",
@@ -3682,7 +3682,7 @@ func TestIdentityWithError(t *testing.T) {
36823682
Version: "v1",
36833683
}
36843684

3685-
testIntf := k8s.TypedInterface[CR](client.Dynamic, testGVR).Namespace("default")
3685+
testIntf := k8s.TypedInterface[CR](client, testGVR).Namespace("default")
36863686

36873687
test, err := testIntf.Create(
36883688
context.Background(),
@@ -3798,7 +3798,7 @@ func TestInvalidFlightURL(t *testing.T) {
37983798
Resource: "backends",
37993799
}
38003800

3801-
backendIntf := k8s.TypedInterface[backendv1.Backend](client.Dynamic, backendGVR).Namespace("default")
3801+
backendIntf := k8s.TypedInterface[backendv1.Backend](client, backendGVR).Namespace("default")
38023802

38033803
be, err := backendIntf.Create(
38043804
context.Background(),
@@ -3890,7 +3890,7 @@ func TestInvalidChecksum(t *testing.T) {
38903890
Resource: "backends",
38913891
}
38923892

3893-
backendIntf := k8s.TypedInterface[backendv1.Backend](client.Dynamic, backendGVR).Namespace("default")
3893+
backendIntf := k8s.TypedInterface[backendv1.Backend](client, backendGVR).Namespace("default")
38943894

38953895
be, err := backendIntf.Create(
38963896
context.Background(),

internal/atc/reconciler_flight.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func flightReconciler(modules *cache.ModuleCache, clusterScope bool) ctrl.Funcs
5555
var (
5656
client = (*k8s.Client)(ctrl.Client(ctx))
5757
commander = yoke.FromK8Client(client)
58-
flightIntf = k8s.TypedInterface[AltFlight](client.Dynamic, gvr).Namespace(evt.Namespace)
58+
flightIntf = k8s.TypedInterface[AltFlight](client, gvr).Namespace(evt.Namespace)
5959
flightCache = ctrl.CacheFromEvent[AltFlight](ctx, evt)
6060
)
6161

internal/k8s/client.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func (c TypedIntf[T]) Get(ctx context.Context, name string, options metav1.GetOp
3636
}
3737
var result T
3838
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &result); err != nil {
39-
return nil, fmt.Errorf("failed to convert unstructerd value to typed api: %w", err)
39+
return nil, fmt.Errorf("failed to convert unstructured value to typed api: %w", err)
4040
}
4141
return &result, nil
4242
}
@@ -46,6 +46,9 @@ func (c TypedIntf[T]) Create(ctx context.Context, api *T, options metav1.CreateO
4646
if err != nil {
4747
return nil, fmt.Errorf("failed to convert typed api to unstructured object: %w", err)
4848
}
49+
if ns := obj.GetNamespace(); ns != "" {
50+
c = c.Namespace(ns)
51+
}
4952
obj, err = c.getIntf().Create(ctx, obj, options)
5053
if err != nil {
5154
return nil, err
@@ -62,6 +65,9 @@ func (c TypedIntf[T]) Update(ctx context.Context, api *T, options metav1.UpdateO
6265
if err != nil {
6366
return nil, fmt.Errorf("failed to convert typed api to unstructured object: %w", err)
6467
}
68+
if ns := obj.GetNamespace(); ns != "" {
69+
c = c.Namespace(ns)
70+
}
6571
obj, err = c.getIntf().Update(ctx, obj, options)
6672
if err != nil {
6773
return nil, err
@@ -78,6 +84,9 @@ func (c TypedIntf[T]) Apply(ctx context.Context, api *T, options metav1.ApplyOpt
7884
if err != nil {
7985
return nil, fmt.Errorf("failed to convert typed api to unstructured object: %w", err)
8086
}
87+
if ns := obj.GetNamespace(); ns != "" {
88+
c = c.Namespace(ns)
89+
}
8190
obj, err = c.getIntf().Apply(ctx, obj.GetName(), obj, options)
8291
if err != nil {
8392
return nil, err
@@ -94,6 +103,9 @@ func (c TypedIntf[T]) UpdateStatus(ctx context.Context, api *T, options metav1.U
94103
if err != nil {
95104
return nil, fmt.Errorf("failed to convert typed api to unstructured object: %w", err)
96105
}
106+
if ns := obj.GetNamespace(); ns != "" {
107+
c = c.Namespace(ns)
108+
}
97109
obj, err = c.getIntf().UpdateStatus(ctx, obj, options)
98110
if err != nil {
99111
return nil, err
@@ -130,9 +142,9 @@ type MetaObject[T any] interface {
130142
metav1.Object
131143
}
132144

133-
func TypedInterface[T any, obj MetaObject[T]](client *dynamic.DynamicClient, resource schema.GroupVersionResource) TypedIntf[T] {
145+
func TypedInterface[T any, obj MetaObject[T]](client *Client, resource schema.GroupVersionResource) TypedIntf[T] {
134146
return TypedIntf[T]{
135-
intf: client.Resource(resource),
147+
intf: client.Dynamic.Resource(resource),
136148
ns: "",
137149
}
138150
}

internal/k8s/k8s.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ type Client struct {
5151
DefaultNamespace string
5252
}
5353

54-
func (client Client) AirwayIntf() TypedIntf[v1alpha1.Airway] {
55-
return TypedInterface[v1alpha1.Airway](client.Dynamic, v1alpha1.AirwayGVR())
54+
func (client *Client) AirwayIntf() TypedIntf[v1alpha1.Airway] {
55+
return TypedInterface[v1alpha1.Airway](client, v1alpha1.AirwayGVR())
5656
}
5757

5858
func NewClientFromConfigFlags(cfgFlags *genericclioptions.ConfigFlags) (*Client, error) {

pkg/k8s/client.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
88
"k8s.io/apimachinery/pkg/runtime"
99
"k8s.io/apimachinery/pkg/runtime/schema"
10-
"k8s.io/client-go/dynamic"
1110
"k8s.io/client-go/rest"
1211

1312
"github.com/yokecd/yoke/internal/k8s"
@@ -30,8 +29,8 @@ type TypedIntf[T any] = k8s.TypedIntf[T]
3029
// TypedInterface returns a typed wrapper over the client-go dynamic client.
3130
//
3231
// TODO: once go1.27 is out and generic functions are added this should become a method of the standard client.
33-
func TypedInterface[T any, obj k8s.MetaObject[T]](client *dynamic.DynamicClient, resource schema.GroupVersionResource) TypedIntf[T] {
34-
return k8s.TypedInterface[T, obj](client, resource)
32+
func TypedInterface[T any, obj k8s.MetaObject[T]](client *Client, resource schema.GroupVersionResource) TypedIntf[T] {
33+
return k8s.TypedInterface[T, obj]((*k8s.Client)(client), resource)
3534
}
3635

3736
type WaitOptions = k8s.WaitOptions

0 commit comments

Comments
 (0)