0
# Dynamic Client Operations
1
2
Generic client for working with any Kubernetes resource without pre-generated classes. Enables operations on custom resources, API discovery, and flexible resource manipulation with runtime type resolution. Ideal for working with resources that may not have static client support.
3
4
## Capabilities
5
6
### Dynamic Client Creation
7
8
Create a dynamic client that can work with any Kubernetes resource by discovering API structure at runtime.
9
10
```python { .api }
11
class DynamicClient:
12
def __init__(
13
self,
14
client: ApiClient,
15
cache_file: str = None,
16
discoverer = None
17
):
18
"""
19
Create dynamic client instance.
20
21
Parameters:
22
- client: Configured ApiClient instance
23
- cache_file: File to cache API discovery information
24
- discoverer: Custom discoverer instance (EagerDiscoverer or LazyDiscoverer)
25
"""
26
```
27
28
### Resource Operations
29
30
Perform CRUD operations on any Kubernetes resource using generic methods.
31
32
```python { .api }
33
class DynamicClient:
34
def get(
35
self,
36
resource: Resource,
37
name: str = None,
38
namespace: str = None,
39
label_selector: str = None,
40
field_selector: str = None,
41
**kwargs
42
) -> ResourceInstance:
43
"""
44
Get resource(s) by name or list all resources.
45
46
Parameters:
47
- resource: Resource definition
48
- name: Resource name (if None, lists all resources)
49
- namespace: Namespace (for namespaced resources)
50
- label_selector: Label selector filter
51
- field_selector: Field selector filter
52
53
Returns:
54
ResourceInstance or ResourceList
55
"""
56
57
def create(
58
self,
59
resource: Resource,
60
body: dict = None,
61
namespace: str = None,
62
**kwargs
63
) -> ResourceInstance:
64
"""
65
Create a new resource.
66
67
Parameters:
68
- resource: Resource definition
69
- body: Resource specification as dictionary
70
- namespace: Namespace (for namespaced resources)
71
72
Returns:
73
Created ResourceInstance
74
"""
75
76
def delete(
77
self,
78
resource: Resource,
79
name: str = None,
80
namespace: str = None,
81
body: dict = None,
82
label_selector: str = None,
83
field_selector: str = None,
84
**kwargs
85
) -> ResourceInstance:
86
"""
87
Delete resource(s).
88
89
Parameters:
90
- resource: Resource definition
91
- name: Resource name (if None, uses selectors)
92
- namespace: Namespace (for namespaced resources)
93
- body: Delete options
94
- label_selector: Label selector for bulk delete
95
- field_selector: Field selector for bulk delete
96
97
Returns:
98
Status or deleted ResourceInstance
99
"""
100
101
def patch(
102
self,
103
resource: Resource,
104
body: dict = None,
105
name: str = None,
106
namespace: str = None,
107
**kwargs
108
) -> ResourceInstance:
109
"""
110
Patch (partially update) a resource.
111
112
Parameters:
113
- resource: Resource definition
114
- body: Patch data as dictionary
115
- name: Resource name
116
- namespace: Namespace (for namespaced resources)
117
118
Returns:
119
Patched ResourceInstance
120
"""
121
122
def replace(
123
self,
124
resource: Resource,
125
body: dict = None,
126
name: str = None,
127
namespace: str = None,
128
**kwargs
129
) -> ResourceInstance:
130
"""
131
Replace (fully update) a resource.
132
133
Parameters:
134
- resource: Resource definition
135
- body: Complete resource specification
136
- name: Resource name
137
- namespace: Namespace (for namespaced resources)
138
139
Returns:
140
Replaced ResourceInstance
141
"""
142
```
143
144
### Resource Discovery
145
146
Discover and access API resources dynamically.
147
148
```python { .api }
149
class DynamicClient:
150
@property
151
def resources(self) -> ResourceRegistry:
152
"""Access to resource registry for API discovery."""
153
154
def ensure_namespace(
155
self,
156
resource: Resource,
157
namespace: str,
158
body: dict
159
) -> dict:
160
"""Ensure namespace is set in resource body if needed."""
161
```
162
163
### API Discovery Classes
164
165
Control how API resources are discovered and cached.
166
167
```python { .api }
168
class EagerDiscoverer:
169
"""Preloads all API resources at initialization for faster access."""
170
def __init__(self, client: ApiClient): ...
171
172
class LazyDiscoverer:
173
"""Discovers API resources on-demand as they are accessed."""
174
def __init__(self, client: ApiClient): ...
175
```
176
177
## Resource Models
178
179
### Resource
180
```python { .api }
181
class Resource:
182
"""Represents a Kubernetes API resource."""
183
group: str
184
version: str
185
kind: str
186
name: str # Plural name
187
singular_name: str
188
namespaced: bool
189
api_version: str
190
client: DynamicClient
191
192
def create(self, body: dict = None, namespace: str = None, **kwargs) -> ResourceInstance: ...
193
def get(self, name: str = None, namespace: str = None, **kwargs) -> ResourceInstance: ...
194
def delete(self, name: str = None, namespace: str = None, **kwargs) -> ResourceInstance: ...
195
def patch(self, body: dict = None, name: str = None, namespace: str = None, **kwargs) -> ResourceInstance: ...
196
def replace(self, body: dict = None, name: str = None, namespace: str = None, **kwargs) -> ResourceInstance: ...
197
```
198
199
### ResourceInstance
200
```python { .api }
201
class ResourceInstance:
202
"""Instance of a Kubernetes resource with dynamic attributes."""
203
204
# Dynamic attributes based on resource structure
205
api_version: str
206
kind: str
207
metadata: dict
208
spec: dict
209
status: dict
210
211
def to_dict(self) -> dict: ...
212
def to_str(self) -> str: ...
213
```
214
215
### ResourceList
216
```python { .api }
217
class ResourceList:
218
"""List of ResourceInstance objects."""
219
api_version: str
220
kind: str
221
metadata: dict
222
items: list # List of ResourceInstance
223
224
def to_dict(self) -> dict: ...
225
```
226
227
### ResourceField
228
```python { .api }
229
class ResourceField:
230
"""Field descriptor for resource attributes."""
231
name: str
232
type: str
233
description: str
234
```
235
236
### Subresource
237
```python { .api }
238
class Subresource:
239
"""Represents a subresource (logs, exec, status, etc.)."""
240
def get(self, name: str = None, namespace: str = None, **kwargs): ...
241
def create(self, body: dict = None, name: str = None, namespace: str = None, **kwargs): ...
242
def patch(self, body: dict = None, name: str = None, namespace: str = None, **kwargs): ...
243
def replace(self, body: dict = None, name: str = None, namespace: str = None, **kwargs): ...
244
```
245
246
## Usage Examples
247
248
### Basic Dynamic Client Usage
249
250
```python
251
from kubernetes import client, config, dynamic
252
253
# Load configuration
254
config.load_kube_config()
255
256
# Create dynamic client
257
dyn_client = dynamic.DynamicClient(client.ApiClient())
258
259
# Get pods resource
260
pods = dyn_client.resources.get(api_version="v1", kind="Pod")
261
262
# List all pods
263
pod_list = pods.get()
264
for pod in pod_list.items:
265
print(f"Pod: {pod.metadata.name}")
266
267
# Get specific pod
268
pod = pods.get(name="my-pod", namespace="default")
269
print(f"Pod status: {pod.status.phase}")
270
```
271
272
### Working with Custom Resources
273
274
```python
275
from kubernetes import client, config, dynamic
276
277
config.load_kube_config()
278
dyn_client = dynamic.DynamicClient(client.ApiClient())
279
280
# Access custom resource
281
my_crds = dyn_client.resources.get(
282
api_version="mycompany.io/v1",
283
kind="MyCustomResource"
284
)
285
286
# Create custom resource
287
custom_resource = {
288
"apiVersion": "mycompany.io/v1",
289
"kind": "MyCustomResource",
290
"metadata": {
291
"name": "my-resource",
292
"namespace": "default"
293
},
294
"spec": {
295
"field1": "value1",
296
"field2": "value2"
297
}
298
}
299
300
# Create the resource
301
created = my_crds.create(body=custom_resource, namespace="default")
302
print(f"Created: {created.metadata.name}")
303
304
# List custom resources
305
resources = my_crds.get()
306
for resource in resources.items:
307
print(f"Custom resource: {resource.metadata.name}")
308
```
309
310
### Resource Discovery
311
312
```python
313
from kubernetes import client, config, dynamic
314
315
config.load_kube_config()
316
dyn_client = dynamic.DynamicClient(client.ApiClient())
317
318
# Discover all available resources
319
for resource in dyn_client.resources.search():
320
print(f"Resource: {resource.kind} ({resource.api_version})")
321
print(f" Namespaced: {resource.namespaced}")
322
print(f" Name: {resource.name}")
323
324
# Find resources by group
325
apps_resources = dyn_client.resources.search(group="apps")
326
for resource in apps_resources:
327
print(f"Apps resource: {resource.kind}")
328
329
# Find specific resource
330
deployments = dyn_client.resources.get(api_version="apps/v1", kind="Deployment")
331
print(f"Found deployments resource: {deployments.name}")
332
```
333
334
### Patching Resources
335
336
```python
337
from kubernetes import client, config, dynamic
338
339
config.load_kube_config()
340
dyn_client = dynamic.DynamicClient(client.ApiClient())
341
342
# Get deployments resource
343
deployments = dyn_client.resources.get(api_version="apps/v1", kind="Deployment")
344
345
# Scale deployment using patch
346
patch_body = {
347
"spec": {
348
"replicas": 5
349
}
350
}
351
352
patched = deployments.patch(
353
name="my-deployment",
354
namespace="default",
355
body=patch_body
356
)
357
print(f"Deployment scaled to {patched.spec.replicas} replicas")
358
359
# Strategic merge patch for labels
360
label_patch = {
361
"metadata": {
362
"labels": {
363
"environment": "production",
364
"version": "v2.0"
365
}
366
}
367
}
368
369
deployments.patch(
370
name="my-deployment",
371
namespace="default",
372
body=label_patch
373
)
374
```
375
376
### Using Different Discoverers
377
378
```python
379
from kubernetes import client, config, dynamic
380
381
config.load_kube_config()
382
383
# Use eager discoverer (preloads all resources)
384
eager_discoverer = dynamic.EagerDiscoverer(client.ApiClient())
385
dyn_client_eager = dynamic.DynamicClient(
386
client.ApiClient(),
387
discoverer=eager_discoverer
388
)
389
390
# Use lazy discoverer (discovers on-demand)
391
lazy_discoverer = dynamic.LazyDiscoverer(client.ApiClient())
392
dyn_client_lazy = dynamic.DynamicClient(
393
client.ApiClient(),
394
discoverer=lazy_discoverer
395
)
396
397
# Both clients work the same way
398
pods = dyn_client_eager.resources.get(api_version="v1", kind="Pod")
399
pod_list = pods.get()
400
```