br-rapp-sdk 2025.7.4.dev2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of br-rapp-sdk might be problematic. Click here for more details.

@@ -0,0 +1,452 @@
1
+ from kubernetes import client, config
2
+ import requests
3
+ from .a1_policy_types import *
4
+ from ..oam_services.oam_services import OAMServices
5
+ from ..common import (
6
+ load_kubeconfig,
7
+ get_cr,
8
+ list_cr,
9
+ apply_cr,
10
+ delete_cr,
11
+ KubectlOperationResult,
12
+ )
13
+ from .common import (
14
+ ODIN_GROUP,
15
+ ODIN_VERSION,
16
+ ODIN_POLICYJOB_KIND,
17
+ ODIN_POLICYJOB_PLURAL,
18
+ )
19
+ class A1Services:
20
+ """ This class provides methods to interact with the A1 Services API in BubbleRAN environment.
21
+
22
+ A1Services is a client for managing A1 policies in the BubbleRAN environment.
23
+
24
+ Attributes:
25
+ kubeconfig_path (Optional[str]): Path to the kubeconfig file.
26
+ namespace (str): Kubernetes namespace for A1 policy jobs.
27
+
28
+ Examples :
29
+ ```python
30
+ from br_rapp_sdk import A1Services
31
+ from br_rapp_sdk.a1_services.a1_policy_types import PolicyObjectInformation, PolicyId
32
+ a1_services = A1Services()
33
+ # List all policies
34
+ result = a1_services.list_policies()
35
+ if result.status == "success":
36
+ for policy_id, policy_info in result.data:
37
+ print(f"Policy ID: {policy_id}, Info: {policy_info}")
38
+ else:
39
+ print(f"Error: {result.error}")
40
+ # Get a specific policy
41
+ policy_id = PolicyId("example-policy")
42
+ result = a1_services.get_policy(policy_id)
43
+ if result.status == "success":
44
+ policy_info = result.data.get('item')
45
+ print(f"Policy Info: {policy_info}")
46
+ else:
47
+ print(f"Error: {result.error}")
48
+ ```
49
+ """
50
+
51
+ def __init__(
52
+ self,
53
+ kubeconfig_path: Optional[str] = None,
54
+ namespace: str = "trirematics"
55
+ ):
56
+ """
57
+ Initialize the A1Services client by loading the Kubernetes configuration and setting up defaults.
58
+
59
+ Parameters:
60
+ kubeconfig_path (Optional[str]): Path to the kubeconfig file. If None, uses the default kubeconfig.
61
+ namespace (str): Kubernetes namespace for A1 policy jobs. Default is "trirematics".
62
+
63
+ Raises:
64
+ RuntimeError: If kubeconfig cannot be loaded or if there are issues with the API.
65
+ """
66
+ load_kubeconfig(kubeconfig_path)
67
+
68
+ self.kubeconfig_path = kubeconfig_path
69
+ self.namespace = namespace
70
+
71
+ self._api = client.CustomObjectsApi()
72
+ self._group = ODIN_GROUP
73
+ self._version = ODIN_VERSION
74
+ self._plural = ODIN_POLICYJOB_PLURAL
75
+ self._kind = ODIN_POLICYJOB_KIND
76
+
77
+ def list_policies(
78
+ self,
79
+ policy_id: Optional[PolicyId] = None,
80
+ ) -> KubectlOperationResult:
81
+ """ This method lists all policies in the A1 Services API.
82
+
83
+ Parameters:
84
+ Policy_id (Optional[PolicyId]): If provided, filters policies by the given ID.
85
+
86
+ Returns:
87
+ KubectlOperationResult: An object representing the result of the operation, containing a list of PolicyId and PolicyObjectInformation tuples if successful, or an error message if not.
88
+
89
+ Example:
90
+ ```python
91
+ from br_rapp_sdk import A1Services
92
+ a1_services = A1Services()
93
+ result = a1_services.list_policies()
94
+ # Check if the operation was successful
95
+ if result.status == "success":
96
+ for policy_id, policy_info in result.data:
97
+ print(f"Policy ID: {policy_id}, Info: {policy_info}")
98
+ else:
99
+ print(f"Error: {result.error}")
100
+ ```
101
+ """
102
+ policies = []
103
+
104
+ list_policy_result = list_cr(
105
+ kube_api_instance=self._api,
106
+ group=self._group,
107
+ version=self._version,
108
+ plural=self._plural,
109
+ namespace=self.namespace
110
+ )
111
+ if list_policy_result.status == "success":
112
+ items = list_policy_result.data.get("items", [])
113
+ if policy_id:
114
+ # Filter policies by the given PolicyId
115
+ items = [
116
+ item for item in items if
117
+ item["metadata"]["name"] == policy_id
118
+ ]
119
+
120
+ for item in items:
121
+ policy_id = PolicyId(item.get("metadata", {}).get("name"))
122
+ policy_obj = PolicyObjectInformation(**item.get('spec', {}))
123
+ policies.append((policy_id, policy_obj))
124
+ list_policy_result.data['items'] = policies
125
+
126
+ return list_policy_result
127
+
128
+ def get_policy(
129
+ self,
130
+ policy_id: PolicyId
131
+ ) -> KubectlOperationResult:
132
+ """
133
+ Get a specific policy from the A1 Services API.
134
+
135
+ Parameters:
136
+ policy_id (PolicyId): The ID of the policy to retrieve.
137
+
138
+ Returns:
139
+ KubectlOperationResult: An object representing the result of the operation, containing the PolicyObjectInformation if successful, or an error message if not.
140
+
141
+ Example:
142
+ ```python
143
+ from br_rapp_sdk import A1Services
144
+ from br_rapp_sdk.a1_services.a1_policy_types import PolicyId
145
+ a1_services = A1Services()
146
+ policy_id = PolicyId("example-policy")
147
+ result = a1_services.get_policy(policy_id)
148
+ if result.status == "success":
149
+ policy_info = result.data.get('item')
150
+ print(f"Policy Info: {policy_info}")
151
+ else:
152
+ print(f"Error: {result.error}")
153
+ ```
154
+ """
155
+
156
+ get_policy_result = get_cr(
157
+ kube_api_instance=self._api,
158
+ group=self._group,
159
+ version=self._version,
160
+ plural=self._plural,
161
+ namespace=self.namespace,
162
+ name=policy_id
163
+ )
164
+ if get_policy_result.status == "success":
165
+ item = get_policy_result.data.get("item", {})
166
+ policy_obj = PolicyObjectInformation(**item.get('spec', {}))
167
+ get_policy_result.data = {'item': policy_obj}
168
+ return get_policy_result
169
+
170
+ def get_policy_feedback_api_urls(
171
+ self,
172
+ policy_id: PolicyId
173
+ ) -> KubectlOperationResult:
174
+ """
175
+ Get the feedback API URLs for dynamic xApps in a specific policy.
176
+
177
+ Parameters:
178
+ policy_id (PolicyId): The ID of the policy to retrieve feedback URLs for.
179
+
180
+ Returns:
181
+ KubectlOperationResult: An object representing the result of the operation, containing a list of tuples with DynamicXappId and their corresponding feedback URLs if successful, or an error message if not.
182
+
183
+ Example:
184
+ ```python
185
+ from br_rapp_sdk import A1Services
186
+ from br_rapp_sdk.a1_services.a1_policy_types import PolicyId, DynamicXappId
187
+ a1_services = A1Services()
188
+ policy_id = PolicyId("example-policy")
189
+ result = a1_services.get_policy_feedback_api_urls(policy_id)
190
+ if result.status == "success":
191
+ for dynamic_xapp, feedback_urls in result.data:
192
+ print(f"Dynamic xApp: {dynamic_xapp}, Feedback URLs: {[url.ip for url in feedback_urls]}")
193
+ else:
194
+ print(f"Error getting policy feedback URLs: {result.error}")
195
+ ```
196
+ """
197
+
198
+ get_policy_result = get_cr(
199
+ kube_api_instance=self._api,
200
+ group=self._group,
201
+ version=self._version,
202
+ plural=self._plural,
203
+ namespace=self.namespace,
204
+ name=policy_id
205
+ )
206
+
207
+ if get_policy_result.status == "success":
208
+ item = get_policy_result.data.get("item", {})
209
+ status = item.get("status", {})
210
+ dyn_xapps_map = status.get("dynXAppsElementsMap", {})
211
+
212
+ feedback_urls = []
213
+ for dyn_xapp_key, dyn_xapp_value in dyn_xapps_map.items():
214
+ dyn_xapp_name, dyn_xapp_target, dyn_xapps_network, dyn_xapp_namespace = dyn_xapp_key.split('.')
215
+ dynamic_xapp = DynamicXappId(f"{dyn_xapp_name}.{dyn_xapp_target}.{dyn_xapps_network}")
216
+ urls = [PolicyFeedbackDestination(**fb) for fb in dyn_xapp_value.get("feedbackUrls", [])]
217
+ feedback_urls.append((dynamic_xapp, urls))
218
+
219
+ get_policy_result.data = {'items': feedback_urls}
220
+
221
+ return get_policy_result
222
+
223
+ def get_policy_feedback(
224
+ self,
225
+ policy_feedback_dest: PolicyFeedbackDestination,
226
+ time_out: int = 5
227
+ ) -> KubectlOperationResult:
228
+ """
229
+ Get the policy feedback from a specific feedback destination.
230
+
231
+ Parameters:
232
+ policy_feedback (PolicyFeedbackDestination): The feedback destination containing the full URL to retrieve feedback from.
233
+ time_out (int): The timeout for the HTTP request in seconds. Default is 5 seconds.
234
+
235
+ Returns:
236
+ KubectlOperationResult: An object representing the result of the operation, containing the feedback data if successful, or an error message if not.
237
+
238
+ Example:
239
+ ```python
240
+ from br_rapp_sdk import A1Services
241
+ from br_rapp_sdk.a1_services.a1_policy_types import PolicyFeedbackDestination
242
+ a1_services = A1Services()
243
+ policy_feedback = PolicyFeedbackDestination(...)
244
+ result = a1_services.get_policy_feedback(policy_feedback)
245
+ if result.status == "success":
246
+ print(f"Policy Feedback: {result.data.get('item', {})}")
247
+ else:
248
+ print(f"Error getting policy feedback: {result.error}")
249
+ ```
250
+ """
251
+ try:
252
+ response = requests.get(
253
+ url=policy_feedback_dest.full_url,
254
+ timeout=time_out
255
+ )
256
+ response.raise_for_status()
257
+ feedback_data = response.json()
258
+ return KubectlOperationResult(status="success", operation="get", data={'item': feedback_data})
259
+ except requests.RequestException as e:
260
+ return KubectlOperationResult(
261
+ status="error",
262
+ operation="get",
263
+ error={
264
+ "code": 408,
265
+ "message": str(e)
266
+ }
267
+ )
268
+
269
+ def apply_policy(
270
+ self,
271
+ policy_name: str,
272
+ policy_object: PolicyObjectInformation
273
+ ) -> KubectlOperationResult:
274
+ """
275
+ Apply a policy to the A1 Services API.
276
+
277
+ Parameters:
278
+ policy_name (str): The name of the policy to apply.
279
+ policy_object (PolicyObjectInformation): The policy object containing the specifications.
280
+
281
+ Returns:
282
+ KubectlOperationResult: An object representing the result of the operation, containing the PolicyId if successful, or an error message if not.
283
+
284
+ Example:
285
+ ```python
286
+ from br_rapp_sdk import A1Services
287
+ from br_rapp_sdk.a1_services.a1_policy_types import PolicyObjectInformation, PolicyId, NearRtRicId, PolicyTypeId, PolicyObject, ScopeIdentifier, PolicyStatements
288
+ a1_services = A1Services()
289
+ policy_object = PolicyObjectInformation(
290
+ near_rt_ric_id=NearRtRicId("ric-name.network-name"),
291
+ policy_type_id=PolicyTypeId("cm/example"),
292
+ policy_object=PolicyObject(
293
+ scope_identifier=ScopeIdentifier(...),
294
+ policy_statements=PolicyStatements(...)
295
+ )
296
+ )
297
+ result = a1_services.apply_policy(policy_name="example-policy", policy_object=policy_object)
298
+ if result.status == 'success':
299
+ policy_id = result.data.get('policy_id')
300
+ print(f"Policy applied successfully: {policy_id}")
301
+ else:
302
+ print(f"Error applying policy: {result.error}")
303
+ ```
304
+ """
305
+ body = {
306
+ "apiVersion": f"{self._group}/{self._version}",
307
+ "kind": self._kind,
308
+ "metadata": {
309
+ "name": policy_name,
310
+ "namespace": self.namespace
311
+ },
312
+ "spec": policy_object.model_dump(exclude_none=True, by_alias=True)
313
+ }
314
+
315
+ apply_result = apply_cr(
316
+ kube_api_instance=self._api,
317
+ group=self._group,
318
+ version=self._version,
319
+ plural=self._plural,
320
+ namespace=self.namespace,
321
+ body=body
322
+ )
323
+
324
+ if apply_result.status == "success":
325
+ policy_id = PolicyId(apply_result.data.get("metadata", {}).get("name"))
326
+ apply_result.data = {'policy_id': policy_id}
327
+
328
+ return apply_result
329
+
330
+ def delete_policy(
331
+ self,
332
+ policy_id: PolicyId
333
+ ) -> KubectlOperationResult:
334
+ """
335
+ Delete a policy from the A1 Services API.
336
+
337
+ Parameters:
338
+ policy_id (PolicyId): The ID of the policy to delete.
339
+
340
+ Returns:
341
+ KubectlOperationResult: An object representing the result of the operation, indicating success or failure.
342
+
343
+ Example:
344
+ ```python
345
+ from br_rapp_sdk import A1Services
346
+ from br_rapp_sdk.a1_services.a1_policy_types import PolicyId
347
+ a1_services = A1Services()
348
+ policy_id = PolicyId("example-policy")
349
+ result = a1_services.delete_policy(policy_id)
350
+ if result.status == "success":
351
+ print(f"Policy {policy_id} deleted successfully.")
352
+ else:
353
+ print(f"Error deleting policy: {result.error}")
354
+ ```
355
+ """
356
+
357
+ delete_result = delete_cr(
358
+ kube_api_instance=self._api,
359
+ group=self._group,
360
+ version=self._version,
361
+ plural=self._plural,
362
+ namespace=self.namespace,
363
+ name=policy_id
364
+ )
365
+
366
+ if delete_result.status == "success":
367
+ delete_result.data = {'policy_id': policy_id}
368
+
369
+ return delete_result
370
+
371
+ def get_policy_status(
372
+ self,
373
+ policy_id: PolicyId
374
+ ) -> KubectlOperationResult:
375
+ """
376
+ Get the status of a specific policy in the A1 Services API.
377
+
378
+ Parameters:
379
+ policy_id (PolicyId): The ID of the policy to check.
380
+
381
+ Returns:
382
+ KubectlOperationResult: An object representing the result of the operation, containing the policy status if successful, or an error message if not.
383
+
384
+ Example:
385
+ ```python
386
+ from br_rapp_sdk import A1Services
387
+ from br_rapp_sdk.a1_services.a1_policy_types import PolicyId
388
+ a1_services = A1Services()
389
+ policy_id = PolicyId("example-policy")
390
+ result = a1_services.get_policy_status(policy_id)
391
+ if result.status == "success":
392
+ print(f"Policy Status: {result.data.get('status')}")
393
+ else:
394
+ print(f"Error getting policy status: {result.error}")
395
+ ```
396
+ """
397
+
398
+ get_policy_result = get_cr(
399
+ kube_api_instance=self._api,
400
+ group=self._group,
401
+ version=self._version,
402
+ plural=self._plural,
403
+ namespace=self.namespace,
404
+ name=policy_id
405
+ )
406
+
407
+ if get_policy_result.status == "success":
408
+ item = get_policy_result.data.get("item", {})
409
+ get_policy_result.data["status"] = item.get("status", {})
410
+
411
+
412
+ return get_policy_result
413
+
414
+ def get_rics(
415
+ self,
416
+ network_id: Optional[NetworkId] = None
417
+ ) -> KubectlOperationResult:
418
+ """
419
+ Get the list of Near RT RICs from the OAM services.
420
+ This method retrieves the Near RT RICs from the OAM services and returns their IDs.
421
+
422
+ Parameters:
423
+ Optional[NetworkId]: If provided, filters Near RT RICs by the given NetworkId.
424
+
425
+ Returns:
426
+ KubectlOperationResult: An object representing the result of the operation, containing a list of NearRtRicId if successful, or an error message if not.
427
+
428
+ Example:
429
+ ```python
430
+ from br_rapp_sdk import A1Services
431
+ a1_services = A1Services()
432
+ result = a1_services.get_rics()
433
+ if result.status == "success":
434
+ near_rt_rics = result.data.get('items', [])
435
+ for near_rt_ric in near_rt_rics:
436
+ print(f"Near RT RIC ID: {near_rt_ric}")
437
+ else:
438
+ print(f"Error getting Near RT RICs: {result.error}")
439
+ ```
440
+ """
441
+ oam_services = OAMServices(kubeconfig_path=self.kubeconfig_path, namespace=self.namespace)
442
+ result = oam_services.network.list_networks(network_id=network_id, part="edge")
443
+ if result.status == "success":
444
+ near_rt_rics = []
445
+ items = result.data.get('items', [])
446
+
447
+ for element_name, element_spec in items:
448
+ model = element_spec.model
449
+ if model == "mosaic5g/flexric":
450
+ near_rt_rics.append(NearRtRicId(element_name))
451
+ result.data['items'] = near_rt_rics
452
+ return result
@@ -0,0 +1,6 @@
1
+ ODIN_GROUP = "odin.trirematics.io"
2
+ ODIN_VERSION = "v1"
3
+
4
+ ODIN_POLICYJOB_KIND = "PolicyJob"
5
+
6
+ ODIN_POLICYJOB_PLURAL = "policyjobs"
@@ -0,0 +1,4 @@
1
+ from .chat_model_config import ChatModelClientConfig
2
+ from .chat_model_client import ChatModelClient
3
+ from .tools import ToolCall
4
+ from .agent import AgentApplication, AgentGraph, AgentTaskResult