0
# Dynamic Client
1
2
Runtime API discovery and interaction with any Kubernetes resource, including custom resources defined by Custom Resource Definitions (CRDs). The dynamic client enables working with resources not known at compile time and provides a flexible interface for any Kubernetes API.
3
4
## Capabilities
5
6
### Dynamic Client
7
8
The main entry point for dynamic Kubernetes API interactions with automatic resource discovery.
9
10
```python { .api }
11
class DynamicClient:
12
def __init__(self, client, cache_file=None, discoverer=None):
13
"""
14
Initialize dynamic client with API discovery.
15
16
Parameters:
17
- client: ApiClient, authenticated Kubernetes API client
18
- cache_file: str, path to cache discovered API resources (optional)
19
- discoverer: Discoverer, custom discovery implementation (optional)
20
"""
21
22
async def __aenter__(self):
23
"""Async context manager entry."""
24
25
async def __aexit__(self, exc_type, exc_val, exc_tb):
26
"""Async context manager exit with cleanup."""
27
28
@property
29
def resources(self):
30
"""
31
Access to discovered resources.
32
33
Returns:
34
- ResourceRegistry: Registry of all discovered API resources
35
"""
36
37
@property
38
def version(self):
39
"""
40
Kubernetes API server version information.
41
42
Returns:
43
- dict: Version details including major, minor, git version, etc.
44
"""
45
```
46
47
### Resource Access
48
49
Interface for accessing and manipulating any Kubernetes resource type dynamically.
50
51
```python { .api }
52
class Resource:
53
def __init__(self, api_version, kind, client, **kwargs):
54
"""
55
Represents a Kubernetes API resource type.
56
57
Parameters:
58
- api_version: str, API version (e.g., "v1", "apps/v1")
59
- kind: str, resource kind (e.g., "Pod", "Deployment")
60
- client: DynamicClient, parent dynamic client
61
"""
62
63
def get(self, name=None, namespace=None, label_selector=None, field_selector=None, **kwargs):
64
"""
65
Get resource(s) by name or selectors.
66
67
Parameters:
68
- name: str, specific resource name (for single resource)
69
- namespace: str, namespace to search (for namespaced resources)
70
- label_selector: str, label selector query
71
- field_selector: str, field selector query
72
- **kwargs: Additional query parameters
73
74
Returns:
75
- ResourceInstance or ResourceList: Single resource or list of resources
76
"""
77
78
def create(self, body=None, namespace=None, **kwargs):
79
"""
80
Create a new resource.
81
82
Parameters:
83
- body: dict, resource definition
84
- namespace: str, target namespace (for namespaced resources)
85
- **kwargs: Additional creation parameters
86
87
Returns:
88
- ResourceInstance: Created resource
89
"""
90
91
def patch(self, body=None, name=None, namespace=None, **kwargs):
92
"""
93
Partially update a resource.
94
95
Parameters:
96
- body: dict, patch data
97
- name: str, resource name to patch
98
- namespace: str, resource namespace (for namespaced resources)
99
- **kwargs: Additional patch parameters
100
101
Returns:
102
- ResourceInstance: Updated resource
103
"""
104
105
def replace(self, body=None, name=None, namespace=None, **kwargs):
106
"""
107
Replace entire resource.
108
109
Parameters:
110
- body: dict, complete resource definition
111
- name: str, resource name to replace
112
- namespace: str, resource namespace (for namespaced resources)
113
- **kwargs: Additional replace parameters
114
115
Returns:
116
- ResourceInstance: Replaced resource
117
"""
118
119
def delete(self, name=None, namespace=None, label_selector=None, field_selector=None, **kwargs):
120
"""
121
Delete resource(s).
122
123
Parameters:
124
- name: str, specific resource name
125
- namespace: str, resource namespace (for namespaced resources)
126
- label_selector: str, label selector for bulk deletion
127
- field_selector: str, field selector for bulk deletion
128
- **kwargs: Additional deletion parameters
129
130
Returns:
131
- ResourceInstance or ResourceList: Deleted resource(s) or status
132
"""
133
134
def watch(self, namespace=None, name=None, label_selector=None, field_selector=None,
135
resource_version=None, timeout_seconds=None, **kwargs):
136
"""
137
Watch for resource changes.
138
139
Parameters:
140
- namespace: str, namespace to watch (for namespaced resources)
141
- name: str, specific resource name to watch
142
- label_selector: str, label selector for filtering
143
- field_selector: str, field selector for filtering
144
- resource_version: str, resource version to start watching from
145
- timeout_seconds: int, watch timeout
146
- **kwargs: Additional watch parameters
147
148
Returns:
149
- generator: Stream of watch events
150
"""
151
152
@property
153
def subresources(self):
154
"""
155
Access to resource subresources (scale, status, etc.).
156
157
Returns:
158
- dict: Mapping of subresource names to Subresource objects
159
"""
160
```
161
162
### Resource Objects
163
164
Wrappers for individual Kubernetes resource instances with convenient access patterns.
165
166
```python { .api }
167
class ResourceInstance:
168
def __init__(self, resource, instance):
169
"""
170
Wrapper for individual Kubernetes resource.
171
172
Parameters:
173
- resource: Resource, parent resource type
174
- instance: dict, resource data from API
175
"""
176
177
@property
178
def metadata(self):
179
"""Resource metadata (name, namespace, labels, annotations, etc.)."""
180
181
@property
182
def spec(self):
183
"""Resource specification."""
184
185
@property
186
def status(self):
187
"""Resource status."""
188
189
def to_dict(self):
190
"""Convert to dictionary representation."""
191
192
def patch(self, body=None, **kwargs):
193
"""Patch this specific resource instance."""
194
195
def replace(self, body=None, **kwargs):
196
"""Replace this specific resource instance."""
197
198
def delete(self, **kwargs):
199
"""Delete this specific resource instance."""
200
201
class ResourceList:
202
def __init__(self, resource, items):
203
"""
204
List of Kubernetes resources.
205
206
Parameters:
207
- resource: Resource, parent resource type
208
- items: list, resource instances
209
"""
210
211
@property
212
def items(self):
213
"""List of ResourceInstance objects."""
214
215
@property
216
def metadata(self):
217
"""List metadata (resource version, continue token, etc.)."""
218
219
def to_dict(self):
220
"""Convert entire list to dictionary representation."""
221
```
222
223
### Subresources
224
225
Access to Kubernetes subresources like scale, status, and custom subresources.
226
227
```python { .api }
228
class Subresource:
229
def __init__(self, parent_resource, name):
230
"""
231
Kubernetes resource subresource.
232
233
Parameters:
234
- parent_resource: Resource, parent resource type
235
- name: str, subresource name (e.g., "scale", "status")
236
"""
237
238
def get(self, name, namespace=None, **kwargs):
239
"""Get subresource for specific parent resource."""
240
241
def patch(self, name, body, namespace=None, **kwargs):
242
"""Patch subresource for specific parent resource."""
243
244
def replace(self, name, body, namespace=None, **kwargs):
245
"""Replace subresource for specific parent resource."""
246
```
247
248
### Discovery System
249
250
API discovery implementations for loading Kubernetes API resources at runtime.
251
252
```python { .api }
253
class EagerDiscoverer:
254
def __init__(self, client, cache_file=None):
255
"""
256
Pre-loads all API resource information at initialization.
257
258
Parameters:
259
- client: ApiClient, authenticated Kubernetes client
260
- cache_file: str, path to cache file for discovered resources
261
"""
262
263
def get_resources_for_api_version(self, prefix, group_version):
264
"""Get all resources for specific API version."""
265
266
class LazyDiscoverer:
267
def __init__(self, client, cache_file=None):
268
"""
269
Loads API resources on-demand as they are accessed (default).
270
271
Parameters:
272
- client: ApiClient, authenticated Kubernetes client
273
- cache_file: str, path to cache file for discovered resources
274
"""
275
276
def get_resources_for_api_version(self, prefix, group_version):
277
"""Get resources for API version, loading if not cached."""
278
```
279
280
### Exception Classes
281
282
Dynamic client specific exceptions for error handling.
283
284
```python { .api }
285
class KubernetesValidateMissing(Exception):
286
"""Raised when kubernetes-validate library is not available for client-side validation."""
287
288
def api_exception(e):
289
"""
290
Wrapper function that converts API exceptions to appropriate types.
291
292
Parameters:
293
- e: Exception, original API exception
294
295
Returns:
296
- Exception: Appropriately typed exception
297
"""
298
```
299
300
## Usage Examples
301
302
### Basic Dynamic Client Usage
303
304
```python
305
import asyncio
306
from kubernetes_asyncio import client, config, dynamic
307
308
async def basic_dynamic():
309
await config.load_config()
310
api_client = client.ApiClient()
311
312
async with dynamic.DynamicClient(api_client) as dyn_client:
313
# Access any Kubernetes resource
314
pods = dyn_client.resources.get(api_version="v1", kind="Pod")
315
316
# List all pods across all namespaces
317
pod_list = pods.get()
318
print(f"Found {len(pod_list.items)} pods")
319
320
# List pods in specific namespace
321
default_pods = pods.get(namespace="default")
322
for pod in default_pods.items:
323
print(f"Pod: {pod.metadata.name} in {pod.metadata.namespace}")
324
325
asyncio.run(basic_dynamic())
326
```
327
328
### Working with Custom Resources
329
330
```python
331
async def custom_resources():
332
await config.load_config()
333
api_client = client.ApiClient()
334
335
async with dynamic.DynamicClient(api_client) as dyn_client:
336
# Access custom resource (assuming CRD exists)
337
custom_resource = dyn_client.resources.get(
338
api_version="example.com/v1",
339
kind="MyCustomResource"
340
)
341
342
# Create custom resource
343
custom_obj = {
344
"apiVersion": "example.com/v1",
345
"kind": "MyCustomResource",
346
"metadata": {
347
"name": "my-custom-object",
348
"namespace": "default"
349
},
350
"spec": {
351
"replicas": 3,
352
"template": "nginx"
353
}
354
}
355
356
created = custom_resource.create(body=custom_obj, namespace="default")
357
print(f"Created custom resource: {created.metadata.name}")
358
359
# List custom resources
360
custom_list = custom_resource.get(namespace="default")
361
for item in custom_list.items:
362
print(f"Custom resource: {item.metadata.name}")
363
364
asyncio.run(custom_resources())
365
```
366
367
### Resource Discovery and Exploration
368
369
```python
370
async def explore_resources():
371
await config.load_config()
372
api_client = client.ApiClient()
373
374
async with dynamic.DynamicClient(api_client) as dyn_client:
375
# Explore available API resources
376
print(f"Kubernetes version: {dyn_client.version}")
377
378
# Get all available resources
379
all_resources = dyn_client.resources.search()
380
381
print("Available API resources:")
382
for resource in all_resources:
383
print(f" {resource.api_version}/{resource.kind} - {resource.name}")
384
385
# Find resources by kind
386
deployment_resources = dyn_client.resources.search(kind="Deployment")
387
for res in deployment_resources:
388
print(f"Deployment resource: {res.api_version}/{res.kind}")
389
390
asyncio.run(explore_resources())
391
```
392
393
### Watching Resources
394
395
```python
396
async def watch_resources():
397
await config.load_config()
398
api_client = client.ApiClient()
399
400
async with dynamic.DynamicClient(api_client) as dyn_client:
401
pods = dyn_client.resources.get(api_version="v1", kind="Pod")
402
403
# Watch for pod changes in default namespace
404
print("Watching for pod changes...")
405
406
async for event in pods.watch(namespace="default", timeout_seconds=300):
407
event_type = event['type'] # ADDED, MODIFIED, DELETED
408
pod = event['object']
409
print(f"{event_type}: Pod {pod.metadata.name} - {pod.status.phase}")
410
411
asyncio.run(watch_resources())
412
```
413
414
### Scaling Deployments
415
416
```python
417
async def scale_deployment():
418
await config.load_config()
419
api_client = client.ApiClient()
420
421
async with dynamic.DynamicClient(api_client) as dyn_client:
422
deployments = dyn_client.resources.get(api_version="apps/v1", kind="Deployment")
423
424
# Get current deployment
425
deployment = deployments.get(name="nginx-deployment", namespace="default")
426
print(f"Current replicas: {deployment.spec.replicas}")
427
428
# Scale using the scale subresource
429
scale_resource = deployments.subresources["scale"]
430
current_scale = scale_resource.get(name="nginx-deployment", namespace="default")
431
432
# Update replica count
433
new_scale = {
434
"apiVersion": "autoscaling/v1",
435
"kind": "Scale",
436
"metadata": current_scale.metadata.to_dict(),
437
"spec": {"replicas": 5}
438
}
439
440
updated_scale = scale_resource.replace(
441
name="nginx-deployment",
442
namespace="default",
443
body=new_scale
444
)
445
print(f"Scaled to {updated_scale.spec.replicas} replicas")
446
447
asyncio.run(scale_deployment())
448
```
449
450
### Bulk Operations with Label Selectors
451
452
```python
453
async def bulk_operations():
454
await config.load_config()
455
api_client = client.ApiClient()
456
457
async with dynamic.DynamicClient(api_client) as dyn_client:
458
pods = dyn_client.resources.get(api_version="v1", kind="Pod")
459
460
# List pods with specific labels
461
labeled_pods = pods.get(
462
namespace="default",
463
label_selector="app=nginx,env=production"
464
)
465
466
print(f"Found {len(labeled_pods.items)} nginx production pods")
467
468
# Patch all matching pods
469
for pod in labeled_pods.items:
470
patch_body = {
471
"metadata": {
472
"annotations": {
473
"last-updated": "2024-01-15T10:00:00Z"
474
}
475
}
476
}
477
478
patched = pods.patch(
479
name=pod.metadata.name,
480
namespace=pod.metadata.namespace,
481
body=patch_body
482
)
483
print(f"Patched pod: {patched.metadata.name}")
484
485
asyncio.run(bulk_operations())
486
```