@@ -17,16 +17,17 @@ limitations under the License.
17
17
package client
18
18
19
19
import (
20
+ "fmt"
20
21
"net/http"
21
22
"strings"
22
23
"sync"
23
24
24
25
"k8s.io/apimachinery/pkg/api/meta"
25
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26
26
"k8s.io/apimachinery/pkg/runtime"
27
27
"k8s.io/apimachinery/pkg/runtime/schema"
28
28
"k8s.io/apimachinery/pkg/runtime/serializer"
29
29
"k8s.io/client-go/rest"
30
+ "k8s.io/utils/ptr"
30
31
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
31
32
)
32
33
@@ -56,13 +57,17 @@ type clientRestResources struct {
56
57
57
58
// newResource maps obj to a Kubernetes Resource and constructs a client for that Resource.
58
59
// If the object is a list, the resource represents the item's type instead.
59
- func (c * clientRestResources ) newResource (gvk schema.GroupVersionKind , isList , isUnstructured bool ) (* resourceMeta , error ) {
60
+ func (c * clientRestResources ) newResource (gvk schema.GroupVersionKind ,
61
+ isList bool ,
62
+ forceDisableProtoBuf bool ,
63
+ isUnstructured bool ,
64
+ ) (* resourceMeta , error ) {
60
65
if strings .HasSuffix (gvk .Kind , "List" ) && isList {
61
66
// if this was a list, treat it as a request for the item's resource
62
67
gvk .Kind = gvk .Kind [:len (gvk .Kind )- 4 ]
63
68
}
64
69
65
- client , err := apiutil .RESTClientForGVK (gvk , isUnstructured , c .config , c .codecs , c .httpClient )
70
+ client , err := apiutil .RESTClientForGVK (gvk , forceDisableProtoBuf , isUnstructured , c .config , c .codecs , c .httpClient )
66
71
if err != nil {
67
72
return nil , err
68
73
}
@@ -73,15 +78,41 @@ func (c *clientRestResources) newResource(gvk schema.GroupVersionKind, isList, i
73
78
return & resourceMeta {Interface : client , mapping : mapping , gvk : gvk }, nil
74
79
}
75
80
81
+ type applyConfiguration interface {
82
+ GetName () * string
83
+ GetNamespace () * string
84
+ GetKind () * string
85
+ GetAPIVersion () * string
86
+ }
87
+
76
88
// getResource returns the resource meta information for the given type of object.
77
89
// If the object is a list, the resource represents the item's type instead.
78
- func (c * clientRestResources ) getResource (obj runtime.Object ) (* resourceMeta , error ) {
79
- gvk , err := apiutil .GVKForObject (obj , c .scheme )
80
- if err != nil {
81
- return nil , err
90
+ func (c * clientRestResources ) getResource (obj any ) (* resourceMeta , error ) {
91
+ var gvk schema.GroupVersionKind
92
+ var err error
93
+ var isApplyConfiguration bool
94
+ switch o := obj .(type ) {
95
+ case runtime.Object :
96
+ gvk , err = apiutil .GVKForObject (o , c .scheme )
97
+ if err != nil {
98
+ return nil , err
99
+ }
100
+ case runtime.ApplyConfiguration :
101
+ ac , ok := o .(applyConfiguration )
102
+ if ! ok {
103
+ return nil , fmt .Errorf ("%T is a runtime.ApplyConfiguration but not an applyConfiguration" , o )
104
+ }
105
+ gvk , err = gvkFromApplyConfiguration (ac )
106
+ if err != nil {
107
+ return nil , err
108
+ }
109
+ isApplyConfiguration = true
110
+ default :
111
+ return nil , fmt .Errorf ("bug: %T is neither a runtime.Object nor a runtime.ApplyConfiguration" , o )
82
112
}
83
113
84
114
_ , isUnstructured := obj .(runtime.Unstructured )
115
+ forceDisableProtoBuf := isUnstructured || isApplyConfiguration
85
116
86
117
// It's better to do creation work twice than to not let multiple
87
118
// people make requests at once
@@ -97,10 +128,15 @@ func (c *clientRestResources) getResource(obj runtime.Object) (*resourceMeta, er
97
128
return r , nil
98
129
}
99
130
131
+ var isList bool
132
+ if runtimeObject , ok := obj .(runtime.Object ); ok && meta .IsListType (runtimeObject ) {
133
+ isList = true
134
+ }
135
+
100
136
// Initialize a new Client
101
137
c .mu .Lock ()
102
138
defer c .mu .Unlock ()
103
- r , err = c .newResource (gvk , meta . IsListType ( obj ) , isUnstructured )
139
+ r , err = c .newResource (gvk , isList , forceDisableProtoBuf , isUnstructured )
104
140
if err != nil {
105
141
return nil , err
106
142
}
@@ -109,16 +145,29 @@ func (c *clientRestResources) getResource(obj runtime.Object) (*resourceMeta, er
109
145
}
110
146
111
147
// getObjMeta returns objMeta containing both type and object metadata and state.
112
- func (c * clientRestResources ) getObjMeta (obj runtime. Object ) (* objMeta , error ) {
148
+ func (c * clientRestResources ) getObjMeta (obj any ) (* objMeta , error ) {
113
149
r , err := c .getResource (obj )
114
150
if err != nil {
115
151
return nil , err
116
152
}
117
- m , err := meta .Accessor (obj )
118
- if err != nil {
119
- return nil , err
153
+ objMeta := & objMeta {resourceMeta : r }
154
+
155
+ switch o := obj .(type ) {
156
+ case runtime.Object :
157
+ m , err := meta .Accessor (obj )
158
+ if err != nil {
159
+ return nil , err
160
+ }
161
+ objMeta .namespace = m .GetNamespace ()
162
+ objMeta .name = m .GetName ()
163
+ case applyConfiguration :
164
+ objMeta .namespace = ptr .Deref (o .GetNamespace (), "" )
165
+ objMeta .name = ptr .Deref (o .GetName (), "" )
166
+ default :
167
+ return nil , fmt .Errorf ("object %T is neither a runtime.Object nor a runtime.ApplyConfiguration" , obj )
120
168
}
121
- return & objMeta {resourceMeta : r , Object : m }, err
169
+
170
+ return objMeta , nil
122
171
}
123
172
124
173
// resourceMeta stores state for a Kubernetes type.
@@ -146,6 +195,6 @@ type objMeta struct {
146
195
// resourceMeta contains type information for the object
147
196
* resourceMeta
148
197
149
- // Object contains meta data for the object instance
150
- metav1. Object
198
+ namespace string
199
+ name string
151
200
}
0 commit comments