@@ -22,30 +22,44 @@ import (
22
22
"k8s.io/apimachinery/pkg/api/meta"
23
23
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
24
24
"k8s.io/apimachinery/pkg/runtime"
25
+ "k8s.io/apimachinery/pkg/runtime/schema"
26
+ "sigs.k8s.io/controller-runtime/pkg/client/apiutil"
25
27
)
26
28
27
29
// NewDelegatingClientInput encapsulates the input parameters to create a new delegating client.
28
30
type NewDelegatingClientInput struct {
29
- CacheReader Reader
30
- Client Client
31
+ CacheReader Reader
32
+ Client Client
33
+ UncachedObjects []Object
31
34
}
32
35
33
36
// NewDelegatingClient creates a new delegating client.
34
37
//
35
38
// A delegating client forms a Client by composing separate reader, writer and
36
39
// statusclient interfaces. This way, you can have an Client that reads from a
37
40
// cache and writes to the API server.
38
- func NewDelegatingClient (in NewDelegatingClientInput ) Client {
41
+ func NewDelegatingClient (in NewDelegatingClientInput ) (Client , error ) {
42
+ uncachedGVKs := map [schema.GroupVersionKind ]struct {}{}
43
+ for _ , obj := range in .UncachedObjects {
44
+ gvk , err := apiutil .GVKForObject (obj , in .Client .Scheme ())
45
+ if err != nil {
46
+ return nil , err
47
+ }
48
+ uncachedGVKs [gvk ] = struct {}{}
49
+ }
50
+
39
51
return & delegatingClient {
40
52
scheme : in .Client .Scheme (),
41
53
mapper : in .Client .RESTMapper (),
42
54
Reader : & delegatingReader {
43
55
CacheReader : in .CacheReader ,
44
56
ClientReader : in .Client ,
57
+ scheme : in .Client .Scheme (),
58
+ uncachedGVKs : uncachedGVKs ,
45
59
},
46
60
Writer : in .Client ,
47
61
StatusClient : in .Client ,
48
- }
62
+ }, nil
49
63
}
50
64
51
65
type delegatingClient struct {
@@ -75,21 +89,37 @@ func (d *delegatingClient) RESTMapper() meta.RESTMapper {
75
89
type delegatingReader struct {
76
90
CacheReader Reader
77
91
ClientReader Reader
92
+
93
+ uncachedGVKs map [schema.GroupVersionKind ]struct {}
94
+ scheme * runtime.Scheme
95
+ }
96
+
97
+ func (d * delegatingReader ) shouldBypassCache (obj runtime.Object ) (bool , error ) {
98
+ gvk , err := apiutil .GVKForObject (obj , d .scheme )
99
+ if err != nil {
100
+ return false , err
101
+ }
102
+ _ , isUncached := d .uncachedGVKs [gvk ]
103
+ _ , isUnstructured := obj .(* unstructured.Unstructured )
104
+ _ , isUnstructuredList := obj .(* unstructured.UnstructuredList )
105
+ return isUncached || isUnstructured || isUnstructuredList , nil
78
106
}
79
107
80
108
// Get retrieves an obj for a given object key from the Kubernetes Cluster.
81
109
func (d * delegatingReader ) Get (ctx context.Context , key ObjectKey , obj Object ) error {
82
- _ , isUnstructured := obj .(* unstructured.Unstructured )
83
- if isUnstructured {
110
+ if isUncached , err := d .shouldBypassCache (obj ); err != nil {
111
+ return err
112
+ } else if isUncached {
84
113
return d .ClientReader .Get (ctx , key , obj )
85
114
}
86
115
return d .CacheReader .Get (ctx , key , obj )
87
116
}
88
117
89
118
// List retrieves list of objects for a given namespace and list options.
90
119
func (d * delegatingReader ) List (ctx context.Context , list ObjectList , opts ... ListOption ) error {
91
- _ , isUnstructured := list .(* unstructured.UnstructuredList )
92
- if isUnstructured {
120
+ if isUncached , err := d .shouldBypassCache (list ); err != nil {
121
+ return err
122
+ } else if isUncached {
93
123
return d .ClientReader .List (ctx , list , opts ... )
94
124
}
95
125
return d .CacheReader .List (ctx , list , opts ... )
0 commit comments